From 996824d6fb2fa6e8506693c7d4a478c88a4ec795 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Wed, 1 Feb 2023 06:19:36 +0200 Subject: [PATCH 001/525] New Rust release 0.11.3 --- rust/CHANGELOG.md | 4 ++++ rust/Cargo.toml | 4 ++-- worker/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index 5d501f9b8a..c79d1c79da 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +# 0.11.3 + +* Updates from mediasoup TypeScript `3.10.13..=3.11.8`. + # 0.11.2 * Updates from mediasoup TypeScript `3.10.11..=3.11.2`. diff --git a/rust/Cargo.toml b/rust/Cargo.toml index c635ad067b..fbc913c1cf 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup" -version = "0.11.2" +version = "0.11.3" description = "Cutting Edge WebRTC Video Conferencing in Rust" categories = ["api-bindings", "multimedia", "network-programming"] authors = ["Nazar Mokrynskyi "] @@ -45,7 +45,7 @@ version = "0.8.1" [dependencies.mediasoup-sys] path = "../worker" -version = "0.5.3" +version = "0.5.4" [dependencies.parking_lot] version = "0.12.1" diff --git a/worker/Cargo.toml b/worker/Cargo.toml index 1acefdea2e..3a58bc967b 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup-sys" -version = "0.5.3" +version = "0.5.4" description = "FFI bindings to C++ libmediasoup-worker" authors = ["Nazar Mokrynskyi "] edition = "2021" From 64e4d89bd8385dc664cecb231a1338c6acbe04b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 1 Feb 2023 11:05:03 +0100 Subject: [PATCH 002/525] pull-request-stats.yml: make stats be only generated every Monday And remove `telemetry: false` since it's a premium feature and even setting it to `false` generates an error log (AFAIR). --- .github/workflows/pull-request-stats.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/pull-request-stats.yml b/.github/workflows/pull-request-stats.yml index bbc6a41f3a..1035c0188b 100644 --- a/.github/workflows/pull-request-stats.yml +++ b/.github/workflows/pull-request-stats.yml @@ -1,8 +1,6 @@ name: Pull Request Stats on: - pull_request: - types: [opened] schedule: - cron: "0 13 * * 1" # Run it every Monday at 1PM UTC. @@ -17,4 +15,3 @@ jobs: charts: true disable-links: false sort-by: 'REVIEWS' - telemetry: false From 8c2ba4411cb16d84cd5619cfb9872d1b9210eac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 1 Feb 2023 11:15:56 +0100 Subject: [PATCH 003/525] codecs cpp: add proper curly braces always --- worker/src/RTC/Codecs/H264.cpp | 12 ++++++++++++ worker/src/RTC/Codecs/VP8.cpp | 22 ++++++++++++++++++++++ worker/src/RTC/Codecs/VP9.cpp | 29 +++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/worker/src/RTC/Codecs/H264.cpp b/worker/src/RTC/Codecs/H264.cpp index 8b894570f6..01f73e5908 100644 --- a/worker/src/RTC/Codecs/H264.cpp +++ b/worker/src/RTC/Codecs/H264.cpp @@ -17,7 +17,9 @@ namespace RTC MS_TRACE(); if (len < 2) + { return nullptr; + } std::unique_ptr payloadDescriptor(new PayloadDescriptor()); @@ -48,7 +50,9 @@ namespace RTC // Detect key frame. if (frameMarking->start && frameMarking->independent) + { payloadDescriptor->isKeyFrame = true; + } } // NOTE: Unfortunately libwebrtc produces wrong Frame-Marking (without i=1 in @@ -95,7 +99,9 @@ namespace RTC // Check if there is room for the indicated NAL unit size. if (len < (naluSize + sizeof(naluSize))) + { break; + } offset += naluSize + sizeof(naluSize); len -= naluSize + sizeof(naluSize); @@ -113,7 +119,9 @@ namespace RTC uint8_t startBit = *(data + 1) & 0x80; if (subnal == 7 && startBit == 128) + { payloadDescriptor->isKeyFrame = true; + } break; } @@ -138,7 +146,9 @@ namespace RTC PayloadDescriptor* payloadDescriptor = H264::Parse(data, len, frameMarking, frameMarkingLen); if (!payloadDescriptor) + { return; + } auto* payloadDescriptorHandler = new PayloadDescriptorHandler(payloadDescriptor); @@ -231,7 +241,9 @@ namespace RTC } if (context->GetCurrentTemporalLayer() > context->GetTargetTemporalLayer()) + { context->SetCurrentTemporalLayer(context->GetTargetTemporalLayer()); + } return true; } diff --git a/worker/src/RTC/Codecs/VP8.cpp b/worker/src/RTC/Codecs/VP8.cpp index 3d5a2139ca..bab206bd04 100644 --- a/worker/src/RTC/Codecs/VP8.cpp +++ b/worker/src/RTC/Codecs/VP8.cpp @@ -20,7 +20,9 @@ namespace RTC MS_TRACE(); if (len < 1) + { return nullptr; + } std::unique_ptr payloadDescriptor(new PayloadDescriptor()); @@ -39,7 +41,9 @@ namespace RTC else { if (len < ++offset + 1) + { return nullptr; + } byte = data[offset]; @@ -52,14 +56,18 @@ namespace RTC if (payloadDescriptor->i) { if (len < ++offset + 1) + { return nullptr; + } byte = data[offset]; if ((byte >> 7) & 0x01) { if (len < ++offset + 1) + { return nullptr; + } payloadDescriptor->hasTwoBytesPictureId = true; payloadDescriptor->pictureId = (byte & 0x7F) << 8; @@ -77,7 +85,9 @@ namespace RTC if (payloadDescriptor->l) { if (len < ++offset + 1) + { return nullptr; + } payloadDescriptor->hasTl0PictureIndex = true; payloadDescriptor->tl0PictureIndex = data[offset]; @@ -86,7 +96,9 @@ namespace RTC if (payloadDescriptor->t || payloadDescriptor->k) { if (len < ++offset + 1) + { return nullptr; + } byte = data[offset]; @@ -126,7 +138,9 @@ namespace RTC PayloadDescriptor* payloadDescriptor = VP8::Parse(data, len, frameMarking, frameMarkingLen); if (!payloadDescriptor) + { return; + } auto* payloadDescriptorHandler = new PayloadDescriptorHandler(payloadDescriptor); @@ -180,7 +194,9 @@ namespace RTC // Nothing to do. if (!this->extended) + { return; + } data += 2; @@ -200,12 +216,16 @@ namespace RTC data++; if (pictureId > 127) + { MS_DEBUG_TAG(rtp, "casting pictureId value to one byte"); + } } } if (this->l) + { *data = tl0PictureIndex; + } } void VP8::PayloadDescriptor::Restore(uint8_t* data) const @@ -337,7 +357,9 @@ namespace RTC } if (context->GetCurrentTemporalLayer() > context->GetTargetTemporalLayer()) + { context->SetCurrentTemporalLayer(context->GetTargetTemporalLayer()); + } // clang-format off if ( diff --git a/worker/src/RTC/Codecs/VP9.cpp b/worker/src/RTC/Codecs/VP9.cpp index 539308f1af..a9b61747e0 100644 --- a/worker/src/RTC/Codecs/VP9.cpp +++ b/worker/src/RTC/Codecs/VP9.cpp @@ -19,7 +19,9 @@ namespace RTC MS_TRACE(); if (len < 1) + { return nullptr; + } std::unique_ptr payloadDescriptor(new PayloadDescriptor()); @@ -37,14 +39,18 @@ namespace RTC if (payloadDescriptor->i) { if (len < ++offset + 1) + { return nullptr; + } byte = data[offset]; if (byte >> 7 & 0x01) { if (len < ++offset + 1) + { return nullptr; + } payloadDescriptor->pictureId = (byte & 0x7F) << 8; payloadDescriptor->pictureId += data[offset]; @@ -62,7 +68,9 @@ namespace RTC if (payloadDescriptor->l) { if (len < ++offset + 1) + { return nullptr; + } byte = data[offset]; @@ -74,7 +82,9 @@ namespace RTC payloadDescriptor->hasTlIndex = true; if (len < ++offset + 1) + { return nullptr; + } // Read TL0PICIDX if flexible mode is unset. if (!payloadDescriptor->f) @@ -113,7 +123,9 @@ namespace RTC PayloadDescriptor* payloadDescriptor = VP9::Parse(data, len, frameMarking, frameMarkingLen); if (!payloadDescriptor) + { return; + } if (payloadDescriptor->isKeyFrame) { @@ -285,10 +297,15 @@ namespace RTC // * higher than current one // * different than the current one when KSVC is enabled and this is not a keyframe // (interframe p bit = 1) + // clang-format off if ( !isOldPacket && - (packetSpatialLayer > tmpSpatialLayer || - (context->IsKSvc() && this->payloadDescriptor->p && packetSpatialLayer != tmpSpatialLayer))) + ( + packetSpatialLayer > tmpSpatialLayer || + (context->IsKSvc() && this->payloadDescriptor->p && packetSpatialLayer != tmpSpatialLayer) + ) + ) + // clang-format on { return false; } @@ -345,12 +362,16 @@ namespace RTC // Filter temporal layers higher than current one. if (packetTemporalLayer > tmpTemporalLayer) + { return false; + } } // Set marker bit if needed. if (packetSpatialLayer == tmpSpatialLayer && this->payloadDescriptor->e) + { marker = true; + } // Update the pictureId manager. if (this->payloadDescriptor->hasPictureId) @@ -362,11 +383,15 @@ namespace RTC // Update current spatial layer if needed. if (tmpSpatialLayer != context->GetCurrentSpatialLayer()) + { context->SetCurrentSpatialLayer(tmpSpatialLayer); + } // Update current temporal layer if needed. if (tmpTemporalLayer != context->GetCurrentTemporalLayer()) + { context->SetCurrentTemporalLayer(tmpTemporalLayer); + } return true; } From fe8e84a6750615c67d9a83a20789d2b2b3fac986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Wed, 1 Feb 2023 18:40:49 +0100 Subject: [PATCH 004/525] Worker: const correctness (#1002) --- worker/src/DepLibSRTP.cpp | 2 +- worker/src/DepLibUV.cpp | 4 ++-- worker/src/DepUsrSCTP.cpp | 4 ++-- worker/src/RTC/Codecs/H264.cpp | 10 +++++----- worker/src/RTC/Codecs/H264_SVC.cpp | 8 ++++---- worker/src/RTC/Codecs/VP9.cpp | 2 +- worker/src/RTC/RTCP/Bye.cpp | 2 +- worker/src/RTC/RTCP/FeedbackPsRpsi.cpp | 4 ++-- worker/src/RTC/RTCP/FeedbackPsSli.cpp | 4 ++-- worker/src/RTC/RTCP/FeedbackPsVbcm.cpp | 4 ++-- worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp | 6 +++--- worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 6 +++--- worker/src/RTC/RTCP/Packet.cpp | 2 +- worker/src/RTC/RTCP/ReceiverReport.cpp | 2 +- worker/src/RTC/RTCP/Sdes.cpp | 4 ++-- worker/src/RTC/RTCP/SenderReport.cpp | 2 +- worker/src/RTC/RTCP/XR.cpp | 2 +- worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp | 2 +- worker/src/handles/TcpConnectionHandler.cpp | 10 +++++----- worker/src/handles/TcpServerHandler.cpp | 2 +- worker/src/handles/Timer.cpp | 10 +++++----- worker/src/handles/UdpSocketHandler.cpp | 4 ++-- worker/src/handles/UnixStreamSocket.cpp | 6 +++--- 23 files changed, 51 insertions(+), 51 deletions(-) diff --git a/worker/src/DepLibSRTP.cpp b/worker/src/DepLibSRTP.cpp index ea888bf296..70c7b8530a 100644 --- a/worker/src/DepLibSRTP.cpp +++ b/worker/src/DepLibSRTP.cpp @@ -56,7 +56,7 @@ void DepLibSRTP::ClassInit() { MS_DEBUG_TAG(info, "libsrtp version: \"%s\"", srtp_get_version_string()); - srtp_err_status_t err = srtp_init(); + const srtp_err_status_t err = srtp_init(); if (DepLibSRTP::IsError(err)) MS_THROW_ERROR("srtp_init() failed: %s", DepLibSRTP::GetErrorString(err)); diff --git a/worker/src/DepLibUV.cpp b/worker/src/DepLibUV.cpp index ed6c7b4a9b..aaa697baa5 100644 --- a/worker/src/DepLibUV.cpp +++ b/worker/src/DepLibUV.cpp @@ -38,7 +38,7 @@ void DepLibUV::ClassInit() DepLibUV::loop = new uv_loop_t; - int err = uv_loop_init(DepLibUV::loop); + const int err = uv_loop_init(DepLibUV::loop); if (err != 0) MS_ABORT("libuv loop initialization failed"); @@ -88,7 +88,7 @@ void DepLibUV::RunLoop() // This should never happen. MS_ASSERT(DepLibUV::loop != nullptr, "loop unset"); - int ret = uv_run(DepLibUV::loop, UV_RUN_DEFAULT); + const int ret = uv_run(DepLibUV::loop, UV_RUN_DEFAULT); MS_ASSERT(ret == 0, "uv_run() returned %s", uv_err_name(ret)); } diff --git a/worker/src/DepUsrSCTP.cpp b/worker/src/DepUsrSCTP.cpp index 28ca0896a0..0a969de927 100644 --- a/worker/src/DepUsrSCTP.cpp +++ b/worker/src/DepUsrSCTP.cpp @@ -236,8 +236,8 @@ void DepUsrSCTP::Checker::OnTimer(Timer* /*timer*/) { MS_TRACE(); - auto nowMs = DepLibUV::GetTimeMs(); - int elapsedMs = this->lastCalledAtMs ? static_cast(nowMs - this->lastCalledAtMs) : 0; + auto nowMs = DepLibUV::GetTimeMs(); + const int elapsedMs = this->lastCalledAtMs ? static_cast(nowMs - this->lastCalledAtMs) : 0; usrsctp_handle_timers(elapsedMs); diff --git a/worker/src/RTC/Codecs/H264.cpp b/worker/src/RTC/Codecs/H264.cpp index 01f73e5908..2aa999f376 100644 --- a/worker/src/RTC/Codecs/H264.cpp +++ b/worker/src/RTC/Codecs/H264.cpp @@ -63,7 +63,7 @@ namespace RTC // there is no frame-marking or if there is but keyframe was not detected above. if (!frameMarking || !payloadDescriptor->isKeyFrame) { - uint8_t nal = *data & 0x1F; + const uint8_t nal = *data & 0x1F; switch (nal) { @@ -87,8 +87,8 @@ namespace RTC // Iterate NAL units. while (len >= 3) { - auto naluSize = Utils::Byte::Get2Bytes(data, offset); - uint8_t subnal = *(data + offset + sizeof(naluSize)) & 0x1F; + auto naluSize = Utils::Byte::Get2Bytes(data, offset); + const uint8_t subnal = *(data + offset + sizeof(naluSize)) & 0x1F; if (subnal == 7) { @@ -115,8 +115,8 @@ namespace RTC case 28: case 29: { - uint8_t subnal = *(data + 1) & 0x1F; - uint8_t startBit = *(data + 1) & 0x80; + const uint8_t subnal = *(data + 1) & 0x1F; + const uint8_t startBit = *(data + 1) & 0x80; if (subnal == 7 && startBit == 128) { diff --git a/worker/src/RTC/Codecs/H264_SVC.cpp b/worker/src/RTC/Codecs/H264_SVC.cpp index a926006cba..193e75d08c 100644 --- a/worker/src/RTC/Codecs/H264_SVC.cpp +++ b/worker/src/RTC/Codecs/H264_SVC.cpp @@ -58,7 +58,7 @@ namespace RTC // there is no frame-marking or if there is but keyframe was not detected above. if (!frameMarking || !payloadDescriptor->isKeyFrame) { - uint8_t nal = *data & 0x1F; + const uint8_t nal = *data & 0x1F; switch (nal) { @@ -121,7 +121,7 @@ namespace RTC case 28: case 29: { - uint8_t startBit = *(data + 1) & 0x80; + const uint8_t startBit = *(data + 1) & 0x80; if (startBit == 128) { @@ -145,7 +145,7 @@ namespace RTC std::unique_ptr payloadDescriptor, bool isStartBit) { - uint8_t nal = *data & 0x1F; + const uint8_t nal = *data & 0x1F; switch (nal) { @@ -286,7 +286,7 @@ namespace RTC } // clang-format off - bool isOldPacket = false; + const bool isOldPacket = false; // Upgrade current spatial layer if needed. if (context->GetTargetSpatialLayer() > context->GetCurrentSpatialLayer()) diff --git a/worker/src/RTC/Codecs/VP9.cpp b/worker/src/RTC/Codecs/VP9.cpp index a9b61747e0..7f4b2d7c00 100644 --- a/worker/src/RTC/Codecs/VP9.cpp +++ b/worker/src/RTC/Codecs/VP9.cpp @@ -223,7 +223,7 @@ namespace RTC } // clang-format off - bool isOldPacket = ( + const bool isOldPacket = ( this->payloadDescriptor->hasPictureId && RTC::SeqManager::IsSeqLowerThan( this->payloadDescriptor->pictureId, diff --git a/worker/src/RTC/RTCP/Bye.cpp b/worker/src/RTC/RTCP/Bye.cpp index 70981cf319..8673d06449 100644 --- a/worker/src/RTC/RTCP/Bye.cpp +++ b/worker/src/RTC/RTCP/Bye.cpp @@ -75,7 +75,7 @@ namespace RTC } // 32 bits padding. - size_t padding = (-offset) & 3; + const size_t padding = (-offset) & 3; for (size_t i{ 0 }; i < padding; ++i) { diff --git a/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp b/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp index 7f87aeb668..0ec4c0a63b 100644 --- a/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp @@ -25,7 +25,7 @@ namespace RTC isCorrect = false; } - size_t paddingBytes = this->header->paddingBits / 8; + const size_t paddingBytes = this->header->paddingBits / 8; if (paddingBytes > FeedbackPsRpsiItem::maxBitStringSize) { @@ -50,7 +50,7 @@ namespace RTC this->header = reinterpret_cast(this->raw); // 32 bits padding. - size_t padding = (-length) & 3; + const size_t padding = (-length) & 3; this->header->paddingBits = padding * 8; this->header->zero = 0; diff --git a/worker/src/RTC/RTCP/FeedbackPsSli.cpp b/worker/src/RTC/RTCP/FeedbackPsSli.cpp index 596ba29ded..23516def7c 100644 --- a/worker/src/RTC/RTCP/FeedbackPsSli.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsSli.cpp @@ -26,8 +26,8 @@ namespace RTC size_t FeedbackPsSliItem::Serialize(uint8_t* buffer) { - uint32_t compact = (this->first << 19) | (this->number << 6) | this->pictureId; - auto* header = reinterpret_cast(buffer); + const uint32_t compact = (this->first << 19) | (this->number << 6) | this->pictureId; + auto* header = reinterpret_cast(buffer); header->compact = uint32_t{ htonl(compact) }; std::memcpy(buffer, header, HeaderSize); diff --git a/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp b/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp index 49314ce0f3..d57c86e56a 100644 --- a/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp @@ -34,9 +34,9 @@ namespace RTC // Copy the content. std::memcpy(buffer + 8, this->header->value, GetLength()); - size_t offset = 8 + GetLength(); + const size_t offset = 8 + GetLength(); // 32 bits padding. - size_t padding = (-offset) & 3; + const size_t padding = (-offset) & 3; for (size_t i{ 0 }; i < padding; ++i) { diff --git a/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp b/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp index fd8234e993..cd6a0b6e87 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp @@ -23,10 +23,10 @@ namespace RTC this->ssrc = Utils::Byte::Get4Bytes(data, 0); // Read the 4 bytes block. - uint32_t compact = Utils::Byte::Get4Bytes(data, 4); + const uint32_t compact = Utils::Byte::Get4Bytes(data, 4); // Read each component. - uint8_t exponent = compact >> 26; // 6 bits. - uint64_t mantissa = (compact >> 9) & 0x1ffff; // 17 bits. + const uint8_t exponent = compact >> 26; // 6 bits. + const uint64_t mantissa = (compact >> 9) & 0x1ffff; // 17 bits. this->overhead = compact & 0x1ff; // 9 bits. // Get the bitrate out of exponent and mantissa. diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index b1c99f034c..e2cc570a35 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -265,7 +265,7 @@ namespace RTC } // 32 bits padding. - size_t padding = (-offset) & 3; + const size_t padding = (-offset) & 3; for (size_t i{ 0u }; i < padding; ++i) { @@ -318,7 +318,7 @@ namespace RTC // Deltas are represented as multiples of 250 us. // NOTE: Read it as int 64 to detect long elapsed times. - int64_t delta64 = (timestamp - this->latestTimestamp) * 4; + const int64_t delta64 = (timestamp - this->latestTimestamp) * 4; // clang-format off if ( @@ -414,7 +414,7 @@ namespace RTC { MS_TRACE(); - uint16_t expected = this->packetStatusCount; + const uint16_t expected = this->packetStatusCount; uint16_t lost{ 0u }; if (expected == 0u) diff --git a/worker/src/RTC/RTCP/Packet.cpp b/worker/src/RTC/RTCP/Packet.cpp index d2f38e8c0d..599a94a435 100644 --- a/worker/src/RTC/RTCP/Packet.cpp +++ b/worker/src/RTC/RTCP/Packet.cpp @@ -204,7 +204,7 @@ namespace RTC this->header = reinterpret_cast(buffer); - size_t length = (GetSize() / 4) - 1; + const size_t length = (GetSize() / 4) - 1; // Fill the common header. this->header->version = 2; diff --git a/worker/src/RTC/RTCP/ReceiverReport.cpp b/worker/src/RTC/RTCP/ReceiverReport.cpp index 761f6dcd49..2ae8f747fe 100644 --- a/worker/src/RTC/RTCP/ReceiverReport.cpp +++ b/worker/src/RTC/RTCP/ReceiverReport.cpp @@ -86,7 +86,7 @@ namespace RTC std::unique_ptr packet(new ReceiverReportPacket(header)); - uint32_t ssrc = + const uint32_t ssrc = Utils::Byte::Get4Bytes(reinterpret_cast(header), Packet::CommonHeaderSize); packet->SetSsrc(ssrc); diff --git a/worker/src/RTC/RTCP/Sdes.cpp b/worker/src/RTC/RTCP/Sdes.cpp index 574df0b4dc..91244c7589 100644 --- a/worker/src/RTC/RTCP/Sdes.cpp +++ b/worker/src/RTC/RTCP/Sdes.cpp @@ -119,7 +119,7 @@ namespace RTC return nullptr; } - uint32_t ssrc = Utils::Byte::Get4Bytes(data, 0); + const uint32_t ssrc = Utils::Byte::Get4Bytes(data, 0); std::unique_ptr chunk(new SdesChunk(ssrc)); @@ -156,7 +156,7 @@ namespace RTC } // 32 bits padding. - size_t padding = (-offset) & 3; + const size_t padding = (-offset) & 3; for (size_t i{ 0 }; i < padding; ++i) { diff --git a/worker/src/RTC/RTCP/SenderReport.cpp b/worker/src/RTC/RTCP/SenderReport.cpp index a3d2171588..89d835c6ec 100644 --- a/worker/src/RTC/RTCP/SenderReport.cpp +++ b/worker/src/RTC/RTCP/SenderReport.cpp @@ -65,7 +65,7 @@ namespace RTC auto* header = const_cast(reinterpret_cast(data)); std::unique_ptr packet(new SenderReportPacket(header)); - size_t offset = Packet::CommonHeaderSize; + const size_t offset = Packet::CommonHeaderSize; SenderReport* report = SenderReport::Parse(data + offset, len - offset); diff --git a/worker/src/RTC/RTCP/XR.cpp b/worker/src/RTC/RTCP/XR.cpp index 26cdb8240a..973ff942ab 100644 --- a/worker/src/RTC/RTCP/XR.cpp +++ b/worker/src/RTC/RTCP/XR.cpp @@ -71,7 +71,7 @@ namespace RTC std::unique_ptr packet(new ExtendedReportPacket(header)); - uint32_t ssrc = + const uint32_t ssrc = Utils::Byte::Get4Bytes(reinterpret_cast(header), Packet::CommonHeaderSize); packet->SetSsrc(ssrc); diff --git a/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp b/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp index eab47c8073..ace7ef334d 100644 --- a/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp +++ b/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp @@ -94,7 +94,7 @@ namespace RTC { MS_TRACE(); - size_t length = static_cast((SsrcInfo::BodySize * this->ssrcInfos.size() / 4)); + const size_t length = static_cast((SsrcInfo::BodySize * this->ssrcInfos.size() / 4)); // Fill the common header. this->header->blockType = static_cast(this->type); diff --git a/worker/src/handles/TcpConnectionHandler.cpp b/worker/src/handles/TcpConnectionHandler.cpp index 5fd6a7f045..9fc9c44fbe 100644 --- a/worker/src/handles/TcpConnectionHandler.cpp +++ b/worker/src/handles/TcpConnectionHandler.cpp @@ -135,7 +135,7 @@ void TcpConnectionHandler::Setup( MS_TRACE(); // Set the UV handle. - int err = uv_tcp_init(DepLibUV::GetLoop(), this->uvHandle); + const int err = uv_tcp_init(DepLibUV::GetLoop(), this->uvHandle); if (err != 0) { @@ -205,7 +205,7 @@ void TcpConnectionHandler::Write( return; } - size_t totalLen = len1 + len2; + const size_t totalLen = len1 + len2; uv_buf_t buffers[2]; int written{ 0 }; int err; @@ -246,8 +246,8 @@ void TcpConnectionHandler::Write( written = 0; } - size_t pendingLen = totalLen - written; - auto* writeData = new UvWriteData(pendingLen); + const size_t pendingLen = totalLen - written; + auto* writeData = new UvWriteData(pendingLen); writeData->req.data = static_cast(writeData); @@ -269,7 +269,7 @@ void TcpConnectionHandler::Write( writeData->cb = cb; - uv_buf_t buffer = uv_buf_init(reinterpret_cast(writeData->store), pendingLen); + const uv_buf_t buffer = uv_buf_init(reinterpret_cast(writeData->store), pendingLen); err = uv_write( &writeData->req, diff --git a/worker/src/handles/TcpServerHandler.cpp b/worker/src/handles/TcpServerHandler.cpp index a3213d709e..f6513603f0 100644 --- a/worker/src/handles/TcpServerHandler.cpp +++ b/worker/src/handles/TcpServerHandler.cpp @@ -117,7 +117,7 @@ void TcpServerHandler::AcceptTcpConnection(TcpConnectionHandler* connection) } // Accept the connection. - int err = uv_accept( + const int err = uv_accept( reinterpret_cast(this->uvHandle), reinterpret_cast(connection->GetUvHandle())); diff --git a/worker/src/handles/Timer.cpp b/worker/src/handles/Timer.cpp index 825382bc35..f46cbfe345 100644 --- a/worker/src/handles/Timer.cpp +++ b/worker/src/handles/Timer.cpp @@ -27,7 +27,7 @@ Timer::Timer(Listener* listener) : listener(listener) this->uvHandle = new uv_timer_t; this->uvHandle->data = static_cast(this); - int err = uv_timer_init(DepLibUV::GetLoop(), this->uvHandle); + const int err = uv_timer_init(DepLibUV::GetLoop(), this->uvHandle); if (err != 0) { @@ -71,7 +71,7 @@ void Timer::Start(uint64_t timeout, uint64_t repeat) if (uv_is_active(reinterpret_cast(this->uvHandle)) != 0) Stop(); - int err = uv_timer_start(this->uvHandle, static_cast(onTimer), timeout, repeat); + const int err = uv_timer_start(this->uvHandle, static_cast(onTimer), timeout, repeat); if (err != 0) MS_THROW_ERROR("uv_timer_start() failed: %s", uv_strerror(err)); @@ -84,7 +84,7 @@ void Timer::Stop() if (this->closed) MS_THROW_ERROR("closed"); - int err = uv_timer_stop(this->uvHandle); + const int err = uv_timer_stop(this->uvHandle); if (err != 0) MS_THROW_ERROR("uv_timer_stop() failed: %s", uv_strerror(err)); @@ -103,7 +103,7 @@ void Timer::Reset() if (this->repeat == 0u) return; - int err = + const int err = uv_timer_start(this->uvHandle, static_cast(onTimer), this->repeat, this->repeat); if (err != 0) @@ -120,7 +120,7 @@ void Timer::Restart() if (uv_is_active(reinterpret_cast(this->uvHandle)) != 0) Stop(); - int err = + const int err = uv_timer_start(this->uvHandle, static_cast(onTimer), this->timeout, this->repeat); if (err != 0) diff --git a/worker/src/handles/UdpSocketHandler.cpp b/worker/src/handles/UdpSocketHandler.cpp index 6cd1fa8e3e..6cb7ef3702 100644 --- a/worker/src/handles/UdpSocketHandler.cpp +++ b/worker/src/handles/UdpSocketHandler.cpp @@ -101,7 +101,7 @@ void UdpSocketHandler::Close() this->uvHandle->data = nullptr; // Don't read more. - int err = uv_udp_recv_stop(this->uvHandle); + const int err = uv_udp_recv_stop(this->uvHandle); if (err != 0) MS_ABORT("uv_udp_recv_stop() failed: %s", uv_strerror(err)); @@ -149,7 +149,7 @@ void UdpSocketHandler::Send( // then build a uv_req_t and use uv_udp_send(). uv_buf_t buffer = uv_buf_init(reinterpret_cast(const_cast(data)), len); - int sent = uv_udp_try_send(this->uvHandle, &buffer, 1, addr); + const int sent = uv_udp_try_send(this->uvHandle, &buffer, 1, addr); // Entire datagram was sent. Done. if (sent == static_cast(len)) diff --git a/worker/src/handles/UnixStreamSocket.cpp b/worker/src/handles/UnixStreamSocket.cpp index cb7c16e49c..bacf533513 100644 --- a/worker/src/handles/UnixStreamSocket.cpp +++ b/worker/src/handles/UnixStreamSocket.cpp @@ -197,15 +197,15 @@ void UnixStreamSocket::Write(const uint8_t* data, size_t len) written = 0; } - size_t pendingLen = len - written; - auto* writeData = new UvWriteData(pendingLen); + const size_t pendingLen = len - written; + auto* writeData = new UvWriteData(pendingLen); writeData->req.data = static_cast(writeData); std::memcpy(writeData->store, data + written, pendingLen); buffer = uv_buf_init(reinterpret_cast(writeData->store), pendingLen); - int err = uv_write( + const int err = uv_write( &writeData->req, reinterpret_cast(this->uvHandle), &buffer, From d7f8909bc2e9d6fc9499f82f3f1321e7318290be Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Thu, 2 Feb 2023 15:28:04 +0200 Subject: [PATCH 005/525] Update libsrtp2 to 2.5.0 (#1005) --- worker/subprojects/libsrtp2.wrap | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/worker/subprojects/libsrtp2.wrap b/worker/subprojects/libsrtp2.wrap index 89fc64cfee..fac0fc01eb 100644 --- a/worker/subprojects/libsrtp2.wrap +++ b/worker/subprojects/libsrtp2.wrap @@ -1,8 +1,9 @@ [wrap-file] -directory = libsrtp-2.4.2 -source_url = https://github.com/cisco/libsrtp/archive/refs/tags/v2.4.2.zip -source_filename = libsrtp-2.4.2.zip -source_hash = 35b1ae7a6256224feb058f1feb42170537a44896340f80e77b49cc59af686a82 +directory = libsrtp-2.5.0 +source_url = https://github.com/cisco/libsrtp/archive/refs/tags/v2.5.0.tar.gz +source_filename = libsrtp-2.5.0.tar.gz +source_hash = 8a43ef8e9ae2b665292591af62aa1a4ae41e468b6d98d8258f91478735da4e09 +wrapdb_version = 2.5.0-1 [provide] libsrtp2 = libsrtp2_dep From f02edc62e764b061917cbd215528db62e27fc9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 2 Feb 2023 14:29:02 +0100 Subject: [PATCH 006/525] Update CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80818464cc..c1421c75fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +* Update libsrtp to 2.5.0. + + ### 3.11.8 * `SimulcastConsumer::GetDesiredBitrate()`: Choose the highest bitrate among all Producer streams ([PR #992](https://github.com/versatica/mediasoup/pull/992)). From 3bdad19378ba4bc0c70a289bbbea84708c9ac4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Fri, 3 Feb 2023 15:22:17 +0100 Subject: [PATCH 007/525] Worker: More const correctness and qualified auto enhancements (#1006) --- worker/.clang-tidy | 2 +- worker/src/RTC/Consumer.cpp | 2 +- worker/src/RTC/DirectTransport.cpp | 6 +- worker/src/RTC/PipeConsumer.cpp | 6 +- worker/src/RTC/PortManager.cpp | 6 +- worker/src/RTC/Producer.cpp | 56 +++++++++---------- worker/src/RTC/RateCalculator.cpp | 2 +- worker/src/RTC/Router.cpp | 4 +- worker/src/RTC/RtpListener.cpp | 22 ++++---- worker/src/RTC/RtpPacket.cpp | 2 +- worker/src/RTC/RtpProbationGenerator.cpp | 2 +- worker/src/RTC/RtpStreamRecv.cpp | 21 +++---- worker/src/RTC/RtpStreamSend.cpp | 8 +-- worker/src/RTC/SctpAssociation.cpp | 6 +- worker/src/RTC/SenderBandwidthEstimator.cpp | 4 +- worker/src/RTC/SeqManager.cpp | 6 +- worker/src/RTC/SimulcastConsumer.cpp | 10 ++-- worker/src/RTC/StunPacket.cpp | 11 ++-- worker/src/RTC/Transport.cpp | 16 +++--- .../RTC/TransportCongestionControlServer.cpp | 4 +- worker/src/RTC/TrendCalculator.cpp | 2 +- worker/src/RTC/WebRtcServer.cpp | 4 +- worker/src/RTC/WebRtcTransport.cpp | 8 +-- worker/src/Settings.cpp | 2 +- worker/src/Worker.cpp | 10 ++-- worker/src/handles/SignalsHandler.cpp | 2 +- worker/src/handles/TcpConnectionHandler.cpp | 2 +- worker/src/handles/UnixStreamSocket.cpp | 2 +- worker/src/main.cpp | 2 +- worker/test/src/RTC/TestRtpPacket.cpp | 2 +- worker/test/src/RTC/TestRtpStreamSend.cpp | 42 +++++++------- 31 files changed, 138 insertions(+), 136 deletions(-) diff --git a/worker/.clang-tidy b/worker/.clang-tidy index 5e120619de..861037e299 100644 --- a/worker/.clang-tidy +++ b/worker/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: '*,-llvmlibc-*,-boost-use-to-string,-cert-*,-clang-analyzer-osx.*,-clang-analyzer-optin.osx.*,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-special-member-functions,-google-readability-*,-llvm-include-order,-readability-else-after-return,-readability-implicit-bool-cast,-modernize-pass-by-value,-cppcoreguidelines-no-malloc,-modernize-make-unique,-google-default-arguments,-hicpp-uppercase-literal-suffix,-readability-uppercase-literal-suffix,-hicpp-braces-around-statements,-hicpp-vararg,-hicpp-no-array-decay,-cppcoreguidelines-avoid-c-arrays,-hicpp-avoid-c-arrays,-modernize-avoid-c-arrays,-fuchsia-default-arguments-calls,-readability-implicit-bool-conversion,-modernize-use-trailing-return-type,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-init-variables,-readability-magic-numbers,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-cppcoreguidelines-owning-memory,-hicpp-special-member-functions,-google-runtime-references,-fuchsia-default-arguments-declarations,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-hicpp-signed-bitwise,-readability-function-cognitive-complexity,-altera*' +Checks: '*,-llvmlibc-*,-boost-use-to-string,-cert-*,-clang-analyzer-osx.*,-clang-analyzer-optin.osx.*,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-special-member-functions,-google-readability-*,-llvm-include-order,-readability-else-after-return,-readability-implicit-bool-cast,-modernize-pass-by-value,-cppcoreguidelines-no-malloc,-modernize-make-unique,-google-default-arguments,-hicpp-uppercase-literal-suffix,-readability-uppercase-literal-suffix,-hicpp-braces-around-statements,-hicpp-vararg,-hicpp-no-array-decay,-cppcoreguidelines-avoid-c-arrays,-hicpp-avoid-c-arrays,-modernize-avoid-c-arrays,-fuchsia-default-arguments-calls,-readability-implicit-bool-conversion,-modernize-use-trailing-return-type,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-init-variables,-readability-magic-numbers,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-cppcoreguidelines-owning-memory,-hicpp-special-member-functions,-google-runtime-references,-fuchsia-default-arguments-declarations,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-hicpp-signed-bitwise,-readability-function-cognitive-complexity,-altera*,-readability-identifier-length' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false diff --git a/worker/src/RTC/Consumer.cpp b/worker/src/RTC/Consumer.cpp index 0f09842377..0d1cc9dd9a 100644 --- a/worker/src/RTC/Consumer.cpp +++ b/worker/src/RTC/Consumer.cpp @@ -347,7 +347,7 @@ namespace RTC if (!type.is_string()) MS_THROW_TYPE_ERROR("wrong type (not a string)"); - std::string typeStr = type.get(); + const std::string typeStr = type.get(); if (typeStr == "rtp") newTraceEventTypes.rtp = true; diff --git a/worker/src/RTC/DirectTransport.cpp b/worker/src/RTC/DirectTransport.cpp index bc12150a39..fe28591730 100644 --- a/worker/src/RTC/DirectTransport.cpp +++ b/worker/src/RTC/DirectTransport.cpp @@ -122,7 +122,7 @@ namespace RTC } const uint8_t* data = packet->GetData(); - size_t len = packet->GetSize(); + const size_t len = packet->GetSize(); // Notify the Node DirectTransport. this->shared->payloadChannelNotifier->Emit(consumer->id, "rtp", data, len); @@ -142,7 +142,7 @@ namespace RTC MS_TRACE(); const uint8_t* data = packet->GetData(); - size_t len = packet->GetSize(); + const size_t len = packet->GetSize(); // Notify the Node DirectTransport. this->shared->payloadChannelNotifier->Emit(this->id, "rtcp", data, len); @@ -158,7 +158,7 @@ namespace RTC packet->Serialize(RTC::RTCP::Buffer); const uint8_t* data = packet->GetData(); - size_t len = packet->GetSize(); + const size_t len = packet->GetSize(); // Notify the Node DirectTransport. this->shared->payloadChannelNotifier->Emit(this->id, "rtcp", data, len); diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index 5cbb7e72b6..be42f16730 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -25,8 +25,8 @@ namespace RTC if (this->rtpParameters.encodings.size() != this->consumableRtpEncodings.size()) MS_THROW_TYPE_ERROR("number of rtpParameters.encodings and consumableRtpEncodings do not match"); - auto& encoding = this->rtpParameters.encodings[0]; - auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); + auto& encoding = this->rtpParameters.encodings[0]; + const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); this->keyFrameSupported = RTC::Codecs::Tools::CanBeKeyFrame(mediaCodec->mimeType); @@ -226,7 +226,7 @@ namespace RTC return; // Whether this is the first packet after re-sync. - bool isSyncPacket = syncRequired; + const bool isSyncPacket = syncRequired; // Sync sequence number and timestamp if required. if (isSyncPacket) diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index b8afdfce10..5269fced06 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -39,13 +39,13 @@ namespace RTC Utils::IP::NormalizeIp(ip); int err; - int family = Utils::IP::GetFamily(ip); + const int family = Utils::IP::GetFamily(ip); struct sockaddr_storage bindAddr; // NOLINT(cppcoreguidelines-pro-type-member-init) size_t portIdx; int flags{ 0 }; std::vector& ports = PortManager::GetPorts(transport, ip); size_t attempt{ 0u }; - size_t numAttempts = ports.size(); + const size_t numAttempts = ports.size(); uv_handle_t* uvHandle{ nullptr }; uint16_t port; std::string transportStr; @@ -322,7 +322,7 @@ namespace RTC Utils::IP::NormalizeIp(ip); int err; - int family = Utils::IP::GetFamily(ip); + const int family = Utils::IP::GetFamily(ip); struct sockaddr_storage bindAddr; // NOLINT(cppcoreguidelines-pro-type-member-init) int flags{ 0 }; uv_handle_t* uvHandle{ nullptr }; diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index 4b0c353513..18e7ef527e 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -66,8 +66,8 @@ namespace RTC this->rtpStreamByEncodingIdx.resize(this->rtpParameters.encodings.size(), nullptr); this->rtpStreamScores.resize(this->rtpParameters.encodings.size(), 0u); - auto& encoding = this->rtpParameters.encodings[0]; - auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); + auto& encoding = this->rtpParameters.encodings[0]; + const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); if (!RTC::Codecs::Tools::IsValidTypeForCodec(this->type, mediaCodec->mimeType)) { @@ -373,7 +373,7 @@ namespace RTC auto jsonCodecsIt = jsonRtpMappingIt->find("codecs"); size_t idx{ 0 }; - for (auto& kv : this->rtpMapping.codecs) + for (const auto& kv : this->rtpMapping.codecs) { jsonCodecsIt->emplace_back(json::value_t::object); @@ -590,7 +590,7 @@ namespace RTC if (!type.is_string()) MS_THROW_TYPE_ERROR("wrong type (not a string)"); - std::string typeStr = type.get(); + const std::string typeStr = type.get(); if (typeStr == "rtp") newTraceEventTypes.rtp = true; @@ -781,8 +781,8 @@ namespace RTC if (it != this->mapSsrcRtpStream.end()) { - auto* rtpStream = it->second; - bool first = rtpStream->GetSenderReportNtpMs() == 0; + auto* rtpStream = it->second; + const bool first = rtpStream->GetSenderReportNtpMs() == 0; rtpStream->ReceiveRtcpSenderReport(report); @@ -882,7 +882,7 @@ namespace RTC return; } - uint32_t ssrc = it->second; + const uint32_t ssrc = it->second; // If the current RTP packet is a key frame for the given mapped SSRC do // nothing since we are gonna provide Consumers with the requested key frame @@ -909,8 +909,8 @@ namespace RTC { MS_TRACE(); - uint32_t ssrc = packet->GetSsrc(); - uint8_t payloadType = packet->GetPayloadType(); + const uint32_t ssrc = packet->GetSsrc(); + const uint8_t payloadType = packet->GetPayloadType(); // If stream found in media ssrcs map, return it. { @@ -941,11 +941,11 @@ namespace RTC // First, look for an encoding with matching media or RTX ssrc value. for (size_t i{ 0 }; i < this->rtpParameters.encodings.size(); ++i) { - auto& encoding = this->rtpParameters.encodings[i]; - const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); - const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); - bool isMediaPacket = (mediaCodec->payloadType == payloadType); - bool isRtxPacket = (rtxCodec && rtxCodec->payloadType == payloadType); + auto& encoding = this->rtpParameters.encodings[i]; + const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); + const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); + const bool isMediaPacket = (mediaCodec->payloadType == payloadType); + const bool isRtxPacket = (rtxCodec && rtxCodec->payloadType == payloadType); if (isMediaPacket && encoding.ssrc == ssrc) { @@ -997,10 +997,10 @@ namespace RTC if (encoding.rid != rid) continue; - const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); - const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); - bool isMediaPacket = (mediaCodec->payloadType == payloadType); - bool isRtxPacket = (rtxCodec && rtxCodec->payloadType == payloadType); + const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); + const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); + const bool isMediaPacket = (mediaCodec->payloadType == payloadType); + const bool isRtxPacket = (rtxCodec && rtxCodec->payloadType == payloadType); if (isMediaPacket) { @@ -1071,11 +1071,11 @@ namespace RTC ) // clang-format on { - auto& encoding = this->rtpParameters.encodings[0]; - const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); - const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); - bool isMediaPacket = (mediaCodec->payloadType == payloadType); - bool isRtxPacket = (rtxCodec && rtxCodec->payloadType == payloadType); + auto& encoding = this->rtpParameters.encodings[0]; + const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); + const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); + const bool isMediaPacket = (mediaCodec->payloadType == payloadType); + const bool isRtxPacket = (rtxCodec && rtxCodec->payloadType == payloadType); if (isMediaPacket) { @@ -1134,7 +1134,7 @@ namespace RTC { MS_TRACE(); - uint32_t ssrc = packet->GetSsrc(); + const uint32_t ssrc = packet->GetSsrc(); MS_ASSERT( this->mapSsrcRtpStream.find(ssrc) == this->mapSsrcRtpStream.end(), @@ -1263,8 +1263,8 @@ namespace RTC // Mangle the payload type. { - uint8_t payloadType = packet->GetPayloadType(); - auto it = this->rtpMapping.codecs.find(payloadType); + const uint8_t payloadType = packet->GetPayloadType(); + auto it = this->rtpMapping.codecs.find(payloadType); if (it == this->rtpMapping.codecs.end()) { @@ -1273,14 +1273,14 @@ namespace RTC return false; } - uint8_t mappedPayloadType = it->second; + const uint8_t mappedPayloadType = it->second; packet->SetPayloadType(mappedPayloadType); } // Mangle the SSRC. { - uint32_t mappedSsrc = this->mapRtpStreamMappedSsrc.at(rtpStream); + const uint32_t mappedSsrc = this->mapRtpStreamMappedSsrc.at(rtpStream); packet->SetSsrc(mappedSsrc); } diff --git a/worker/src/RTC/RateCalculator.cpp b/worker/src/RTC/RateCalculator.cpp index 929692fc8f..b449eb7d06 100644 --- a/worker/src/RTC/RateCalculator.cpp +++ b/worker/src/RTC/RateCalculator.cpp @@ -116,7 +116,7 @@ namespace RTC void RtpDataCounter::Update(RTC::RtpPacket* packet) { - uint64_t nowMs = DepLibUV::GetTimeMs(); + const uint64_t nowMs = DepLibUV::GetTimeMs(); this->packets++; this->rate.Update(packet->GetSize(), nowMs); diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index 0dd3b34a43..5ee105a029 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -789,8 +789,8 @@ namespace RTC // Get all streams in the Producer and provide the Consumer with them. for (const auto& kv : producer->GetRtpStreams()) { - auto* rtpStream = kv.first; - uint32_t mappedSsrc = kv.second; + auto* rtpStream = kv.first; + const uint32_t mappedSsrc = kv.second; consumer->ProducerRtpStream(rtpStream, mappedSsrc); } diff --git a/worker/src/RTC/RtpListener.cpp b/worker/src/RTC/RtpListener.cpp index 2afef5e1b4..5c21c60cf9 100644 --- a/worker/src/RTC/RtpListener.cpp +++ b/worker/src/RTC/RtpListener.cpp @@ -23,7 +23,7 @@ namespace RTC auto jsonRidTableIt = jsonObject.find("ridTable"); // Add ssrcTable. - for (auto& kv : this->ssrcTable) + for (const auto& kv : this->ssrcTable) { auto ssrc = kv.first; auto* producer = kv.second; @@ -32,19 +32,19 @@ namespace RTC } // Add midTable. - for (auto& kv : this->midTable) + for (const auto& kv : this->midTable) { - auto& mid = kv.first; - auto* producer = kv.second; + const auto& mid = kv.first; + auto* producer = kv.second; (*jsonMidTableIt)[mid] = producer->id; } // Add ridTable. - for (auto& kv : this->ridTable) + for (const auto& kv : this->ridTable) { - auto& rid = kv.first; - auto* producer = kv.second; + const auto& rid = kv.first; + auto* producer = kv.second; (*jsonRidTableIt)[rid] = producer->id; } @@ -57,7 +57,7 @@ namespace RTC const auto& rtpParameters = producer->GetRtpParameters(); // Add entries into the ssrcTable. - for (auto& encoding : rtpParameters.encodings) + for (const auto& encoding : rtpParameters.encodings) { uint32_t ssrc; @@ -99,7 +99,7 @@ namespace RTC // Add entries into midTable. if (!rtpParameters.mid.empty()) { - auto& mid = rtpParameters.mid; + const auto& mid = rtpParameters.mid; if (this->midTable.find(mid) == this->midTable.end()) { @@ -114,9 +114,9 @@ namespace RTC } // Add entries into ridTable. - for (auto& encoding : rtpParameters.encodings) + for (const auto& encoding : rtpParameters.encodings) { - auto& rid = encoding.rid; + const auto& rid = encoding.rid; if (rid.empty()) continue; diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index 51d4757eab..b959464959 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -543,7 +543,7 @@ namespace RTC if (!extenValue) return; - size_t midLen = mid.length(); + const size_t midLen = mid.length(); // Here we assume that there is MidMaxLength available bytes, even if now // they are padding bytes. diff --git a/worker/src/RTC/RtpProbationGenerator.cpp b/worker/src/RTC/RtpProbationGenerator.cpp index 66984ec1d7..1fe7ec6596 100644 --- a/worker/src/RTC/RtpProbationGenerator.cpp +++ b/worker/src/RTC/RtpProbationGenerator.cpp @@ -17,7 +17,7 @@ namespace RTC // Probation RTP header. // Caution: This must have an exact size for the RTP extensions to be added // and must align extensions to 4 bytes. - static uint8_t ProbationPacketHeader[] = + static const uint8_t ProbationPacketHeader[] = { 0b10010000, 0b01111111, 0, 0, // PayloadType: 127, Sequence Number: 0 0, 0, 0, 0, // Timestamp: 0 diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index 4988e4163f..532e3f1bb0 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -440,11 +440,12 @@ namespace RTC this->packetsLost = 0u; // Calculate Fraction Lost. - uint32_t expectedInterval = expected - this->expectedPrior; + const uint32_t expectedInterval = expected - this->expectedPrior; this->expectedPrior = expected; - uint32_t receivedInterval = this->mediaTransmissionCounter.GetPacketCount() - this->receivedPrior; + const uint32_t receivedInterval = + this->mediaTransmissionCounter.GetPacketCount() - this->receivedPrior; this->receivedPrior = this->mediaTransmissionCounter.GetPacketCount(); @@ -669,14 +670,14 @@ namespace RTC MS_TRACE(); // Calculate number of packets expected in this interval. - auto totalExpected = GetExpectedPackets(); - uint32_t expected = totalExpected - this->expectedPriorScore; + const auto totalExpected = GetExpectedPackets(); + const uint32_t expected = totalExpected - this->expectedPriorScore; this->expectedPriorScore = totalExpected; // Calculate number of packets received in this interval. - auto totalReceived = this->mediaTransmissionCounter.GetPacketCount(); - uint32_t received = totalReceived - this->receivedPriorScore; + const auto totalReceived = this->mediaTransmissionCounter.GetPacketCount(); + const uint32_t received = totalReceived - this->receivedPriorScore; this->receivedPriorScore = totalReceived; @@ -689,14 +690,14 @@ namespace RTC lost = expected - received; // Calculate number of packets repaired in this interval. - auto totalRepaired = this->packetsRepaired; - uint32_t repaired = totalRepaired - this->repairedPriorScore; + const auto totalRepaired = this->packetsRepaired; + uint32_t repaired = totalRepaired - this->repairedPriorScore; this->repairedPriorScore = totalRepaired; // Calculate number of packets retransmitted in this interval. - auto totatRetransmitted = this->packetsRetransmitted; - uint32_t retransmitted = totatRetransmitted - this->retransmittedPriorScore; + const auto totatRetransmitted = this->packetsRetransmitted; + uint32_t retransmitted = totatRetransmitted - this->retransmittedPriorScore; this->retransmittedPriorScore = totatRetransmitted; diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 85eb69dae1..78204c387c 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -180,7 +180,7 @@ namespace RTC { MS_TRACE(); - uint64_t nowMs = DepLibUV::GetTimeMs(); + const uint64_t nowMs = DepLibUV::GetTimeMs(); RTC::RtpStream::FillJsonStats(jsonObject); @@ -465,7 +465,7 @@ namespace RTC // Processing RTP packet is older than first one. if (RTC::SeqManager::IsSeqLowerThan(packet->GetTimestamp(), storageItem->timestamp)) { - uint32_t diffTs{ storageItem->timestamp - packet->GetTimestamp() }; + const uint32_t diffTs{ storageItem->timestamp - packet->GetTimestamp() }; // RTP packet is older than the retransmission buffer size. if (static_cast(diffTs * 1000 / this->params.clockRate) >= this->retransmissionBufferSize) @@ -523,7 +523,7 @@ namespace RTC for (size_t i{ 0 }; i < bufferSize && this->storageItemBuffer.GetBufferSize() != 0; ++i) { auto* storageItem = this->storageItemBuffer.GetFirst(); - uint32_t diffTs{ packet->GetTimestamp() - storageItem->timestamp }; + const uint32_t diffTs{ packet->GetTimestamp() - storageItem->timestamp }; // Processing RTP packet is older than first one. if (RTC::SeqManager::IsSeqLowerThan(packet->GetTimestamp(), storageItem->timestamp)) @@ -605,7 +605,7 @@ namespace RTC if (!this->mid.empty()) packet->UpdateMid(mid); - uint32_t diffTs = this->maxPacketTs - packet->GetTimestamp(); + const uint32_t diffTs = this->maxPacketTs - packet->GetTimestamp(); diffMs = diffTs * 1000 / this->params.clockRate; } diff --git a/worker/src/RTC/SctpAssociation.cpp b/worker/src/RTC/SctpAssociation.cpp index 2c0ee8cf6e..8a5b6c2df6 100644 --- a/worker/src/RTC/SctpAssociation.cpp +++ b/worker/src/RTC/SctpAssociation.cpp @@ -11,12 +11,12 @@ #include // Free send buffer threshold (in bytes) upon which send_cb will be executed. -static uint32_t SendBufferThreshold{ 256u }; +static const uint32_t SendBufferThreshold{ 256u }; /* SCTP events to which we are subscribing. */ /* clang-format off */ -uint16_t EventTypes[] = +const uint16_t EventTypes[] = { SCTP_ADAPTATION_INDICATION, SCTP_ASSOC_CHANGE, @@ -59,7 +59,7 @@ inline static int onRecvSctpData( else { const uint16_t streamId = rcv.rcv_sid; - uint32_t ppid = ntohl(rcv.rcv_ppid); + const uint32_t ppid = ntohl(rcv.rcv_ppid); const uint16_t ssn = rcv.rcv_ssn; MS_DEBUG_TAG( diff --git a/worker/src/RTC/SenderBandwidthEstimator.cpp b/worker/src/RTC/SenderBandwidthEstimator.cpp index ca98eda585..7de3504e04 100644 --- a/worker/src/RTC/SenderBandwidthEstimator.cpp +++ b/worker/src/RTC/SenderBandwidthEstimator.cpp @@ -95,8 +95,8 @@ namespace RTC if (!result.received) continue; - uint16_t wideSeq = result.sequenceNumber; - auto it = this->sentInfos.find(wideSeq); + const uint16_t wideSeq = result.sequenceNumber; + auto it = this->sentInfos.find(wideSeq); if (it == this->sentInfos.end()) { diff --git a/worker/src/RTC/SeqManager.cpp b/worker/src/RTC/SeqManager.cpp index 47f1731f69..d2e8558ca3 100644 --- a/worker/src/RTC/SeqManager.cpp +++ b/worker/src/RTC/SeqManager.cpp @@ -85,9 +85,9 @@ namespace RTC if (!this->dropped.empty()) { // Delete dropped inputs older than input - MaxValue/2. - size_t droppedCount = this->dropped.size(); - size_t threshold = (input - MaxValue / 2) & MaxValue; - auto it = this->dropped.lower_bound(threshold); + size_t droppedCount = this->dropped.size(); + const size_t threshold = (input - MaxValue / 2) & MaxValue; + auto it = this->dropped.lower_bound(threshold); this->dropped.erase(this->dropped.begin(), it); this->base = (this->base - (droppedCount - this->dropped.size())) & MaxValue; diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index a129555bb9..c3ad9f7550 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -309,7 +309,7 @@ namespace RTC MS_ASSERT(it != this->mapMappedSsrcSpatialLayer.end(), "unknown mappedSsrc"); - int16_t spatialLayer = it->second; + const int16_t spatialLayer = it->second; this->producerRtpStreams[spatialLayer] = rtpStream; } @@ -322,7 +322,7 @@ namespace RTC MS_ASSERT(it != this->mapMappedSsrcSpatialLayer.end(), "unknown mappedSsrc"); - int16_t spatialLayer = it->second; + const int16_t spatialLayer = it->second; this->producerRtpStreams[spatialLayer] = rtpStream; @@ -750,7 +750,7 @@ namespace RTC else diffMs = -1 * (ntpMs1 - ntpMs2); - int64_t diffTs = diffMs * this->rtpStream->GetClockRate() / 1000; + const int64_t diffTs = diffMs * this->rtpStream->GetClockRate() / 1000; const uint32_t newTs2 = ts2 - diffTs; // Apply offset. This is the difference that later must be removed from the @@ -778,8 +778,8 @@ namespace RTC // Apply an expected offset for a new frame in a 30fps stream. static const uint8_t MsOffset{ 33u }; // (1 / 30 * 1000). - int64_t maxTsExtraOffset = MaxExtraOffsetMs * this->rtpStream->GetClockRate() / 1000; - uint32_t tsExtraOffset = this->rtpStream->GetMaxPacketTs() - packet->GetTimestamp() + + const int64_t maxTsExtraOffset = MaxExtraOffsetMs * this->rtpStream->GetClockRate() / 1000; + uint32_t tsExtraOffset = this->rtpStream->GetMaxPacketTs() - packet->GetTimestamp() + tsOffset + MsOffset * this->rtpStream->GetClockRate() / 1000; // NOTE: Don't ask for a key frame if already done. diff --git a/worker/src/RTC/StunPacket.cpp b/worker/src/RTC/StunPacket.cpp index 6a453bca24..b49ecdd796 100644 --- a/worker/src/RTC/StunPacket.cpp +++ b/worker/src/RTC/StunPacket.cpp @@ -434,7 +434,7 @@ namespace RTC return Authentication::BAD_REQUEST; // Check that USERNAME attribute begins with our local username plus ":". - size_t localUsernameLen = localUsername.length(); + const size_t localUsernameLen = localUsername.length(); if ( this->username.length() <= localUsernameLen || this->username.at(localUsernameLen) != ':' || @@ -531,8 +531,9 @@ namespace RTC bool addXorMappedAddress = ((this->xorMappedAddress != nullptr) && this->method == StunPacket::Method::BINDING && this->klass == Class::SUCCESS_RESPONSE); - bool addErrorCode = ((this->errorCode != 0u) && this->klass == Class::ERROR_RESPONSE); - bool addMessageIntegrity = (this->klass != Class::ERROR_RESPONSE && !this->password.empty()); + const bool addErrorCode = ((this->errorCode != 0u) && this->klass == Class::ERROR_RESPONSE); + const bool addMessageIntegrity = + (this->klass != Class::ERROR_RESPONSE && !this->password.empty()); const bool addFingerprint{ true }; // Do always. // Update data pointer. @@ -748,8 +749,8 @@ namespace RTC Utils::Byte::Set2Bytes(buffer, pos, static_cast(Attribute::ERROR_CODE)); Utils::Byte::Set2Bytes(buffer, pos + 2, 4); - auto codeClass = static_cast(this->errorCode / 100); - uint8_t codeNumber = static_cast(this->errorCode) - (codeClass * 100); + auto codeClass = static_cast(this->errorCode / 100); + const uint8_t codeNumber = static_cast(this->errorCode) - (codeClass * 100); Utils::Byte::Set2Bytes(buffer, pos + 4, 0); Utils::Byte::Set1Byte(buffer, pos + 6, codeClass); diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index efcbe6815d..9aef0f78cc 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -25,8 +25,8 @@ namespace RTC { - static size_t DefaultSctpSendBufferSize{ 262144 }; // 2^18. - static size_t MaxSctpSendBufferSize{ 268435456 }; // 2^28. + static const size_t DefaultSctpSendBufferSize{ 262144 }; // 2^18. + static const size_t MaxSctpSendBufferSize{ 268435456 }; // 2^28. /* Instance methods. */ @@ -622,7 +622,7 @@ namespace RTC MS_THROW_TYPE_ERROR("missing bitrate"); } - uint32_t bitrate = jsonBitrateIt->get(); + const uint32_t bitrate = jsonBitrateIt->get(); if (bitrate < RTC::TransportCongestionControlMinOutgoingBitrate) { @@ -1287,7 +1287,7 @@ namespace RTC if (!type.is_string()) MS_THROW_TYPE_ERROR("wrong type (not a string)"); - std::string typeStr = type.get(); + const std::string typeStr = type.get(); if (typeStr == "probation") newTraceEventTypes.probation = true; @@ -2324,7 +2324,7 @@ namespace RTC for (uint8_t i{ 1u }; i <= (baseAllocation ? 1u : priority); ++i) { uint32_t usedBitrate{ 0u }; - bool considerLoss = (bweType == RTC::BweType::REMB); + const bool considerLoss = (bweType == RTC::BweType::REMB); usedBitrate = consumer->IncreaseLayer(availableBitrate, considerLoss); @@ -2525,7 +2525,7 @@ namespace RTC // invoked *after* the WebRtcTransport has been closed (freed). To avoid // invalid memory access we need to use weak_ptr. Same applies in other // send callbacks. - std::weak_ptr tccClientWeakPtr(this->tccClient); + const std::weak_ptr tccClientWeakPtr(this->tccClient); #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR std::weak_ptr senderBweWeakPtr(this->senderBwe); @@ -2614,7 +2614,7 @@ namespace RTC // Indicate the pacer (and prober) that a packet is to be sent. this->tccClient->InsertPacket(packetInfo); - std::weak_ptr tccClientWeakPtr(this->tccClient); + const std::weak_ptr tccClientWeakPtr(this->tccClient); #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR std::weak_ptr senderBweWeakPtr = this->senderBwe; @@ -2970,7 +2970,7 @@ namespace RTC // Indicate the pacer (and prober) that a packet is to be sent. this->tccClient->InsertPacket(packetInfo); - std::weak_ptr tccClientWeakPtr(this->tccClient); + const std::weak_ptr tccClientWeakPtr(this->tccClient); #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR std::weak_ptr senderBweWeakPtr = this->senderBwe; diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index d171d1d99d..d04ee93f6a 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -232,8 +232,8 @@ namespace RTC this, this->transportCcFeedbackPacket.get()); // Update packet loss history. - size_t expected_packets = this->transportCcFeedbackPacket->GetPacketStatusCount(); - size_t lost_packets = 0; + const size_t expected_packets = this->transportCcFeedbackPacket->GetPacketStatusCount(); + size_t lost_packets = 0; for (const auto& result : this->transportCcFeedbackPacket->GetPacketResults()) { if (!result.received) diff --git a/worker/src/RTC/TrendCalculator.cpp b/worker/src/RTC/TrendCalculator.cpp index 4fa757dc1f..356dceb40f 100644 --- a/worker/src/RTC/TrendCalculator.cpp +++ b/worker/src/RTC/TrendCalculator.cpp @@ -34,7 +34,7 @@ namespace RTC // Otherwise decrease current value. else { - uint64_t elapsedMs = nowMs - this->highestValueUpdatedAtMs; + const uint64_t elapsedMs = nowMs - this->highestValueUpdatedAtMs; auto subtraction = static_cast(this->highestValue * this->decreaseFactor * (elapsedMs / 1000.0)); diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 25d315f98f..fab070a96c 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -359,8 +359,8 @@ namespace RTC // local usernameFragment) which is the first value in the attribute value // before the ":" symbol. - auto& username = packet->GetUsername(); - size_t colonPos = username.find(':'); + const auto& username = packet->GetUsername(); + const size_t colonPos = username.find(':'); // If no colon is found just return the whole USERNAME attribute anyway. if (colonPos == std::string::npos) diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index b3ce40ff55..4ec9065d50 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -365,8 +365,8 @@ namespace RTC { jsonIceCandidatesIt->emplace_back(json::value_t::object); - auto& jsonEntry = (*jsonIceCandidatesIt)[i]; - auto& iceCandidate = this->iceCandidates[i]; + auto& jsonEntry = (*jsonIceCandidatesIt)[i]; + const auto& iceCandidate = this->iceCandidates[i]; iceCandidate.FillJson(jsonEntry); } @@ -648,8 +648,8 @@ namespace RTC case Channel::ChannelRequest::MethodId::TRANSPORT_RESTART_ICE: { - std::string usernameFragment = Utils::Crypto::GetRandomString(32); - std::string password = Utils::Crypto::GetRandomString(32); + const std::string usernameFragment = Utils::Crypto::GetRandomString(32); + const std::string password = Utils::Crypto::GetRandomString(32); this->iceServer->RestartIce(usernameFragment, password); diff --git a/worker/src/Settings.cpp b/worker/src/Settings.cpp index 1c13237150..786064d42d 100644 --- a/worker/src/Settings.cpp +++ b/worker/src/Settings.cpp @@ -328,7 +328,7 @@ void Settings::SetLogTags(const std::vector& tags) // Reset logTags. struct LogTags newLogTags; - for (auto& tag : tags) + for (const auto& tag : tags) { if (tag == "info") newLogTags.info = true; diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 659f84f8d4..9914efb9c2 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -114,20 +114,20 @@ void Worker::FillJson(json& jsonObject) const jsonObject["webRtcServerIds"] = json::array(); auto jsonWebRtcServerIdsIt = jsonObject.find("webRtcServerIds"); - for (auto& kv : this->mapWebRtcServers) + for (const auto& kv : this->mapWebRtcServers) { - auto& WebRtcServerId = kv.first; + const auto& webRtcServerId = kv.first; - jsonWebRtcServerIdsIt->emplace_back(WebRtcServerId); + jsonWebRtcServerIdsIt->emplace_back(webRtcServerId); } // Add routerIds. jsonObject["routerIds"] = json::array(); auto jsonRouterIdsIt = jsonObject.find("routerIds"); - for (auto& kv : this->mapRouters) + for (const auto& kv : this->mapRouters) { - auto& routerId = kv.first; + const auto& routerId = kv.first; jsonRouterIdsIt->emplace_back(routerId); } diff --git a/worker/src/handles/SignalsHandler.cpp b/worker/src/handles/SignalsHandler.cpp index 60a63c5c0c..f23240bd5b 100644 --- a/worker/src/handles/SignalsHandler.cpp +++ b/worker/src/handles/SignalsHandler.cpp @@ -56,7 +56,7 @@ void SignalsHandler::AddSignal(int signum, const std::string& name) MS_THROW_ERROR("closed"); int err; - auto uvHandle = new uv_signal_t; + auto* uvHandle = new uv_signal_t; uvHandle->data = static_cast(this); diff --git a/worker/src/handles/TcpConnectionHandler.cpp b/worker/src/handles/TcpConnectionHandler.cpp index 9fc9c44fbe..5e3fa110ed 100644 --- a/worker/src/handles/TcpConnectionHandler.cpp +++ b/worker/src/handles/TcpConnectionHandler.cpp @@ -103,7 +103,7 @@ void TcpConnectionHandler::Close() { // Use uv_shutdown() so pending data to be written will be sent to the peer // before closing. - auto req = new uv_shutdown_t; + auto* req = new uv_shutdown_t; req->data = static_cast(this); err = uv_shutdown( req, reinterpret_cast(this->uvHandle), static_cast(onShutdown)); diff --git a/worker/src/handles/UnixStreamSocket.cpp b/worker/src/handles/UnixStreamSocket.cpp index bacf533513..8f4f5b5aca 100644 --- a/worker/src/handles/UnixStreamSocket.cpp +++ b/worker/src/handles/UnixStreamSocket.cpp @@ -146,7 +146,7 @@ void UnixStreamSocket::Close() if (this->role == UnixStreamSocket::Role::PRODUCER && !this->hasError && !this->isClosedByPeer) { // Use uv_shutdown() so pending data to be written will be sent to the peer before closing. - auto req = new uv_shutdown_t; + auto* req = new uv_shutdown_t; req->data = static_cast(this); err = uv_shutdown( req, reinterpret_cast(this->uvHandle), static_cast(onShutdown)); diff --git a/worker/src/main.cpp b/worker/src/main.cpp index 363ae1a213..fcf4f47872 100644 --- a/worker/src/main.cpp +++ b/worker/src/main.cpp @@ -21,7 +21,7 @@ int main(int argc, char* argv[]) std::_Exit(EXIT_FAILURE); } - std::string version = std::getenv("MEDIASOUP_VERSION"); + const std::string version = std::getenv("MEDIASOUP_VERSION"); auto statusCode = mediasoup_worker_run( argc, diff --git a/worker/test/src/RTC/TestRtpPacket.cpp b/worker/test/src/RTC/TestRtpPacket.cpp index 327f9f3fac..5c0368fbe3 100644 --- a/worker/test/src/RTC/TestRtpPacket.cpp +++ b/worker/test/src/RTC/TestRtpPacket.cpp @@ -338,7 +338,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasOneByteExtensions() == false); REQUIRE(packet->HasTwoBytesExtensions()); - auto rtxPacket = packet->Clone(); + auto* rtxPacket = packet->Clone(); delete packet; diff --git a/worker/test/src/RTC/TestRtpStreamSend.cpp b/worker/test/src/RTC/TestRtpStreamSend.cpp index b981730cc6..067e8ebd7f 100644 --- a/worker/test/src/RTC/TestRtpStreamSend.cpp +++ b/worker/test/src/RTC/TestRtpStreamSend.cpp @@ -78,15 +78,15 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get retransmitted packets") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); + auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); + auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); // packet3 [pt:123, seq:21008, timestamp:1533793871] - auto packet3 = CreateRtpPacket(rtpBuffer3, 21008, 1533793871); + auto* packet3 = CreateRtpPacket(rtpBuffer3, 21008, 1533793871); // packet4 [pt:123, seq:21009, timestamp:1533793871] - auto packet4 = CreateRtpPacket(rtpBuffer4, 21009, 1533793871); + auto* packet4 = CreateRtpPacket(rtpBuffer4, 21009, 1533793871); // packet5 [pt:123, seq:21010, timestamp:1533796931] - auto packet5 = CreateRtpPacket(rtpBuffer5, 21010, 1533796931); + auto* packet5 = CreateRtpPacket(rtpBuffer5, 21010, 1533796931); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -143,15 +143,15 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get zero retransmitted packets if useNack is not set") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); + auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); + auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); // packet3 [pt:123, seq:21008, timestamp:1533793871] - auto packet3 = CreateRtpPacket(rtpBuffer3, 21008, 1533793871); + auto* packet3 = CreateRtpPacket(rtpBuffer3, 21008, 1533793871); // packet4 [pt:123, seq:21009, timestamp:1533793871] - auto packet4 = CreateRtpPacket(rtpBuffer4, 21009, 1533793871); + auto* packet4 = CreateRtpPacket(rtpBuffer4, 21009, 1533793871); // packet5 [pt:123, seq:21010, timestamp:1533796931] - auto packet5 = CreateRtpPacket(rtpBuffer5, 21010, 1533796931); + auto* packet5 = CreateRtpPacket(rtpBuffer5, 21010, 1533796931); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -196,15 +196,15 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get zero retransmitted packets for audio") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); + auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); + auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); // packet3 [pt:123, seq:21008, timestamp:1533793871] - auto packet3 = CreateRtpPacket(rtpBuffer3, 21008, 1533793871); + auto* packet3 = CreateRtpPacket(rtpBuffer3, 21008, 1533793871); // packet4 [pt:123, seq:21009, timestamp:1533793871] - auto packet4 = CreateRtpPacket(rtpBuffer4, 21009, 1533793871); + auto* packet4 = CreateRtpPacket(rtpBuffer4, 21009, 1533793871); // packet5 [pt:123, seq:21010, timestamp:1533796931] - auto packet5 = CreateRtpPacket(rtpBuffer5, 21010, 1533796931); + auto* packet5 = CreateRtpPacket(rtpBuffer5, 21010, 1533796931); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -249,9 +249,9 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK in different RtpStreamSend instances and get retransmitted packets") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); + auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); + auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); // Create two RtpStreamSend instances. TestRtpStreamListener testRtpStreamListener1; @@ -326,8 +326,8 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelay * clockRate / 1000; uint32_t secondTs = firstTs + diffTs; - auto packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); - auto packet2 = CreateRtpPacket(rtpBuffer2, 21007, secondTs - 1); + auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); + auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, secondTs - 1); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener1; @@ -378,8 +378,8 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelay * clockRate / 1000; uint32_t secondTs = firstTs + diffTs; - auto packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); - auto packet2 = CreateRtpPacket(rtpBuffer2, 21007, secondTs); + auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); + auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, secondTs); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener1; From 2503904867fef0e6017575b1ffce22c1b045153c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s-Combarro?= Date: Fri, 3 Feb 2023 18:26:25 +0400 Subject: [PATCH 008/525] Clean-ups (#1003) --- .github/workflows/mediasoup-node.yaml | 6 +-- .github/workflows/mediasoup-rust.yaml | 4 +- .github/workflows/mediasoup-worker.yaml | 6 +-- .gitignore | 3 ++ doc/Building.md | 52 ++++--------------------- doc/Fuzzer.md | 16 +++----- node/src/Worker.ts | 8 ++-- package.json | 26 ++++++------- worker/Makefile | 2 +- 9 files changed, 43 insertions(+), 80 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 6757c20211..eef5549b6a 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -20,15 +20,15 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.ci.node }} - name: Configure cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.npm diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index 1cf1584694..424113a365 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -19,10 +19,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Configure cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.cargo/registry diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index c879093f62..3ef8fa58c9 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -47,10 +47,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node }} @@ -62,7 +62,7 @@ jobs: if: runner.os != 'Windows' - name: Configure cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.npm diff --git a/.gitignore b/.gitignore index abfd211219..be274839a7 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,6 @@ /.vscode # JetBrains IDE stuff. /.idea + +# Packaged module. +*.tgz diff --git a/doc/Building.md b/doc/Building.md index 456c312724..013c4c2a37 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -2,133 +2,108 @@ This document is intended for mediasoup developers. - ## NPM scripts The `package.json` file in the main folder includes the following scripts: - ### `npm run typescript:build` Compiles mediasoup TypeScript code (`lib` folder) JavaScript and places it into the `lib` directory. - ### `npm run typescript:watch` Compiles mediasoup TypeScript code (`lib` folder) JavaScript, places it into the `lib` directory an watches for changes in the TypeScript files. - ### `npm run worker:build` Builds the `mediasoup-worker` binary. It invokes `make`below. - ### `npm run lint` Runs both `npm run lint:node` and `npm run lint:worker`. - ### `npm run lint:node` Validates mediasoup JavaScript files using [ESLint](https://eslint.org). - ### `npm run lint:worker` Validates mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It invokes `make lint` below. - ### `npm run format:worker` Rewrites mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It invokes `make format` below. - ### `npm run test` Runs both `npm run test:node` and `npm run test:worker`. - ### `npm run test:node` Runs [Jest](https://jestjs.io) test units located at `test/` folder. - ### `npm run test:worker` Runs [Catch2](https://github.com/catchorg/Catch2) test units located at `worker/test/` folder. It invokes `make test` below. - ### `npm run coverage:node` Same as `npm run test:node` but it also opens a browser window with JavaScript coverage results. - ### `npm run install-deps:node` Installs NPM dependencies and updates `package-lock.json`. - ### `npm run install-clang-tools` Installs clang tools needed for local development. - ## Rust The only special feature in Rust case is special environment variable `KEEP_BUILD_ARTIFACTS`, that when set to `1` will allow incremental recompilation of changed C++ sources during hacking on mediasoup. It is not necessary for normal usage of mediasoup as a dependency. - ## Makefile The `worker` folder contains a `Makefile` for the mediasoup-worker C++ subproject. It includes the following tasks: - ### `make` or `make mediasoup-worker` Alias of ``make mediasoup-worker` below. - ### `make meson-ninja` Installs `meson` and `ninja`. - ### `make clean` Cleans built objects and binaries. - ### `make clean-build` Cleans built objects and other artifacts, but keeps `mediasoup-worker` binary in place. - ### `make clean-pip` Cleans `meson` and `ninja` installed in local prefix with pip. - ### `make clean-subprojects` Cleans subprojects downloaded with Meson. - ### `make clean-all` Cleans built objects and binaries, `meson` and `ninja` installed in local prefix with pip and all subprojects downloaded with Meson. - ### `make update-wrap-file` Update the wrap file of a subproject with Meson. Usage example: ```bash -$ cd worker -$ make update-wrap-file SUBPROJECT=openssl +cd worker +make update-wrap-file SUBPROJECT=openssl ``` - ### `make mediasoup-worker` Builds the `mediasoup-worker` binary at `worker/out/Release/`. @@ -139,49 +114,42 @@ If the "MEDIASOUP_MAX_CORES" environment variable is set, the build process will Other build types are possible too, but they are not presets and will require "MESON_ARGS" use to customize build configuration. Check the meaning of useful macros in the `worker/include/Logger.hpp` header file if you want to enable tracing or other debug information. -Binary is built at `worker/out/MEDIASOUP_BUILDTYPE/build`. +Binary is built at `worker/out/MEDIASOUP_BUILDTYPE/build`. In order to instruct the mediasoup Node.js module to use the `Debug` mediasoup-worker binary, an environment variable must be set before running the Node.js application: ```bash -$ MEDIASOUP_BUILDTYPE=Debug node myapp.js +MEDIASOUP_BUILDTYPE=Debug node myapp.js ``` If the "MEDIASOUP_WORKER_BIN" environment variable is set, mediasoup will use the it as mediasoup-worker binary and **won't** compile the binary: ```bash -$ MEDIASOUP_WORKER_BIN="/home/xxx/src/foo/mediasoup-worker" node myapp.js +MEDIASOUP_WORKER_BIN="/home/xxx/src/foo/mediasoup-worker" node myapp.js ``` - - ### `make libmediasoup-worker` Builds the `libmediasoup-worker` static library at `worker/out/Release/`. `MEDIASOUP_MAX_CORES` and `MEDIASOUP_BUILDTYPE` environment variables from above still apply for static library build. - ### `make xcode` Builds a Xcode project for the mediasoup-worker subproject. - ### `make lint` Validates mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html) and rules in `worker/.clang-format`. - ### `make format` Rewrites mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). - ### `make test` Builds and runs the `mediasoup-worker-test` binary at `worker/out/Release/` (or at `worker/out/Debug/` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"), which uses [Catch2](https://github.com/catchorg/Catch2) to run test units located at `worker/test/` folder. - ### `make tidy` Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy/) and performs C++ code checks following `worker/.clang-tidy` rules. @@ -190,8 +158,7 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy/) and performs C++ code * `make clean` and `make` must have been called first. * [PyYAML](https://pyyaml.org/) is required. - - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. - + * In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. ### `make fuzzer` @@ -205,12 +172,10 @@ Builds the `mediasoup-worker-fuzzer` binary (which uses [libFuzzer](http://llvm. Read the [Fuzzer](Fuzzer.md) documentation for detailed information. - ### `make fuzzer-run-all` Runs all fuzzer cases. - ### `make docker` Builds a Linux image with fuzzer capable clang++. @@ -218,11 +183,10 @@ Builds a Linux image with fuzzer capable clang++. **NOTE:** Before running this command, a specific version of Linux clang must be downloaded. To get it, run: ```bash -$ cd worker -$ ./scripts/get-dep.sh clang-fuzzer +cd worker +./scripts/get-dep.sh clang-fuzzer ``` - ### `make docker-run` Runs a container of the Docker image created with `make docker`. It automatically executes a `bash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. diff --git a/doc/Fuzzer.md b/doc/Fuzzer.md index 8e39c13406..fb478d5fbd 100644 --- a/doc/Fuzzer.md +++ b/doc/Fuzzer.md @@ -4,7 +4,6 @@ Once we have built the `mediasoup-worker-fuzzer` target in a Linux environment w **NOTE:** From now on, we assume we are in the mediasoup `worker` directory. - ## Related documentation * [libFuzzer documentation](http://llvm.org/docs/LibFuzzer.html) @@ -12,14 +11,12 @@ Once we have built the `mediasoup-worker-fuzzer` target in a Linux environment w * [webrtcH4cKS ~ Lets get better at fuzzing in 2019](https://webrtchacks.com/lets-get-better-at-fuzzing-in-2019-heres-how/) * [OSS-Fuzz](https://github.com/google/oss-fuzz) - Continuous fuzzing of open source software ("fuzz for me") - ## Corpus files The `deps/webrtc-fuzzer-corpora/corpora` directory has corpus directories taken from the [webrtc-fuzzer-corpora](https://github.com/RTC-Cartel/webrtc-fuzzer-corpora) project. They should be use to feed fuzzer with appropriate input. However, given how `libFuzzer` [works](http://llvm.org/docs/LibFuzzer.html#options), the first directory given as command line parameter is not just used for reading corpus files, but also to store newly generated ones. So, it's recommended to pass `fuzzer/new-corpus` as first directory. Such a directory is gitignored. - ## Crash reports When the fuzzer detects an issue it generates a crash report file which contains the bytes given as input. Those files can be individually used later (instead of passing corpus directories) to the fuzzer to verify that the issue has been fixed. @@ -50,41 +47,40 @@ The mediasoup-worker fuzzer reads some custom environment variables to decide wh The log level can also be set by setting the `MS_FUZZ_LOG_LEVEL` environment variable to "debug", "warn" or "error" (it is "none" if unset). - ## Usage examples * Detect memory leaks and just fuzz STUN: ```bash -$ MS_FUZZ_STUN=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus +MS_FUZZ_STUN=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus ``` * Detect memory leaks and just fuzz RTP: ```bash -$ MS_FUZZ_RTP=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus +MS_FUZZ_RTP=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus ``` * Detect memory leaks and just fuzz RTCP: ```bash -$ MS_FUZZ_RTCP=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus +MS_FUZZ_RTCP=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus ``` * Detect memory leaks and just fuzz mediasoup-worker C++ utils: ```bash -$ MS_FUZZ_UTILS=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=2000 fuzzer/new-corpus +MS_FUZZ_UTILS=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=2000 fuzzer/new-corpus ``` * Detect memory leaks and fuzz everything with log level "warn": ```bash -$ MS_FUZZ_LOG_LEVEL=warn LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus +MS_FUZZ_LOG_LEVEL=warn LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus ``` * Verify that a specific crash is fixed: ```bash -$ LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer fuzzer/reports/crash-f39771f7a03c0e7e539d4e52f48f7adad8976404 +LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer fuzzer/reports/crash-f39771f7a03c0e7e539d4e52f48f7adad8976404 ``` diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 74eec53483..626c82000a 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -175,15 +175,15 @@ export type WorkerResourceUsage = /* eslint-enable camelcase */ }; -export type WorkerEvents = -{ +export type WorkerEvents = +{ died: [Error]; // Private events. '@success': []; '@failure': [Error]; }; -export type WorkerObserverEvents = +export type WorkerObserverEvents = { close: []; newwebrtcserver: [WebRtcServer]; @@ -655,7 +655,7 @@ export class Worker extends EnhancedEventEmitter const data = { rtpCapabilities }; const router = new Router( { - internal : + internal : { routerId : reqData.routerId }, diff --git a/package.json b/package.json index f84904edb3..30a37474c4 100644 --- a/package.json +++ b/package.json @@ -20,23 +20,23 @@ "main": "node/lib/index.js", "types": "node/lib/index.d.ts", "files": [ - "npm-scripts.js", "node/lib", - "worker/Makefile", - "worker/meson.build", - "worker/meson_options.txt", - "worker/src", - "worker/include", - "worker/test/src", - "worker/test/include", - "worker/fuzzer/src", - "worker/fuzzer/include", - "worker/subprojects/*.wrap", "worker/deps/libwebrtc", + "worker/fuzzer/include", + "worker/fuzzer/src", + "worker/include", + "worker/scripts/*.js", + "worker/scripts/*.json", "worker/scripts/*.py", "worker/scripts/*.sh", - "worker/scripts/*.js", - "worker/scripts/*.json" + "worker/src", + "worker/subprojects/*.wrap", + "worker/test/include", + "worker/test/src", + "worker/Makefile", + "worker/meson.build", + "worker/meson_options.txt", + "npm-scripts.js" ], "keywords": [ "webrtc", diff --git a/worker/Makefile b/worker/Makefile index 6329667836..4547ae13d4 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -18,7 +18,7 @@ LCOV = ./deps/lcov/bin/lcov DOCKER ?= docker PIP_DIR = $(MEDIASOUP_OUT_DIR)/pip INSTALL_DIR ?= $(MEDIASOUP_OUT_DIR)/$(MEDIASOUP_BUILDTYPE) -BUILD_DIR ?= $(MEDIASOUP_OUT_DIR)/$(MEDIASOUP_BUILDTYPE)/build +BUILD_DIR ?= $(INSTALL_DIR)/build MESON ?= $(PIP_DIR)/bin/meson MESON_VERSION ?= 0.61.5 # `MESON_ARGS` can be used to provide extra configuration parameters to Meson, From 9a9818465152d028310d79b59a31d48fe49aee9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Fri, 3 Feb 2023 20:21:06 +0100 Subject: [PATCH 009/525] Worker: .clang-tidy fix and cleanup (#1010) - Comment FormatStile option, not supported by older versions of clang-tidy. - Make check list more readable. - Improve Build.md --- doc/Building.md | 4 +++- worker/.clang-tidy | 57 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/doc/Building.md b/doc/Building.md index 013c4c2a37..5b273f976f 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -158,7 +158,9 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy/) and performs C++ code * `make clean` and `make` must have been called first. * [PyYAML](https://pyyaml.org/) is required. - * In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. + - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. + +`MEDIASOUP_TIDY_CHECKS` environment variable with a comma separated list of checks overrides the checks defined in .clang-tidy file. ### `make fuzzer` diff --git a/worker/.clang-tidy b/worker/.clang-tidy index 861037e299..f3ade0aca9 100644 --- a/worker/.clang-tidy +++ b/worker/.clang-tidy @@ -1,10 +1,63 @@ --- -Checks: '*,-llvmlibc-*,-boost-use-to-string,-cert-*,-clang-analyzer-osx.*,-clang-analyzer-optin.osx.*,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-special-member-functions,-google-readability-*,-llvm-include-order,-readability-else-after-return,-readability-implicit-bool-cast,-modernize-pass-by-value,-cppcoreguidelines-no-malloc,-modernize-make-unique,-google-default-arguments,-hicpp-uppercase-literal-suffix,-readability-uppercase-literal-suffix,-hicpp-braces-around-statements,-hicpp-vararg,-hicpp-no-array-decay,-cppcoreguidelines-avoid-c-arrays,-hicpp-avoid-c-arrays,-modernize-avoid-c-arrays,-fuchsia-default-arguments-calls,-readability-implicit-bool-conversion,-modernize-use-trailing-return-type,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-init-variables,-readability-magic-numbers,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-cppcoreguidelines-owning-memory,-hicpp-special-member-functions,-google-runtime-references,-fuchsia-default-arguments-declarations,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-hicpp-signed-bitwise,-readability-function-cognitive-complexity,-altera*,-readability-identifier-length' +Checks: "*,\ + -altera*,\ + -boost-use-to-string,\ + -cert-*,\ + -clang-analyzer-optin.osx.*,\ + -clang-analyzer-osx.*,\ + -cppcoreguidelines-avoid-c-arrays,\ + -cppcoreguidelines-avoid-goto,\ + -cppcoreguidelines-avoid-magic-numbers,\ + -cppcoreguidelines-init-variables,\ + -cppcoreguidelines-no-malloc,\ + -cppcoreguidelines-non-private-member-variables-in-classes,\ + -cppcoreguidelines-owning-memory,\ + -cppcoreguidelines-pro-bounds-array-to-pointer-decay,\ + -cppcoreguidelines-pro-bounds-constant-array-index,\ + -cppcoreguidelines-pro-bounds-pointer-arithmetic,\ + -cppcoreguidelines-pro-type-const-cast,\ + -cppcoreguidelines-pro-type-reinterpret-cast,\ + -cppcoreguidelines-pro-type-static-cast-downcast,\ + -cppcoreguidelines-pro-type-union-access,\ + -cppcoreguidelines-pro-type-vararg,\ + -cppcoreguidelines-special-member-functions,\ + -fuchsia-default-arguments-calls,\ + -fuchsia-default-arguments-declarations,\ + -google-default-arguments,\ + -google-readability-*,\ + -google-runtime-references,\ + -hicpp-avoid-c-arrays,\ + -hicpp-avoid-goto,\ + -hicpp-braces-around-statements,\ + -hicpp-no-array-decay,\ + -hicpp-signed-bitwise,\ + -hicpp-special-member-functions,\ + -hicpp-uppercase-literal-suffix,\ + -hicpp-vararg,\ + -llvm-include-order,\ + -llvmlibc-*,\ + -misc-non-private-member-variables-in-classes,\ + -modernize-avoid-c-arrays,\ + -modernize-make-unique,\ + -modernize-pass-by-value,\ + -modernize-use-trailing-return-type,\ + -readability-else-after-return,\ + -readability-function-cognitive-complexity,\ + -readability-identifier-length,\ + -readability-implicit-bool-cast,\ + -readability-implicit-bool-conversion,\ + -readability-magic-numbers,\ + -readability-uppercase-literal-suffix,\ + " HeaderFilterRegex: '' AnalyzeTemporaryDtors: false User: mediasoup -FormatStyle: file + +# Old clang-tidy does not support this option which indicates to take the +# format options from .clang-format when applying fixes. +#FormatStyle: file + CheckOptions: - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader value: '' From 8dfeb1e249423487967a01e0daa89994cc3e0df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Kalbe?= Date: Sat, 4 Feb 2023 13:58:26 +0100 Subject: [PATCH 010/525] Introduce OwnedWebRtcMessage (#1008) Introduce OwnedWebRtcMessage --- rust/src/data_structures.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index 798de4bf9d..a27d5a5ec1 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -811,6 +811,30 @@ impl<'a> WebRtcMessage<'a> { WebRtcMessage::EmptyBinary => (57_u32, Cow::from(vec![0_u8])), } } + + /// Convert to owned message + pub fn into_owned(self) -> OwnedWebRtcMessage { + match self { + WebRtcMessage::String(string) => OwnedWebRtcMessage::String(string), + WebRtcMessage::Binary(binary) => OwnedWebRtcMessage::Binary(binary.into_owned()), + WebRtcMessage::EmptyString => OwnedWebRtcMessage::EmptyString, + WebRtcMessage::EmptyBinary => OwnedWebRtcMessage::EmptyBinary, + } + } +} + +/// Similar to WebRtcMessage but represents +/// messages that have ownership over the data +#[derive(Debug, Clone)] +pub enum OwnedWebRtcMessage { + /// String + String(String), + /// Binary + Binary(Vec), + /// EmptyString + EmptyString, + /// EmptyBinary + EmptyBinary, } /// RTP packet info in trace event. From a19058dc969fc82efd42c19be2531a7c105a323a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 6 Feb 2023 17:22:22 +0100 Subject: [PATCH 011/525] Update types/node dep --- CHANGELOG.md | 1 + package-lock.json | 14 +++++++------- package.json | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1421c75fb..75792498ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Next * Update libsrtp to 2.5.0. +* Update NPM deps. ### 3.11.8 diff --git a/package-lock.json b/package-lock.json index a868d9e406..eb5981cac8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.11.18", + "@types/node": "^18.11.19", "@types/uuid": "^9.0.0", "@typescript-eslint/eslint-plugin": "^5.50.0", "@typescript-eslint/parser": "^5.50.0", @@ -1308,9 +1308,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "version": "18.11.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz", + "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -6739,9 +6739,9 @@ "dev": true }, "@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "version": "18.11.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz", + "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 30a37474c4..3837879d03 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.11.18", + "@types/node": "^18.11.19", "@types/uuid": "^9.0.0", "@typescript-eslint/eslint-plugin": "^5.50.0", "@typescript-eslint/parser": "^5.50.0", From 28b770bf9e1178c180f500ff0737651e293ae494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 14 Feb 2023 13:37:20 +0100 Subject: [PATCH 012/525] Update deps --- package-lock.json | 1456 ++++++++++++++++++++++----------------------- package.json | 10 +- 2 files changed, 733 insertions(+), 733 deletions(-) diff --git a/package-lock.json b/package-lock.json index eb5981cac8..490b5e9fbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,13 +18,13 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.11.19", + "@types/node": "^18.13.0", "@types/uuid": "^9.0.0", - "@typescript-eslint/eslint-plugin": "^5.50.0", - "@typescript-eslint/parser": "^5.50.0", - "eslint": "^8.33.0", + "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/parser": "^5.52.0", + "eslint": "^8.34.0", "eslint-plugin-jest": "^27.2.1", - "jest": "^29.4.1", + "jest": "^29.4.2", "open-cli": "^7.1.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -807,16 +807,16 @@ } }, "node_modules/@jest/console": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.1.tgz", - "integrity": "sha512-m+XpwKSi3PPM9znm5NGS8bBReeAJJpSkL1OuFCqaMaJL2YX9YXLkkI+MBchMPwu+ZuM2rynL51sgfkQteQ1CKQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.2.tgz", + "integrity": "sha512-0I/rEJwMpV9iwi9cDEnT71a5nNGK9lj8Z4+1pRAU2x/thVXCDnaTGrvxyK+cAqZTFVFCiR+hfVrP4l2m+dCmQg==", "dev": true, "dependencies": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.4.1", - "jest-util": "^29.4.1", + "jest-message-util": "^29.4.2", + "jest-util": "^29.4.2", "slash": "^3.0.0" }, "engines": { @@ -824,37 +824,37 @@ } }, "node_modules/@jest/core": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.1.tgz", - "integrity": "sha512-RXFTohpBqpaTebNdg5l3I5yadnKo9zLBajMT0I38D0tDhreVBYv3fA8kywthI00sWxPztWLD3yjiUkewwu/wKA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.2.tgz", + "integrity": "sha512-KGuoQah0P3vGNlaS/l9/wQENZGNKGoWb+OPxh3gz+YzG7/XExvYu34MzikRndQCdM2S0tzExN4+FL37i6gZmCQ==", "dev": true, "dependencies": { - "@jest/console": "^29.4.1", - "@jest/reporters": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/console": "^29.4.2", + "@jest/reporters": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.4.0", - "jest-config": "^29.4.1", - "jest-haste-map": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.4.1", - "jest-resolve-dependencies": "^29.4.1", - "jest-runner": "^29.4.1", - "jest-runtime": "^29.4.1", - "jest-snapshot": "^29.4.1", - "jest-util": "^29.4.1", - "jest-validate": "^29.4.1", - "jest-watcher": "^29.4.1", + "jest-changed-files": "^29.4.2", + "jest-config": "^29.4.2", + "jest-haste-map": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-regex-util": "^29.4.2", + "jest-resolve": "^29.4.2", + "jest-resolve-dependencies": "^29.4.2", + "jest-runner": "^29.4.2", + "jest-runtime": "^29.4.2", + "jest-snapshot": "^29.4.2", + "jest-util": "^29.4.2", + "jest-validate": "^29.4.2", + "jest-watcher": "^29.4.2", "micromatch": "^4.0.4", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -871,88 +871,88 @@ } }, "node_modules/@jest/environment": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.1.tgz", - "integrity": "sha512-pJ14dHGSQke7Q3mkL/UZR9ZtTOxqskZaC91NzamEH4dlKRt42W+maRBXiw/LWkdJe+P0f/zDR37+SPMplMRlPg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.2.tgz", + "integrity": "sha512-JKs3VUtse0vQfCaFGJRX1bir9yBdtasxziSyu+pIiEllAQOe4oQhdCYIf3+Lx+nGglFktSKToBnRJfD5QKp+NQ==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/fake-timers": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", - "jest-mock": "^29.4.1" + "jest-mock": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.1.tgz", - "integrity": "sha512-ZxKJP5DTUNF2XkpJeZIzvnzF1KkfrhEF6Rz0HGG69fHl6Bgx5/GoU3XyaeFYEjuuKSOOsbqD/k72wFvFxc3iTw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.2.tgz", + "integrity": "sha512-NUAeZVApzyaeLjfWIV/64zXjA2SS+NuUPHpAlO7IwVMGd5Vf9szTl9KEDlxY3B4liwLO31os88tYNHl6cpjtKQ==", "dev": true, "dependencies": { - "expect": "^29.4.1", - "jest-snapshot": "^29.4.1" + "expect": "^29.4.2", + "jest-snapshot": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.1.tgz", - "integrity": "sha512-w6YJMn5DlzmxjO00i9wu2YSozUYRBhIoJ6nQwpMYcBMtiqMGJm1QBzOf6DDgRao8dbtpDoaqLg6iiQTvv0UHhQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.2.tgz", + "integrity": "sha512-Dd3ilDJpBnqa0GiPN7QrudVs0cczMMHtehSo2CSTjm3zdHx0RcpmhFNVEltuEFeqfLIyWKFI224FsMSQ/nsJQA==", "dev": true, "dependencies": { - "jest-get-type": "^29.2.0" + "jest-get-type": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.1.tgz", - "integrity": "sha512-/1joI6rfHFmmm39JxNfmNAO3Nwm6Y0VoL5fJDy7H1AtWrD1CgRtqJbN9Ld6rhAkGO76qqp4cwhhxJ9o9kYjQMw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.2.tgz", + "integrity": "sha512-Ny1u0Wg6kCsHFWq7A/rW/tMhIedq2siiyHyLpHCmIhP7WmcAmd2cx95P+0xtTZlj5ZbJxIRQi4OPydZZUoiSQQ==", "dev": true, "dependencies": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.4.1", - "jest-mock": "^29.4.1", - "jest-util": "^29.4.1" + "jest-message-util": "^29.4.2", + "jest-mock": "^29.4.2", + "jest-util": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.1.tgz", - "integrity": "sha512-znoK2EuFytbHH0ZSf2mQK2K1xtIgmaw4Da21R2C/NE/+NnItm5mPEFQmn8gmF3f0rfOlmZ3Y3bIf7bFj7DHxAA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.2.tgz", + "integrity": "sha512-zCk70YGPzKnz/I9BNFDPlK+EuJLk21ur/NozVh6JVM86/YYZtZHqxFFQ62O9MWq7uf3vIZnvNA0BzzrtxD9iyg==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.1", - "@jest/expect": "^29.4.1", - "@jest/types": "^29.4.1", - "jest-mock": "^29.4.1" + "@jest/environment": "^29.4.2", + "@jest/expect": "^29.4.2", + "@jest/types": "^29.4.2", + "jest-mock": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.1.tgz", - "integrity": "sha512-AISY5xpt2Xpxj9R6y0RF1+O6GRy9JsGa8+vK23Lmzdy1AYcpQn5ItX79wJSsTmfzPKSAcsY1LNt/8Y5Xe5LOSg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.2.tgz", + "integrity": "sha512-10yw6YQe75zCgYcXgEND9kw3UZZH5tJeLzWv4vTk/2mrS1aY50A37F+XT2hPO5OqQFFnUWizXD8k1BMiATNfUw==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/console": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", @@ -965,9 +965,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.4.1", - "jest-util": "^29.4.1", - "jest-worker": "^29.4.1", + "jest-message-util": "^29.4.2", + "jest-util": "^29.4.2", + "jest-worker": "^29.4.2", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -986,9 +986,9 @@ } }, "node_modules/@jest/schemas": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.0.tgz", - "integrity": "sha512-0E01f/gOZeNTG76i5eWWSupvSHaIINrTie7vCyjiYFKgzNdyEGd12BUv4oNBFHOqlHDbtoJi3HrQ38KCC90NsQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.2.tgz", + "integrity": "sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g==", "dev": true, "dependencies": { "@sinclair/typebox": "^0.25.16" @@ -998,9 +998,9 @@ } }, "node_modules/@jest/source-map": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", - "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.2.tgz", + "integrity": "sha512-tIoqV5ZNgYI9XCKXMqbYe5JbumcvyTgNN+V5QW4My033lanijvCD0D4PI9tBw4pRTqWOc00/7X3KVvUh+qnF4Q==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.15", @@ -1012,13 +1012,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.1.tgz", - "integrity": "sha512-WRt29Lwt+hEgfN8QDrXqXGgCTidq1rLyFqmZ4lmJOpVArC8daXrZWkWjiaijQvgd3aOUj2fM8INclKHsQW9YyQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.2.tgz", + "integrity": "sha512-HZsC3shhiHVvMtP+i55MGR5bPcc3obCFbA5bzIOb8pCjwBZf11cZliJncCgaVUbC5yoQNuGqCkC0Q3t6EItxZA==", "dev": true, "dependencies": { - "@jest/console": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/console": "^29.4.2", + "@jest/types": "^29.4.2", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1027,14 +1027,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.1.tgz", - "integrity": "sha512-v5qLBNSsM0eHzWLXsQ5fiB65xi49A3ILPSFQKPXzGL4Vyux0DPZAIN7NAFJa9b4BiTDP9MBF/Zqc/QA1vuiJ0w==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.2.tgz", + "integrity": "sha512-9Z2cVsD6CcObIVrWigHp2McRJhvCxL27xHtrZFgNC1RwnoSpDx6fZo8QYjJmziFlW9/hr78/3sxF54S8B6v8rg==", "dev": true, "dependencies": { - "@jest/test-result": "^29.4.1", + "@jest/test-result": "^29.4.2", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.1", + "jest-haste-map": "^29.4.2", "slash": "^3.0.0" }, "engines": { @@ -1042,38 +1042,38 @@ } }, "node_modules/@jest/transform": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.1.tgz", - "integrity": "sha512-5w6YJrVAtiAgr0phzKjYd83UPbCXsBRTeYI4BXokv9Er9CcrH9hfXL/crCvP2d2nGOcovPUnlYiLPFLZrkG5Hg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.2.tgz", + "integrity": "sha512-kf1v5iTJHn7p9RbOsBuc/lcwyPtJaZJt5885C98omWz79NIeD3PfoiiaPSu7JyCyFzNOIzKhmMhQLUhlTL9BvQ==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.1", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.4.1", + "jest-haste-map": "^29.4.2", + "jest-regex-util": "^29.4.2", + "jest-util": "^29.4.2", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", - "write-file-atomic": "^5.0.0" + "write-file-atomic": "^4.0.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/types": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.1.tgz", - "integrity": "sha512-zbrAXDUOnpJ+FMST2rV7QZOgec8rskg2zv8g2ajeqitp4tvZiyqTCYXANrKsM+ryj5o+LI+ZN2EgU9drrkiwSA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.2.tgz", + "integrity": "sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.0", + "@jest/schemas": "^29.4.2", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1308,9 +1308,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz", - "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==", + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1359,14 +1359,14 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.50.0.tgz", - "integrity": "sha512-vwksQWSFZiUhgq3Kv7o1Jcj0DUNylwnIlGvKvLLYsq8pAWha6/WCnXUeaSoNNha/K7QSf2+jvmkxggC1u3pIwQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz", + "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/type-utils": "5.50.0", - "@typescript-eslint/utils": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/type-utils": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1393,14 +1393,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.50.0.tgz", - "integrity": "sha512-KCcSyNaogUDftK2G9RXfQyOCt51uB5yqC6pkUYqhYh8Kgt+DwR5M0EwEAxGPy/+DH6hnmKeGsNhiZRQxjH71uQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", + "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "debug": "^4.3.4" }, "engines": { @@ -1420,13 +1420,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.50.0.tgz", - "integrity": "sha512-rt03kaX+iZrhssaT974BCmoUikYtZI24Vp/kwTSy841XhiYShlqoshRFDvN1FKKvU2S3gK+kcBW1EA7kNUrogg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", + "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0" + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1437,13 +1437,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.50.0.tgz", - "integrity": "sha512-dcnXfZ6OGrNCO7E5UY/i0ktHb7Yx1fV6fnQGGrlnfDhilcs6n19eIRcvLBqx6OQkrPaFlDPk3OJ0WlzQfrV0bQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz", + "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.50.0", - "@typescript-eslint/utils": "5.50.0", + "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1464,9 +1464,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.50.0.tgz", - "integrity": "sha512-atruOuJpir4OtyNdKahiHZobPKFvZnBnfDiyEaBf6d9vy9visE7gDjlmhl+y29uxZ2ZDgvXijcungGFjGGex7w==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", + "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1477,13 +1477,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.50.0.tgz", - "integrity": "sha512-Gq4zapso+OtIZlv8YNAStFtT6d05zyVCK7Fx3h5inlLBx2hWuc/0465C2mg/EQDDU2LKe52+/jN4f0g9bd+kow==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", + "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1504,16 +1504,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.50.0.tgz", - "integrity": "sha512-v/AnUFImmh8G4PH0NDkf6wA8hujNNcrwtecqW4vtQ1UOSNBaZl49zP1SHoZ/06e+UiwzHpgb5zP5+hwlYYWYAw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz", + "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -1530,12 +1530,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.50.0.tgz", - "integrity": "sha512-cdMeD9HGu6EXIeGOh2yVW6oGf9wq8asBgZx7nsR/D36gTfQ0odE5kcRYe5M81vjEFAcPeugXrHg78Imu55F6gg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", + "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.50.0", + "@typescript-eslint/types": "5.52.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1672,15 +1672,15 @@ } }, "node_modules/babel-jest": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.1.tgz", - "integrity": "sha512-xBZa/pLSsF/1sNpkgsiT3CmY7zV1kAsZ9OxxtrFqYucnOuRftXAfcJqcDVyOPeN4lttWTwhLdu0T9f8uvoPEUg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.2.tgz", + "integrity": "sha512-vcghSqhtowXPG84posYkkkzcZsdayFkubUgbE3/1tuGbX7AQtwCkkNA/wIbB0BMjuCPoqTkiDyKN7Ty7d3uwNQ==", "dev": true, "dependencies": { - "@jest/transform": "^29.4.1", + "@jest/transform": "^29.4.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.4.0", + "babel-preset-jest": "^29.4.2", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -1709,9 +1709,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.0.tgz", - "integrity": "sha512-a/sZRLQJEmsmejQ2rPEUe35nO1+C9dc9O1gplH1SXmJxveQSRUYdBk8yGZG/VOUuZs1u2aHZJusEGoRMbhhwCg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.2.tgz", + "integrity": "sha512-5HZRCfMeWypFEonRbEkwWXtNS1sQK159LhRVyRuLzyfVBxDy/34Tr/rg4YVi0SScSJ4fqeaR/OIeceJ/LaQ0pQ==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -1747,12 +1747,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.0.tgz", - "integrity": "sha512-fUB9vZflUSM3dO/6M2TCAepTzvA4VkOvl67PjErcrQMGt9Eve7uazaeyCZ2th3UtI7ljpiBJES0F7A1vBRsLZA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.2.tgz", + "integrity": "sha512-ecWdaLY/8JyfUDr0oELBMpj3R5I1L6ZqG+kRJmwqfHtLWuPrJStR0LUkvUhfykJWTsXXMnohsayN/twltBbDrQ==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.4.0", + "babel-plugin-jest-hoist": "^29.4.2", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -2158,9 +2158,9 @@ "dev": true }, "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", + "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", "dev": true, "engines": { "node": ">=0.10.0" @@ -2185,9 +2185,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", - "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.2.tgz", + "integrity": "sha512-R6P0Y6PrsH3n4hUXxL3nns0rbRk6Q33js3ygJBeEpbzLzgcNuJ61+u0RXasFpTKISw99TxUzFnumSnRLsjhLaw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2278,9 +2278,9 @@ } }, "node_modules/eslint": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz", - "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", + "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.4.1", @@ -2566,16 +2566,16 @@ } }, "node_modules/expect": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.1.tgz", - "integrity": "sha512-OKrGESHOaMxK3b6zxIq9SOW8kEXztKff/Dvg88j4xIJxur1hspEbedVkR3GpHe5LO+WB2Qw7OWN0RMTdp6as5A==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.2.tgz", + "integrity": "sha512-+JHYg9O3hd3RlICG90OPVjRkPBoiUH7PxvDVMnRiaq1g6JUgZStX514erMl0v2Dc5SkfVbm7ztqbd6qHHPn+mQ==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.4.1", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-util": "^29.4.1" + "@jest/expect-utils": "^29.4.2", + "jest-get-type": "^29.4.2", + "jest-matcher-utils": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-util": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3284,15 +3284,15 @@ } }, "node_modules/jest": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.1.tgz", - "integrity": "sha512-cknimw7gAXPDOmj0QqztlxVtBVCw2lYY9CeIE5N6kD+kET1H4H79HSNISJmijb1HF+qk+G+ploJgiDi5k/fRlg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.2.tgz", + "integrity": "sha512-+5hLd260vNIHu+7ZgMIooSpKl7Jp5pHKb51e73AJU3owd5dEo/RfVwHbA/na3C/eozrt3hJOLGf96c7EWwIAzg==", "dev": true, "dependencies": { - "@jest/core": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/core": "^29.4.2", + "@jest/types": "^29.4.2", "import-local": "^3.0.2", - "jest-cli": "^29.4.1" + "jest-cli": "^29.4.2" }, "bin": { "jest": "bin/jest.js" @@ -3310,9 +3310,9 @@ } }, "node_modules/jest-changed-files": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.0.tgz", - "integrity": "sha512-rnI1oPxgFghoz32Y8eZsGJMjW54UlqT17ycQeCEktcxxwqqKdlj9afl8LNeO0Pbu+h2JQHThQP0BzS67eTRx4w==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.2.tgz", + "integrity": "sha512-Qdd+AXdqD16PQa+VsWJpxR3kN0JyOCX1iugQfx5nUgAsI4gwsKviXkpclxOK9ZnwaY2IQVHz+771eAvqeOlfuw==", "dev": true, "dependencies": { "execa": "^5.0.0", @@ -3323,28 +3323,28 @@ } }, "node_modules/jest-circus": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.1.tgz", - "integrity": "sha512-v02NuL5crMNY4CGPHBEflLzl4v91NFb85a+dH9a1pUNx6Xjggrd8l9pPy4LZ1VYNRXlb+f65+7O/MSIbLir6pA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.2.tgz", + "integrity": "sha512-wW3ztp6a2P5c1yOc1Cfrt5ozJ7neWmqeXm/4SYiqcSriyisgq63bwFj1NuRdSR5iqS0CMEYwSZd89ZA47W9zUg==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.1", - "@jest/expect": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/environment": "^29.4.2", + "@jest/expect": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.4.1", - "jest-matcher-utils": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-runtime": "^29.4.1", - "jest-snapshot": "^29.4.1", - "jest-util": "^29.4.1", + "jest-each": "^29.4.2", + "jest-matcher-utils": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-runtime": "^29.4.2", + "jest-snapshot": "^29.4.2", + "jest-util": "^29.4.2", "p-limit": "^3.1.0", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3353,21 +3353,21 @@ } }, "node_modules/jest-cli": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.1.tgz", - "integrity": "sha512-jz7GDIhtxQ37M+9dlbv5K+/FVcIo1O/b1sX3cJgzlQUf/3VG25nvuWzlDC4F1FLLzUThJeWLu8I7JF9eWpuURQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.2.tgz", + "integrity": "sha512-b+eGUtXq/K2v7SH3QcJvFvaUaCDS1/YAZBYz0m28Q/Ppyr+1qNaHmVYikOrbHVbZqYQs2IeI3p76uy6BWbXq8Q==", "dev": true, "dependencies": { - "@jest/core": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/core": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/types": "^29.4.2", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.4.1", - "jest-util": "^29.4.1", - "jest-validate": "^29.4.1", + "jest-config": "^29.4.2", + "jest-util": "^29.4.2", + "jest-validate": "^29.4.2", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -3387,31 +3387,31 @@ } }, "node_modules/jest-config": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.1.tgz", - "integrity": "sha512-g7p3q4NuXiM4hrS4XFATTkd+2z0Ml2RhFmFPM8c3WyKwVDNszbl4E7cV7WIx1YZeqqCtqbtTtZhGZWJlJqngzg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.2.tgz", + "integrity": "sha512-919CtnXic52YM0zW4C1QxjG6aNueX1kBGthuMtvFtRTAxhKfJmiXC9qwHmi6o2josjbDz8QlWyY55F1SIVmCWA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.4.1", - "@jest/types": "^29.4.1", - "babel-jest": "^29.4.1", + "@jest/test-sequencer": "^29.4.2", + "@jest/types": "^29.4.2", + "babel-jest": "^29.4.2", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.4.1", - "jest-environment-node": "^29.4.1", - "jest-get-type": "^29.2.0", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.4.1", - "jest-runner": "^29.4.1", - "jest-util": "^29.4.1", - "jest-validate": "^29.4.1", + "jest-circus": "^29.4.2", + "jest-environment-node": "^29.4.2", + "jest-get-type": "^29.4.2", + "jest-regex-util": "^29.4.2", + "jest-resolve": "^29.4.2", + "jest-runner": "^29.4.2", + "jest-util": "^29.4.2", + "jest-validate": "^29.4.2", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3432,24 +3432,24 @@ } }, "node_modules/jest-diff": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.1.tgz", - "integrity": "sha512-uazdl2g331iY56CEyfbNA0Ut7Mn2ulAG5vUaEHXycf1L6IPyuImIxSz4F0VYBKi7LYIuxOwTZzK3wh5jHzASMw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.2.tgz", + "integrity": "sha512-EK8DSajVtnjx9sa1BkjZq3mqChm2Cd8rIzdXkQMA8e0wuXq53ypz6s5o5V8HRZkoEt2ywJ3eeNWFKWeYr8HK4g==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.4.1" + "diff-sequences": "^29.4.2", + "jest-get-type": "^29.4.2", + "pretty-format": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", - "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.2.tgz", + "integrity": "sha512-dV2JdahgClL34Y5vLrAHde3nF3yo2jKRH+GIYJuCpfqwEJZcikzeafVTGAjbOfKPG17ez9iWXwUYp7yefeCRag==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" @@ -3459,62 +3459,62 @@ } }, "node_modules/jest-each": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.1.tgz", - "integrity": "sha512-QlYFiX3llJMWUV0BtWht/esGEz9w+0i7BHwODKCze7YzZzizgExB9MOfiivF/vVT0GSQ8wXLhvHXh3x2fVD4QQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.2.tgz", + "integrity": "sha512-trvKZb0JYiCndc55V1Yh0Luqi7AsAdDWpV+mKT/5vkpnnFQfuQACV72IoRV161aAr6kAVIBpmYzwhBzm34vQkA==", "dev": true, "dependencies": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "chalk": "^4.0.0", - "jest-get-type": "^29.2.0", - "jest-util": "^29.4.1", - "pretty-format": "^29.4.1" + "jest-get-type": "^29.4.2", + "jest-util": "^29.4.2", + "pretty-format": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.1.tgz", - "integrity": "sha512-x/H2kdVgxSkxWAIlIh9MfMuBa0hZySmfsC5lCsWmWr6tZySP44ediRKDUiNggX/eHLH7Cd5ZN10Rw+XF5tXsqg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.2.tgz", + "integrity": "sha512-MLPrqUcOnNBc8zTOfqBbxtoa8/Ee8tZ7UFW7hRDQSUT+NGsvS96wlbHGTf+EFAT9KC3VNb7fWEM6oyvmxtE/9w==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.1", - "@jest/fake-timers": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/environment": "^29.4.2", + "@jest/fake-timers": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", - "jest-mock": "^29.4.1", - "jest-util": "^29.4.1" + "jest-mock": "^29.4.2", + "jest-util": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.2.tgz", + "integrity": "sha512-vERN30V5i2N6lqlFu4ljdTqQAgrkTFMC9xaIIfOPYBw04pufjXRty5RuXBiB1d72tGbURa/UgoiHB90ruOSivg==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.1.tgz", - "integrity": "sha512-imTjcgfVVTvg02khXL11NNLTx9ZaofbAWhilrMg/G8dIkp+HYCswhxf0xxJwBkfhWb3e8dwbjuWburvxmcr58w==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.2.tgz", + "integrity": "sha512-WkUgo26LN5UHPknkezrBzr7lUtV1OpGsp+NfXbBwHztsFruS3gz+AMTTBcEklvi8uPzpISzYjdKXYZQJXBnfvw==", "dev": true, "dependencies": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.4.1", - "jest-worker": "^29.4.1", + "jest-regex-util": "^29.4.2", + "jest-util": "^29.4.2", + "jest-worker": "^29.4.2", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3526,46 +3526,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.1.tgz", - "integrity": "sha512-akpZv7TPyGMnH2RimOCgy+hPmWZf55EyFUvymQ4LMsQP8xSPlZumCPtXGoDhFNhUE2039RApZkTQDKU79p/FiQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.2.tgz", + "integrity": "sha512-Wa62HuRJmWXtX9F00nUpWlrbaH5axeYCdyRsOs/+Rb1Vb6+qWTlB5rKwCCRKtorM7owNwKsyJ8NRDUcZ8ghYUA==", "dev": true, "dependencies": { - "jest-get-type": "^29.2.0", - "pretty-format": "^29.4.1" + "jest-get-type": "^29.4.2", + "pretty-format": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.1.tgz", - "integrity": "sha512-k5h0u8V4nAEy6lSACepxL/rw78FLDkBnXhZVgFneVpnJONhb2DhZj/Gv4eNe+1XqQ5IhgUcqj745UwH0HJmMnA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.2.tgz", + "integrity": "sha512-EZaAQy2je6Uqkrm6frnxBIdaWtSYFoR8SVb2sNLAtldswlR/29JAgx+hy67llT3+hXBaLB0zAm5UfeqerioZyg==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.4.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.4.1" + "jest-diff": "^29.4.2", + "jest-get-type": "^29.4.2", + "pretty-format": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.1.tgz", - "integrity": "sha512-H4/I0cXUaLeCw6FM+i4AwCnOwHRgitdaUFOdm49022YD5nfyr8C/DrbXOBEyJaj+w/y0gGJ57klssOaUiLLQGQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.2.tgz", + "integrity": "sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3574,14 +3574,14 @@ } }, "node_modules/jest-mock": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.1.tgz", - "integrity": "sha512-MwA4hQ7zBOcgVCVnsM8TzaFLVUD/pFWTfbkY953Y81L5ret3GFRZtmPmRFAjKQSdCKoJvvqOu6Bvfpqlwwb0dQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.2.tgz", + "integrity": "sha512-x1FSd4Gvx2yIahdaIKoBjwji6XpboDunSJ95RpntGrYulI1ByuYQCKN/P7hvk09JB74IonU3IPLdkutEWYt++g==", "dev": true, "dependencies": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/node": "*", - "jest-util": "^29.4.1" + "jest-util": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3605,26 +3605,26 @@ } }, "node_modules/jest-regex-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", - "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.2.tgz", + "integrity": "sha512-XYZXOqUl1y31H6VLMrrUL1ZhXuiymLKPz0BO1kEeR5xER9Tv86RZrjTm74g5l9bPJQXA/hyLdaVPN/sdqfteig==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.1.tgz", - "integrity": "sha512-j/ZFNV2lm9IJ2wmlq1uYK0Y/1PiyDq9g4HEGsNTNr3viRbJdV+8Lf1SXIiLZXFvyiisu0qUyIXGBnw+OKWkJwQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.2.tgz", + "integrity": "sha512-RtKWW0mbR3I4UdkOrW7552IFGLYQ5AF9YrzD0FnIOkDu0rAMlA5/Y1+r7lhCAP4nXSBTaE7ueeqj6IOwZpgoqw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.1", + "jest-haste-map": "^29.4.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.4.1", - "jest-validate": "^29.4.1", + "jest-util": "^29.4.2", + "jest-validate": "^29.4.2", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -3634,43 +3634,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.1.tgz", - "integrity": "sha512-Y3QG3M1ncAMxfjbYgtqNXC5B595zmB6e//p/qpA/58JkQXu/IpLDoLeOa8YoYfsSglBKQQzNUqtfGJJT/qLmJg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.2.tgz", + "integrity": "sha512-6pL4ptFw62rjdrPk7rRpzJYgcRqRZNsZTF1VxVTZMishbO6ObyWvX57yHOaNGgKoADtAHRFYdHQUEvYMJATbDg==", "dev": true, "dependencies": { - "jest-regex-util": "^29.2.0", - "jest-snapshot": "^29.4.1" + "jest-regex-util": "^29.4.2", + "jest-snapshot": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.1.tgz", - "integrity": "sha512-8d6XXXi7GtHmsHrnaqBKWxjKb166Eyj/ksSaUYdcBK09VbjPwIgWov1VwSmtupCIz8q1Xv4Qkzt/BTo3ZqiCeg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.2.tgz", + "integrity": "sha512-wqwt0drm7JGjwdH+x1XgAl+TFPH7poowMguPQINYxaukCqlczAcNLJiK+OLxUxQAEWMdy+e6nHZlFHO5s7EuRg==", "dev": true, "dependencies": { - "@jest/console": "^29.4.1", - "@jest/environment": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/console": "^29.4.2", + "@jest/environment": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.2.0", - "jest-environment-node": "^29.4.1", - "jest-haste-map": "^29.4.1", - "jest-leak-detector": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-resolve": "^29.4.1", - "jest-runtime": "^29.4.1", - "jest-util": "^29.4.1", - "jest-watcher": "^29.4.1", - "jest-worker": "^29.4.1", + "jest-docblock": "^29.4.2", + "jest-environment-node": "^29.4.2", + "jest-haste-map": "^29.4.2", + "jest-leak-detector": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-resolve": "^29.4.2", + "jest-runtime": "^29.4.2", + "jest-util": "^29.4.2", + "jest-watcher": "^29.4.2", + "jest-worker": "^29.4.2", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -3679,31 +3679,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.1.tgz", - "integrity": "sha512-UXTMU9uKu2GjYwTtoAw5rn4STxWw/nadOfW7v1sx6LaJYa3V/iymdCLQM6xy3+7C6mY8GfX22vKpgxY171UIoA==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.4.1", - "@jest/fake-timers": "^29.4.1", - "@jest/globals": "^29.4.1", - "@jest/source-map": "^29.2.0", - "@jest/test-result": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.2.tgz", + "integrity": "sha512-3fque9vtpLzGuxT9eZqhxi+9EylKK/ESfhClv4P7Y9sqJPs58LjVhTt8jaMp/pRO38agll1CkSu9z9ieTQeRrw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.4.2", + "@jest/fake-timers": "^29.4.2", + "@jest/globals": "^29.4.2", + "@jest/source-map": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-mock": "^29.4.1", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.4.1", - "jest-snapshot": "^29.4.1", - "jest-util": "^29.4.1", + "jest-haste-map": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-mock": "^29.4.2", + "jest-regex-util": "^29.4.2", + "jest-resolve": "^29.4.2", + "jest-snapshot": "^29.4.2", + "jest-util": "^29.4.2", "semver": "^7.3.5", "slash": "^3.0.0", "strip-bom": "^4.0.0" @@ -3713,9 +3713,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.1.tgz", - "integrity": "sha512-l4iV8EjGgQWVz3ee/LR9sULDk2pCkqb71bjvlqn+qp90lFwpnulHj4ZBT8nm1hA1C5wowXLc7MGnw321u0tsYA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.2.tgz", + "integrity": "sha512-PdfubrSNN5KwroyMH158R23tWcAXJyx4pvSvWls1dHoLCaUhGul9rsL3uVjtqzRpkxlkMavQjGuWG1newPgmkw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -3724,23 +3724,23 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/expect-utils": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.4.1", + "expect": "^29.4.2", "graceful-fs": "^4.2.9", - "jest-diff": "^29.4.1", - "jest-get-type": "^29.2.0", - "jest-haste-map": "^29.4.1", - "jest-matcher-utils": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-util": "^29.4.1", + "jest-diff": "^29.4.2", + "jest-get-type": "^29.4.2", + "jest-haste-map": "^29.4.2", + "jest-matcher-utils": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-util": "^29.4.2", "natural-compare": "^1.4.0", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "semver": "^7.3.5" }, "engines": { @@ -3748,12 +3748,12 @@ } }, "node_modules/jest-util": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.1.tgz", - "integrity": "sha512-bQy9FPGxVutgpN4VRc0hk6w7Hx/m6L53QxpDreTZgJd9gfx/AV2MjyPde9tGyZRINAUrSv57p2inGBu2dRLmkQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.2.tgz", + "integrity": "sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g==", "dev": true, "dependencies": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3765,17 +3765,17 @@ } }, "node_modules/jest-validate": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.1.tgz", - "integrity": "sha512-qNZXcZQdIQx4SfUB/atWnI4/I2HUvhz8ajOSYUu40CSmf9U5emil8EDHgE7M+3j9/pavtk3knlZBDsgFvv/SWw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.2.tgz", + "integrity": "sha512-tto7YKGPJyFbhcKhIDFq8B5od+eVWD/ySZ9Tvcp/NGCvYA4RQbuzhbwYWtIjMT5W5zA2W0eBJwu4HVw34d5G6Q==", "dev": true, "dependencies": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.2.0", + "jest-get-type": "^29.4.2", "leven": "^3.1.0", - "pretty-format": "^29.4.1" + "pretty-format": "^29.4.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3794,18 +3794,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.1.tgz", - "integrity": "sha512-vFOzflGFs27nU6h8dpnVRER3O2rFtL+VMEwnG0H3KLHcllLsU8y9DchSh0AL/Rg5nN1/wSiQ+P4ByMGpuybaVw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.2.tgz", + "integrity": "sha512-onddLujSoGiMJt+tKutehIidABa175i/Ays+QvKxCqBwp7fvxP3ZhKsrIdOodt71dKxqk4sc0LN41mWLGIK44w==", "dev": true, "dependencies": { - "@jest/test-result": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/test-result": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.4.1", + "jest-util": "^29.4.2", "string-length": "^4.0.1" }, "engines": { @@ -3813,13 +3813,13 @@ } }, "node_modules/jest-worker": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.1.tgz", - "integrity": "sha512-O9doU/S1EBe+yp/mstQ0VpPwpv0Clgn68TkNwGxL6/usX/KUW9Arnn4ag8C3jc6qHcXznhsT5Na1liYzAsuAbQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.2.tgz", + "integrity": "sha512-VIuZA2hZmFyRbchsUCHEehoSf2HEl0YVF8SDJqtPnKorAaBuh42V8QsLnde0XP5F6TyCynGPEGgBOn3Fc+wZGw==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.4.1", + "jest-util": "^29.4.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4569,12 +4569,12 @@ } }, "node_modules/pretty-format": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.1.tgz", - "integrity": "sha512-dt/Z761JUVsrIKaY215o1xQJBGlSmTx/h4cSqXqjHLnU1+Kt+mavVE7UgqJJO5ukx5HjSswHfmXz4LjS2oIJfg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.2.tgz", + "integrity": "sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.0", + "@jest/schemas": "^29.4.2", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -5655,16 +5655,16 @@ "dev": true }, "node_modules/write-file-atomic": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.0.tgz", - "integrity": "sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/y18n": { @@ -6314,123 +6314,123 @@ "dev": true }, "@jest/console": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.1.tgz", - "integrity": "sha512-m+XpwKSi3PPM9znm5NGS8bBReeAJJpSkL1OuFCqaMaJL2YX9YXLkkI+MBchMPwu+ZuM2rynL51sgfkQteQ1CKQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.2.tgz", + "integrity": "sha512-0I/rEJwMpV9iwi9cDEnT71a5nNGK9lj8Z4+1pRAU2x/thVXCDnaTGrvxyK+cAqZTFVFCiR+hfVrP4l2m+dCmQg==", "dev": true, "requires": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.4.1", - "jest-util": "^29.4.1", + "jest-message-util": "^29.4.2", + "jest-util": "^29.4.2", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.1.tgz", - "integrity": "sha512-RXFTohpBqpaTebNdg5l3I5yadnKo9zLBajMT0I38D0tDhreVBYv3fA8kywthI00sWxPztWLD3yjiUkewwu/wKA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.2.tgz", + "integrity": "sha512-KGuoQah0P3vGNlaS/l9/wQENZGNKGoWb+OPxh3gz+YzG7/XExvYu34MzikRndQCdM2S0tzExN4+FL37i6gZmCQ==", "dev": true, "requires": { - "@jest/console": "^29.4.1", - "@jest/reporters": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/console": "^29.4.2", + "@jest/reporters": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.4.0", - "jest-config": "^29.4.1", - "jest-haste-map": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.4.1", - "jest-resolve-dependencies": "^29.4.1", - "jest-runner": "^29.4.1", - "jest-runtime": "^29.4.1", - "jest-snapshot": "^29.4.1", - "jest-util": "^29.4.1", - "jest-validate": "^29.4.1", - "jest-watcher": "^29.4.1", + "jest-changed-files": "^29.4.2", + "jest-config": "^29.4.2", + "jest-haste-map": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-regex-util": "^29.4.2", + "jest-resolve": "^29.4.2", + "jest-resolve-dependencies": "^29.4.2", + "jest-runner": "^29.4.2", + "jest-runtime": "^29.4.2", + "jest-snapshot": "^29.4.2", + "jest-util": "^29.4.2", + "jest-validate": "^29.4.2", + "jest-watcher": "^29.4.2", "micromatch": "^4.0.4", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.1.tgz", - "integrity": "sha512-pJ14dHGSQke7Q3mkL/UZR9ZtTOxqskZaC91NzamEH4dlKRt42W+maRBXiw/LWkdJe+P0f/zDR37+SPMplMRlPg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.2.tgz", + "integrity": "sha512-JKs3VUtse0vQfCaFGJRX1bir9yBdtasxziSyu+pIiEllAQOe4oQhdCYIf3+Lx+nGglFktSKToBnRJfD5QKp+NQ==", "dev": true, "requires": { - "@jest/fake-timers": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/fake-timers": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", - "jest-mock": "^29.4.1" + "jest-mock": "^29.4.2" } }, "@jest/expect": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.1.tgz", - "integrity": "sha512-ZxKJP5DTUNF2XkpJeZIzvnzF1KkfrhEF6Rz0HGG69fHl6Bgx5/GoU3XyaeFYEjuuKSOOsbqD/k72wFvFxc3iTw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.2.tgz", + "integrity": "sha512-NUAeZVApzyaeLjfWIV/64zXjA2SS+NuUPHpAlO7IwVMGd5Vf9szTl9KEDlxY3B4liwLO31os88tYNHl6cpjtKQ==", "dev": true, "requires": { - "expect": "^29.4.1", - "jest-snapshot": "^29.4.1" + "expect": "^29.4.2", + "jest-snapshot": "^29.4.2" } }, "@jest/expect-utils": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.1.tgz", - "integrity": "sha512-w6YJMn5DlzmxjO00i9wu2YSozUYRBhIoJ6nQwpMYcBMtiqMGJm1QBzOf6DDgRao8dbtpDoaqLg6iiQTvv0UHhQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.2.tgz", + "integrity": "sha512-Dd3ilDJpBnqa0GiPN7QrudVs0cczMMHtehSo2CSTjm3zdHx0RcpmhFNVEltuEFeqfLIyWKFI224FsMSQ/nsJQA==", "dev": true, "requires": { - "jest-get-type": "^29.2.0" + "jest-get-type": "^29.4.2" } }, "@jest/fake-timers": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.1.tgz", - "integrity": "sha512-/1joI6rfHFmmm39JxNfmNAO3Nwm6Y0VoL5fJDy7H1AtWrD1CgRtqJbN9Ld6rhAkGO76qqp4cwhhxJ9o9kYjQMw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.2.tgz", + "integrity": "sha512-Ny1u0Wg6kCsHFWq7A/rW/tMhIedq2siiyHyLpHCmIhP7WmcAmd2cx95P+0xtTZlj5ZbJxIRQi4OPydZZUoiSQQ==", "dev": true, "requires": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.4.1", - "jest-mock": "^29.4.1", - "jest-util": "^29.4.1" + "jest-message-util": "^29.4.2", + "jest-mock": "^29.4.2", + "jest-util": "^29.4.2" } }, "@jest/globals": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.1.tgz", - "integrity": "sha512-znoK2EuFytbHH0ZSf2mQK2K1xtIgmaw4Da21R2C/NE/+NnItm5mPEFQmn8gmF3f0rfOlmZ3Y3bIf7bFj7DHxAA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.2.tgz", + "integrity": "sha512-zCk70YGPzKnz/I9BNFDPlK+EuJLk21ur/NozVh6JVM86/YYZtZHqxFFQ62O9MWq7uf3vIZnvNA0BzzrtxD9iyg==", "dev": true, "requires": { - "@jest/environment": "^29.4.1", - "@jest/expect": "^29.4.1", - "@jest/types": "^29.4.1", - "jest-mock": "^29.4.1" + "@jest/environment": "^29.4.2", + "@jest/expect": "^29.4.2", + "@jest/types": "^29.4.2", + "jest-mock": "^29.4.2" } }, "@jest/reporters": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.1.tgz", - "integrity": "sha512-AISY5xpt2Xpxj9R6y0RF1+O6GRy9JsGa8+vK23Lmzdy1AYcpQn5ItX79wJSsTmfzPKSAcsY1LNt/8Y5Xe5LOSg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.2.tgz", + "integrity": "sha512-10yw6YQe75zCgYcXgEND9kw3UZZH5tJeLzWv4vTk/2mrS1aY50A37F+XT2hPO5OqQFFnUWizXD8k1BMiATNfUw==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/console": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", @@ -6443,9 +6443,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.4.1", - "jest-util": "^29.4.1", - "jest-worker": "^29.4.1", + "jest-message-util": "^29.4.2", + "jest-util": "^29.4.2", + "jest-worker": "^29.4.2", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -6453,18 +6453,18 @@ } }, "@jest/schemas": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.0.tgz", - "integrity": "sha512-0E01f/gOZeNTG76i5eWWSupvSHaIINrTie7vCyjiYFKgzNdyEGd12BUv4oNBFHOqlHDbtoJi3HrQ38KCC90NsQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.2.tgz", + "integrity": "sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g==", "dev": true, "requires": { "@sinclair/typebox": "^0.25.16" } }, "@jest/source-map": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", - "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.2.tgz", + "integrity": "sha512-tIoqV5ZNgYI9XCKXMqbYe5JbumcvyTgNN+V5QW4My033lanijvCD0D4PI9tBw4pRTqWOc00/7X3KVvUh+qnF4Q==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.15", @@ -6473,59 +6473,59 @@ } }, "@jest/test-result": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.1.tgz", - "integrity": "sha512-WRt29Lwt+hEgfN8QDrXqXGgCTidq1rLyFqmZ4lmJOpVArC8daXrZWkWjiaijQvgd3aOUj2fM8INclKHsQW9YyQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.2.tgz", + "integrity": "sha512-HZsC3shhiHVvMtP+i55MGR5bPcc3obCFbA5bzIOb8pCjwBZf11cZliJncCgaVUbC5yoQNuGqCkC0Q3t6EItxZA==", "dev": true, "requires": { - "@jest/console": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/console": "^29.4.2", + "@jest/types": "^29.4.2", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.1.tgz", - "integrity": "sha512-v5qLBNSsM0eHzWLXsQ5fiB65xi49A3ILPSFQKPXzGL4Vyux0DPZAIN7NAFJa9b4BiTDP9MBF/Zqc/QA1vuiJ0w==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.2.tgz", + "integrity": "sha512-9Z2cVsD6CcObIVrWigHp2McRJhvCxL27xHtrZFgNC1RwnoSpDx6fZo8QYjJmziFlW9/hr78/3sxF54S8B6v8rg==", "dev": true, "requires": { - "@jest/test-result": "^29.4.1", + "@jest/test-result": "^29.4.2", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.1", + "jest-haste-map": "^29.4.2", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.1.tgz", - "integrity": "sha512-5w6YJrVAtiAgr0phzKjYd83UPbCXsBRTeYI4BXokv9Er9CcrH9hfXL/crCvP2d2nGOcovPUnlYiLPFLZrkG5Hg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.2.tgz", + "integrity": "sha512-kf1v5iTJHn7p9RbOsBuc/lcwyPtJaZJt5885C98omWz79NIeD3PfoiiaPSu7JyCyFzNOIzKhmMhQLUhlTL9BvQ==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.1", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.4.1", + "jest-haste-map": "^29.4.2", + "jest-regex-util": "^29.4.2", + "jest-util": "^29.4.2", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", - "write-file-atomic": "^5.0.0" + "write-file-atomic": "^4.0.2" } }, "@jest/types": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.1.tgz", - "integrity": "sha512-zbrAXDUOnpJ+FMST2rV7QZOgec8rskg2zv8g2ajeqitp4tvZiyqTCYXANrKsM+ryj5o+LI+ZN2EgU9drrkiwSA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.2.tgz", + "integrity": "sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw==", "dev": true, "requires": { - "@jest/schemas": "^29.4.0", + "@jest/schemas": "^29.4.2", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -6739,9 +6739,9 @@ "dev": true }, "@types/node": { - "version": "18.11.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz", - "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==", + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", "dev": true }, "@types/normalize-package-data": { @@ -6790,14 +6790,14 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.50.0.tgz", - "integrity": "sha512-vwksQWSFZiUhgq3Kv7o1Jcj0DUNylwnIlGvKvLLYsq8pAWha6/WCnXUeaSoNNha/K7QSf2+jvmkxggC1u3pIwQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz", + "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/type-utils": "5.50.0", - "@typescript-eslint/utils": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/type-utils": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -6808,53 +6808,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.50.0.tgz", - "integrity": "sha512-KCcSyNaogUDftK2G9RXfQyOCt51uB5yqC6pkUYqhYh8Kgt+DwR5M0EwEAxGPy/+DH6hnmKeGsNhiZRQxjH71uQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", + "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.50.0.tgz", - "integrity": "sha512-rt03kaX+iZrhssaT974BCmoUikYtZI24Vp/kwTSy841XhiYShlqoshRFDvN1FKKvU2S3gK+kcBW1EA7kNUrogg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", + "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0" + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0" } }, "@typescript-eslint/type-utils": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.50.0.tgz", - "integrity": "sha512-dcnXfZ6OGrNCO7E5UY/i0ktHb7Yx1fV6fnQGGrlnfDhilcs6n19eIRcvLBqx6OQkrPaFlDPk3OJ0WlzQfrV0bQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz", + "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.50.0", - "@typescript-eslint/utils": "5.50.0", + "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.50.0.tgz", - "integrity": "sha512-atruOuJpir4OtyNdKahiHZobPKFvZnBnfDiyEaBf6d9vy9visE7gDjlmhl+y29uxZ2ZDgvXijcungGFjGGex7w==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", + "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.50.0.tgz", - "integrity": "sha512-Gq4zapso+OtIZlv8YNAStFtT6d05zyVCK7Fx3h5inlLBx2hWuc/0465C2mg/EQDDU2LKe52+/jN4f0g9bd+kow==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", + "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -6863,28 +6863,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.50.0.tgz", - "integrity": "sha512-v/AnUFImmh8G4PH0NDkf6wA8hujNNcrwtecqW4vtQ1UOSNBaZl49zP1SHoZ/06e+UiwzHpgb5zP5+hwlYYWYAw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz", + "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.50.0.tgz", - "integrity": "sha512-cdMeD9HGu6EXIeGOh2yVW6oGf9wq8asBgZx7nsR/D36gTfQ0odE5kcRYe5M81vjEFAcPeugXrHg78Imu55F6gg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", + "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.50.0", + "@typescript-eslint/types": "5.52.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -6974,15 +6974,15 @@ "dev": true }, "babel-jest": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.1.tgz", - "integrity": "sha512-xBZa/pLSsF/1sNpkgsiT3CmY7zV1kAsZ9OxxtrFqYucnOuRftXAfcJqcDVyOPeN4lttWTwhLdu0T9f8uvoPEUg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.2.tgz", + "integrity": "sha512-vcghSqhtowXPG84posYkkkzcZsdayFkubUgbE3/1tuGbX7AQtwCkkNA/wIbB0BMjuCPoqTkiDyKN7Ty7d3uwNQ==", "dev": true, "requires": { - "@jest/transform": "^29.4.1", + "@jest/transform": "^29.4.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.4.0", + "babel-preset-jest": "^29.4.2", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -7002,9 +7002,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.0.tgz", - "integrity": "sha512-a/sZRLQJEmsmejQ2rPEUe35nO1+C9dc9O1gplH1SXmJxveQSRUYdBk8yGZG/VOUuZs1u2aHZJusEGoRMbhhwCg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.2.tgz", + "integrity": "sha512-5HZRCfMeWypFEonRbEkwWXtNS1sQK159LhRVyRuLzyfVBxDy/34Tr/rg4YVi0SScSJ4fqeaR/OIeceJ/LaQ0pQ==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -7034,12 +7034,12 @@ } }, "babel-preset-jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.0.tgz", - "integrity": "sha512-fUB9vZflUSM3dO/6M2TCAepTzvA4VkOvl67PjErcrQMGt9Eve7uazaeyCZ2th3UtI7ljpiBJES0F7A1vBRsLZA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.2.tgz", + "integrity": "sha512-ecWdaLY/8JyfUDr0oELBMpj3R5I1L6ZqG+kRJmwqfHtLWuPrJStR0LUkvUhfykJWTsXXMnohsayN/twltBbDrQ==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^29.4.0", + "babel-plugin-jest-hoist": "^29.4.2", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -7322,9 +7322,9 @@ "dev": true }, "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", + "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", "dev": true }, "define-lazy-prop": { @@ -7340,9 +7340,9 @@ "dev": true }, "diff-sequences": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", - "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.2.tgz", + "integrity": "sha512-R6P0Y6PrsH3n4hUXxL3nns0rbRk6Q33js3ygJBeEpbzLzgcNuJ61+u0RXasFpTKISw99TxUzFnumSnRLsjhLaw==", "dev": true }, "dir-glob": { @@ -7409,9 +7409,9 @@ "dev": true }, "eslint": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz", - "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", + "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", "dev": true, "requires": { "@eslint/eslintrc": "^1.4.1", @@ -7617,16 +7617,16 @@ "dev": true }, "expect": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.1.tgz", - "integrity": "sha512-OKrGESHOaMxK3b6zxIq9SOW8kEXztKff/Dvg88j4xIJxur1hspEbedVkR3GpHe5LO+WB2Qw7OWN0RMTdp6as5A==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.2.tgz", + "integrity": "sha512-+JHYg9O3hd3RlICG90OPVjRkPBoiUH7PxvDVMnRiaq1g6JUgZStX514erMl0v2Dc5SkfVbm7ztqbd6qHHPn+mQ==", "dev": true, "requires": { - "@jest/expect-utils": "^29.4.1", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-util": "^29.4.1" + "@jest/expect-utils": "^29.4.2", + "jest-get-type": "^29.4.2", + "jest-matcher-utils": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-util": "^29.4.2" } }, "fast-deep-equal": { @@ -8137,21 +8137,21 @@ } }, "jest": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.1.tgz", - "integrity": "sha512-cknimw7gAXPDOmj0QqztlxVtBVCw2lYY9CeIE5N6kD+kET1H4H79HSNISJmijb1HF+qk+G+ploJgiDi5k/fRlg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.2.tgz", + "integrity": "sha512-+5hLd260vNIHu+7ZgMIooSpKl7Jp5pHKb51e73AJU3owd5dEo/RfVwHbA/na3C/eozrt3hJOLGf96c7EWwIAzg==", "dev": true, "requires": { - "@jest/core": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/core": "^29.4.2", + "@jest/types": "^29.4.2", "import-local": "^3.0.2", - "jest-cli": "^29.4.1" + "jest-cli": "^29.4.2" } }, "jest-changed-files": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.0.tgz", - "integrity": "sha512-rnI1oPxgFghoz32Y8eZsGJMjW54UlqT17ycQeCEktcxxwqqKdlj9afl8LNeO0Pbu+h2JQHThQP0BzS67eTRx4w==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.2.tgz", + "integrity": "sha512-Qdd+AXdqD16PQa+VsWJpxR3kN0JyOCX1iugQfx5nUgAsI4gwsKviXkpclxOK9ZnwaY2IQVHz+771eAvqeOlfuw==", "dev": true, "requires": { "execa": "^5.0.0", @@ -8159,204 +8159,204 @@ } }, "jest-circus": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.1.tgz", - "integrity": "sha512-v02NuL5crMNY4CGPHBEflLzl4v91NFb85a+dH9a1pUNx6Xjggrd8l9pPy4LZ1VYNRXlb+f65+7O/MSIbLir6pA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.2.tgz", + "integrity": "sha512-wW3ztp6a2P5c1yOc1Cfrt5ozJ7neWmqeXm/4SYiqcSriyisgq63bwFj1NuRdSR5iqS0CMEYwSZd89ZA47W9zUg==", "dev": true, "requires": { - "@jest/environment": "^29.4.1", - "@jest/expect": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/environment": "^29.4.2", + "@jest/expect": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.4.1", - "jest-matcher-utils": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-runtime": "^29.4.1", - "jest-snapshot": "^29.4.1", - "jest-util": "^29.4.1", + "jest-each": "^29.4.2", + "jest-matcher-utils": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-runtime": "^29.4.2", + "jest-snapshot": "^29.4.2", + "jest-util": "^29.4.2", "p-limit": "^3.1.0", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.1.tgz", - "integrity": "sha512-jz7GDIhtxQ37M+9dlbv5K+/FVcIo1O/b1sX3cJgzlQUf/3VG25nvuWzlDC4F1FLLzUThJeWLu8I7JF9eWpuURQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.2.tgz", + "integrity": "sha512-b+eGUtXq/K2v7SH3QcJvFvaUaCDS1/YAZBYz0m28Q/Ppyr+1qNaHmVYikOrbHVbZqYQs2IeI3p76uy6BWbXq8Q==", "dev": true, "requires": { - "@jest/core": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/core": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/types": "^29.4.2", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.4.1", - "jest-util": "^29.4.1", - "jest-validate": "^29.4.1", + "jest-config": "^29.4.2", + "jest-util": "^29.4.2", + "jest-validate": "^29.4.2", "prompts": "^2.0.1", "yargs": "^17.3.1" } }, "jest-config": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.1.tgz", - "integrity": "sha512-g7p3q4NuXiM4hrS4XFATTkd+2z0Ml2RhFmFPM8c3WyKwVDNszbl4E7cV7WIx1YZeqqCtqbtTtZhGZWJlJqngzg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.2.tgz", + "integrity": "sha512-919CtnXic52YM0zW4C1QxjG6aNueX1kBGthuMtvFtRTAxhKfJmiXC9qwHmi6o2josjbDz8QlWyY55F1SIVmCWA==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.4.1", - "@jest/types": "^29.4.1", - "babel-jest": "^29.4.1", + "@jest/test-sequencer": "^29.4.2", + "@jest/types": "^29.4.2", + "babel-jest": "^29.4.2", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.4.1", - "jest-environment-node": "^29.4.1", - "jest-get-type": "^29.2.0", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.4.1", - "jest-runner": "^29.4.1", - "jest-util": "^29.4.1", - "jest-validate": "^29.4.1", + "jest-circus": "^29.4.2", + "jest-environment-node": "^29.4.2", + "jest-get-type": "^29.4.2", + "jest-regex-util": "^29.4.2", + "jest-resolve": "^29.4.2", + "jest-runner": "^29.4.2", + "jest-util": "^29.4.2", + "jest-validate": "^29.4.2", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" } }, "jest-diff": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.1.tgz", - "integrity": "sha512-uazdl2g331iY56CEyfbNA0Ut7Mn2ulAG5vUaEHXycf1L6IPyuImIxSz4F0VYBKi7LYIuxOwTZzK3wh5jHzASMw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.2.tgz", + "integrity": "sha512-EK8DSajVtnjx9sa1BkjZq3mqChm2Cd8rIzdXkQMA8e0wuXq53ypz6s5o5V8HRZkoEt2ywJ3eeNWFKWeYr8HK4g==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.4.1" + "diff-sequences": "^29.4.2", + "jest-get-type": "^29.4.2", + "pretty-format": "^29.4.2" } }, "jest-docblock": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", - "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.2.tgz", + "integrity": "sha512-dV2JdahgClL34Y5vLrAHde3nF3yo2jKRH+GIYJuCpfqwEJZcikzeafVTGAjbOfKPG17ez9iWXwUYp7yefeCRag==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.1.tgz", - "integrity": "sha512-QlYFiX3llJMWUV0BtWht/esGEz9w+0i7BHwODKCze7YzZzizgExB9MOfiivF/vVT0GSQ8wXLhvHXh3x2fVD4QQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.2.tgz", + "integrity": "sha512-trvKZb0JYiCndc55V1Yh0Luqi7AsAdDWpV+mKT/5vkpnnFQfuQACV72IoRV161aAr6kAVIBpmYzwhBzm34vQkA==", "dev": true, "requires": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "chalk": "^4.0.0", - "jest-get-type": "^29.2.0", - "jest-util": "^29.4.1", - "pretty-format": "^29.4.1" + "jest-get-type": "^29.4.2", + "jest-util": "^29.4.2", + "pretty-format": "^29.4.2" } }, "jest-environment-node": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.1.tgz", - "integrity": "sha512-x/H2kdVgxSkxWAIlIh9MfMuBa0hZySmfsC5lCsWmWr6tZySP44ediRKDUiNggX/eHLH7Cd5ZN10Rw+XF5tXsqg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.2.tgz", + "integrity": "sha512-MLPrqUcOnNBc8zTOfqBbxtoa8/Ee8tZ7UFW7hRDQSUT+NGsvS96wlbHGTf+EFAT9KC3VNb7fWEM6oyvmxtE/9w==", "dev": true, "requires": { - "@jest/environment": "^29.4.1", - "@jest/fake-timers": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/environment": "^29.4.2", + "@jest/fake-timers": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", - "jest-mock": "^29.4.1", - "jest-util": "^29.4.1" + "jest-mock": "^29.4.2", + "jest-util": "^29.4.2" } }, "jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.2.tgz", + "integrity": "sha512-vERN30V5i2N6lqlFu4ljdTqQAgrkTFMC9xaIIfOPYBw04pufjXRty5RuXBiB1d72tGbURa/UgoiHB90ruOSivg==", "dev": true }, "jest-haste-map": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.1.tgz", - "integrity": "sha512-imTjcgfVVTvg02khXL11NNLTx9ZaofbAWhilrMg/G8dIkp+HYCswhxf0xxJwBkfhWb3e8dwbjuWburvxmcr58w==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.2.tgz", + "integrity": "sha512-WkUgo26LN5UHPknkezrBzr7lUtV1OpGsp+NfXbBwHztsFruS3gz+AMTTBcEklvi8uPzpISzYjdKXYZQJXBnfvw==", "dev": true, "requires": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.4.1", - "jest-worker": "^29.4.1", + "jest-regex-util": "^29.4.2", + "jest-util": "^29.4.2", + "jest-worker": "^29.4.2", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "jest-leak-detector": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.1.tgz", - "integrity": "sha512-akpZv7TPyGMnH2RimOCgy+hPmWZf55EyFUvymQ4LMsQP8xSPlZumCPtXGoDhFNhUE2039RApZkTQDKU79p/FiQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.2.tgz", + "integrity": "sha512-Wa62HuRJmWXtX9F00nUpWlrbaH5axeYCdyRsOs/+Rb1Vb6+qWTlB5rKwCCRKtorM7owNwKsyJ8NRDUcZ8ghYUA==", "dev": true, "requires": { - "jest-get-type": "^29.2.0", - "pretty-format": "^29.4.1" + "jest-get-type": "^29.4.2", + "pretty-format": "^29.4.2" } }, "jest-matcher-utils": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.1.tgz", - "integrity": "sha512-k5h0u8V4nAEy6lSACepxL/rw78FLDkBnXhZVgFneVpnJONhb2DhZj/Gv4eNe+1XqQ5IhgUcqj745UwH0HJmMnA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.2.tgz", + "integrity": "sha512-EZaAQy2je6Uqkrm6frnxBIdaWtSYFoR8SVb2sNLAtldswlR/29JAgx+hy67llT3+hXBaLB0zAm5UfeqerioZyg==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.4.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.4.1" + "jest-diff": "^29.4.2", + "jest-get-type": "^29.4.2", + "pretty-format": "^29.4.2" } }, "jest-message-util": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.1.tgz", - "integrity": "sha512-H4/I0cXUaLeCw6FM+i4AwCnOwHRgitdaUFOdm49022YD5nfyr8C/DrbXOBEyJaj+w/y0gGJ57klssOaUiLLQGQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.2.tgz", + "integrity": "sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.1.tgz", - "integrity": "sha512-MwA4hQ7zBOcgVCVnsM8TzaFLVUD/pFWTfbkY953Y81L5ret3GFRZtmPmRFAjKQSdCKoJvvqOu6Bvfpqlwwb0dQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.2.tgz", + "integrity": "sha512-x1FSd4Gvx2yIahdaIKoBjwji6XpboDunSJ95RpntGrYulI1ByuYQCKN/P7hvk09JB74IonU3IPLdkutEWYt++g==", "dev": true, "requires": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/node": "*", - "jest-util": "^29.4.1" + "jest-util": "^29.4.2" } }, "jest-pnp-resolver": { @@ -8367,102 +8367,102 @@ "requires": {} }, "jest-regex-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", - "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.2.tgz", + "integrity": "sha512-XYZXOqUl1y31H6VLMrrUL1ZhXuiymLKPz0BO1kEeR5xER9Tv86RZrjTm74g5l9bPJQXA/hyLdaVPN/sdqfteig==", "dev": true }, "jest-resolve": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.1.tgz", - "integrity": "sha512-j/ZFNV2lm9IJ2wmlq1uYK0Y/1PiyDq9g4HEGsNTNr3viRbJdV+8Lf1SXIiLZXFvyiisu0qUyIXGBnw+OKWkJwQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.2.tgz", + "integrity": "sha512-RtKWW0mbR3I4UdkOrW7552IFGLYQ5AF9YrzD0FnIOkDu0rAMlA5/Y1+r7lhCAP4nXSBTaE7ueeqj6IOwZpgoqw==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.1", + "jest-haste-map": "^29.4.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.4.1", - "jest-validate": "^29.4.1", + "jest-util": "^29.4.2", + "jest-validate": "^29.4.2", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.1.tgz", - "integrity": "sha512-Y3QG3M1ncAMxfjbYgtqNXC5B595zmB6e//p/qpA/58JkQXu/IpLDoLeOa8YoYfsSglBKQQzNUqtfGJJT/qLmJg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.2.tgz", + "integrity": "sha512-6pL4ptFw62rjdrPk7rRpzJYgcRqRZNsZTF1VxVTZMishbO6ObyWvX57yHOaNGgKoADtAHRFYdHQUEvYMJATbDg==", "dev": true, "requires": { - "jest-regex-util": "^29.2.0", - "jest-snapshot": "^29.4.1" + "jest-regex-util": "^29.4.2", + "jest-snapshot": "^29.4.2" } }, "jest-runner": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.1.tgz", - "integrity": "sha512-8d6XXXi7GtHmsHrnaqBKWxjKb166Eyj/ksSaUYdcBK09VbjPwIgWov1VwSmtupCIz8q1Xv4Qkzt/BTo3ZqiCeg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.2.tgz", + "integrity": "sha512-wqwt0drm7JGjwdH+x1XgAl+TFPH7poowMguPQINYxaukCqlczAcNLJiK+OLxUxQAEWMdy+e6nHZlFHO5s7EuRg==", "dev": true, "requires": { - "@jest/console": "^29.4.1", - "@jest/environment": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/console": "^29.4.2", + "@jest/environment": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.2.0", - "jest-environment-node": "^29.4.1", - "jest-haste-map": "^29.4.1", - "jest-leak-detector": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-resolve": "^29.4.1", - "jest-runtime": "^29.4.1", - "jest-util": "^29.4.1", - "jest-watcher": "^29.4.1", - "jest-worker": "^29.4.1", + "jest-docblock": "^29.4.2", + "jest-environment-node": "^29.4.2", + "jest-haste-map": "^29.4.2", + "jest-leak-detector": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-resolve": "^29.4.2", + "jest-runtime": "^29.4.2", + "jest-util": "^29.4.2", + "jest-watcher": "^29.4.2", + "jest-worker": "^29.4.2", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.1.tgz", - "integrity": "sha512-UXTMU9uKu2GjYwTtoAw5rn4STxWw/nadOfW7v1sx6LaJYa3V/iymdCLQM6xy3+7C6mY8GfX22vKpgxY171UIoA==", - "dev": true, - "requires": { - "@jest/environment": "^29.4.1", - "@jest/fake-timers": "^29.4.1", - "@jest/globals": "^29.4.1", - "@jest/source-map": "^29.2.0", - "@jest/test-result": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.2.tgz", + "integrity": "sha512-3fque9vtpLzGuxT9eZqhxi+9EylKK/ESfhClv4P7Y9sqJPs58LjVhTt8jaMp/pRO38agll1CkSu9z9ieTQeRrw==", + "dev": true, + "requires": { + "@jest/environment": "^29.4.2", + "@jest/fake-timers": "^29.4.2", + "@jest/globals": "^29.4.2", + "@jest/source-map": "^29.4.2", + "@jest/test-result": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-mock": "^29.4.1", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.4.1", - "jest-snapshot": "^29.4.1", - "jest-util": "^29.4.1", + "jest-haste-map": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-mock": "^29.4.2", + "jest-regex-util": "^29.4.2", + "jest-resolve": "^29.4.2", + "jest-snapshot": "^29.4.2", + "jest-util": "^29.4.2", "semver": "^7.3.5", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.1.tgz", - "integrity": "sha512-l4iV8EjGgQWVz3ee/LR9sULDk2pCkqb71bjvlqn+qp90lFwpnulHj4ZBT8nm1hA1C5wowXLc7MGnw321u0tsYA==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.2.tgz", + "integrity": "sha512-PdfubrSNN5KwroyMH158R23tWcAXJyx4pvSvWls1dHoLCaUhGul9rsL3uVjtqzRpkxlkMavQjGuWG1newPgmkw==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -8471,33 +8471,33 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.4.1", - "@jest/transform": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/expect-utils": "^29.4.2", + "@jest/transform": "^29.4.2", + "@jest/types": "^29.4.2", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.4.1", + "expect": "^29.4.2", "graceful-fs": "^4.2.9", - "jest-diff": "^29.4.1", - "jest-get-type": "^29.2.0", - "jest-haste-map": "^29.4.1", - "jest-matcher-utils": "^29.4.1", - "jest-message-util": "^29.4.1", - "jest-util": "^29.4.1", + "jest-diff": "^29.4.2", + "jest-get-type": "^29.4.2", + "jest-haste-map": "^29.4.2", + "jest-matcher-utils": "^29.4.2", + "jest-message-util": "^29.4.2", + "jest-util": "^29.4.2", "natural-compare": "^1.4.0", - "pretty-format": "^29.4.1", + "pretty-format": "^29.4.2", "semver": "^7.3.5" } }, "jest-util": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.1.tgz", - "integrity": "sha512-bQy9FPGxVutgpN4VRc0hk6w7Hx/m6L53QxpDreTZgJd9gfx/AV2MjyPde9tGyZRINAUrSv57p2inGBu2dRLmkQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.2.tgz", + "integrity": "sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g==", "dev": true, "requires": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -8506,17 +8506,17 @@ } }, "jest-validate": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.1.tgz", - "integrity": "sha512-qNZXcZQdIQx4SfUB/atWnI4/I2HUvhz8ajOSYUu40CSmf9U5emil8EDHgE7M+3j9/pavtk3knlZBDsgFvv/SWw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.2.tgz", + "integrity": "sha512-tto7YKGPJyFbhcKhIDFq8B5od+eVWD/ySZ9Tvcp/NGCvYA4RQbuzhbwYWtIjMT5W5zA2W0eBJwu4HVw34d5G6Q==", "dev": true, "requires": { - "@jest/types": "^29.4.1", + "@jest/types": "^29.4.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.2.0", + "jest-get-type": "^29.4.2", "leven": "^3.1.0", - "pretty-format": "^29.4.1" + "pretty-format": "^29.4.2" }, "dependencies": { "camelcase": { @@ -8528,29 +8528,29 @@ } }, "jest-watcher": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.1.tgz", - "integrity": "sha512-vFOzflGFs27nU6h8dpnVRER3O2rFtL+VMEwnG0H3KLHcllLsU8y9DchSh0AL/Rg5nN1/wSiQ+P4ByMGpuybaVw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.2.tgz", + "integrity": "sha512-onddLujSoGiMJt+tKutehIidABa175i/Ays+QvKxCqBwp7fvxP3ZhKsrIdOodt71dKxqk4sc0LN41mWLGIK44w==", "dev": true, "requires": { - "@jest/test-result": "^29.4.1", - "@jest/types": "^29.4.1", + "@jest/test-result": "^29.4.2", + "@jest/types": "^29.4.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.4.1", + "jest-util": "^29.4.2", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.1.tgz", - "integrity": "sha512-O9doU/S1EBe+yp/mstQ0VpPwpv0Clgn68TkNwGxL6/usX/KUW9Arnn4ag8C3jc6qHcXznhsT5Na1liYzAsuAbQ==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.2.tgz", + "integrity": "sha512-VIuZA2hZmFyRbchsUCHEehoSf2HEl0YVF8SDJqtPnKorAaBuh42V8QsLnde0XP5F6TyCynGPEGgBOn3Fc+wZGw==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.4.1", + "jest-util": "^29.4.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -9109,12 +9109,12 @@ "dev": true }, "pretty-format": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.1.tgz", - "integrity": "sha512-dt/Z761JUVsrIKaY215o1xQJBGlSmTx/h4cSqXqjHLnU1+Kt+mavVE7UgqJJO5ukx5HjSswHfmXz4LjS2oIJfg==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.2.tgz", + "integrity": "sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg==", "dev": true, "requires": { - "@jest/schemas": "^29.4.0", + "@jest/schemas": "^29.4.2", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -9836,9 +9836,9 @@ "dev": true }, "write-file-atomic": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.0.tgz", - "integrity": "sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "requires": { "imurmurhash": "^0.1.4", diff --git a/package.json b/package.json index 3837879d03..5a8018ac18 100644 --- a/package.json +++ b/package.json @@ -93,13 +93,13 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.11.19", + "@types/node": "^18.13.0", "@types/uuid": "^9.0.0", - "@typescript-eslint/eslint-plugin": "^5.50.0", - "@typescript-eslint/parser": "^5.50.0", - "eslint": "^8.33.0", + "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/parser": "^5.52.0", + "eslint": "^8.34.0", "eslint-plugin-jest": "^27.2.1", - "jest": "^29.4.1", + "jest": "^29.4.2", "open-cli": "^7.1.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From 3a6bb2f90468925ab465556206626d33830c8131 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Wed, 15 Feb 2023 22:04:38 +0200 Subject: [PATCH 013/525] Fix consuming data producer from direct transport by data consumer on non-direct transport --- rust/CHANGELOG.md | 4 ++++ rust/Cargo.toml | 2 +- rust/src/router/transport.rs | 44 ++++++++++++++++++++++-------------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index c79d1c79da..2e5fb0a19b 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +# 0.11.4 + +* Fix consuming data producer from direct transport by data consumer on non-direct transport. + # 0.11.3 * Updates from mediasoup TypeScript `3.10.13..=3.11.8`. diff --git a/rust/Cargo.toml b/rust/Cargo.toml index fbc913c1cf..c1042bed60 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup" -version = "0.11.3" +version = "0.11.4" description = "Cutting Edge WebRTC Video Conferencing in Rust" categories = ["api-bindings", "multimedia", "network-programming"] authors = ["Nazar Mokrynskyi "] diff --git a/rust/src/router/transport.rs b/rust/src/router/transport.rs index e71616ee4b..a57aedbde3 100644 --- a/rust/src/router/transport.rs +++ b/rust/src/router/transport.rs @@ -14,6 +14,7 @@ pub use crate::ortc::{ use crate::producer::{Producer, ProducerId, ProducerOptions}; use crate::router::Router; use crate::rtp_parameters::RtpEncodingParameters; +use crate::sctp_parameters::SctpStreamParameters; use crate::worker::{Channel, PayloadChannel, RequestError}; use crate::{ortc, uuid_based_wrapper_type}; use async_executor::Executor; @@ -687,24 +688,33 @@ pub(super) trait TransportImpl: TransportGeneric { let sctp_stream_parameters = match r#type { DataConsumerType::Sctp => { - let mut sctp_stream_parameters = data_producer.sctp_stream_parameters(); - if let Some(sctp_stream_parameters) = &mut sctp_stream_parameters { - if let Some(stream_id) = self.allocate_sctp_stream_id() { - sctp_stream_parameters.stream_id = stream_id; - } else { - return Err(ConsumeDataError::NoSctpStreamId); - } - if let Some(ordered) = ordered { - sctp_stream_parameters.ordered = ordered; - } - if let Some(max_packet_life_time) = max_packet_life_time { - sctp_stream_parameters.max_packet_life_time = Some(max_packet_life_time); - } - if let Some(max_retransmits) = max_retransmits { - sctp_stream_parameters.max_retransmits = Some(max_retransmits); - } + let stream_id = self + .allocate_sctp_stream_id() + .ok_or(ConsumeDataError::NoSctpStreamId)?; + let mut sctp_stream_parameters = data_producer.sctp_stream_parameters().map_or( + SctpStreamParameters { + stream_id, + ordered: true, + max_packet_life_time, + max_retransmits, + }, + |mut sctp_parameters| { + sctp_parameters.stream_id = stream_id; + + sctp_parameters + }, + ); + if let Some(ordered) = ordered { + sctp_stream_parameters.ordered = ordered; } - sctp_stream_parameters + if let Some(max_packet_life_time) = max_packet_life_time { + sctp_stream_parameters.max_packet_life_time = Some(max_packet_life_time); + } + if let Some(max_retransmits) = max_retransmits { + sctp_stream_parameters.max_retransmits = Some(max_retransmits); + } + + Some(sctp_stream_parameters) } DataConsumerType::Direct => { if ordered.is_some() || max_packet_life_time.is_some() || max_retransmits.is_some() From f399c45c0230002fe520b3d8386a594756457f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Feb 2023 13:06:14 +0100 Subject: [PATCH 014/525] Allow simulcast with a single encoding (and N temporal layers) (#1013) --- node/src/ortc.ts | 2 +- node/src/tests/test-Consumer.ts | 2 +- node/src/tests/test-ortc.ts | 2 +- rust/src/ortc.rs | 2 +- rust/src/ortc/tests.rs | 2 +- rust/tests/integration/consumer.rs | 2 +- .../src/RTC/RtpDictionaries/RtpParameters.cpp | 21 ++++++++++++++++++- worker/src/RTC/SimulcastConsumer.cpp | 7 ++++--- 8 files changed, 30 insertions(+), 10 deletions(-) diff --git a/node/src/ortc.ts b/node/src/ortc.ts index 2677487934..5899715cf4 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -1064,7 +1064,7 @@ export function getConsumerRtpParameters( { const { temporalLayers } = parseScalabilityMode(scalabilityMode); - scalabilityMode = `S${consumableParams.encodings!.length}T${temporalLayers}`; + scalabilityMode = `L${consumableParams.encodings!.length}T${temporalLayers}`; } if (scalabilityMode) diff --git a/node/src/tests/test-Consumer.ts b/node/src/tests/test-Consumer.ts index bdee353a10..121b167070 100644 --- a/node/src/tests/test-Consumer.ts +++ b/node/src/tests/test-Consumer.ts @@ -715,7 +715,7 @@ test('consumer.dump() succeeds', async () => { ssrc : videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc }, - scalabilityMode : 'S4T1' + scalabilityMode : 'L4T1' } ]); expect(Array.isArray(data.consumableRtpEncodings)).toBe(true); diff --git a/node/src/tests/test-ortc.ts b/node/src/tests/test-ortc.ts index abe9558956..bfbd9c1e83 100644 --- a/node/src/tests/test-ortc.ts +++ b/node/src/tests/test-ortc.ts @@ -469,7 +469,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(typeof consumerRtpParameters.encodings?.[0].ssrc).toBe('number'); expect(typeof consumerRtpParameters.encodings?.[0].rtx).toBe('object'); expect(typeof consumerRtpParameters.encodings?.[0].rtx?.ssrc).toBe('number'); - expect(consumerRtpParameters.encodings?.[0].scalabilityMode).toBe('S3T3'); + expect(consumerRtpParameters.encodings?.[0].scalabilityMode).toBe('L3T3'); expect(consumerRtpParameters.encodings?.[0].maxBitrate).toBe(333333); expect(consumerRtpParameters.headerExtensions).toEqual( diff --git a/rust/src/ortc.rs b/rust/src/ortc.rs index c626ee47fa..ccc656a3c6 100644 --- a/rust/src/ortc.rs +++ b/rust/src/ortc.rs @@ -777,7 +777,7 @@ pub(crate) fn get_consumer_rtp_parameters( // If there is simulcast, mangle spatial layers in scalabilityMode. if consumable_params.encodings.len() > 1 { scalability_mode = format!( - "S{}T{}", + "L{}T{}", consumable_params.encodings.len(), scalability_mode.temporal_layers() ) diff --git a/rust/src/ortc/tests.rs b/rust/src/ortc/tests.rs index 8020a11b30..837928e4ce 100644 --- a/rust/src/ortc/tests.rs +++ b/rust/src/ortc/tests.rs @@ -502,7 +502,7 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume .get(0) .unwrap() .scalability_mode, - ScalabilityMode::S3T3, + ScalabilityMode::L3T3, ); assert_eq!( consumer_rtp_parameters diff --git a/rust/tests/integration/consumer.rs b/rust/tests/integration/consumer.rs index 62c9b250ff..0554cfb785 100644 --- a/rust/tests/integration/consumer.rs +++ b/rust/tests/integration/consumer.rs @@ -1047,7 +1047,7 @@ fn dump_succeeds() { .unwrap() .rtx, dtx: None, - scalability_mode: "S4T1".parse().unwrap(), + scalability_mode: "L4T1".parse().unwrap(), scale_resolution_down_by: None, rid: None, max_bitrate: None, diff --git a/worker/src/RTC/RtpDictionaries/RtpParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpParameters.cpp index 5ea8bc1bc4..2a0010affa 100644 --- a/worker/src/RTC/RtpDictionaries/RtpParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpParameters.cpp @@ -3,6 +3,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "RTC/Codecs/Tools.hpp" #include "RTC/RtpDictionaries.hpp" #include @@ -38,11 +39,29 @@ namespace RTC if (rtpParameters.encodings.size() == 1) { auto& encoding = rtpParameters.encodings[0]; + const auto* mediaCodec = + rtpParameters.GetCodecForEncoding(const_cast(encoding)); if (encoding.spatialLayers > 1 || encoding.temporalLayers > 1) - return RtpParameters::Type::SVC; + { + if (RTC::Codecs::Tools::IsValidTypeForCodec(RtpParameters::Type::SVC, mediaCodec->mimeType)) + { + return RtpParameters::Type::SVC; + } + else if (RTC::Codecs::Tools::IsValidTypeForCodec( + RtpParameters::Type::SIMULCAST, mediaCodec->mimeType)) + { + return RtpParameters::Type::SIMULCAST; + } + else + { + return RtpParameters::Type::NONE; + } + } else + { return RtpParameters::Type::SIMPLE; + } } else if (rtpParameters.encodings.size() > 1) { diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index c3ad9f7550..81871cf2f4 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -30,9 +30,10 @@ namespace RTC { MS_TRACE(); - // Ensure there are N > 1 encodings. - if (this->consumableRtpEncodings.size() <= 1u) - MS_THROW_TYPE_ERROR("invalid consumableRtpEncodings with size <= 1"); + // We allow a single encoding in simulcast (so we can enable temporal layers + // with a single simulcast stream). + // NOTE: No need to check this->consumableRtpEncodings.size() > 0 here since + // it's already done in Consumer constructor. auto& encoding = this->rtpParameters.encodings[0]; From 8c847d1c26ac644bea5e15a0bed85650bbd9bad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Feb 2023 13:10:13 +0100 Subject: [PATCH 015/525] 3.11.9 --- CHANGELOG.md | 4 + package-lock.json | 1264 ++++++++++++++++++++++----------------------- package.json | 4 +- 3 files changed, 637 insertions(+), 635 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75792498ef..c540f92c20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ ### Next + +### 3.11.9 + +* Allow simulcast with a single encoding (and N temporal layers) ([PR #1013](https://github.com/versatica/mediasoup/pull/1013)). * Update libsrtp to 2.5.0. * Update NPM deps. diff --git a/package-lock.json b/package-lock.json index 490b5e9fbf..34cac63916 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.8", + "version": "3.11.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.8", + "version": "3.11.9", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -24,7 +24,7 @@ "@typescript-eslint/parser": "^5.52.0", "eslint": "^8.34.0", "eslint-plugin-jest": "^27.2.1", - "jest": "^29.4.2", + "jest": "^29.4.3", "open-cli": "^7.1.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -807,16 +807,16 @@ } }, "node_modules/@jest/console": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.2.tgz", - "integrity": "sha512-0I/rEJwMpV9iwi9cDEnT71a5nNGK9lj8Z4+1pRAU2x/thVXCDnaTGrvxyK+cAqZTFVFCiR+hfVrP4l2m+dCmQg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.3.tgz", + "integrity": "sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A==", "dev": true, "dependencies": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.4.2", - "jest-util": "^29.4.2", + "jest-message-util": "^29.4.3", + "jest-util": "^29.4.3", "slash": "^3.0.0" }, "engines": { @@ -824,37 +824,37 @@ } }, "node_modules/@jest/core": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.2.tgz", - "integrity": "sha512-KGuoQah0P3vGNlaS/l9/wQENZGNKGoWb+OPxh3gz+YzG7/XExvYu34MzikRndQCdM2S0tzExN4+FL37i6gZmCQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.3.tgz", + "integrity": "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ==", "dev": true, "dependencies": { - "@jest/console": "^29.4.2", - "@jest/reporters": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/console": "^29.4.3", + "@jest/reporters": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.4.2", - "jest-config": "^29.4.2", - "jest-haste-map": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-regex-util": "^29.4.2", - "jest-resolve": "^29.4.2", - "jest-resolve-dependencies": "^29.4.2", - "jest-runner": "^29.4.2", - "jest-runtime": "^29.4.2", - "jest-snapshot": "^29.4.2", - "jest-util": "^29.4.2", - "jest-validate": "^29.4.2", - "jest-watcher": "^29.4.2", + "jest-changed-files": "^29.4.3", + "jest-config": "^29.4.3", + "jest-haste-map": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.4.3", + "jest-resolve-dependencies": "^29.4.3", + "jest-runner": "^29.4.3", + "jest-runtime": "^29.4.3", + "jest-snapshot": "^29.4.3", + "jest-util": "^29.4.3", + "jest-validate": "^29.4.3", + "jest-watcher": "^29.4.3", "micromatch": "^4.0.4", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -871,88 +871,88 @@ } }, "node_modules/@jest/environment": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.2.tgz", - "integrity": "sha512-JKs3VUtse0vQfCaFGJRX1bir9yBdtasxziSyu+pIiEllAQOe4oQhdCYIf3+Lx+nGglFktSKToBnRJfD5QKp+NQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.3.tgz", + "integrity": "sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/fake-timers": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", - "jest-mock": "^29.4.2" + "jest-mock": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.2.tgz", - "integrity": "sha512-NUAeZVApzyaeLjfWIV/64zXjA2SS+NuUPHpAlO7IwVMGd5Vf9szTl9KEDlxY3B4liwLO31os88tYNHl6cpjtKQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.3.tgz", + "integrity": "sha512-iktRU/YsxEtumI9zsPctYUk7ptpC+AVLLk1Ax3AsA4g1C+8OOnKDkIQBDHtD5hA/+VtgMd5AWI5gNlcAlt2vxQ==", "dev": true, "dependencies": { - "expect": "^29.4.2", - "jest-snapshot": "^29.4.2" + "expect": "^29.4.3", + "jest-snapshot": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.2.tgz", - "integrity": "sha512-Dd3ilDJpBnqa0GiPN7QrudVs0cczMMHtehSo2CSTjm3zdHx0RcpmhFNVEltuEFeqfLIyWKFI224FsMSQ/nsJQA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.3.tgz", + "integrity": "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==", "dev": true, "dependencies": { - "jest-get-type": "^29.4.2" + "jest-get-type": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.2.tgz", - "integrity": "sha512-Ny1u0Wg6kCsHFWq7A/rW/tMhIedq2siiyHyLpHCmIhP7WmcAmd2cx95P+0xtTZlj5ZbJxIRQi4OPydZZUoiSQQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.3.tgz", + "integrity": "sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw==", "dev": true, "dependencies": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.4.2", - "jest-mock": "^29.4.2", - "jest-util": "^29.4.2" + "jest-message-util": "^29.4.3", + "jest-mock": "^29.4.3", + "jest-util": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.2.tgz", - "integrity": "sha512-zCk70YGPzKnz/I9BNFDPlK+EuJLk21ur/NozVh6JVM86/YYZtZHqxFFQ62O9MWq7uf3vIZnvNA0BzzrtxD9iyg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.3.tgz", + "integrity": "sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.2", - "@jest/expect": "^29.4.2", - "@jest/types": "^29.4.2", - "jest-mock": "^29.4.2" + "@jest/environment": "^29.4.3", + "@jest/expect": "^29.4.3", + "@jest/types": "^29.4.3", + "jest-mock": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.2.tgz", - "integrity": "sha512-10yw6YQe75zCgYcXgEND9kw3UZZH5tJeLzWv4vTk/2mrS1aY50A37F+XT2hPO5OqQFFnUWizXD8k1BMiATNfUw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.3.tgz", + "integrity": "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/console": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", @@ -965,9 +965,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.4.2", - "jest-util": "^29.4.2", - "jest-worker": "^29.4.2", + "jest-message-util": "^29.4.3", + "jest-util": "^29.4.3", + "jest-worker": "^29.4.3", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -986,9 +986,9 @@ } }, "node_modules/@jest/schemas": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.2.tgz", - "integrity": "sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "dev": true, "dependencies": { "@sinclair/typebox": "^0.25.16" @@ -998,9 +998,9 @@ } }, "node_modules/@jest/source-map": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.2.tgz", - "integrity": "sha512-tIoqV5ZNgYI9XCKXMqbYe5JbumcvyTgNN+V5QW4My033lanijvCD0D4PI9tBw4pRTqWOc00/7X3KVvUh+qnF4Q==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", + "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.15", @@ -1012,13 +1012,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.2.tgz", - "integrity": "sha512-HZsC3shhiHVvMtP+i55MGR5bPcc3obCFbA5bzIOb8pCjwBZf11cZliJncCgaVUbC5yoQNuGqCkC0Q3t6EItxZA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.3.tgz", + "integrity": "sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA==", "dev": true, "dependencies": { - "@jest/console": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/console": "^29.4.3", + "@jest/types": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1027,14 +1027,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.2.tgz", - "integrity": "sha512-9Z2cVsD6CcObIVrWigHp2McRJhvCxL27xHtrZFgNC1RwnoSpDx6fZo8QYjJmziFlW9/hr78/3sxF54S8B6v8rg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.3.tgz", + "integrity": "sha512-yi/t2nES4GB4G0mjLc0RInCq/cNr9dNwJxcGg8sslajua5Kb4kmozAc+qPLzplhBgfw1vLItbjyHzUN92UXicw==", "dev": true, "dependencies": { - "@jest/test-result": "^29.4.2", + "@jest/test-result": "^29.4.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.2", + "jest-haste-map": "^29.4.3", "slash": "^3.0.0" }, "engines": { @@ -1042,22 +1042,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.2.tgz", - "integrity": "sha512-kf1v5iTJHn7p9RbOsBuc/lcwyPtJaZJt5885C98omWz79NIeD3PfoiiaPSu7JyCyFzNOIzKhmMhQLUhlTL9BvQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.3.tgz", + "integrity": "sha512-8u0+fBGWolDshsFgPQJESkDa72da/EVwvL+II0trN2DR66wMwiQ9/CihaGfHdlLGFzbBZwMykFtxuwFdZqlKwg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.2", - "jest-regex-util": "^29.4.2", - "jest-util": "^29.4.2", + "jest-haste-map": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.4.3", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1068,12 +1068,12 @@ } }, "node_modules/@jest/types": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.2.tgz", - "integrity": "sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.3.tgz", + "integrity": "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.2", + "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1167,9 +1167,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.25.21", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.21.tgz", - "integrity": "sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g==", + "version": "0.25.23", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.23.tgz", + "integrity": "sha512-VEB8ygeP42CFLWyAJhN5OklpxUliqdNEUcXb4xZ/CINqtYGTjL5ukluKdKzQ0iWdUxyQ7B0539PAUhHKrCNWSQ==", "dev": true }, "node_modules/@sinonjs/commons": { @@ -1672,15 +1672,15 @@ } }, "node_modules/babel-jest": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.2.tgz", - "integrity": "sha512-vcghSqhtowXPG84posYkkkzcZsdayFkubUgbE3/1tuGbX7AQtwCkkNA/wIbB0BMjuCPoqTkiDyKN7Ty7d3uwNQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.3.tgz", + "integrity": "sha512-o45Wyn32svZE+LnMVWv/Z4x0SwtLbh4FyGcYtR20kIWd+rdrDZ9Fzq8Ml3MYLD+mZvEdzCjZsCnYZ2jpJyQ+Nw==", "dev": true, "dependencies": { - "@jest/transform": "^29.4.2", + "@jest/transform": "^29.4.3", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.4.2", + "babel-preset-jest": "^29.4.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -1709,9 +1709,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.2.tgz", - "integrity": "sha512-5HZRCfMeWypFEonRbEkwWXtNS1sQK159LhRVyRuLzyfVBxDy/34Tr/rg4YVi0SScSJ4fqeaR/OIeceJ/LaQ0pQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.3.tgz", + "integrity": "sha512-mB6q2q3oahKphy5V7CpnNqZOCkxxZ9aokf1eh82Dy3jQmg4xvM1tGrh5y6BQUJh4a3Pj9+eLfwvAZ7VNKg7H8Q==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -1747,12 +1747,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.2.tgz", - "integrity": "sha512-ecWdaLY/8JyfUDr0oELBMpj3R5I1L6ZqG+kRJmwqfHtLWuPrJStR0LUkvUhfykJWTsXXMnohsayN/twltBbDrQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.3.tgz", + "integrity": "sha512-gWx6COtSuma6n9bw+8/F+2PCXrIgxV/D1TJFnp6OyBK2cxPWg0K9p/sriNYeifKjpUkMViWQ09DSWtzJQRETsw==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.4.2", + "babel-plugin-jest-hoist": "^29.4.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -2185,9 +2185,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.2.tgz", - "integrity": "sha512-R6P0Y6PrsH3n4hUXxL3nns0rbRk6Q33js3ygJBeEpbzLzgcNuJ61+u0RXasFpTKISw99TxUzFnumSnRLsjhLaw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2566,16 +2566,16 @@ } }, "node_modules/expect": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.2.tgz", - "integrity": "sha512-+JHYg9O3hd3RlICG90OPVjRkPBoiUH7PxvDVMnRiaq1g6JUgZStX514erMl0v2Dc5SkfVbm7ztqbd6qHHPn+mQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.3.tgz", + "integrity": "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.4.2", - "jest-get-type": "^29.4.2", - "jest-matcher-utils": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-util": "^29.4.2" + "@jest/expect-utils": "^29.4.3", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-util": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3284,15 +3284,15 @@ } }, "node_modules/jest": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.2.tgz", - "integrity": "sha512-+5hLd260vNIHu+7ZgMIooSpKl7Jp5pHKb51e73AJU3owd5dEo/RfVwHbA/na3C/eozrt3hJOLGf96c7EWwIAzg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.3.tgz", + "integrity": "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA==", "dev": true, "dependencies": { - "@jest/core": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/core": "^29.4.3", + "@jest/types": "^29.4.3", "import-local": "^3.0.2", - "jest-cli": "^29.4.2" + "jest-cli": "^29.4.3" }, "bin": { "jest": "bin/jest.js" @@ -3310,9 +3310,9 @@ } }, "node_modules/jest-changed-files": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.2.tgz", - "integrity": "sha512-Qdd+AXdqD16PQa+VsWJpxR3kN0JyOCX1iugQfx5nUgAsI4gwsKviXkpclxOK9ZnwaY2IQVHz+771eAvqeOlfuw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.3.tgz", + "integrity": "sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ==", "dev": true, "dependencies": { "execa": "^5.0.0", @@ -3323,28 +3323,28 @@ } }, "node_modules/jest-circus": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.2.tgz", - "integrity": "sha512-wW3ztp6a2P5c1yOc1Cfrt5ozJ7neWmqeXm/4SYiqcSriyisgq63bwFj1NuRdSR5iqS0CMEYwSZd89ZA47W9zUg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.3.tgz", + "integrity": "sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.2", - "@jest/expect": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/environment": "^29.4.3", + "@jest/expect": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.4.2", - "jest-matcher-utils": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-runtime": "^29.4.2", - "jest-snapshot": "^29.4.2", - "jest-util": "^29.4.2", + "jest-each": "^29.4.3", + "jest-matcher-utils": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-runtime": "^29.4.3", + "jest-snapshot": "^29.4.3", + "jest-util": "^29.4.3", "p-limit": "^3.1.0", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3353,21 +3353,21 @@ } }, "node_modules/jest-cli": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.2.tgz", - "integrity": "sha512-b+eGUtXq/K2v7SH3QcJvFvaUaCDS1/YAZBYz0m28Q/Ppyr+1qNaHmVYikOrbHVbZqYQs2IeI3p76uy6BWbXq8Q==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.3.tgz", + "integrity": "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg==", "dev": true, "dependencies": { - "@jest/core": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/core": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/types": "^29.4.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.4.2", - "jest-util": "^29.4.2", - "jest-validate": "^29.4.2", + "jest-config": "^29.4.3", + "jest-util": "^29.4.3", + "jest-validate": "^29.4.3", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -3387,31 +3387,31 @@ } }, "node_modules/jest-config": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.2.tgz", - "integrity": "sha512-919CtnXic52YM0zW4C1QxjG6aNueX1kBGthuMtvFtRTAxhKfJmiXC9qwHmi6o2josjbDz8QlWyY55F1SIVmCWA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.3.tgz", + "integrity": "sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.4.2", - "@jest/types": "^29.4.2", - "babel-jest": "^29.4.2", + "@jest/test-sequencer": "^29.4.3", + "@jest/types": "^29.4.3", + "babel-jest": "^29.4.3", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.4.2", - "jest-environment-node": "^29.4.2", - "jest-get-type": "^29.4.2", - "jest-regex-util": "^29.4.2", - "jest-resolve": "^29.4.2", - "jest-runner": "^29.4.2", - "jest-util": "^29.4.2", - "jest-validate": "^29.4.2", + "jest-circus": "^29.4.3", + "jest-environment-node": "^29.4.3", + "jest-get-type": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.4.3", + "jest-runner": "^29.4.3", + "jest-util": "^29.4.3", + "jest-validate": "^29.4.3", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3432,24 +3432,24 @@ } }, "node_modules/jest-diff": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.2.tgz", - "integrity": "sha512-EK8DSajVtnjx9sa1BkjZq3mqChm2Cd8rIzdXkQMA8e0wuXq53ypz6s5o5V8HRZkoEt2ywJ3eeNWFKWeYr8HK4g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.3.tgz", + "integrity": "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.2", - "jest-get-type": "^29.4.2", - "pretty-format": "^29.4.2" + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.2.tgz", - "integrity": "sha512-dV2JdahgClL34Y5vLrAHde3nF3yo2jKRH+GIYJuCpfqwEJZcikzeafVTGAjbOfKPG17ez9iWXwUYp7yefeCRag==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", + "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" @@ -3459,62 +3459,62 @@ } }, "node_modules/jest-each": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.2.tgz", - "integrity": "sha512-trvKZb0JYiCndc55V1Yh0Luqi7AsAdDWpV+mKT/5vkpnnFQfuQACV72IoRV161aAr6kAVIBpmYzwhBzm34vQkA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.3.tgz", + "integrity": "sha512-1ElHNAnKcbJb/b+L+7j0/w7bDvljw4gTv1wL9fYOczeJrbTbkMGQ5iQPFJ3eFQH19VPTx1IyfePdqSpePKss7Q==", "dev": true, "dependencies": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.2", - "jest-util": "^29.4.2", - "pretty-format": "^29.4.2" + "jest-get-type": "^29.4.3", + "jest-util": "^29.4.3", + "pretty-format": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.2.tgz", - "integrity": "sha512-MLPrqUcOnNBc8zTOfqBbxtoa8/Ee8tZ7UFW7hRDQSUT+NGsvS96wlbHGTf+EFAT9KC3VNb7fWEM6oyvmxtE/9w==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.3.tgz", + "integrity": "sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.2", - "@jest/fake-timers": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/environment": "^29.4.3", + "@jest/fake-timers": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", - "jest-mock": "^29.4.2", - "jest-util": "^29.4.2" + "jest-mock": "^29.4.3", + "jest-util": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.2.tgz", - "integrity": "sha512-vERN30V5i2N6lqlFu4ljdTqQAgrkTFMC9xaIIfOPYBw04pufjXRty5RuXBiB1d72tGbURa/UgoiHB90ruOSivg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.2.tgz", - "integrity": "sha512-WkUgo26LN5UHPknkezrBzr7lUtV1OpGsp+NfXbBwHztsFruS3gz+AMTTBcEklvi8uPzpISzYjdKXYZQJXBnfvw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.3.tgz", + "integrity": "sha512-eZIgAS8tvm5IZMtKlR8Y+feEOMfo2pSQkmNbufdbMzMSn9nitgGxF1waM/+LbryO3OkMcKS98SUb+j/cQxp/vQ==", "dev": true, "dependencies": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.2", - "jest-util": "^29.4.2", - "jest-worker": "^29.4.2", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.4.3", + "jest-worker": "^29.4.3", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3526,46 +3526,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.2.tgz", - "integrity": "sha512-Wa62HuRJmWXtX9F00nUpWlrbaH5axeYCdyRsOs/+Rb1Vb6+qWTlB5rKwCCRKtorM7owNwKsyJ8NRDUcZ8ghYUA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.3.tgz", + "integrity": "sha512-9yw4VC1v2NspMMeV3daQ1yXPNxMgCzwq9BocCwYrRgXe4uaEJPAN0ZK37nFBhcy3cUwEVstFecFLaTHpF7NiGA==", "dev": true, "dependencies": { - "jest-get-type": "^29.4.2", - "pretty-format": "^29.4.2" + "jest-get-type": "^29.4.3", + "pretty-format": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.2.tgz", - "integrity": "sha512-EZaAQy2je6Uqkrm6frnxBIdaWtSYFoR8SVb2sNLAtldswlR/29JAgx+hy67llT3+hXBaLB0zAm5UfeqerioZyg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz", + "integrity": "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.4.2", - "jest-get-type": "^29.4.2", - "pretty-format": "^29.4.2" + "jest-diff": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.2.tgz", - "integrity": "sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.3.tgz", + "integrity": "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3574,14 +3574,14 @@ } }, "node_modules/jest-mock": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.2.tgz", - "integrity": "sha512-x1FSd4Gvx2yIahdaIKoBjwji6XpboDunSJ95RpntGrYulI1ByuYQCKN/P7hvk09JB74IonU3IPLdkutEWYt++g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.3.tgz", + "integrity": "sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg==", "dev": true, "dependencies": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/node": "*", - "jest-util": "^29.4.2" + "jest-util": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3605,26 +3605,26 @@ } }, "node_modules/jest-regex-util": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.2.tgz", - "integrity": "sha512-XYZXOqUl1y31H6VLMrrUL1ZhXuiymLKPz0BO1kEeR5xER9Tv86RZrjTm74g5l9bPJQXA/hyLdaVPN/sdqfteig==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", + "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.2.tgz", - "integrity": "sha512-RtKWW0mbR3I4UdkOrW7552IFGLYQ5AF9YrzD0FnIOkDu0rAMlA5/Y1+r7lhCAP4nXSBTaE7ueeqj6IOwZpgoqw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.3.tgz", + "integrity": "sha512-GPokE1tzguRyT7dkxBim4wSx6E45S3bOQ7ZdKEG+Qj0Oac9+6AwJPCk0TZh5Vu0xzeX4afpb+eDmgbmZFFwpOw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.2", + "jest-haste-map": "^29.4.3", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.4.2", - "jest-validate": "^29.4.2", + "jest-util": "^29.4.3", + "jest-validate": "^29.4.3", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -3634,43 +3634,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.2.tgz", - "integrity": "sha512-6pL4ptFw62rjdrPk7rRpzJYgcRqRZNsZTF1VxVTZMishbO6ObyWvX57yHOaNGgKoADtAHRFYdHQUEvYMJATbDg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.3.tgz", + "integrity": "sha512-uvKMZAQ3nmXLH7O8WAOhS5l0iWyT3WmnJBdmIHiV5tBbdaDZ1wqtNX04FONGoaFvSOSHBJxnwAVnSn1WHdGVaw==", "dev": true, "dependencies": { - "jest-regex-util": "^29.4.2", - "jest-snapshot": "^29.4.2" + "jest-regex-util": "^29.4.3", + "jest-snapshot": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.2.tgz", - "integrity": "sha512-wqwt0drm7JGjwdH+x1XgAl+TFPH7poowMguPQINYxaukCqlczAcNLJiK+OLxUxQAEWMdy+e6nHZlFHO5s7EuRg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.3.tgz", + "integrity": "sha512-GWPTEiGmtHZv1KKeWlTX9SIFuK19uLXlRQU43ceOQ2hIfA5yPEJC7AMkvFKpdCHx6pNEdOD+2+8zbniEi3v3gA==", "dev": true, "dependencies": { - "@jest/console": "^29.4.2", - "@jest/environment": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/console": "^29.4.3", + "@jest/environment": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.2", - "jest-environment-node": "^29.4.2", - "jest-haste-map": "^29.4.2", - "jest-leak-detector": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-resolve": "^29.4.2", - "jest-runtime": "^29.4.2", - "jest-util": "^29.4.2", - "jest-watcher": "^29.4.2", - "jest-worker": "^29.4.2", + "jest-docblock": "^29.4.3", + "jest-environment-node": "^29.4.3", + "jest-haste-map": "^29.4.3", + "jest-leak-detector": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-resolve": "^29.4.3", + "jest-runtime": "^29.4.3", + "jest-util": "^29.4.3", + "jest-watcher": "^29.4.3", + "jest-worker": "^29.4.3", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -3679,32 +3679,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.2.tgz", - "integrity": "sha512-3fque9vtpLzGuxT9eZqhxi+9EylKK/ESfhClv4P7Y9sqJPs58LjVhTt8jaMp/pRO38agll1CkSu9z9ieTQeRrw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.4.2", - "@jest/fake-timers": "^29.4.2", - "@jest/globals": "^29.4.2", - "@jest/source-map": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.3.tgz", + "integrity": "sha512-F5bHvxSH+LvLV24vVB3L8K467dt3y3dio6V3W89dUz9nzvTpqd/HcT9zfYKL2aZPvD63vQFgLvaUX/UpUhrP6Q==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.4.3", + "@jest/fake-timers": "^29.4.3", + "@jest/globals": "^29.4.3", + "@jest/source-map": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-mock": "^29.4.2", - "jest-regex-util": "^29.4.2", - "jest-resolve": "^29.4.2", - "jest-snapshot": "^29.4.2", - "jest-util": "^29.4.2", - "semver": "^7.3.5", + "jest-haste-map": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-mock": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.4.3", + "jest-snapshot": "^29.4.3", + "jest-util": "^29.4.3", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -3713,9 +3712,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.2.tgz", - "integrity": "sha512-PdfubrSNN5KwroyMH158R23tWcAXJyx4pvSvWls1dHoLCaUhGul9rsL3uVjtqzRpkxlkMavQjGuWG1newPgmkw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.3.tgz", + "integrity": "sha512-NGlsqL0jLPDW91dz304QTM/SNO99lpcSYYAjNiX0Ou+sSGgkanKBcSjCfp/pqmiiO1nQaOyLp6XQddAzRcx3Xw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -3724,23 +3723,23 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/expect-utils": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.4.2", + "expect": "^29.4.3", "graceful-fs": "^4.2.9", - "jest-diff": "^29.4.2", - "jest-get-type": "^29.4.2", - "jest-haste-map": "^29.4.2", - "jest-matcher-utils": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-util": "^29.4.2", + "jest-diff": "^29.4.3", + "jest-get-type": "^29.4.3", + "jest-haste-map": "^29.4.3", + "jest-matcher-utils": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-util": "^29.4.3", "natural-compare": "^1.4.0", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "semver": "^7.3.5" }, "engines": { @@ -3748,12 +3747,12 @@ } }, "node_modules/jest-util": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.2.tgz", - "integrity": "sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.3.tgz", + "integrity": "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==", "dev": true, "dependencies": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3765,17 +3764,17 @@ } }, "node_modules/jest-validate": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.2.tgz", - "integrity": "sha512-tto7YKGPJyFbhcKhIDFq8B5od+eVWD/ySZ9Tvcp/NGCvYA4RQbuzhbwYWtIjMT5W5zA2W0eBJwu4HVw34d5G6Q==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.3.tgz", + "integrity": "sha512-J3u5v7aPQoXPzaar6GndAVhdQcZr/3osWSgTeKg5v574I9ybX/dTyH0AJFb5XgXIB7faVhf+rS7t4p3lL9qFaw==", "dev": true, "dependencies": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.2", + "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.4.2" + "pretty-format": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3794,18 +3793,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.2.tgz", - "integrity": "sha512-onddLujSoGiMJt+tKutehIidABa175i/Ays+QvKxCqBwp7fvxP3ZhKsrIdOodt71dKxqk4sc0LN41mWLGIK44w==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.3.tgz", + "integrity": "sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/test-result": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.4.2", + "jest-util": "^29.4.3", "string-length": "^4.0.1" }, "engines": { @@ -3813,13 +3812,13 @@ } }, "node_modules/jest-worker": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.2.tgz", - "integrity": "sha512-VIuZA2hZmFyRbchsUCHEehoSf2HEl0YVF8SDJqtPnKorAaBuh42V8QsLnde0XP5F6TyCynGPEGgBOn3Fc+wZGw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.3.tgz", + "integrity": "sha512-GLHN/GTAAMEy5BFdvpUfzr9Dr80zQqBrh0fz1mtRMe05hqP45+HfQltu7oTBfduD0UeZs09d+maFtFYAXFWvAA==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.4.2", + "jest-util": "^29.4.3", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4569,12 +4568,12 @@ } }, "node_modules/pretty-format": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.2.tgz", - "integrity": "sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", + "integrity": "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.2", + "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -5569,9 +5568,9 @@ } }, "node_modules/v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", @@ -6314,123 +6313,123 @@ "dev": true }, "@jest/console": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.2.tgz", - "integrity": "sha512-0I/rEJwMpV9iwi9cDEnT71a5nNGK9lj8Z4+1pRAU2x/thVXCDnaTGrvxyK+cAqZTFVFCiR+hfVrP4l2m+dCmQg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.3.tgz", + "integrity": "sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A==", "dev": true, "requires": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.4.2", - "jest-util": "^29.4.2", + "jest-message-util": "^29.4.3", + "jest-util": "^29.4.3", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.2.tgz", - "integrity": "sha512-KGuoQah0P3vGNlaS/l9/wQENZGNKGoWb+OPxh3gz+YzG7/XExvYu34MzikRndQCdM2S0tzExN4+FL37i6gZmCQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.3.tgz", + "integrity": "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ==", "dev": true, "requires": { - "@jest/console": "^29.4.2", - "@jest/reporters": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/console": "^29.4.3", + "@jest/reporters": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.4.2", - "jest-config": "^29.4.2", - "jest-haste-map": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-regex-util": "^29.4.2", - "jest-resolve": "^29.4.2", - "jest-resolve-dependencies": "^29.4.2", - "jest-runner": "^29.4.2", - "jest-runtime": "^29.4.2", - "jest-snapshot": "^29.4.2", - "jest-util": "^29.4.2", - "jest-validate": "^29.4.2", - "jest-watcher": "^29.4.2", + "jest-changed-files": "^29.4.3", + "jest-config": "^29.4.3", + "jest-haste-map": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.4.3", + "jest-resolve-dependencies": "^29.4.3", + "jest-runner": "^29.4.3", + "jest-runtime": "^29.4.3", + "jest-snapshot": "^29.4.3", + "jest-util": "^29.4.3", + "jest-validate": "^29.4.3", + "jest-watcher": "^29.4.3", "micromatch": "^4.0.4", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.2.tgz", - "integrity": "sha512-JKs3VUtse0vQfCaFGJRX1bir9yBdtasxziSyu+pIiEllAQOe4oQhdCYIf3+Lx+nGglFktSKToBnRJfD5QKp+NQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.3.tgz", + "integrity": "sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA==", "dev": true, "requires": { - "@jest/fake-timers": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/fake-timers": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", - "jest-mock": "^29.4.2" + "jest-mock": "^29.4.3" } }, "@jest/expect": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.2.tgz", - "integrity": "sha512-NUAeZVApzyaeLjfWIV/64zXjA2SS+NuUPHpAlO7IwVMGd5Vf9szTl9KEDlxY3B4liwLO31os88tYNHl6cpjtKQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.3.tgz", + "integrity": "sha512-iktRU/YsxEtumI9zsPctYUk7ptpC+AVLLk1Ax3AsA4g1C+8OOnKDkIQBDHtD5hA/+VtgMd5AWI5gNlcAlt2vxQ==", "dev": true, "requires": { - "expect": "^29.4.2", - "jest-snapshot": "^29.4.2" + "expect": "^29.4.3", + "jest-snapshot": "^29.4.3" } }, "@jest/expect-utils": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.2.tgz", - "integrity": "sha512-Dd3ilDJpBnqa0GiPN7QrudVs0cczMMHtehSo2CSTjm3zdHx0RcpmhFNVEltuEFeqfLIyWKFI224FsMSQ/nsJQA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.3.tgz", + "integrity": "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==", "dev": true, "requires": { - "jest-get-type": "^29.4.2" + "jest-get-type": "^29.4.3" } }, "@jest/fake-timers": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.2.tgz", - "integrity": "sha512-Ny1u0Wg6kCsHFWq7A/rW/tMhIedq2siiyHyLpHCmIhP7WmcAmd2cx95P+0xtTZlj5ZbJxIRQi4OPydZZUoiSQQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.3.tgz", + "integrity": "sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw==", "dev": true, "requires": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.4.2", - "jest-mock": "^29.4.2", - "jest-util": "^29.4.2" + "jest-message-util": "^29.4.3", + "jest-mock": "^29.4.3", + "jest-util": "^29.4.3" } }, "@jest/globals": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.2.tgz", - "integrity": "sha512-zCk70YGPzKnz/I9BNFDPlK+EuJLk21ur/NozVh6JVM86/YYZtZHqxFFQ62O9MWq7uf3vIZnvNA0BzzrtxD9iyg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.3.tgz", + "integrity": "sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA==", "dev": true, "requires": { - "@jest/environment": "^29.4.2", - "@jest/expect": "^29.4.2", - "@jest/types": "^29.4.2", - "jest-mock": "^29.4.2" + "@jest/environment": "^29.4.3", + "@jest/expect": "^29.4.3", + "@jest/types": "^29.4.3", + "jest-mock": "^29.4.3" } }, "@jest/reporters": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.2.tgz", - "integrity": "sha512-10yw6YQe75zCgYcXgEND9kw3UZZH5tJeLzWv4vTk/2mrS1aY50A37F+XT2hPO5OqQFFnUWizXD8k1BMiATNfUw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.3.tgz", + "integrity": "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/console": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", @@ -6443,9 +6442,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.4.2", - "jest-util": "^29.4.2", - "jest-worker": "^29.4.2", + "jest-message-util": "^29.4.3", + "jest-util": "^29.4.3", + "jest-worker": "^29.4.3", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -6453,18 +6452,18 @@ } }, "@jest/schemas": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.2.tgz", - "integrity": "sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "dev": true, "requires": { "@sinclair/typebox": "^0.25.16" } }, "@jest/source-map": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.2.tgz", - "integrity": "sha512-tIoqV5ZNgYI9XCKXMqbYe5JbumcvyTgNN+V5QW4My033lanijvCD0D4PI9tBw4pRTqWOc00/7X3KVvUh+qnF4Q==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", + "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.15", @@ -6473,46 +6472,46 @@ } }, "@jest/test-result": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.2.tgz", - "integrity": "sha512-HZsC3shhiHVvMtP+i55MGR5bPcc3obCFbA5bzIOb8pCjwBZf11cZliJncCgaVUbC5yoQNuGqCkC0Q3t6EItxZA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.3.tgz", + "integrity": "sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA==", "dev": true, "requires": { - "@jest/console": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/console": "^29.4.3", + "@jest/types": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.2.tgz", - "integrity": "sha512-9Z2cVsD6CcObIVrWigHp2McRJhvCxL27xHtrZFgNC1RwnoSpDx6fZo8QYjJmziFlW9/hr78/3sxF54S8B6v8rg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.3.tgz", + "integrity": "sha512-yi/t2nES4GB4G0mjLc0RInCq/cNr9dNwJxcGg8sslajua5Kb4kmozAc+qPLzplhBgfw1vLItbjyHzUN92UXicw==", "dev": true, "requires": { - "@jest/test-result": "^29.4.2", + "@jest/test-result": "^29.4.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.2", + "jest-haste-map": "^29.4.3", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.2.tgz", - "integrity": "sha512-kf1v5iTJHn7p9RbOsBuc/lcwyPtJaZJt5885C98omWz79NIeD3PfoiiaPSu7JyCyFzNOIzKhmMhQLUhlTL9BvQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.3.tgz", + "integrity": "sha512-8u0+fBGWolDshsFgPQJESkDa72da/EVwvL+II0trN2DR66wMwiQ9/CihaGfHdlLGFzbBZwMykFtxuwFdZqlKwg==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.2", - "jest-regex-util": "^29.4.2", - "jest-util": "^29.4.2", + "jest-haste-map": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.4.3", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -6520,12 +6519,12 @@ } }, "@jest/types": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.2.tgz", - "integrity": "sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.3.tgz", + "integrity": "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==", "dev": true, "requires": { - "@jest/schemas": "^29.4.2", + "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -6598,9 +6597,9 @@ } }, "@sinclair/typebox": { - "version": "0.25.21", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.21.tgz", - "integrity": "sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g==", + "version": "0.25.23", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.23.tgz", + "integrity": "sha512-VEB8ygeP42CFLWyAJhN5OklpxUliqdNEUcXb4xZ/CINqtYGTjL5ukluKdKzQ0iWdUxyQ7B0539PAUhHKrCNWSQ==", "dev": true }, "@sinonjs/commons": { @@ -6974,15 +6973,15 @@ "dev": true }, "babel-jest": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.2.tgz", - "integrity": "sha512-vcghSqhtowXPG84posYkkkzcZsdayFkubUgbE3/1tuGbX7AQtwCkkNA/wIbB0BMjuCPoqTkiDyKN7Ty7d3uwNQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.3.tgz", + "integrity": "sha512-o45Wyn32svZE+LnMVWv/Z4x0SwtLbh4FyGcYtR20kIWd+rdrDZ9Fzq8Ml3MYLD+mZvEdzCjZsCnYZ2jpJyQ+Nw==", "dev": true, "requires": { - "@jest/transform": "^29.4.2", + "@jest/transform": "^29.4.3", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.4.2", + "babel-preset-jest": "^29.4.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -7002,9 +7001,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.2.tgz", - "integrity": "sha512-5HZRCfMeWypFEonRbEkwWXtNS1sQK159LhRVyRuLzyfVBxDy/34Tr/rg4YVi0SScSJ4fqeaR/OIeceJ/LaQ0pQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.3.tgz", + "integrity": "sha512-mB6q2q3oahKphy5V7CpnNqZOCkxxZ9aokf1eh82Dy3jQmg4xvM1tGrh5y6BQUJh4a3Pj9+eLfwvAZ7VNKg7H8Q==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -7034,12 +7033,12 @@ } }, "babel-preset-jest": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.2.tgz", - "integrity": "sha512-ecWdaLY/8JyfUDr0oELBMpj3R5I1L6ZqG+kRJmwqfHtLWuPrJStR0LUkvUhfykJWTsXXMnohsayN/twltBbDrQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.3.tgz", + "integrity": "sha512-gWx6COtSuma6n9bw+8/F+2PCXrIgxV/D1TJFnp6OyBK2cxPWg0K9p/sriNYeifKjpUkMViWQ09DSWtzJQRETsw==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^29.4.2", + "babel-plugin-jest-hoist": "^29.4.3", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -7340,9 +7339,9 @@ "dev": true }, "diff-sequences": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.2.tgz", - "integrity": "sha512-R6P0Y6PrsH3n4hUXxL3nns0rbRk6Q33js3ygJBeEpbzLzgcNuJ61+u0RXasFpTKISw99TxUzFnumSnRLsjhLaw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", "dev": true }, "dir-glob": { @@ -7617,16 +7616,16 @@ "dev": true }, "expect": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.2.tgz", - "integrity": "sha512-+JHYg9O3hd3RlICG90OPVjRkPBoiUH7PxvDVMnRiaq1g6JUgZStX514erMl0v2Dc5SkfVbm7ztqbd6qHHPn+mQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.3.tgz", + "integrity": "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==", "dev": true, "requires": { - "@jest/expect-utils": "^29.4.2", - "jest-get-type": "^29.4.2", - "jest-matcher-utils": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-util": "^29.4.2" + "@jest/expect-utils": "^29.4.3", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-util": "^29.4.3" } }, "fast-deep-equal": { @@ -8137,21 +8136,21 @@ } }, "jest": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.2.tgz", - "integrity": "sha512-+5hLd260vNIHu+7ZgMIooSpKl7Jp5pHKb51e73AJU3owd5dEo/RfVwHbA/na3C/eozrt3hJOLGf96c7EWwIAzg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.3.tgz", + "integrity": "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA==", "dev": true, "requires": { - "@jest/core": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/core": "^29.4.3", + "@jest/types": "^29.4.3", "import-local": "^3.0.2", - "jest-cli": "^29.4.2" + "jest-cli": "^29.4.3" } }, "jest-changed-files": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.2.tgz", - "integrity": "sha512-Qdd+AXdqD16PQa+VsWJpxR3kN0JyOCX1iugQfx5nUgAsI4gwsKviXkpclxOK9ZnwaY2IQVHz+771eAvqeOlfuw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.3.tgz", + "integrity": "sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ==", "dev": true, "requires": { "execa": "^5.0.0", @@ -8159,204 +8158,204 @@ } }, "jest-circus": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.2.tgz", - "integrity": "sha512-wW3ztp6a2P5c1yOc1Cfrt5ozJ7neWmqeXm/4SYiqcSriyisgq63bwFj1NuRdSR5iqS0CMEYwSZd89ZA47W9zUg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.3.tgz", + "integrity": "sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw==", "dev": true, "requires": { - "@jest/environment": "^29.4.2", - "@jest/expect": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/environment": "^29.4.3", + "@jest/expect": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.4.2", - "jest-matcher-utils": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-runtime": "^29.4.2", - "jest-snapshot": "^29.4.2", - "jest-util": "^29.4.2", + "jest-each": "^29.4.3", + "jest-matcher-utils": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-runtime": "^29.4.3", + "jest-snapshot": "^29.4.3", + "jest-util": "^29.4.3", "p-limit": "^3.1.0", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.2.tgz", - "integrity": "sha512-b+eGUtXq/K2v7SH3QcJvFvaUaCDS1/YAZBYz0m28Q/Ppyr+1qNaHmVYikOrbHVbZqYQs2IeI3p76uy6BWbXq8Q==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.3.tgz", + "integrity": "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg==", "dev": true, "requires": { - "@jest/core": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/core": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/types": "^29.4.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.4.2", - "jest-util": "^29.4.2", - "jest-validate": "^29.4.2", + "jest-config": "^29.4.3", + "jest-util": "^29.4.3", + "jest-validate": "^29.4.3", "prompts": "^2.0.1", "yargs": "^17.3.1" } }, "jest-config": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.2.tgz", - "integrity": "sha512-919CtnXic52YM0zW4C1QxjG6aNueX1kBGthuMtvFtRTAxhKfJmiXC9qwHmi6o2josjbDz8QlWyY55F1SIVmCWA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.3.tgz", + "integrity": "sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.4.2", - "@jest/types": "^29.4.2", - "babel-jest": "^29.4.2", + "@jest/test-sequencer": "^29.4.3", + "@jest/types": "^29.4.3", + "babel-jest": "^29.4.3", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.4.2", - "jest-environment-node": "^29.4.2", - "jest-get-type": "^29.4.2", - "jest-regex-util": "^29.4.2", - "jest-resolve": "^29.4.2", - "jest-runner": "^29.4.2", - "jest-util": "^29.4.2", - "jest-validate": "^29.4.2", + "jest-circus": "^29.4.3", + "jest-environment-node": "^29.4.3", + "jest-get-type": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.4.3", + "jest-runner": "^29.4.3", + "jest-util": "^29.4.3", + "jest-validate": "^29.4.3", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" } }, "jest-diff": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.2.tgz", - "integrity": "sha512-EK8DSajVtnjx9sa1BkjZq3mqChm2Cd8rIzdXkQMA8e0wuXq53ypz6s5o5V8HRZkoEt2ywJ3eeNWFKWeYr8HK4g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.3.tgz", + "integrity": "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.2", - "jest-get-type": "^29.4.2", - "pretty-format": "^29.4.2" + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.4.3" } }, "jest-docblock": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.2.tgz", - "integrity": "sha512-dV2JdahgClL34Y5vLrAHde3nF3yo2jKRH+GIYJuCpfqwEJZcikzeafVTGAjbOfKPG17ez9iWXwUYp7yefeCRag==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", + "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.2.tgz", - "integrity": "sha512-trvKZb0JYiCndc55V1Yh0Luqi7AsAdDWpV+mKT/5vkpnnFQfuQACV72IoRV161aAr6kAVIBpmYzwhBzm34vQkA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.3.tgz", + "integrity": "sha512-1ElHNAnKcbJb/b+L+7j0/w7bDvljw4gTv1wL9fYOczeJrbTbkMGQ5iQPFJ3eFQH19VPTx1IyfePdqSpePKss7Q==", "dev": true, "requires": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.2", - "jest-util": "^29.4.2", - "pretty-format": "^29.4.2" + "jest-get-type": "^29.4.3", + "jest-util": "^29.4.3", + "pretty-format": "^29.4.3" } }, "jest-environment-node": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.2.tgz", - "integrity": "sha512-MLPrqUcOnNBc8zTOfqBbxtoa8/Ee8tZ7UFW7hRDQSUT+NGsvS96wlbHGTf+EFAT9KC3VNb7fWEM6oyvmxtE/9w==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.3.tgz", + "integrity": "sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg==", "dev": true, "requires": { - "@jest/environment": "^29.4.2", - "@jest/fake-timers": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/environment": "^29.4.3", + "@jest/fake-timers": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", - "jest-mock": "^29.4.2", - "jest-util": "^29.4.2" + "jest-mock": "^29.4.3", + "jest-util": "^29.4.3" } }, "jest-get-type": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.2.tgz", - "integrity": "sha512-vERN30V5i2N6lqlFu4ljdTqQAgrkTFMC9xaIIfOPYBw04pufjXRty5RuXBiB1d72tGbURa/UgoiHB90ruOSivg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "dev": true }, "jest-haste-map": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.2.tgz", - "integrity": "sha512-WkUgo26LN5UHPknkezrBzr7lUtV1OpGsp+NfXbBwHztsFruS3gz+AMTTBcEklvi8uPzpISzYjdKXYZQJXBnfvw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.3.tgz", + "integrity": "sha512-eZIgAS8tvm5IZMtKlR8Y+feEOMfo2pSQkmNbufdbMzMSn9nitgGxF1waM/+LbryO3OkMcKS98SUb+j/cQxp/vQ==", "dev": true, "requires": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.2", - "jest-util": "^29.4.2", - "jest-worker": "^29.4.2", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.4.3", + "jest-worker": "^29.4.3", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "jest-leak-detector": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.2.tgz", - "integrity": "sha512-Wa62HuRJmWXtX9F00nUpWlrbaH5axeYCdyRsOs/+Rb1Vb6+qWTlB5rKwCCRKtorM7owNwKsyJ8NRDUcZ8ghYUA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.3.tgz", + "integrity": "sha512-9yw4VC1v2NspMMeV3daQ1yXPNxMgCzwq9BocCwYrRgXe4uaEJPAN0ZK37nFBhcy3cUwEVstFecFLaTHpF7NiGA==", "dev": true, "requires": { - "jest-get-type": "^29.4.2", - "pretty-format": "^29.4.2" + "jest-get-type": "^29.4.3", + "pretty-format": "^29.4.3" } }, "jest-matcher-utils": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.2.tgz", - "integrity": "sha512-EZaAQy2je6Uqkrm6frnxBIdaWtSYFoR8SVb2sNLAtldswlR/29JAgx+hy67llT3+hXBaLB0zAm5UfeqerioZyg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz", + "integrity": "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.4.2", - "jest-get-type": "^29.4.2", - "pretty-format": "^29.4.2" + "jest-diff": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.4.3" } }, "jest-message-util": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.2.tgz", - "integrity": "sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.3.tgz", + "integrity": "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.2.tgz", - "integrity": "sha512-x1FSd4Gvx2yIahdaIKoBjwji6XpboDunSJ95RpntGrYulI1ByuYQCKN/P7hvk09JB74IonU3IPLdkutEWYt++g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.3.tgz", + "integrity": "sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg==", "dev": true, "requires": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/node": "*", - "jest-util": "^29.4.2" + "jest-util": "^29.4.3" } }, "jest-pnp-resolver": { @@ -8367,102 +8366,101 @@ "requires": {} }, "jest-regex-util": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.2.tgz", - "integrity": "sha512-XYZXOqUl1y31H6VLMrrUL1ZhXuiymLKPz0BO1kEeR5xER9Tv86RZrjTm74g5l9bPJQXA/hyLdaVPN/sdqfteig==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", + "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", "dev": true }, "jest-resolve": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.2.tgz", - "integrity": "sha512-RtKWW0mbR3I4UdkOrW7552IFGLYQ5AF9YrzD0FnIOkDu0rAMlA5/Y1+r7lhCAP4nXSBTaE7ueeqj6IOwZpgoqw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.3.tgz", + "integrity": "sha512-GPokE1tzguRyT7dkxBim4wSx6E45S3bOQ7ZdKEG+Qj0Oac9+6AwJPCk0TZh5Vu0xzeX4afpb+eDmgbmZFFwpOw==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.2", + "jest-haste-map": "^29.4.3", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.4.2", - "jest-validate": "^29.4.2", + "jest-util": "^29.4.3", + "jest-validate": "^29.4.3", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.2.tgz", - "integrity": "sha512-6pL4ptFw62rjdrPk7rRpzJYgcRqRZNsZTF1VxVTZMishbO6ObyWvX57yHOaNGgKoADtAHRFYdHQUEvYMJATbDg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.3.tgz", + "integrity": "sha512-uvKMZAQ3nmXLH7O8WAOhS5l0iWyT3WmnJBdmIHiV5tBbdaDZ1wqtNX04FONGoaFvSOSHBJxnwAVnSn1WHdGVaw==", "dev": true, "requires": { - "jest-regex-util": "^29.4.2", - "jest-snapshot": "^29.4.2" + "jest-regex-util": "^29.4.3", + "jest-snapshot": "^29.4.3" } }, "jest-runner": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.2.tgz", - "integrity": "sha512-wqwt0drm7JGjwdH+x1XgAl+TFPH7poowMguPQINYxaukCqlczAcNLJiK+OLxUxQAEWMdy+e6nHZlFHO5s7EuRg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.3.tgz", + "integrity": "sha512-GWPTEiGmtHZv1KKeWlTX9SIFuK19uLXlRQU43ceOQ2hIfA5yPEJC7AMkvFKpdCHx6pNEdOD+2+8zbniEi3v3gA==", "dev": true, "requires": { - "@jest/console": "^29.4.2", - "@jest/environment": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/console": "^29.4.3", + "@jest/environment": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.2", - "jest-environment-node": "^29.4.2", - "jest-haste-map": "^29.4.2", - "jest-leak-detector": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-resolve": "^29.4.2", - "jest-runtime": "^29.4.2", - "jest-util": "^29.4.2", - "jest-watcher": "^29.4.2", - "jest-worker": "^29.4.2", + "jest-docblock": "^29.4.3", + "jest-environment-node": "^29.4.3", + "jest-haste-map": "^29.4.3", + "jest-leak-detector": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-resolve": "^29.4.3", + "jest-runtime": "^29.4.3", + "jest-util": "^29.4.3", + "jest-watcher": "^29.4.3", + "jest-worker": "^29.4.3", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.2.tgz", - "integrity": "sha512-3fque9vtpLzGuxT9eZqhxi+9EylKK/ESfhClv4P7Y9sqJPs58LjVhTt8jaMp/pRO38agll1CkSu9z9ieTQeRrw==", - "dev": true, - "requires": { - "@jest/environment": "^29.4.2", - "@jest/fake-timers": "^29.4.2", - "@jest/globals": "^29.4.2", - "@jest/source-map": "^29.4.2", - "@jest/test-result": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.3.tgz", + "integrity": "sha512-F5bHvxSH+LvLV24vVB3L8K467dt3y3dio6V3W89dUz9nzvTpqd/HcT9zfYKL2aZPvD63vQFgLvaUX/UpUhrP6Q==", + "dev": true, + "requires": { + "@jest/environment": "^29.4.3", + "@jest/fake-timers": "^29.4.3", + "@jest/globals": "^29.4.3", + "@jest/source-map": "^29.4.3", + "@jest/test-result": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-mock": "^29.4.2", - "jest-regex-util": "^29.4.2", - "jest-resolve": "^29.4.2", - "jest-snapshot": "^29.4.2", - "jest-util": "^29.4.2", - "semver": "^7.3.5", + "jest-haste-map": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-mock": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.4.3", + "jest-snapshot": "^29.4.3", + "jest-util": "^29.4.3", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.2.tgz", - "integrity": "sha512-PdfubrSNN5KwroyMH158R23tWcAXJyx4pvSvWls1dHoLCaUhGul9rsL3uVjtqzRpkxlkMavQjGuWG1newPgmkw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.3.tgz", + "integrity": "sha512-NGlsqL0jLPDW91dz304QTM/SNO99lpcSYYAjNiX0Ou+sSGgkanKBcSjCfp/pqmiiO1nQaOyLp6XQddAzRcx3Xw==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -8471,33 +8469,33 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.4.2", - "@jest/transform": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/expect-utils": "^29.4.3", + "@jest/transform": "^29.4.3", + "@jest/types": "^29.4.3", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.4.2", + "expect": "^29.4.3", "graceful-fs": "^4.2.9", - "jest-diff": "^29.4.2", - "jest-get-type": "^29.4.2", - "jest-haste-map": "^29.4.2", - "jest-matcher-utils": "^29.4.2", - "jest-message-util": "^29.4.2", - "jest-util": "^29.4.2", + "jest-diff": "^29.4.3", + "jest-get-type": "^29.4.3", + "jest-haste-map": "^29.4.3", + "jest-matcher-utils": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-util": "^29.4.3", "natural-compare": "^1.4.0", - "pretty-format": "^29.4.2", + "pretty-format": "^29.4.3", "semver": "^7.3.5" } }, "jest-util": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.2.tgz", - "integrity": "sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.3.tgz", + "integrity": "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==", "dev": true, "requires": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -8506,17 +8504,17 @@ } }, "jest-validate": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.2.tgz", - "integrity": "sha512-tto7YKGPJyFbhcKhIDFq8B5od+eVWD/ySZ9Tvcp/NGCvYA4RQbuzhbwYWtIjMT5W5zA2W0eBJwu4HVw34d5G6Q==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.3.tgz", + "integrity": "sha512-J3u5v7aPQoXPzaar6GndAVhdQcZr/3osWSgTeKg5v574I9ybX/dTyH0AJFb5XgXIB7faVhf+rS7t4p3lL9qFaw==", "dev": true, "requires": { - "@jest/types": "^29.4.2", + "@jest/types": "^29.4.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.2", + "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.4.2" + "pretty-format": "^29.4.3" }, "dependencies": { "camelcase": { @@ -8528,29 +8526,29 @@ } }, "jest-watcher": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.2.tgz", - "integrity": "sha512-onddLujSoGiMJt+tKutehIidABa175i/Ays+QvKxCqBwp7fvxP3ZhKsrIdOodt71dKxqk4sc0LN41mWLGIK44w==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.3.tgz", + "integrity": "sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA==", "dev": true, "requires": { - "@jest/test-result": "^29.4.2", - "@jest/types": "^29.4.2", + "@jest/test-result": "^29.4.3", + "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.4.2", + "jest-util": "^29.4.3", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.2.tgz", - "integrity": "sha512-VIuZA2hZmFyRbchsUCHEehoSf2HEl0YVF8SDJqtPnKorAaBuh42V8QsLnde0XP5F6TyCynGPEGgBOn3Fc+wZGw==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.3.tgz", + "integrity": "sha512-GLHN/GTAAMEy5BFdvpUfzr9Dr80zQqBrh0fz1mtRMe05hqP45+HfQltu7oTBfduD0UeZs09d+maFtFYAXFWvAA==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.4.2", + "jest-util": "^29.4.3", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -9109,12 +9107,12 @@ "dev": true }, "pretty-format": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.2.tgz", - "integrity": "sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", + "integrity": "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==", "dev": true, "requires": { - "@jest/schemas": "^29.4.2", + "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -9766,9 +9764,9 @@ "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" }, "v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.12", diff --git a/package.json b/package.json index 5a8018ac18..bf82c4225d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.8", + "version": "3.11.9", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -99,7 +99,7 @@ "@typescript-eslint/parser": "^5.52.0", "eslint": "^8.34.0", "eslint-plugin-jest": "^27.2.1", - "jest": "^29.4.2", + "jest": "^29.4.3", "open-cli": "^7.1.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From 890a25954405dc7d66538ac6e00f161abfe86531 Mon Sep 17 00:00:00 2001 From: snnz Date: Fri, 17 Feb 2023 20:12:48 +0300 Subject: [PATCH 016/525] Download and use MSYS/make locally for Windows postinstall (#792) --- npm-scripts.js | 44 ++++++++++++++++++++++++++++++++++++- worker/build.rs | 35 ++++++++++++++++++++++++++++- worker/scripts/cpu_cores.sh | 3 ++- worker/scripts/getmake.py | 17 ++++++++++++++ 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 worker/scripts/getmake.py diff --git a/npm-scripts.js b/npm-scripts.js index 66ce1e5001..2e8a8ab4b5 100644 --- a/npm-scripts.js +++ b/npm-scripts.js @@ -3,7 +3,7 @@ const process = require('process'); const os = require('os'); const fs = require('fs'); -const { execSync } = require('child_process'); +const { execSync, spawnSync } = require('child_process'); const { version } = require('./package.json'); const isFreeBSD = os.platform() === 'freebsd'; @@ -227,6 +227,21 @@ function buildWorker() { console.log('npm-scripts.js [INFO] buildWorker()'); + if (isWindows) + { + if (!fs.existsSync('worker/out/msys/bin/make.exe')) + { + installMsysMake(); + } + + const msysPath = `${process.cwd()}\\worker\\out\\msys\\bin`; + + if (!process.env['PATH'].includes(msysPath)) + { + process.env['PATH'] = `${msysPath};${process.env['PATH']}`; + } + } + executeCmd(`${MAKE} -C worker`); } @@ -240,6 +255,11 @@ function cleanWorker() executeCmd(`${MAKE} clean-subprojects -C worker`); // Clean PIP/Meson/Ninja. executeCmd(`${MAKE} clean-pip -C worker`); + + if (isWindows) + { + executeCmd('rd /s /q worker\\out\\msys'); + } } function lintNode() @@ -323,3 +343,25 @@ function executeCmd(command, exitOnError = true) } } } + +function installMsysMake() +{ + console.log('npm-scripts.js [INFO] installMsysMake()'); + + let res = spawnSync('where', [ 'python3.exe' ]); + + if (res.status !== 0) + { + res = spawnSync('where', [ 'python.exe' ]); + + if (res.status !== 0) + { + // eslint-disable-next-line no-console + console.error('`npm-scripts.js [ERROR] installMsysMake() cannot find Python executable'); + + process.exit(1); + } + } + + executeCmd(`${String(res.stdout).trim()} worker\\scripts\\getmake.py`); +} diff --git a/worker/build.rs b/worker/build.rs index 1686acf30c..7d2264bfaf 100644 --- a/worker/build.rs +++ b/worker/build.rs @@ -77,7 +77,40 @@ fn main() { } #[cfg(target_os = "windows")] { - // Nothing special is needed so far + if !std::path::Path::new("worker/out/msys/bin/make.exe").exists() { + let python = if Command::new("where") + .arg("python3.exe") + .status() + .expect("Failed to start") + .success() + { + "python3" + } else { + "python" + }; + + if !Command::new(python) + .arg("scripts\\getmake.py") + .status() + .expect("Failed to start") + .success() + { + panic!("Failed to install MSYS/make") + } + } + + env::set_var( + "PATH", + format!( + "{}\\worker\\out\\msys\\bin;{}", + env::current_dir() + .unwrap() + .into_os_string() + .into_string() + .unwrap(), + env::var("PATH").unwrap() + ), + ); } // Build diff --git a/worker/scripts/cpu_cores.sh b/worker/scripts/cpu_cores.sh index e507b693d5..b5cdde81d0 100755 --- a/worker/scripts/cpu_cores.sh +++ b/worker/scripts/cpu_cores.sh @@ -6,8 +6,9 @@ OS="$(uname -s)" NUM_CORES= case "${OS}" in - Linux*|MINGW*) NUM_CORES=$(nproc);; + Linux*) NUM_CORES=$(nproc);; Darwin*|FreeBSD) NUM_CORES=$(sysctl -n hw.ncpu);; + MINGW*) NUM_CORES=$NUMBER_OF_PROCESSORS;; *) NUM_CORES=1;; esac diff --git a/worker/scripts/getmake.py b/worker/scripts/getmake.py new file mode 100644 index 0000000000..c6c0dbb9a3 --- /dev/null +++ b/worker/scripts/getmake.py @@ -0,0 +1,17 @@ +import io, hashlib, tarfile, urllib.request + +def get(url, digest): + data = urllib.request.urlopen(url).read() + assert hashlib.sha256(data).hexdigest() == digest + tar = tarfile.open(fileobj=io.BytesIO(data)) + tar.extractall('worker/out/msys') + tar.close() + +get('https://sourceforge.net/projects/mingw/files/MSYS/Base/msys-core/msys-1.0.19-1/msysCORE-1.0.19-1-msys-1.0.19-bin.tar.xz/download', '8c4157d739a460f85563bc4451e9f1bbd42b13c4f63770d43b9f45a781f07858') +get('https://sourceforge.net/projects/mingw/files/MSYS/Base/libiconv/libiconv-1.14-1/libiconv-1.14-1-msys-1.0.17-dll-2.tar.lzma/download', '196921e8c232259c8e6a6852b9ee8d9ab2d29a91419f0c8dc27ba6f034231683') +get('https://sourceforge.net/projects/mingw/files/MSYS/Base/gettext/gettext-0.18.1.1-1/libintl-0.18.1.1-1-msys-1.0.17-dll-8.tar.lzma/download', '29db8c969661c511fbe2a341ab25c993c5f9c555842a75d6ddbcfa70dec16910') +get('https://sourceforge.net/projects/mingw/files/MSYS/Base/coreutils/coreutils-5.97-3/coreutils-5.97-3-msys-1.0.13-bin.tar.lzma/download', 'f8c7990416ea16a74ac336dcfe0f596bc46b8724b2d58cf8a3509414220b2366') +get('https://sourceforge.net/projects/mingw/files/MSYS/Base/regex/regex-1.20090805-2/libregex-1.20090805-2-msys-1.0.13-dll-1.tar.lzma/download', '85dd8c1e27a90675c5f867be57ba7ae2bb55dde8cd2d19f284c896be134bd3d1') +get('https://sourceforge.net/projects/mingw/files/MSYS/Base/termcap/termcap-0.20050421_1-2/libtermcap-0.20050421_1-2-msys-1.0.13-dll-0.tar.lzma/download', '62b58fe0880f0972fcc84a819265989b02439c1c5185870227bd25f870f7adb6') +get('https://sourceforge.net/projects/mingw/files/MSYS/Base/bash/bash-3.1.23-1/bash-3.1.23-1-msys-1.0.18-bin.tar.xz/download', '38da5419969ab883058a96322bb0f51434dd4e9f71de09cd4f75b96750944533') +get('https://sourceforge.net/projects/mingw/files/MSYS/Base/make/make-3.81-3/make-3.81-3-msys-1.0.13-bin.tar.lzma/download', '847f0cbbf07135801c8e67bf692d29b1821e816ad828753c997fa869a9b89988') From 95ab16ad40f425a2bcc3e922724ea7d611cc2302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Feb 2023 18:17:37 +0100 Subject: [PATCH 017/525] 3.11.10 --- CHANGELOG.md | 4 +++- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c540f92c20..481e9dda95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ # Changelog -### Next +### 3.11.10 + +* Download and use MSYS/make locally for Windows postinstall ([PR #792](https://github.com/versatica/mediasoup/pull/792) by @snnz). ### 3.11.9 diff --git a/package-lock.json b/package-lock.json index 34cac63916..16631444e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.9", + "version": "3.11.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.9", + "version": "3.11.10", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index bf82c4225d..013d955411 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.9", + "version": "3.11.10", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 3c8a6a67844d81820effdd63712993ff35aff9b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Feb 2023 11:18:38 +0100 Subject: [PATCH 018/525] Update NPM deps --- CHANGELOG.md | 5 ++ package-lock.json | 178 +++++++++++++++++++++++----------------------- package.json | 6 +- 3 files changed, 97 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 481e9dda95..101953b44f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +* Update NPM deps. + + ### 3.11.10 * Download and use MSYS/make locally for Windows postinstall ([PR #792](https://github.com/versatica/mediasoup/pull/792) by @snnz). diff --git a/package-lock.json b/package-lock.json index 16631444e8..4f41b3662f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,10 +18,10 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.13.0", + "@types/node": "^18.14.0", "@types/uuid": "^9.0.0", - "@typescript-eslint/eslint-plugin": "^5.52.0", - "@typescript-eslint/parser": "^5.52.0", + "@typescript-eslint/eslint-plugin": "^5.53.0", + "@typescript-eslint/parser": "^5.53.0", "eslint": "^8.34.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.4.3", @@ -1308,9 +1308,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", - "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", + "version": "18.14.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", + "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1359,14 +1359,14 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz", - "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.53.0.tgz", + "integrity": "sha512-alFpFWNucPLdUOySmXCJpzr6HKC3bu7XooShWM+3w/EL6J2HIoB2PFxpLnq4JauWVk6DiVeNKzQlFEaE+X9sGw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.52.0", - "@typescript-eslint/type-utils": "5.52.0", - "@typescript-eslint/utils": "5.52.0", + "@typescript-eslint/scope-manager": "5.53.0", + "@typescript-eslint/type-utils": "5.53.0", + "@typescript-eslint/utils": "5.53.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1393,14 +1393,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", - "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz", + "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.52.0", - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/scope-manager": "5.53.0", + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/typescript-estree": "5.53.0", "debug": "^4.3.4" }, "engines": { @@ -1420,13 +1420,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", - "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz", + "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/visitor-keys": "5.52.0" + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/visitor-keys": "5.53.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1437,13 +1437,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz", - "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.53.0.tgz", + "integrity": "sha512-HO2hh0fmtqNLzTAme/KnND5uFNwbsdYhCZghK2SoxGp3Ifn2emv+hi0PBUjzzSh0dstUIFqOj3bp0AwQlK4OWw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.52.0", - "@typescript-eslint/utils": "5.52.0", + "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/utils": "5.53.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1464,9 +1464,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", - "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz", + "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1477,13 +1477,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", - "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz", + "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/visitor-keys": "5.52.0", + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/visitor-keys": "5.53.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1504,16 +1504,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz", - "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.53.0.tgz", + "integrity": "sha512-VUOOtPv27UNWLxFwQK/8+7kvxVC+hPHNsJjzlJyotlaHjLSIgOCKj9I0DBUjwOOA64qjBwx5afAPjksqOxMO0g==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.52.0", - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/scope-manager": "5.53.0", + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/typescript-estree": "5.53.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -1530,12 +1530,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", - "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz", + "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/types": "5.53.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -6738,9 +6738,9 @@ "dev": true }, "@types/node": { - "version": "18.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", - "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", + "version": "18.14.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", + "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==", "dev": true }, "@types/normalize-package-data": { @@ -6789,14 +6789,14 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz", - "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.53.0.tgz", + "integrity": "sha512-alFpFWNucPLdUOySmXCJpzr6HKC3bu7XooShWM+3w/EL6J2HIoB2PFxpLnq4JauWVk6DiVeNKzQlFEaE+X9sGw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.52.0", - "@typescript-eslint/type-utils": "5.52.0", - "@typescript-eslint/utils": "5.52.0", + "@typescript-eslint/scope-manager": "5.53.0", + "@typescript-eslint/type-utils": "5.53.0", + "@typescript-eslint/utils": "5.53.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -6807,53 +6807,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", - "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz", + "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.52.0", - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/scope-manager": "5.53.0", + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/typescript-estree": "5.53.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", - "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz", + "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==", "dev": true, "requires": { - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/visitor-keys": "5.52.0" + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/visitor-keys": "5.53.0" } }, "@typescript-eslint/type-utils": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz", - "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.53.0.tgz", + "integrity": "sha512-HO2hh0fmtqNLzTAme/KnND5uFNwbsdYhCZghK2SoxGp3Ifn2emv+hi0PBUjzzSh0dstUIFqOj3bp0AwQlK4OWw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.52.0", - "@typescript-eslint/utils": "5.52.0", + "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/utils": "5.53.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", - "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz", + "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", - "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz", + "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==", "dev": true, "requires": { - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/visitor-keys": "5.52.0", + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/visitor-keys": "5.53.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -6862,28 +6862,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz", - "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.53.0.tgz", + "integrity": "sha512-VUOOtPv27UNWLxFwQK/8+7kvxVC+hPHNsJjzlJyotlaHjLSIgOCKj9I0DBUjwOOA64qjBwx5afAPjksqOxMO0g==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.52.0", - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/scope-manager": "5.53.0", + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/typescript-estree": "5.53.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", - "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz", + "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==", "dev": true, "requires": { - "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/types": "5.53.0", "eslint-visitor-keys": "^3.3.0" } }, diff --git a/package.json b/package.json index 013d955411..55507c2f2e 100644 --- a/package.json +++ b/package.json @@ -93,10 +93,10 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.13.0", + "@types/node": "^18.14.0", "@types/uuid": "^9.0.0", - "@typescript-eslint/eslint-plugin": "^5.52.0", - "@typescript-eslint/parser": "^5.52.0", + "@typescript-eslint/eslint-plugin": "^5.53.0", + "@typescript-eslint/parser": "^5.53.0", "eslint": "^8.34.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.4.3", From 80c0f336c41e000bf4a1a970bade6c318c04c229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Feb 2023 12:08:15 +0100 Subject: [PATCH 019/525] Node ESLint: require curly everywhere --- node/.eslintrc.js | 1 + node/src/ActiveSpeakerObserver.ts | 2 + node/src/Channel.ts | 10 ++ node/src/Consumer.ts | 20 +++ node/src/DataConsumer.ts | 12 ++ node/src/DataProducer.ts | 8 + node/src/DirectTransport.ts | 6 + node/src/PayloadChannel.ts | 18 ++ node/src/PipeTransport.ts | 14 ++ node/src/PlainTransport.ts | 12 ++ node/src/Producer.ts | 8 + node/src/Router.ts | 54 ++++++ node/src/RtpObserver.ts | 12 ++ node/src/Transport.ts | 42 +++++ node/src/WebRtcServer.ts | 4 + node/src/WebRtcTransport.ts | 14 ++ node/src/Worker.ts | 26 +++ node/src/errors.ts | 8 + node/src/index.ts | 2 + node/src/ortc.ts | 218 +++++++++++++++++++++++++ node/src/tests/test-DirectTransport.ts | 6 + node/src/tests/test-PipeTransport.ts | 8 + node/src/tests/test-Worker.ts | 2 + node/src/tests/test-node-sctp.ts | 2 + node/src/utils.ts | 8 +- 25 files changed, 515 insertions(+), 2 deletions(-) diff --git a/node/.eslintrc.js b/node/.eslintrc.js index 1fd2b5775c..f681e15d1c 100644 --- a/node/.eslintrc.js +++ b/node/.eslintrc.js @@ -44,6 +44,7 @@ const eslintConfig = 'comma-style' : 2, 'computed-property-spacing' : 2, 'constructor-super' : 2, + 'curly' : [ 2, 'all' ], 'func-call-spacing' : 2, 'generator-star-spacing' : 2, 'guard-for-in' : 2, diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index 063853c882..f5ebd29337 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -71,7 +71,9 @@ export class ActiveSpeakerObserver extends RtpObserver MESSAGE_MAX_LEN) + { throw new Error('Channel request too big'); + } // This may throw if closed or remote side ended. this.#producerSocket.write( @@ -253,14 +259,18 @@ export class Channel extends EnhancedEventEmitter resolve : (data2) => { if (!this.#sents.delete(id)) + { return; + } pResolve(data2); }, reject : (error) => { if (!this.#sents.delete(id)) + { return; + } pReject(error); }, diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 23c5d47a07..1dc32ec5e3 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -421,7 +421,9 @@ export class Consumer extends EnhancedEventEmitter close(): void { if (this.#closed) + { return; + } logger.debug('close()'); @@ -450,7 +452,9 @@ export class Consumer extends EnhancedEventEmitter transportClosed(): void { if (this.#closed) + { return; + } logger.debug('transportClosed()'); @@ -501,7 +505,9 @@ export class Consumer extends EnhancedEventEmitter // Emit observer event. if (!wasPaused) + { this.#observer.safeEmit('pause'); + } } /** @@ -519,7 +525,9 @@ export class Consumer extends EnhancedEventEmitter // Emit observer event. if (wasPaused && !this.#producerPaused) + { this.#observer.safeEmit('resume'); + } } /** @@ -604,7 +612,9 @@ export class Consumer extends EnhancedEventEmitter case 'producerclose': { if (this.#closed) + { break; + } this.#closed = true; @@ -624,7 +634,9 @@ export class Consumer extends EnhancedEventEmitter case 'producerpause': { if (this.#producerPaused) + { break; + } const wasPaused = this.#paused || this.#producerPaused; @@ -634,7 +646,9 @@ export class Consumer extends EnhancedEventEmitter // Emit observer event. if (!wasPaused) + { this.#observer.safeEmit('pause'); + } break; } @@ -642,7 +656,9 @@ export class Consumer extends EnhancedEventEmitter case 'producerresume': { if (!this.#producerPaused) + { break; + } const wasPaused = this.#paused || this.#producerPaused; @@ -652,7 +668,9 @@ export class Consumer extends EnhancedEventEmitter // Emit observer event. if (wasPaused && !this.#paused) + { this.#observer.safeEmit('resume'); + } break; } @@ -713,7 +731,9 @@ export class Consumer extends EnhancedEventEmitter case 'rtp': { if (this.#closed) + { break; + } const packet = payload; diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index bad2dd11ad..79f1742a56 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -233,7 +233,9 @@ export class DataConsumer extends EnhancedEventEmitter close(): void { if (this.#closed) + { return; + } logger.debug('close()'); @@ -262,7 +264,9 @@ export class DataConsumer extends EnhancedEventEmitter transportClosed(): void { if (this.#closed) + { return; + } logger.debug('transportClosed()'); @@ -346,9 +350,13 @@ export class DataConsumer extends EnhancedEventEmitter // Ensure we honor PPIDs. if (ppid === 56) + { message = ' '; + } else if (ppid === 57) + { message = Buffer.alloc(1); + } const requestData = String(ppid); @@ -378,7 +386,9 @@ export class DataConsumer extends EnhancedEventEmitter case 'dataproducerclose': { if (this.#closed) + { break; + } this.#closed = true; @@ -427,7 +437,9 @@ export class DataConsumer extends EnhancedEventEmitter case 'message': { if (this.#closed) + { break; + } const ppid = data.ppid as number; const message = payload; diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 6a99288348..7d48eb8eb9 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -210,7 +210,9 @@ export class DataProducer extends EnhancedEventEmitter close(): void { if (this.#closed) + { return; + } logger.debug('close()'); @@ -239,7 +241,9 @@ export class DataProducer extends EnhancedEventEmitter transportClosed(): void { if (this.#closed) + { return; + } logger.debug('transportClosed()'); @@ -310,9 +314,13 @@ export class DataProducer extends EnhancedEventEmitter // Ensure we honor PPIDs. if (ppid === 56) + { message = ' '; + } else if (ppid === 57) + { message = Buffer.alloc(1); + } const notifData = String(ppid); diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 0b7f7ea865..34ac3789ca 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -101,7 +101,9 @@ export class DirectTransport extends close(): void { if (this.closed) + { return; + } super.close(); } @@ -115,7 +117,9 @@ export class DirectTransport extends routerClosed(): void { if (this.closed) + { return; + } super.routerClosed(); } @@ -210,7 +214,9 @@ export class DirectTransport extends case 'rtcp': { if (this.closed) + { break; + } const packet = payload; diff --git a/node/src/PayloadChannel.ts b/node/src/PayloadChannel.ts index 2b5d83b412..d8f8074703 100644 --- a/node/src/PayloadChannel.ts +++ b/node/src/PayloadChannel.ts @@ -146,7 +146,9 @@ export class PayloadChannel extends EnhancedEventEmitter close(): void { if (this.#closed) + { return; + } logger.debug('close()'); @@ -185,14 +187,20 @@ export class PayloadChannel extends EnhancedEventEmitter logger.debug('notify() [event:%s]', event); if (this.#closed) + { throw new InvalidStateError('PayloadChannel closed'); + } const notification = `n:${event}:${handlerId}:${data}`; if (Buffer.byteLength(notification) > MESSAGE_MAX_LEN) + { throw new Error('PayloadChannel notification too big'); + } else if (Buffer.byteLength(payload) > MESSAGE_MAX_LEN) + { throw new Error('PayloadChannel payload too big'); + } try { @@ -239,14 +247,20 @@ export class PayloadChannel extends EnhancedEventEmitter logger.debug('request() [method:%s, id:%s]', method, id); if (this.#closed) + { throw new InvalidStateError('PayloadChannel closed'); + } const request = `r:${id}:${method}:${handlerId}:${data}`; if (Buffer.byteLength(request) > MESSAGE_MAX_LEN) + { throw new Error('PayloadChannel request too big'); + } else if (Buffer.byteLength(payload) > MESSAGE_MAX_LEN) + { throw new Error('PayloadChannel payload too big'); + } // This may throw if closed or remote side ended. this.#producerSocket.write( @@ -265,14 +279,18 @@ export class PayloadChannel extends EnhancedEventEmitter resolve : (data2) => { if (!this.#sents.delete(id)) + { return; + } pResolve(data2); }, reject : (error) => { if (!this.#sents.delete(id)) + { return; + } pReject(error); }, diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index e9fadbd6e5..d9d8417631 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -206,10 +206,14 @@ export class PipeTransport close(): void { if (this.closed) + { return; + } if (this.#data.sctpState) + { this.#data.sctpState = 'closed'; + } super.close(); } @@ -223,10 +227,14 @@ export class PipeTransport routerClosed(): void { if (this.closed) + { return; + } if (this.#data.sctpState) + { this.#data.sctpState = 'closed'; + } super.routerClosed(); } @@ -282,14 +290,20 @@ export class PipeTransport logger.debug('consume()'); if (!producerId || typeof producerId !== 'string') + { throw new TypeError('missing producerId'); + } else if (appData && typeof appData !== 'object') + { throw new TypeError('if given, appData must be an object'); + } const producer = this.getProducerById(producerId); if (!producer) + { throw Error(`Producer with id "${producerId}" not found`); + } // This may throw. const rtpParameters = ortc.getPipeConsumerRtpParameters( diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index 4286d34c95..256d504950 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -220,10 +220,14 @@ export class PlainTransport extends close(): void { if (this.closed) + { return; + } if (this.#data.sctpState) + { this.#data.sctpState = 'closed'; + } super.close(); } @@ -237,10 +241,14 @@ export class PlainTransport extends routerClosed(): void { if (this.closed) + { return; + } if (this.#data.sctpState) + { this.#data.sctpState = 'closed'; + } super.routerClosed(); } @@ -286,10 +294,14 @@ export class PlainTransport extends // Update data. if (data.tuple) + { this.#data.tuple = data.tuple; + } if (data.rtcpTuple) + { this.#data.rtcpTuple = data.rtcpTuple; + } this.#data.srtpParameters = data.srtpParameters; } diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 95ec93d265..0046b6f672 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -346,7 +346,9 @@ export class Producer extends EnhancedEventEmitter close(): void { if (this.#closed) + { return; + } logger.debug('close()'); @@ -375,7 +377,9 @@ export class Producer extends EnhancedEventEmitter transportClosed(): void { if (this.#closed) + { return; + } logger.debug('transportClosed()'); @@ -426,7 +430,9 @@ export class Producer extends EnhancedEventEmitter // Emit observer event. if (!wasPaused) + { this.#observer.safeEmit('pause'); + } } /** @@ -444,7 +450,9 @@ export class Producer extends EnhancedEventEmitter // Emit observer event. if (wasPaused) + { this.#observer.safeEmit('resume'); + } } /** diff --git a/node/src/Router.ts b/node/src/Router.ts index 0c5bff2ddd..b954f931bb 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -262,7 +262,9 @@ export class Router extends EnhancedEventEmitter close(): void { if (this.#closed) + { return; + } logger.debug('close()'); @@ -307,7 +309,9 @@ export class Router extends EnhancedEventEmitter workerClosed(): void { if (this.#closed) + { return; + } logger.debug('workerClosed()'); @@ -373,9 +377,13 @@ export class Router extends EnhancedEventEmitter logger.debug('createWebRtcTransport()'); if (!webRtcServer && !Array.isArray(listenIps)) + { throw new TypeError('missing webRtcServer and listenIps (one of them is mandatory)'); + } else if (appData && typeof appData !== 'object') + { throw new TypeError('if given, appData must be an object'); + } if (listenIps) { @@ -454,7 +462,9 @@ export class Router extends EnhancedEventEmitter )); if (webRtcServer) + { webRtcServer.handleWebRtcTransport(transport); + } // Emit observer event. this.#observer.safeEmit('newtransport', transport); @@ -484,9 +494,13 @@ export class Router extends EnhancedEventEmitter logger.debug('createPlainTransport()'); if (!listenIp) + { throw new TypeError('missing listenIp'); + } else if (appData && typeof appData !== 'object') + { throw new TypeError('if given, appData must be an object'); + } if (typeof listenIp === 'string' && listenIp) { @@ -582,9 +596,13 @@ export class Router extends EnhancedEventEmitter logger.debug('createPipeTransport()'); if (!listenIp) + { throw new TypeError('missing listenIp'); + } else if (appData && typeof appData !== 'object') + { throw new TypeError('if given, appData must be an object'); + } if (typeof listenIp === 'string' && listenIp) { @@ -740,13 +758,21 @@ export class Router extends EnhancedEventEmitter logger.debug('pipeToRouter()'); if (!producerId && !dataProducerId) + { throw new TypeError('missing producerId or dataProducerId'); + } else if (producerId && dataProducerId) + { throw new TypeError('just producerId or dataProducerId can be given'); + } else if (!router) + { throw new TypeError('Router not found'); + } else if (router === this) + { throw new TypeError('cannot use this Router as destination'); + } let producer: Producer | undefined; let dataProducer: DataProducer | undefined; @@ -756,14 +782,18 @@ export class Router extends EnhancedEventEmitter producer = this.#producers.get(producerId); if (!producer) + { throw new TypeError('Producer not found'); + } } else if (dataProducerId) { dataProducer = this.#dataProducers.get(dataProducerId); if (!dataProducer) + { throw new TypeError('DataProducer not found'); + } } const pipeTransportPairKey = router.id; @@ -842,10 +872,14 @@ export class Router extends EnhancedEventEmitter error); if (localPipeTransport) + { localPipeTransport.close(); + } if (remotePipeTransport) + { remotePipeTransport.close(); + } reject(error); }); @@ -882,16 +916,22 @@ export class Router extends EnhancedEventEmitter // Ensure that the producer has not been closed in the meanwhile. if (producer.closed) + { throw new InvalidStateError('original Producer closed'); + } // Ensure that producer.paused has not changed in the meanwhile and, if // so, sync the pipeProducer. if (pipeProducer.paused !== producer.paused) { if (producer.paused) + { await pipeProducer.pause(); + } else + { await pipeProducer.resume(); + } } // Pipe events from the pipe Consumer to the pipe Producer. @@ -911,10 +951,14 @@ export class Router extends EnhancedEventEmitter error); if (pipeConsumer) + { pipeConsumer.close(); + } if (pipeProducer) + { pipeProducer.close(); + } throw error; } @@ -942,7 +986,9 @@ export class Router extends EnhancedEventEmitter // Ensure that the dataProducer has not been closed in the meanwhile. if (dataProducer.closed) + { throw new InvalidStateError('original DataProducer closed'); + } // Pipe events from the pipe DataConsumer to the pipe DataProducer. pipeDataConsumer!.observer.on('close', () => pipeDataProducer!.close()); @@ -959,10 +1005,14 @@ export class Router extends EnhancedEventEmitter error); if (pipeDataConsumer) + { pipeDataConsumer.close(); + } if (pipeDataProducer) + { pipeDataProducer.close(); + } throw error; } @@ -1023,7 +1073,9 @@ export class Router extends EnhancedEventEmitter logger.debug('createActiveSpeakerObserver()'); if (appData && typeof appData !== 'object') + { throw new TypeError('if given, appData must be an object'); + } const reqData = { @@ -1075,7 +1127,9 @@ export class Router extends EnhancedEventEmitter logger.debug('createAudioLevelObserver()'); if (appData && typeof appData !== 'object') + { throw new TypeError('if given, appData must be an object'); + } const reqData = { diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index d2cd7257d7..324fc3313f 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -151,7 +151,9 @@ export class RtpObserver close(): void { if (this.#closed) + { return; + } logger.debug('close()'); @@ -180,7 +182,9 @@ export class RtpObserver routerClosed(): void { if (this.#closed) + { return; + } logger.debug('routerClosed()'); @@ -211,7 +215,9 @@ export class RtpObserver // Emit observer event. if (!wasPaused) + { this.#observer.safeEmit('pause'); + } } /** @@ -229,7 +235,9 @@ export class RtpObserver // Emit observer event. if (wasPaused) + { this.#observer.safeEmit('resume'); + } } /** @@ -242,7 +250,9 @@ export class RtpObserver const producer = this.getProducerById(producerId); if (!producer) + { throw Error(`Producer with id "${producerId}" not found`); + } const reqData = { producerId }; @@ -262,7 +272,9 @@ export class RtpObserver const producer = this.getProducerById(producerId); if (!producer) + { throw Error(`Producer with id "${producerId}" not found`); + } const reqData = { producerId }; diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 839af7c8d9..ccabeaa293 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -280,7 +280,9 @@ export class Transport { this.dataConsumers.delete(dataConsumer.id); if (this.#sctpStreamIds) + { this.#sctpStreamIds[sctpStreamId] = 0; + } }); // Emit observer event. @@ -974,7 +1014,9 @@ export class Transport close(): void { if (this.#closed) + { return; + } logger.debug('close()'); @@ -197,7 +199,9 @@ export class WebRtcServer extends EnhancedEventEmitter workerClosed(): void { if (this.#closed) + { return; + } logger.debug('workerClosed()'); diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index e8733374bc..8e364fed2e 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -329,14 +329,18 @@ export class WebRtcTransport extends close(): void { if (this.closed) + { return; + } this.#data.iceState = 'closed'; this.#data.iceSelectedTuple = undefined; this.#data.dtlsState = 'closed'; if (this.#data.sctpState) + { this.#data.sctpState = 'closed'; + } super.close(); } @@ -350,14 +354,18 @@ export class WebRtcTransport extends routerClosed(): void { if (this.closed) + { return; + } this.#data.iceState = 'closed'; this.#data.iceSelectedTuple = undefined; this.#data.dtlsState = 'closed'; if (this.#data.sctpState) + { this.#data.sctpState = 'closed'; + } super.routerClosed(); } @@ -370,14 +378,18 @@ export class WebRtcTransport extends webRtcServerClosed(): void { if (this.closed) + { return; + } this.#data.iceState = 'closed'; this.#data.iceSelectedTuple = undefined; this.#data.dtlsState = 'closed'; if (this.#data.sctpState) + { this.#data.sctpState = 'closed'; + } super.listenServerClosed(); } @@ -471,7 +483,9 @@ export class WebRtcTransport extends this.#data.dtlsState = dtlsState; if (dtlsState === 'connected') + { this.#data.dtlsRemoteCert = dtlsRemoteCert; + } this.safeEmit('dtlsstatechange', dtlsState); diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 626c82000a..eefa9c8018 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -269,28 +269,42 @@ export class Worker extends EnhancedEventEmitter } if (typeof logLevel === 'string' && logLevel) + { spawnArgs.push(`--logLevel=${logLevel}`); + } for (const logTag of (Array.isArray(logTags) ? logTags : [])) { if (typeof logTag === 'string' && logTag) + { spawnArgs.push(`--logTag=${logTag}`); + } } if (typeof rtcMinPort === 'number' && !Number.isNaN(rtcMinPort)) + { spawnArgs.push(`--rtcMinPort=${rtcMinPort}`); + } if (typeof rtcMaxPort === 'number' && !Number.isNaN(rtcMaxPort)) + { spawnArgs.push(`--rtcMaxPort=${rtcMaxPort}`); + } if (typeof dtlsCertificateFile === 'string' && dtlsCertificateFile) + { spawnArgs.push(`--dtlsCertificateFile=${dtlsCertificateFile}`); + } if (typeof dtlsPrivateKeyFile === 'string' && dtlsPrivateKeyFile) + { spawnArgs.push(`--dtlsPrivateKeyFile=${dtlsPrivateKeyFile}`); + } if (typeof libwebrtcFieldTrials === 'string' && libwebrtcFieldTrials) + { spawnArgs.push(`--libwebrtcFieldTrials=${libwebrtcFieldTrials}`); + } logger.debug( 'spawning worker process: %s %s', spawnBin, spawnArgs.join(' ')); @@ -427,7 +441,9 @@ export class Worker extends EnhancedEventEmitter for (const line of buffer.toString('utf8').split('\n')) { if (line) + { workerLogger.debug(`(stdout) ${line}`); + } } }); @@ -437,7 +453,9 @@ export class Worker extends EnhancedEventEmitter for (const line of buffer.toString('utf8').split('\n')) { if (line) + { workerLogger.error(`(stderr) ${line}`); + } } }); } @@ -514,7 +532,9 @@ export class Worker extends EnhancedEventEmitter close(): void { if (this.#closed) + { return; + } logger.debug('close()'); @@ -605,7 +625,9 @@ export class Worker extends EnhancedEventEmitter logger.debug('createWebRtcServer()'); if (appData && typeof appData !== 'object') + { throw new TypeError('if given, appData must be an object'); + } const reqData = { @@ -643,7 +665,9 @@ export class Worker extends EnhancedEventEmitter logger.debug('createRouter()'); if (appData && typeof appData !== 'object') + { throw new TypeError('if given, appData must be an object'); + } // This may throw. const rtpCapabilities = ortc.generateRouterRtpCapabilities(mediaCodecs); @@ -677,7 +701,9 @@ export class Worker extends EnhancedEventEmitter private workerDied(error: Error): void { if (this.#closed) + { return; + } logger.debug(`died() [error:${error}]`); diff --git a/node/src/errors.ts b/node/src/errors.ts index 0dff994d6e..b28eba297c 100644 --- a/node/src/errors.ts +++ b/node/src/errors.ts @@ -10,9 +10,13 @@ export class UnsupportedError extends Error this.name = 'UnsupportedError'; if (Error.hasOwnProperty('captureStackTrace')) // Just in V8. + { Error.captureStackTrace(this, UnsupportedError); + } else + { this.stack = (new Error(message)).stack; + } } } @@ -28,8 +32,12 @@ export class InvalidStateError extends Error this.name = 'InvalidStateError'; if (Error.hasOwnProperty('captureStackTrace')) // Just in V8. + { Error.captureStackTrace(this, InvalidStateError); + } else + { this.stack = (new Error(message)).stack; + } } } diff --git a/node/src/index.ts b/node/src/index.ts index b3b5cf6965..83d7967760 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -54,7 +54,9 @@ export async function createWorker( logger.debug('createWorker()'); if (appData && typeof appData !== 'object') + { throw new TypeError('if given, appData must be an object'); + } const worker = new Worker( { diff --git a/node/src/ortc.ts b/node/src/ortc.ts index 5899715cf4..6c591fe2c5 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -54,13 +54,19 @@ const DynamicPayloadTypes = export function validateRtpCapabilities(caps: RtpCapabilities): void { if (typeof caps !== 'object') + { throw new TypeError('caps is not an object'); + } // codecs is optional. If unset, fill with an empty array. if (caps.codecs && !Array.isArray(caps.codecs)) + { throw new TypeError('caps.codecs is not an array'); + } else if (!caps.codecs) + { caps.codecs = []; + } for (const codec of caps.codecs) { @@ -69,9 +75,13 @@ export function validateRtpCapabilities(caps: RtpCapabilities): void // headerExtensions is optional. If unset, fill with an empty array. if (caps.headerExtensions && !Array.isArray(caps.headerExtensions)) + { throw new TypeError('caps.headerExtensions is not an array'); + } else if (!caps.headerExtensions) + { caps.headerExtensions = []; + } for (const ext of caps.headerExtensions) { @@ -89,33 +99,45 @@ export function validateRtpCodecCapability(codec: RtpCodecCapability): void const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i'); if (typeof codec !== 'object') + { throw new TypeError('codec is not an object'); + } // mimeType is mandatory. if (!codec.mimeType || typeof codec.mimeType !== 'string') + { throw new TypeError('missing codec.mimeType'); + } const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType); if (!mimeTypeMatch) + { throw new TypeError('invalid codec.mimeType'); + } // Just override kind with media component of mimeType. codec.kind = mimeTypeMatch[1].toLowerCase() as MediaKind; // preferredPayloadType is optional. if (codec.preferredPayloadType && typeof codec.preferredPayloadType !== 'number') + { throw new TypeError('invalid codec.preferredPayloadType'); + } // clockRate is mandatory. if (typeof codec.clockRate !== 'number') + { throw new TypeError('missing codec.clockRate'); + } // channels is optional. If unset, set it to 1 (just if audio). if (codec.kind === 'audio') { if (typeof codec.channels !== 'number') + { codec.channels = 1; + } } else { @@ -124,7 +146,9 @@ export function validateRtpCodecCapability(codec: RtpCodecCapability): void // parameters is optional. If unset, set it to an empty object. if (!codec.parameters || typeof codec.parameters !== 'object') + { codec.parameters = {}; + } for (const key of Object.keys(codec.parameters)) { @@ -146,13 +170,17 @@ export function validateRtpCodecCapability(codec: RtpCodecCapability): void if (key === 'apt') { if (typeof value !== 'number') + { throw new TypeError('invalid codec apt parameter'); + } } } // rtcpFeedback is optional. If unset, set it to an empty array. if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) + { codec.rtcpFeedback = []; + } for (const fb of codec.rtcpFeedback) { @@ -168,15 +196,21 @@ export function validateRtpCodecCapability(codec: RtpCodecCapability): void export function validateRtcpFeedback(fb: RtcpFeedback): void { if (typeof fb !== 'object') + { throw new TypeError('fb is not an object'); + } // type is mandatory. if (!fb.type || typeof fb.type !== 'string') + { throw new TypeError('missing fb.type'); + } // parameter is optional. If unset set it to an empty string. if (!fb.parameter || typeof fb.parameter !== 'string') + { fb.parameter = ''; + } } /** @@ -188,30 +222,46 @@ export function validateRtpHeaderExtension(ext: RtpHeaderExtension): void { if (typeof ext !== 'object') + { throw new TypeError('ext is not an object'); + } if (ext.kind !== 'audio' && ext.kind !== 'video') + { throw new TypeError('invalid ext.kind'); + } // uri is mandatory. if (!ext.uri || typeof ext.uri !== 'string') + { throw new TypeError('missing ext.uri'); + } // preferredId is mandatory. if (typeof ext.preferredId !== 'number') + { throw new TypeError('missing ext.preferredId'); + } // preferredEncrypt is optional. If unset set it to false. if (ext.preferredEncrypt && typeof ext.preferredEncrypt !== 'boolean') + { throw new TypeError('invalid ext.preferredEncrypt'); + } else if (!ext.preferredEncrypt) + { ext.preferredEncrypt = false; + } // direction is optional. If unset set it to sendrecv. if (ext.direction && typeof ext.direction !== 'string') + { throw new TypeError('invalid ext.direction'); + } else if (!ext.direction) + { ext.direction = 'sendrecv'; + } } /** @@ -222,15 +272,21 @@ export function validateRtpHeaderExtension(ext: RtpHeaderExtension): void export function validateRtpParameters(params: RtpParameters): void { if (typeof params !== 'object') + { throw new TypeError('params is not an object'); + } // mid is optional. if (params.mid && typeof params.mid !== 'string') + { throw new TypeError('params.mid is not a string'); + } // codecs is mandatory. if (!Array.isArray(params.codecs)) + { throw new TypeError('missing params.codecs'); + } for (const codec of params.codecs) { @@ -239,9 +295,13 @@ export function validateRtpParameters(params: RtpParameters): void // headerExtensions is optional. If unset, fill with an empty array. if (params.headerExtensions && !Array.isArray(params.headerExtensions)) + { throw new TypeError('params.headerExtensions is not an array'); + } else if (!params.headerExtensions) + { params.headerExtensions = []; + } for (const ext of params.headerExtensions) { @@ -250,9 +310,13 @@ export function validateRtpParameters(params: RtpParameters): void // encodings is optional. If unset, fill with an empty array. if (params.encodings && !Array.isArray(params.encodings)) + { throw new TypeError('params.encodings is not an array'); + } else if (!params.encodings) + { params.encodings = []; + } for (const encoding of params.encodings) { @@ -261,9 +325,13 @@ export function validateRtpParameters(params: RtpParameters): void // rtcp is optional. If unset, fill with an empty object. if (params.rtcp && typeof params.rtcp !== 'object') + { throw new TypeError('params.rtcp is not an object'); + } else if (!params.rtcp) + { params.rtcp = {}; + } validateRtcpParameters(params.rtcp); } @@ -278,24 +346,34 @@ export function validateRtpCodecParameters(codec: RtpCodecParameters): void const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i'); if (typeof codec !== 'object') + { throw new TypeError('codec is not an object'); + } // mimeType is mandatory. if (!codec.mimeType || typeof codec.mimeType !== 'string') + { throw new TypeError('missing codec.mimeType'); + } const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType); if (!mimeTypeMatch) + { throw new TypeError('invalid codec.mimeType'); + } // payloadType is mandatory. if (typeof codec.payloadType !== 'number') + { throw new TypeError('missing codec.payloadType'); + } // clockRate is mandatory. if (typeof codec.clockRate !== 'number') + { throw new TypeError('missing codec.clockRate'); + } const kind = mimeTypeMatch[1].toLowerCase() as MediaKind; @@ -303,7 +381,9 @@ export function validateRtpCodecParameters(codec: RtpCodecParameters): void if (kind === 'audio') { if (typeof codec.channels !== 'number') + { codec.channels = 1; + } } else { @@ -312,7 +392,9 @@ export function validateRtpCodecParameters(codec: RtpCodecParameters): void // parameters is optional. If unset, set it to an empty object. if (!codec.parameters || typeof codec.parameters !== 'object') + { codec.parameters = {}; + } for (const key of Object.keys(codec.parameters)) { @@ -334,13 +416,17 @@ export function validateRtpCodecParameters(codec: RtpCodecParameters): void if (key === 'apt') { if (typeof value !== 'number') + { throw new TypeError('invalid codec apt parameter'); + } } } // rtcpFeedback is optional. If unset, set it to an empty array. if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) + { codec.rtcpFeedback = []; + } for (const fb of codec.rtcpFeedback) { @@ -359,25 +445,37 @@ export function validateRtpHeaderExtensionParameters( { if (typeof ext !== 'object') + { throw new TypeError('ext is not an object'); + } // uri is mandatory. if (!ext.uri || typeof ext.uri !== 'string') + { throw new TypeError('missing ext.uri'); + } // id is mandatory. if (typeof ext.id !== 'number') + { throw new TypeError('missing ext.id'); + } // encrypt is optional. If unset set it to false. if (ext.encrypt && typeof ext.encrypt !== 'boolean') + { throw new TypeError('invalid ext.encrypt'); + } else if (!ext.encrypt) + { ext.encrypt = false; + } // parameters is optional. If unset, set it to an empty object. if (!ext.parameters || typeof ext.parameters !== 'object') + { ext.parameters = {}; + } for (const key of Object.keys(ext.parameters)) { @@ -390,7 +488,9 @@ export function validateRtpHeaderExtensionParameters( } if (typeof value !== 'string' && typeof value !== 'number') + { throw new TypeError('invalid header extension parameter'); + } } } @@ -402,15 +502,21 @@ export function validateRtpHeaderExtensionParameters( export function validateRtpEncodingParameters(encoding: RtpEncodingParameters): void { if (typeof encoding !== 'object') + { throw new TypeError('encoding is not an object'); + } // ssrc is optional. if (encoding.ssrc && typeof encoding.ssrc !== 'number') + { throw new TypeError('invalid encoding.ssrc'); + } // rid is optional. if (encoding.rid && typeof encoding.rid !== 'string') + { throw new TypeError('invalid encoding.rid'); + } // rtx is optional. if (encoding.rtx && typeof encoding.rtx !== 'object') @@ -421,16 +527,22 @@ export function validateRtpEncodingParameters(encoding: RtpEncodingParameters): { // RTX ssrc is mandatory if rtx is present. if (typeof encoding.rtx.ssrc !== 'number') + { throw new TypeError('missing encoding.rtx.ssrc'); + } } // dtx is optional. If unset set it to false. if (!encoding.dtx || typeof encoding.dtx !== 'boolean') + { encoding.dtx = false; + } // scalabilityMode is optional. if (encoding.scalabilityMode && typeof encoding.scalabilityMode !== 'string') + { throw new TypeError('invalid encoding.scalabilityMode'); + } } /** @@ -441,15 +553,21 @@ export function validateRtpEncodingParameters(encoding: RtpEncodingParameters): export function validateRtcpParameters(rtcp: RtcpParameters): void { if (typeof rtcp !== 'object') + { throw new TypeError('rtcp is not an object'); + } // cname is optional. if (rtcp.cname && typeof rtcp.cname !== 'string') + { throw new TypeError('invalid rtcp.cname'); + } // reducedSize is optional. If unset set it to true. if (!rtcp.reducedSize || typeof rtcp.reducedSize !== 'boolean') + { rtcp.reducedSize = true; + } } /** @@ -460,11 +578,15 @@ export function validateRtcpParameters(rtcp: RtcpParameters): void export function validateSctpCapabilities(caps: SctpCapabilities): void { if (typeof caps !== 'object') + { throw new TypeError('caps is not an object'); + } // numStreams is mandatory. if (!caps.numStreams || typeof caps.numStreams !== 'object') + { throw new TypeError('missing caps.numStreams'); + } validateNumSctpStreams(caps.numStreams); } @@ -477,15 +599,21 @@ export function validateSctpCapabilities(caps: SctpCapabilities): void export function validateNumSctpStreams(numStreams: NumSctpStreams): void { if (typeof numStreams !== 'object') + { throw new TypeError('numStreams is not an object'); + } // OS is mandatory. if (typeof numStreams.OS !== 'number') + { throw new TypeError('missing numStreams.OS'); + } // MIS is mandatory. if (typeof numStreams.MIS !== 'number') + { throw new TypeError('missing numStreams.MIS'); + } } /** @@ -496,23 +624,33 @@ export function validateNumSctpStreams(numStreams: NumSctpStreams): void export function validateSctpParameters(params: SctpParameters): void { if (typeof params !== 'object') + { throw new TypeError('params is not an object'); + } // port is mandatory. if (typeof params.port !== 'number') + { throw new TypeError('missing params.port'); + } // OS is mandatory. if (typeof params.OS !== 'number') + { throw new TypeError('missing params.OS'); + } // MIS is mandatory. if (typeof params.MIS !== 'number') + { throw new TypeError('missing params.MIS'); + } // maxMessageSize is mandatory. if (typeof params.maxMessageSize !== 'number') + { throw new TypeError('missing params.maxMessageSize'); + } } /** @@ -523,30 +661,44 @@ export function validateSctpParameters(params: SctpParameters): void export function validateSctpStreamParameters(params: SctpStreamParameters): void { if (typeof params !== 'object') + { throw new TypeError('params is not an object'); + } // streamId is mandatory. if (typeof params.streamId !== 'number') + { throw new TypeError('missing params.streamId'); + } // ordered is optional. let orderedGiven = false; if (typeof params.ordered === 'boolean') + { orderedGiven = true; + } else + { params.ordered = true; + } // maxPacketLifeTime is optional. if (params.maxPacketLifeTime && typeof params.maxPacketLifeTime !== 'number') + { throw new TypeError('invalid params.maxPacketLifeTime'); + } // maxRetransmits is optional. if (params.maxRetransmits && typeof params.maxRetransmits !== 'number') + { throw new TypeError('invalid params.maxRetransmits'); + } if (params.maxPacketLifeTime && params.maxRetransmits) + { throw new TypeError('cannot provide both maxPacketLifeTime and maxRetransmits'); + } if ( orderedGiven && @@ -574,7 +726,9 @@ export function generateRouterRtpCapabilities( validateRtpCapabilities(supportedRtpCapabilities); if (!Array.isArray(mediaCodecs)) + { throw new TypeError('mediaCodecs must be an Array'); + } const clonedSupportedRtpCapabilities = utils.clone(supportedRtpCapabilities) as RtpCapabilities; @@ -614,7 +768,9 @@ export function generateRouterRtpCapabilities( const idx = dynamicPayloadTypes.indexOf(codec.preferredPayloadType); if (idx > -1) + { dynamicPayloadTypes.splice(idx, 1); + } } // Otherwise if the supported codec has preferredPayloadType, use it. else if (typeof codec.preferredPayloadType === 'number') @@ -628,14 +784,18 @@ export function generateRouterRtpCapabilities( const pt = dynamicPayloadTypes.shift(); if (!pt) + { throw new Error('cannot allocate more dynamic codec payload types'); + } codec.preferredPayloadType = pt; } // Ensure there is not duplicated preferredPayloadType values. if (caps.codecs!.some((c) => c.preferredPayloadType === codec.preferredPayloadType)) + { throw new TypeError('duplicated codec.preferredPayloadType'); + } // Merge the media codec parameters. codec.parameters = { ...codec.parameters, ...mediaCodec.parameters }; @@ -650,7 +810,9 @@ export function generateRouterRtpCapabilities( const pt = dynamicPayloadTypes.shift(); if (!pt) + { throw new Error('cannot allocate more dynamic codec payload types'); + } const rtxCodec: RtpCodecCapability = { @@ -696,7 +858,9 @@ export function getProducerRtpParametersMapping( for (const codec of params.codecs) { if (isRtxCodec(codec)) + { continue; + } // Search for the same media codec in capabilities. const matchedCapCodec = caps.codecs! @@ -717,7 +881,9 @@ export function getProducerRtpParametersMapping( for (const codec of params.codecs) { if (!isRtxCodec(codec)) + { continue; + } // Search for the associated media codec. const associatedMediaCodec = params.codecs @@ -767,11 +933,17 @@ export function getProducerRtpParametersMapping( mappedEncoding.mappedSsrc = mappedSsrc++; if (encoding.rid) + { mappedEncoding.rid = encoding.rid; + } if (encoding.ssrc) + { mappedEncoding.ssrc = encoding.ssrc; + } if (encoding.scalabilityMode) + { mappedEncoding.scalabilityMode = encoding.scalabilityMode; + } rtpMapping.encodings.push(mappedEncoding); } @@ -801,7 +973,9 @@ export function getConsumableRtpParameters( for (const codec of params.codecs) { if (isRtxCodec(codec)) + { continue; + } const consumableCodecPt = rtpMapping.codecs .find((entry) => entry.payloadType === codec.payloadType)! @@ -914,14 +1088,18 @@ export function canConsume( .find((capCodec) => matchCodecs(capCodec, codec, { strict: true })); if (!matchedCapCodec) + { continue; + } matchingCodecs.push(codec); } // Ensure there is at least one media codec. if (matchingCodecs.length === 0 || isRtxCodec(matchingCodecs[0])) + { return false; + } return true; } @@ -963,7 +1141,9 @@ export function getConsumerRtpParameters( .find((capCodec) => matchCodecs(capCodec, codec, { strict: true })); if (!matchedCapCodec) + { continue; + } codec.rtcpFeedback = matchedCapCodec.rtcpFeedback; @@ -982,9 +1162,13 @@ export function getConsumerRtpParameters( .find((mediaCodec) => mediaCodec.payloadType === codec.parameters.apt); if (associatedMediaCodec) + { rtxSupported = true; + } else + { consumerParams.codecs.splice(idx, 1); + } } } @@ -1048,7 +1232,9 @@ export function getConsumerRtpParameters( }; if (rtxSupported) + { consumerEncoding.rtx = { ssrc: consumerEncoding.ssrc! + 1 }; + } // If any of the consumableParams.encodings has scalabilityMode, process it // (assume all encodings have the same value). @@ -1068,7 +1254,9 @@ export function getConsumerRtpParameters( } if (scalabilityMode) + { consumerEncoding.scalabilityMode = scalabilityMode; + } // Use the maximum maxBitrate in any encoding and honor it in the Consumer's // encoding. @@ -1101,9 +1289,13 @@ export function getConsumerRtpParameters( encoding.ssrc = baseSsrc + i; if (rtxSupported) + { encoding.rtx = { ssrc: baseRtxSsrc + i }; + } else + { delete encoding.rtx; + } consumerParams.encodings!.push(encoding); } @@ -1137,7 +1329,9 @@ export function getPipeConsumerRtpParameters( for (const codec of consumableCodecs) { if (!enableRtx && isRtxCodec(codec)) + { continue; + } codec.rtcpFeedback = codec.rtcpFeedback! .filter((fb) => ( @@ -1169,9 +1363,13 @@ export function getPipeConsumerRtpParameters( encoding.ssrc = baseSsrc + i; if (enableRtx) + { encoding.rtx = { ssrc: baseRtxSsrc + i }; + } else + { delete encoding.rtx; + } consumerParams.encodings!.push(encoding); } @@ -1194,13 +1392,19 @@ function matchCodecs( const bMimeType = bCodec.mimeType.toLowerCase(); if (aMimeType !== bMimeType) + { return false; + } if (aCodec.clockRate !== bCodec.clockRate) + { return false; + } if (aCodec.channels !== bCodec.channels) + { return false; + } // Per codec special checks. switch (aMimeType) @@ -1211,13 +1415,17 @@ function matchCodecs( const bNumStreams = bCodec.parameters['num_streams']; if (aNumStreams !== bNumStreams) + { return false; + } const aCoupledStreams = aCodec.parameters['coupled_streams']; const bCoupledStreams = bCodec.parameters['coupled_streams']; if (aCoupledStreams !== bCoupledStreams) + { return false; + } break; } @@ -1231,10 +1439,14 @@ function matchCodecs( const bPacketizationMode = bCodec.parameters['packetization-mode'] || 0; if (aPacketizationMode !== bPacketizationMode) + { return false; + } if (!h264.isSameProfile(aCodec.parameters, bCodec.parameters)) + { return false; + } let selectedProfileLevelId; @@ -1251,9 +1463,13 @@ function matchCodecs( if (modify) { if (selectedProfileLevelId) + { aCodec.parameters['profile-level-id'] = selectedProfileLevelId; + } else + { delete aCodec.parameters['profile-level-id']; + } } } @@ -1268,7 +1484,9 @@ function matchCodecs( const bProfileId = bCodec.parameters['profile-id'] || 0; if (aProfileId !== bProfileId) + { return false; + } } break; diff --git a/node/src/tests/test-DirectTransport.ts b/node/src/tests/test-DirectTransport.ts index a00e88840d..848d696ce7 100644 --- a/node/src/tests/test-DirectTransport.ts +++ b/node/src/tests/test-DirectTransport.ts @@ -146,7 +146,9 @@ test('dataProducer.send() succeeds', async () => sentMessageBytes += Buffer.from(message).byteLength; if (id === numMessages) + { clearInterval(interval); + } }, 0); dataConsumer.on('message', (message, ppid) => @@ -163,9 +165,13 @@ test('dataProducer.send() succeeds', async () => } if (id < numMessages / 2) + { expect(ppid).toBe(51); // PPID of WebRTC DataChannel string. + } else + { expect(ppid).toBe(53); // PPID of WebRTC DataChannel binary. + } expect(id).toBe(++lastRecvMessageId); }); diff --git a/node/src/tests/test-PipeTransport.ts b/node/src/tests/test-PipeTransport.ts index 6ececbbe5e..17153850de 100644 --- a/node/src/tests/test-PipeTransport.ts +++ b/node/src/tests/test-PipeTransport.ts @@ -838,7 +838,9 @@ test('producer.close() is transmitted to pipe Consumer', async () => expect(videoProducer.closed).toBe(true); if (!videoConsumer.closed) + { await new Promise((resolve) => videoConsumer.once('producerclose', resolve)); + } expect(videoConsumer.closed).toBe(true); }, 2000); @@ -919,7 +921,9 @@ test('dataProducer.close() is transmitted to pipe DataConsumer', async () => expect(dataProducer.closed).toBe(true); if (!dataConsumer.closed) + { await new Promise((resolve) => dataConsumer.once('dataproducerclose', resolve)); + } expect(dataConsumer.closed).toBe(true); }, 2000); @@ -984,7 +988,9 @@ test('router.pipeToRouter() called in two Routers passing one to each other as a routerA.observer.on('newtransport', (transport) => { if (transport.constructor.name !== 'PipeTransport') + { return; + } pipeTransportsA.set(transport.id, transport); @@ -994,7 +1000,9 @@ test('router.pipeToRouter() called in two Routers passing one to each other as a routerB.observer.on('newtransport', (transport) => { if (transport.constructor.name !== 'PipeTransport') + { return; + } pipeTransportsB.set(transport.id, transport); diff --git a/node/src/tests/test-Worker.ts b/node/src/tests/test-Worker.ts index 006bdd8be2..feb0232fcc 100644 --- a/node/src/tests/test-Worker.ts +++ b/node/src/tests/test-Worker.ts @@ -297,7 +297,9 @@ test('worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () = // Windows doesn't have some signals such as SIGPIPE, SIGALRM, SIGUSR1, SIGUSR2 // so we just skip this test in Windows. if (os.platform() === 'win32') + { return; + } worker = await createWorker({ logLevel: 'warn' }); diff --git a/node/src/tests/test-node-sctp.ts b/node/src/tests/test-node-sctp.ts index 2aca0a4cfb..ae58c95ea7 100644 --- a/node/src/tests/test-node-sctp.ts +++ b/node/src/tests/test-node-sctp.ts @@ -160,7 +160,9 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn sentMessageBytes += data.byteLength; if (id === numMessages) + { clearInterval(interval); + } }, 10); sctpSocket.on('stream', onStream); diff --git a/node/src/utils.ts b/node/src/utils.ts index cc1a00d2bf..e91bea6604 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -6,7 +6,9 @@ import { randomInt } from 'crypto'; export function clone(data: any): any { if (typeof data !== 'object') + { return {}; + } return JSON.parse(JSON.stringify(data)); } @@ -19,9 +21,11 @@ export function generateRandomNumber() return randomInt(100_000_000, 999_999_999); } -type Only = { +type Only = +{ [P in keyof T]: T[P]; -} & { +} & +{ [P in keyof U]?: never; }; From 72794578faa850b54ddaed61df2498a9c20333f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Feb 2023 14:06:36 +0100 Subject: [PATCH 020/525] Router.ts: add missing RouterData type --- node/src/Router.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/node/src/Router.ts b/node/src/Router.ts index b954f931bb..51a2e876da 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -123,6 +123,11 @@ export type RouterInternal = routerId: string; }; +type RouterData = +{ + rtpCapabilities: RtpCapabilities; +}; + const logger = new Logger('Router'); export class Router extends EnhancedEventEmitter @@ -131,10 +136,7 @@ export class Router extends EnhancedEventEmitter readonly #internal: RouterInternal; // Router data. - readonly #data: - { - rtpCapabilities: RtpCapabilities; - }; + readonly #data: RouterData; // Channel instance. readonly #channel: Channel; @@ -181,7 +183,7 @@ export class Router extends EnhancedEventEmitter }: { internal: RouterInternal; - data: any; + data: RouterData; channel: Channel; payloadChannel: PayloadChannel; appData?: Record; From 79570051ec57891d3edcd35421f5d11b595935a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 22 Feb 2023 12:55:08 +0100 Subject: [PATCH 021/525] RtpStreamSend.cpp: cosmetic, use braces --- worker/src/RTC/RtpStreamSend.cpp | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 78204c387c..fd338c1771 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -49,12 +49,16 @@ namespace RTC RtpStreamSend::StorageItem* RtpStreamSend::StorageItemBuffer::Get(uint16_t seq) const { if (RTC::SeqManager::IsSeqLowerThan(seq, this->startSeq)) + { return nullptr; + } auto idx{ static_cast(seq - this->startSeq) }; if (this->buffer.empty() || idx > static_cast(this->buffer.size() - 1)) + { return nullptr; + } return this->buffer.at(idx); } @@ -141,7 +145,9 @@ namespace RTC for (auto* storageItem : this->buffer) { if (!storageItem) + { continue; + } // Reset the storage item (decrease RTP packet shared pointer counter). storageItem->Reset(); @@ -205,11 +211,15 @@ namespace RTC // Call the parent method. if (!RtpStream::ReceiveStreamPacket(packet)) + { return false; + } // If NACK is enabled, store the packet into the buffer. if (this->params.useNack) + { StorePacket(packet, sharedPacket); + } // Increase transmission counter. this->transmissionCounter.Update(packet); @@ -234,7 +244,9 @@ namespace RTC for (auto* storageItem : RetransmissionContainer) { if (!storageItem) + { break; + } // Note that this is an already RTX encoded packet if RTX is used // (FillRetransmissionContainer() did it). @@ -249,7 +261,9 @@ namespace RTC // Mark the packet as repaired (only if this is the first retransmission). if (storageItem->sentTimes == 1) + { RTC::RtpStream::PacketRepaired(packet.get()); + } if (HasRtx()) { @@ -302,7 +316,9 @@ namespace RTC // If no Sender Report was received by the remote endpoint yet, ignore lastSr // and dlsr values in the Receiver Report. if (lastSr && dlsr && (compactNtp > dlsr + lastSr)) + { rtt = compactNtp - dlsr - lastSr; + } // RTT in milliseconds. this->rtt = static_cast(rtt >> 16) * 1000; @@ -343,7 +359,9 @@ namespace RTC MS_TRACE(); if (this->transmissionCounter.GetPacketCount() == 0u) + { return nullptr; + } auto ntp = Utils::Time::TimeMs2Ntp(nowMs); auto* report = new RTC::RTCP::SenderReport(); @@ -371,7 +389,9 @@ namespace RTC MS_TRACE(); if (this->lastRrReceivedMs == 0u) + { return nullptr; + } // Get delay in milliseconds. auto delayMs = static_cast(nowMs - this->lastRrReceivedMs); @@ -469,7 +489,9 @@ namespace RTC // RTP packet is older than the retransmission buffer size. if (static_cast(diffTs * 1000 / this->params.clockRate) >= this->retransmissionBufferSize) + { return; + } } } @@ -483,7 +505,9 @@ namespace RTC if (storageItem) { if (packet->GetTimestamp() == storageItem->timestamp) + { return; + } // Reset the storage item. storageItem->Reset(); @@ -527,11 +551,15 @@ namespace RTC // Processing RTP packet is older than first one. if (RTC::SeqManager::IsSeqLowerThan(packet->GetTimestamp(), storageItem->timestamp)) + { break; + } // First RTP packet is recent enough. if (static_cast(diffTs * 1000 / clockRate) < this->retransmissionBufferSize) + { break; + } // Unfill the buffer start item. this->storageItemBuffer.RemoveFirst(); @@ -603,7 +631,9 @@ namespace RTC // Update MID RTP extension value. if (!this->mid.empty()) + { packet->UpdateMid(mid); + } const uint32_t diffTs = this->maxPacketTs - packet->GetTimestamp(); @@ -670,7 +700,9 @@ namespace RTC sent = true; if (isFirstPacket) + { firstPacketSent = true; + } } } @@ -728,9 +760,13 @@ namespace RTC uint32_t lost; if (totalLost < this->lostPriorScore) + { lost = 0; + } else + { lost = totalLost - this->lostPriorScore; + } this->lostPriorScore = totalLost; @@ -755,10 +791,14 @@ namespace RTC } if (lost > sent) + { lost = sent; + } if (repaired > lost) + { repaired = lost; + } #if MS_LOG_DEV_LEVEL == 3 MS_DEBUG_TAG( @@ -783,7 +823,9 @@ namespace RTC MS_ASSERT(retransmitted >= repaired, "repaired packets cannot be more than retransmitted ones"); if (retransmitted > 0) + { repairedWeight *= static_cast(repaired) / retransmitted; + } lost -= repaired * repairedWeight; From 601fb37561ec3f20194e58168809e98d824bbfbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 22 Feb 2023 12:59:21 +0100 Subject: [PATCH 022/525] RtpStreamSend.cpp: cosmetic --- worker/src/RTC/RtpStreamSend.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index fd338c1771..7584268501 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -20,9 +20,9 @@ namespace RTC /* Class Static. */ // Minimum retransmission buffer size (ms). - const uint32_t RtpStreamSend::MinRetransmissionDelay{ 200u }; + const uint32_t RtpStreamSend::MinRetransmissionDelayMs{ 200u }; // Maximum retransmission buffer size (ms). - const uint32_t RtpStreamSend::MaxRetransmissionDelay{ 2000u }; + const uint32_t RtpStreamSend::MaxRetransmissionDelayMs{ 2000u }; void RtpStreamSend::StorageItem::Reset() { @@ -169,7 +169,7 @@ namespace RTC RtpStreamSend::RtpStreamSend( RTC::RtpStreamSend::Listener* listener, RTC::RtpStream::Params& params, std::string& mid) : RTC::RtpStream::RtpStream(listener, params, 10), mid(mid), - retransmissionBufferSize(RtpStreamSend::MaxRetransmissionDelay) + retransmissionBufferSize(RtpStreamSend::MaxRetransmissionDelayMs) { MS_TRACE(); } @@ -330,13 +330,13 @@ namespace RTC } // Smoothly change retransmission buffer size towards RTT + 100ms, but not more than - // `MaxRetransmissionDelay`. + // MaxRetransmissionDelayMs. auto newRetransmissionBufferSize = static_cast(this->rtt + 100.0); auto avgRetransmissionBufferSize = (this->retransmissionBufferSize * 7 + newRetransmissionBufferSize) / 8; this->retransmissionBufferSize = std::max( - std::min(avgRetransmissionBufferSize, RtpStreamSend::MaxRetransmissionDelay), - RtpStreamSend::MinRetransmissionDelay); + std::min(avgRetransmissionBufferSize, RtpStreamSend::MaxRetransmissionDelayMs), + RtpStreamSend::MinRetransmissionDelayMs); this->packetsLost = report->GetTotalLost(); this->fractionLost = report->GetFractionLost(); @@ -543,7 +543,7 @@ namespace RTC const auto bufferSize = this->storageItemBuffer.GetBufferSize(); // Go through all buffer items starting with the first and free all storage - // items that contain packets older than `MaxRetransmissionDelay`. + // items that contain packets older than MaxRetransmissionDelayMs. for (size_t i{ 0 }; i < bufferSize && this->storageItemBuffer.GetBufferSize() != 0; ++i) { auto* storageItem = this->storageItemBuffer.GetFirst(); @@ -645,8 +645,8 @@ namespace RTC { // Do nothing. } - // Don't resend the packet if older than MaxRetransmissionDelay ms. - else if (diffMs > MaxRetransmissionDelay) + // Don't resend the packet if older than MaxRetransmissionDelayMs ms. + else if (diffMs > MaxRetransmissionDelayMs) { if (!tooOldPacketFound) { @@ -655,7 +655,7 @@ namespace RTC "ignoring retransmission for too old packet " "[seq:%" PRIu16 ", max age:%" PRIu32 "ms, packet age:%" PRIu32 "ms]", packet->GetSequenceNumber(), - MaxRetransmissionDelay, + MaxRetransmissionDelayMs, diffMs); tooOldPacketFound = true; From 443ccf082f9ede489ee49e6f7eec28f175ea9942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 22 Feb 2023 13:06:12 +0100 Subject: [PATCH 023/525] RtpStreamSend: forgot to rename exported const everywhere --- worker/include/RTC/RtpStreamSend.hpp | 6 +++--- worker/test/src/RTC/TestRtpStreamSend.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/worker/include/RTC/RtpStreamSend.hpp b/worker/include/RTC/RtpStreamSend.hpp index e4b7e43f28..f52a2f59ad 100644 --- a/worker/include/RTC/RtpStreamSend.hpp +++ b/worker/include/RTC/RtpStreamSend.hpp @@ -11,9 +11,9 @@ namespace RTC { public: // Minimum retransmission buffer size (ms). - const static uint32_t MinRetransmissionDelay; + const static uint32_t MinRetransmissionDelayMs; // Maximum retransmission buffer size (ms). - const static uint32_t MaxRetransmissionDelay; + const static uint32_t MaxRetransmissionDelayMs; public: class Listener : public RTC::RtpStream::Listener @@ -46,7 +46,7 @@ namespace RTC // Special container that stores `StorageItem*` elements addressable by // their `uint16_t` sequence number, while only taking as little memory as // necessary to store the range covering a maximum of - // `MaxRetransmissionDelay` milliseconds. + // MaxRetransmissionDelayMs milliseconds. class StorageItemBuffer { public: diff --git a/worker/test/src/RTC/TestRtpStreamSend.cpp b/worker/test/src/RTC/TestRtpStreamSend.cpp index 067e8ebd7f..0f3fdf4d18 100644 --- a/worker/test/src/RTC/TestRtpStreamSend.cpp +++ b/worker/test/src/RTC/TestRtpStreamSend.cpp @@ -319,11 +319,11 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") delete stream2; } - SECTION("packets get retransmitted as long as they don't exceed MaxRetransmissionDelay") + SECTION("packets get retransmitted as long as they don't exceed MaxRetransmissionDelayMs") { uint32_t clockRate = 90000; uint32_t firstTs = 1533790901; - uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelay * clockRate / 1000; + uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayMs * clockRate / 1000; uint32_t secondTs = firstTs + diffTs; auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); @@ -371,11 +371,11 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") delete stream; } - SECTION("packets don't get retransmitted if MaxRetransmissionDelay is exceeded") + SECTION("packets don't get retransmitted if MaxRetransmissionDelayMs is exceeded") { uint32_t clockRate = 90000; uint32_t firstTs = 1533790901; - uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelay * clockRate / 1000; + uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayMs * clockRate / 1000; uint32_t secondTs = firstTs + diffTs; auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); From 1912b7facac3f1fd7e32331eaad767ca540fd7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 24 Feb 2023 14:16:49 +0100 Subject: [PATCH 024/525] Add support for RTCP NACK in OPUS (#1015) --- CHANGELOG.md | 1 + node/src/Consumer.ts | 10 ++++ node/src/PipeTransport.ts | 6 +- node/src/Transport.ts | 15 ++++- node/src/ortc.ts | 71 +++++++++++++++-------- node/src/supportedRtpCapabilities.ts | 4 ++ node/src/tests/test-Consumer.ts | 36 +++++++++++- node/src/tests/test-ortc.ts | 19 ++++-- rust/src/ortc.rs | 52 ++++++++++------- rust/src/ortc/tests.rs | 12 ++-- rust/src/router/consumer.rs | 7 +++ rust/src/router/transport.rs | 6 +- rust/src/supported_rtp_capabilities.rs | 8 +-- rust/tests/integration/consumer.rs | 45 +++++++++++++- worker/include/RTC/RtpStreamSend.hpp | 9 ++- worker/src/RTC/RtpStreamSend.cpp | 47 +++++++++++---- worker/test/src/RTC/TestRtpStreamSend.cpp | 8 +-- 17 files changed, 276 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 101953b44f..2b12e0aef6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Next +* Add support for RTCP NACK in OPUS ([PR #1015](https://github.com/versatica/mediasoup/pull/1015)). * Update NPM deps. diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 1dc32ec5e3..5bf3c6d5cb 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -50,6 +50,16 @@ export type ConsumerOptions = */ preferredLayers?: ConsumerLayers; + /** + * Whether this Consumer should enable RTP retransmissions, storing sent RTP + * and processing the incoming RTCP NACK from the remote Consumer. If not set + * it's true by default for video codecs and false for audio codecs. If set + * to true, NACK will be enabled if both endpoints (mediasoup and the remote + * Consumer) support NACK for this codec. When it comes to audio codecs, just + * OPUS supports NACK. + */ + enableRtx?: boolean; + /** * Whether this Consumer should ignore DTX packets (only valid for Opus codec). * If set, DTX packets are not forwarded to the remote Consumer. diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index d9d8417631..3aced3c836 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -307,7 +307,11 @@ export class PipeTransport // This may throw. const rtpParameters = ortc.getPipeConsumerRtpParameters( - producer.consumableRtpParameters, this.#data.rtx); + { + consumableRtpParameters : producer.consumableRtpParameters, + enableRtx : this.#data.rtx + } + ); const reqData = { diff --git a/node/src/Transport.ts b/node/src/Transport.ts index ccabeaa293..fb65f2e4d2 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -660,6 +660,7 @@ export class Transport matchCodecs(capCodec, codec, { strict: true })); if (!matchedCapCodec) @@ -1145,7 +1159,10 @@ export function getConsumerRtpParameters( continue; } - codec.rtcpFeedback = matchedCapCodec.rtcpFeedback; + codec.rtcpFeedback = matchedCapCodec.rtcpFeedback! + .filter((fb) => ( + (enableRtx || fb.type !== 'nack' || fb.parameter) + )); consumerParams.codecs.push(codec); } @@ -1178,9 +1195,9 @@ export function getConsumerRtpParameters( throw new UnsupportedError('no compatible media codecs'); } - consumerParams.headerExtensions = consumableParams.headerExtensions! + consumerParams.headerExtensions = consumableRtpParameters.headerExtensions! .filter((ext) => ( - caps.headerExtensions! + remoteRtpCapabilities.headerExtensions! .some((capExt) => ( capExt.preferredId === ext.id && capExt.uri === ext.uri @@ -1236,21 +1253,21 @@ export function getConsumerRtpParameters( consumerEncoding.rtx = { ssrc: consumerEncoding.ssrc! + 1 }; } - // If any of the consumableParams.encodings has scalabilityMode, process it - // (assume all encodings have the same value). + // If any of the consumableRtpParameters.encodings has scalabilityMode, + // process it (assume all encodings have the same value). const encodingWithScalabilityMode = - consumableParams.encodings!.find((encoding) => encoding.scalabilityMode); + consumableRtpParameters.encodings!.find((encoding) => encoding.scalabilityMode); let scalabilityMode = encodingWithScalabilityMode ? encodingWithScalabilityMode.scalabilityMode : undefined; // If there is simulast, mangle spatial layers in scalabilityMode. - if (consumableParams.encodings!.length > 1) + if (consumableRtpParameters.encodings!.length > 1) { const { temporalLayers } = parseScalabilityMode(scalabilityMode); - scalabilityMode = `L${consumableParams.encodings!.length}T${temporalLayers}`; + scalabilityMode = `L${consumableRtpParameters.encodings!.length}T${temporalLayers}`; } if (scalabilityMode) @@ -1261,7 +1278,7 @@ export function getConsumerRtpParameters( // Use the maximum maxBitrate in any encoding and honor it in the Consumer's // encoding. const maxEncodingMaxBitrate = - consumableParams.encodings!.reduce((maxBitrate, encoding) => ( + consumableRtpParameters.encodings!.reduce((maxBitrate, encoding) => ( encoding.maxBitrate && encoding.maxBitrate > maxBitrate ? encoding.maxBitrate : maxBitrate @@ -1278,7 +1295,7 @@ export function getConsumerRtpParameters( else { const consumableEncodings = - utils.clone(consumableParams.encodings) as RtpEncodingParameters[]; + utils.clone(consumableRtpParameters.encodings) as RtpEncodingParameters[]; const baseSsrc = utils.generateRandomNumber(); const baseRtxSsrc = utils.generateRandomNumber(); @@ -1311,8 +1328,14 @@ export function getConsumerRtpParameters( * enableRtx is false, it also removes RTX and NACK support. */ export function getPipeConsumerRtpParameters( - consumableParams: RtpParameters, - enableRtx = false + { + consumableRtpParameters, + enableRtx + }: + { + consumableRtpParameters: RtpParameters; + enableRtx: boolean; + } ): RtpParameters { const consumerParams: RtpParameters = @@ -1320,11 +1343,11 @@ export function getPipeConsumerRtpParameters( codecs : [], headerExtensions : [], encodings : [], - rtcp : consumableParams.rtcp + rtcp : consumableRtpParameters.rtcp }; const consumableCodecs = - utils.clone(consumableParams.codecs) as RtpCodecParameters[]; + utils.clone(consumableRtpParameters.codecs) as RtpCodecParameters[]; for (const codec of consumableCodecs) { @@ -1344,7 +1367,7 @@ export function getPipeConsumerRtpParameters( } // Reduce RTP extensions by disabling transport MID and BWE related ones. - consumerParams.headerExtensions = consumableParams.headerExtensions! + consumerParams.headerExtensions = consumableRtpParameters.headerExtensions! .filter((ext) => ( ext.uri !== 'urn:ietf:params:rtp-hdrext:sdes:mid' && ext.uri !== 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' && @@ -1352,7 +1375,7 @@ export function getPipeConsumerRtpParameters( )); const consumableEncodings = - utils.clone(consumableParams.encodings) as RtpEncodingParameters[]; + utils.clone(consumableRtpParameters.encodings) as RtpEncodingParameters[]; const baseSsrc = utils.generateRandomNumber(); const baseRtxSsrc = utils.generateRandomNumber(); diff --git a/node/src/supportedRtpCapabilities.ts b/node/src/supportedRtpCapabilities.ts index e91b92eaed..aa3618c28c 100644 --- a/node/src/supportedRtpCapabilities.ts +++ b/node/src/supportedRtpCapabilities.ts @@ -11,6 +11,7 @@ const supportedRtpCapabilities: RtpCapabilities = channels : 2, rtcpFeedback : [ + { type: 'nack' }, { type: 'transport-cc' } ] }, @@ -28,6 +29,7 @@ const supportedRtpCapabilities: RtpCapabilities = }, rtcpFeedback : [ + { type: 'nack' }, { type: 'transport-cc' } ] }, @@ -45,6 +47,7 @@ const supportedRtpCapabilities: RtpCapabilities = }, rtcpFeedback : [ + { type: 'nack' }, { type: 'transport-cc' } ] }, @@ -62,6 +65,7 @@ const supportedRtpCapabilities: RtpCapabilities = }, rtcpFeedback : [ + { type: 'nack' }, { type: 'transport-cc' } ] }, diff --git a/node/src/tests/test-Consumer.ts b/node/src/tests/test-Consumer.ts index 121b167070..156eb76535 100644 --- a/node/src/tests/test-Consumer.ts +++ b/node/src/tests/test-Consumer.ts @@ -152,7 +152,11 @@ const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = kind : 'audio', preferredPayloadType : 100, clockRate : 48000, - channels : 2 + channels : 2, + rtcpFeedback : + [ + { type: 'nack', parameter: '' } + ] }, { mimeType : 'video/H264', @@ -495,6 +499,36 @@ test('transport.consume() succeeds', async () => }); }, 2000); +test('transport.consume() with enableRtx succeeds', async () => +{ + const audioConsumer2 = await transport2.consume( + { + producerId : audioProducer.id, + rtpCapabilities : consumerDeviceCapabilities, + enableRtx : true + }); + + expect(audioConsumer2.kind).toBe('audio'); + expect(audioConsumer2.rtpParameters.codecs.length).toBe(1); + expect(audioConsumer2.rtpParameters.codecs[0]).toEqual( + { + mimeType : 'audio/opus', + payloadType : 100, + clockRate : 48000, + channels : 2, + parameters : + { + useinbandfec : 1, + usedtx : 1, + foo : 222.222, + bar : '333' + }, + rtcpFeedback : [ { type: 'nack', parameter: '' } ] + }); + + audioConsumer2.close(); +}, 2000); + test('transport.consume() can be created with user provided mid', async () => { const audioConsumer1 = await transport2.consume( diff --git a/node/src/tests/test-ortc.ts b/node/src/tests/test-ortc.ts index bfbd9c1e83..8dbabfb25d 100644 --- a/node/src/tests/test-ortc.ts +++ b/node/src/tests/test-ortc.ts @@ -56,6 +56,7 @@ test('generateRouterRtpCapabilities() succeeds', () => }, rtcpFeedback : [ + { type: 'nack', parameter: '' }, { type: 'transport-cc', parameter: '' } ] }); @@ -431,8 +432,14 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum ] }; - const consumerRtpParameters = - ortc.getConsumerRtpParameters(consumableRtpParameters, remoteRtpCapabilities, false); + const consumerRtpParameters = ortc.getConsumerRtpParameters( + { + consumableRtpParameters, + remoteRtpCapabilities, + pipe : false, + enableRtx : true + } + ); expect(consumerRtpParameters.codecs.length).toEqual(2); expect(consumerRtpParameters.codecs[0]).toEqual( @@ -501,8 +508,12 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum mux : true }); - const pipeConsumerRtpParameters = - ortc.getPipeConsumerRtpParameters(consumableRtpParameters); + const pipeConsumerRtpParameters = ortc.getPipeConsumerRtpParameters( + { + consumableRtpParameters, + enableRtx : false + } + ); expect(pipeConsumerRtpParameters.codecs.length).toEqual(1); expect(pipeConsumerRtpParameters.codecs[0]).toEqual( diff --git a/rust/src/ortc.rs b/rust/src/ortc.rs index ccc656a3c6..489724b6ba 100644 --- a/rust/src/ortc.rs +++ b/rust/src/ortc.rs @@ -641,29 +641,40 @@ pub(crate) fn can_consume( /// codecs' RTCP feedback and header extensions, and also enables or disabled RTX. #[allow(clippy::suspicious_operation_groupings)] pub(crate) fn get_consumer_rtp_parameters( - consumable_params: &RtpParameters, - caps: &RtpCapabilities, + consumable_rtp_parameters: &RtpParameters, + remote_rtp_capabilities: &RtpCapabilities, pipe: bool, + enable_rtx: bool, ) -> Result { let mut consumer_params = RtpParameters { - rtcp: consumable_params.rtcp.clone(), + rtcp: consumable_rtp_parameters.rtcp.clone(), ..RtpParameters::default() }; - for cap_codec in &caps.codecs { + for cap_codec in &remote_rtp_capabilities.codecs { validate_rtp_codec_capability(cap_codec) .map_err(ConsumerRtpParametersError::InvalidCapabilities)?; } let mut rtx_supported = false; - for mut codec in consumable_params.codecs.clone() { - if let Some(matched_cap_codec) = caps + for mut codec in consumable_rtp_parameters.codecs.clone() { + if !enable_rtx && codec.is_rtx() { + continue; + } + + if let Some(matched_cap_codec) = remote_rtp_capabilities .codecs .iter() .find(|cap_codec| match_codecs(cap_codec.deref().into(), (&codec).into(), true).is_ok()) { - *codec.rtcp_feedback_mut() = matched_cap_codec.rtcp_feedback().clone(); + *codec.rtcp_feedback_mut() = matched_cap_codec + .rtcp_feedback() + .iter() + .filter(|&&fb| enable_rtx || fb != RtcpFeedback::Nack) + .copied() + .collect(); + consumer_params.codecs.push(codec); } } @@ -697,11 +708,12 @@ pub(crate) fn get_consumer_rtp_parameters( return Err(ConsumerRtpParametersError::NoCompatibleMediaCodecs); } - consumer_params.header_extensions = consumable_params + consumer_params.header_extensions = consumable_rtp_parameters .header_extensions .iter() .filter(|ext| { - caps.header_extensions + remote_rtp_capabilities + .header_extensions .iter() .any(|cap_ext| cap_ext.preferred_id == ext.id && cap_ext.uri == ext.uri) }) @@ -738,7 +750,7 @@ pub(crate) fn get_consumer_rtp_parameters( } if pipe { - for ((encoding, ssrc), rtx_ssrc) in consumable_params + for ((encoding, ssrc), rtx_ssrc) in consumable_rtp_parameters .encodings .iter() .zip(generate_ssrc()..) @@ -766,19 +778,19 @@ pub(crate) fn get_consumer_rtp_parameters( }); } - // If any of the consumable_params.encodings has scalability_mode, process it + // If any of the consumable_rtp_parameters.encodings has scalability_mode, process it // (assume all encodings have the same value). - let mut scalability_mode = consumable_params + let mut scalability_mode = consumable_rtp_parameters .encodings .get(0) .map(|encoding| encoding.scalability_mode.clone()) .unwrap_or_default(); // If there is simulcast, mangle spatial layers in scalabilityMode. - if consumable_params.encodings.len() > 1 { + if consumable_rtp_parameters.encodings.len() > 1 { scalability_mode = format!( "L{}T{}", - consumable_params.encodings.len(), + consumable_rtp_parameters.encodings.len(), scalability_mode.temporal_layers() ) .parse() @@ -788,7 +800,7 @@ pub(crate) fn get_consumer_rtp_parameters( consumer_encoding.scalability_mode = scalability_mode; // Use the maximum max_bitrate in any encoding and honor it in the Consumer's encoding. - consumer_encoding.max_bitrate = consumable_params + consumer_encoding.max_bitrate = consumable_rtp_parameters .encodings .iter() .map(|encoding| encoding.max_bitrate) @@ -807,7 +819,7 @@ pub(crate) fn get_consumer_rtp_parameters( /// It keeps all original consumable encodings and removes support for BWE. If /// enableRtx is false, it also removes RTX and NACK support. pub(crate) fn get_pipe_consumer_rtp_parameters( - consumable_params: &RtpParameters, + consumable_rtp_parameters: &RtpParameters, enable_rtx: bool, ) -> RtpParameters { let mut consumer_params = RtpParameters { @@ -815,10 +827,10 @@ pub(crate) fn get_pipe_consumer_rtp_parameters( codecs: vec![], header_extensions: vec![], encodings: vec![], - rtcp: consumable_params.rtcp.clone(), + rtcp: consumable_rtp_parameters.rtcp.clone(), }; - for codec in &consumable_params.codecs { + for codec in &consumable_rtp_parameters.codecs { if !enable_rtx && codec.is_rtx() { continue; } @@ -834,7 +846,7 @@ pub(crate) fn get_pipe_consumer_rtp_parameters( } // Reduce RTP extensions by disabling transport MID and BWE related ones. - consumer_params.header_extensions = consumable_params + consumer_params.header_extensions = consumable_rtp_parameters .header_extensions .iter() .filter(|ext| { @@ -848,7 +860,7 @@ pub(crate) fn get_pipe_consumer_rtp_parameters( .cloned() .collect(); - for ((encoding, ssrc), rtx_ssrc) in consumable_params + for ((encoding, ssrc), rtx_ssrc) in consumable_rtp_parameters .encodings .iter() .zip(generate_ssrc()..) diff --git a/rust/src/ortc/tests.rs b/rust/src/ortc/tests.rs index 837928e4ce..c2be87d012 100644 --- a/rust/src/ortc/tests.rs +++ b/rust/src/ortc/tests.rs @@ -51,7 +51,7 @@ fn generate_router_rtp_capabilities_succeeds() { ("useinbandfec", 1_u32.into()), ("foo", "bar".into()), ]), - rtcp_feedback: vec![RtcpFeedback::TransportCc], + rtcp_feedback: vec![RtcpFeedback::Nack, RtcpFeedback::TransportCc,], }, RtpCodecCapabilityFinalized::Video { mime_type: MimeTypeVideo::Vp8, @@ -451,9 +451,13 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume ], }; - let consumer_rtp_parameters = - get_consumer_rtp_parameters(&consumable_rtp_parameters, &remote_rtp_capabilities, false) - .expect("Failed to get consumer RTP parameters"); + let consumer_rtp_parameters = get_consumer_rtp_parameters( + &consumable_rtp_parameters, + &remote_rtp_capabilities, + false, + true, + ) + .expect("Failed to get consumer RTP parameters"); assert_eq!( consumer_rtp_parameters.codecs, diff --git a/rust/src/router/consumer.rs b/rust/src/router/consumer.rs index 7e7804c10f..7cc9e6b223 100644 --- a/rust/src/router/consumer.rs +++ b/rust/src/router/consumer.rs @@ -77,6 +77,12 @@ pub struct ConsumerOptions { /// Preferred spatial and temporal layer for simulcast or SVC media sources. /// If `None`, the highest ones are selected. pub preferred_layers: Option, + /// Whether this Consumer should enable RTP retransmissions, storing sent RTP and processing the + /// incoming RTCP NACK from the remote Consumer. If not set it's true by default for video codecs + /// and false for audio codecs. If set to true, NACK will be enabled if both endpoints (mediasoup + /// and the remote Consumer) support NACK for this codec. When it comes to audio codecs, just + /// OPUS supports NACK. + pub enable_rtx: Option, /// Whether this Consumer should ignore DTX packets (only valid for Opus codec). /// If set, DTX packets are not forwarded to the remote Consumer. pub ignore_dtx: bool, @@ -96,6 +102,7 @@ impl ConsumerOptions { paused: false, preferred_layers: None, ignore_dtx: false, + enable_rtx: None, pipe: false, mid: None, app_data: AppData::default(), diff --git a/rust/src/router/transport.rs b/rust/src/router/transport.rs index a57aedbde3..5ab9362558 100644 --- a/rust/src/router/transport.rs +++ b/rust/src/router/transport.rs @@ -13,7 +13,7 @@ pub use crate::ortc::{ }; use crate::producer::{Producer, ProducerId, ProducerOptions}; use crate::router::Router; -use crate::rtp_parameters::RtpEncodingParameters; +use crate::rtp_parameters::{MediaKind, RtpEncodingParameters}; use crate::sctp_parameters::SctpStreamParameters; use crate::worker::{Channel, PayloadChannel, RequestError}; use crate::{ortc, uuid_based_wrapper_type}; @@ -508,6 +508,7 @@ pub(super) trait TransportImpl: TransportGeneric { paused, mid, preferred_layers, + enable_rtx, ignore_dtx, pipe, app_data, @@ -522,6 +523,8 @@ pub(super) trait TransportImpl: TransportGeneric { } }; + let enable_rtx = enable_rtx.unwrap_or(producer.kind() == MediaKind::Video); + let rtp_parameters = if transport_type == TransportType::Pipe { ortc::get_pipe_consumer_rtp_parameters(producer.consumable_rtp_parameters(), rtx) } else { @@ -529,6 +532,7 @@ pub(super) trait TransportImpl: TransportGeneric { producer.consumable_rtp_parameters(), &rtp_capabilities, pipe, + enable_rtx, ) .map_err(ConsumeError::BadConsumerRtpParameters)?; diff --git a/rust/src/supported_rtp_capabilities.rs b/rust/src/supported_rtp_capabilities.rs index 38ea0e2910..2f49fc6c7a 100644 --- a/rust/src/supported_rtp_capabilities.rs +++ b/rust/src/supported_rtp_capabilities.rs @@ -26,7 +26,7 @@ pub fn get_supported_rtp_capabilities() -> RtpCapabilities { clock_rate: NonZeroU32::new(48000).unwrap(), channels: NonZeroU8::new(2).unwrap(), parameters: RtpCodecParametersParameters::default(), - rtcp_feedback: vec![RtcpFeedback::TransportCc], + rtcp_feedback: vec![RtcpFeedback::Nack, RtcpFeedback::TransportCc], }, RtpCodecCapability::Audio { mime_type: MimeTypeAudio::MultiChannelOpus, @@ -39,7 +39,7 @@ pub fn get_supported_rtp_capabilities() -> RtpCapabilities { ("num_streams", 2_u32.into()), ("coupled_streams", 2_u32.into()), ]), - rtcp_feedback: vec![RtcpFeedback::TransportCc], + rtcp_feedback: vec![RtcpFeedback::Nack, RtcpFeedback::TransportCc], }, RtpCodecCapability::Audio { mime_type: MimeTypeAudio::MultiChannelOpus, @@ -52,7 +52,7 @@ pub fn get_supported_rtp_capabilities() -> RtpCapabilities { ("num_streams", 4_u32.into()), ("coupled_streams", 2_u32.into()), ]), - rtcp_feedback: vec![RtcpFeedback::TransportCc], + rtcp_feedback: vec![RtcpFeedback::Nack, RtcpFeedback::TransportCc], }, RtpCodecCapability::Audio { mime_type: MimeTypeAudio::MultiChannelOpus, @@ -65,7 +65,7 @@ pub fn get_supported_rtp_capabilities() -> RtpCapabilities { ("num_streams", 5_u32.into()), ("coupled_streams", 3_u32.into()), ]), - rtcp_feedback: vec![RtcpFeedback::TransportCc], + rtcp_feedback: vec![RtcpFeedback::Nack, RtcpFeedback::TransportCc], }, RtpCodecCapability::Audio { mime_type: MimeTypeAudio::Pcmu, diff --git a/rust/tests/integration/consumer.rs b/rust/tests/integration/consumer.rs index 0554cfb785..385c92601f 100644 --- a/rust/tests/integration/consumer.rs +++ b/rust/tests/integration/consumer.rs @@ -199,7 +199,7 @@ fn consumer_device_capabilities() -> RtpCapabilities { clock_rate: NonZeroU32::new(48000).unwrap(), channels: NonZeroU8::new(2).unwrap(), parameters: RtpCodecParametersParameters::default(), - rtcp_feedback: vec![], + rtcp_feedback: vec![RtcpFeedback::Nack], }, RtpCodecCapability::Video { mime_type: MimeTypeVideo::H264, @@ -698,6 +698,49 @@ fn consume_succeeds() { }); } +#[test] +fn consume_with_enable_rtx_succeeds() { + future::block_on(async move { + let (_executor_guard, _worker, _router, transport_1, transport_2) = init().await; + + let audio_producer = transport_1 + .produce(audio_producer_options()) + .await + .expect("Failed to produce audio"); + + let consumer_device_capabilities = consumer_device_capabilities(); + + let audio_consumer = transport_2 + .consume({ + let mut options = + ConsumerOptions::new(audio_producer.id(), consumer_device_capabilities.clone()); + options.enable_rtx = Some(true); + options + }) + .await + .expect("Failed to consume audio"); + + assert_eq!(audio_consumer.kind(), MediaKind::Audio); + assert_eq!(audio_consumer.rtp_parameters().mid, Some("0".to_string())); + assert_eq!( + audio_consumer.rtp_parameters().codecs, + vec![RtpCodecParameters::Audio { + mime_type: MimeTypeAudio::Opus, + payload_type: 100, + clock_rate: NonZeroU32::new(48000).unwrap(), + channels: NonZeroU8::new(2).unwrap(), + parameters: RtpCodecParametersParameters::from([ + ("useinbandfec", 1_u32.into()), + ("usedtx", 1_u32.into()), + ("foo", "222.222".into()), + ("bar", "333".into()), + ]), + rtcp_feedback: vec![RtcpFeedback::Nack], + }] + ); + }); +} + #[test] fn consumer_with_user_defined_mid() { future::block_on(async move { diff --git a/worker/include/RTC/RtpStreamSend.hpp b/worker/include/RTC/RtpStreamSend.hpp index f52a2f59ad..da7ab48634 100644 --- a/worker/include/RTC/RtpStreamSend.hpp +++ b/worker/include/RTC/RtpStreamSend.hpp @@ -12,8 +12,10 @@ namespace RTC public: // Minimum retransmission buffer size (ms). const static uint32_t MinRetransmissionDelayMs; - // Maximum retransmission buffer size (ms). - const static uint32_t MaxRetransmissionDelayMs; + // Maximum retransmission buffer size for video (ms). + const static uint32_t MaxRetransmissionDelayForVideoMs; + // Maximum retransmission buffer size for audio (ms). + const static uint32_t MaxRetransmissionDelayForAudioMs; public: class Listener : public RTC::RtpStream::Listener @@ -46,7 +48,7 @@ namespace RTC // Special container that stores `StorageItem*` elements addressable by // their `uint16_t` sequence number, while only taking as little memory as // necessary to store the range covering a maximum of - // MaxRetransmissionDelayMs milliseconds. + // MaxRetransmissionDelayForVideoMs or MaxRetransmissionDelayForAudioMs ms. class StorageItemBuffer { public: @@ -101,6 +103,7 @@ namespace RTC uint32_t sentPriorScore{ 0u }; // Packets sent at last interval for score calculation. StorageItemBuffer storageItemBuffer; std::string mid; + uint32_t maxRetransmissionDelayMs; uint32_t retransmissionBufferSize; uint16_t rtxSeq{ 0u }; RTC::RtpDataCounter transmissionCounter; diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 7584268501..f849d84c9d 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -4,6 +4,7 @@ #include "RTC/RtpStreamSend.hpp" #include "Logger.hpp" #include "Utils.hpp" +#include "RTC/RtpDictionaries.hpp" #include "RTC/SeqManager.hpp" namespace RTC @@ -19,10 +20,9 @@ namespace RTC /* Class Static. */ - // Minimum retransmission buffer size (ms). const uint32_t RtpStreamSend::MinRetransmissionDelayMs{ 200u }; - // Maximum retransmission buffer size (ms). - const uint32_t RtpStreamSend::MaxRetransmissionDelayMs{ 2000u }; + const uint32_t RtpStreamSend::MaxRetransmissionDelayForVideoMs{ 2000u }; + const uint32_t RtpStreamSend::MaxRetransmissionDelayForAudioMs{ 1000u }; void RtpStreamSend::StorageItem::Reset() { @@ -168,10 +168,33 @@ namespace RTC RtpStreamSend::RtpStreamSend( RTC::RtpStreamSend::Listener* listener, RTC::RtpStream::Params& params, std::string& mid) - : RTC::RtpStream::RtpStream(listener, params, 10), mid(mid), - retransmissionBufferSize(RtpStreamSend::MaxRetransmissionDelayMs) + : RTC::RtpStream::RtpStream(listener, params, 10), mid(mid) { MS_TRACE(); + + switch (params.mimeType.type) + { + case RTC::RtpCodecMimeType::Type::VIDEO: + { + this->maxRetransmissionDelayMs = RtpStreamSend::MaxRetransmissionDelayForVideoMs; + this->retransmissionBufferSize = RtpStreamSend::MaxRetransmissionDelayForVideoMs; + + break; + } + + case RTC::RtpCodecMimeType::Type::AUDIO: + { + this->maxRetransmissionDelayMs = RtpStreamSend::MaxRetransmissionDelayForAudioMs; + this->retransmissionBufferSize = RtpStreamSend::MaxRetransmissionDelayForAudioMs; + + break; + } + + case RTC::RtpCodecMimeType::Type::UNSET: + { + MS_ABORT("codec mimeType not set"); + } + } } RtpStreamSend::~RtpStreamSend() @@ -329,13 +352,13 @@ namespace RTC this->hasRtt = true; } - // Smoothly change retransmission buffer size towards RTT + 100ms, but not more than - // MaxRetransmissionDelayMs. + // Smoothly change retransmission buffer size towards RTT + 100ms, but not + // more than this->maxRetransmissionDelayMs. auto newRetransmissionBufferSize = static_cast(this->rtt + 100.0); auto avgRetransmissionBufferSize = (this->retransmissionBufferSize * 7 + newRetransmissionBufferSize) / 8; this->retransmissionBufferSize = std::max( - std::min(avgRetransmissionBufferSize, RtpStreamSend::MaxRetransmissionDelayMs), + std::min(avgRetransmissionBufferSize, this->maxRetransmissionDelayMs), RtpStreamSend::MinRetransmissionDelayMs); this->packetsLost = report->GetTotalLost(); @@ -543,7 +566,7 @@ namespace RTC const auto bufferSize = this->storageItemBuffer.GetBufferSize(); // Go through all buffer items starting with the first and free all storage - // items that contain packets older than MaxRetransmissionDelayMs. + // items that contain packets older than this->maxRetransmissionDelayMs. for (size_t i{ 0 }; i < bufferSize && this->storageItemBuffer.GetBufferSize() != 0; ++i) { auto* storageItem = this->storageItemBuffer.GetFirst(); @@ -645,8 +668,8 @@ namespace RTC { // Do nothing. } - // Don't resend the packet if older than MaxRetransmissionDelayMs ms. - else if (diffMs > MaxRetransmissionDelayMs) + // Don't resend the packet if older than this->maxRetransmissionDelayMs ms. + else if (diffMs > this->maxRetransmissionDelayMs) { if (!tooOldPacketFound) { @@ -655,7 +678,7 @@ namespace RTC "ignoring retransmission for too old packet " "[seq:%" PRIu16 ", max age:%" PRIu32 "ms, packet age:%" PRIu32 "ms]", packet->GetSequenceNumber(), - MaxRetransmissionDelayMs, + this->maxRetransmissionDelayMs, diffMs); tooOldPacketFound = true; diff --git a/worker/test/src/RTC/TestRtpStreamSend.cpp b/worker/test/src/RTC/TestRtpStreamSend.cpp index 0f3fdf4d18..2ff6996357 100644 --- a/worker/test/src/RTC/TestRtpStreamSend.cpp +++ b/worker/test/src/RTC/TestRtpStreamSend.cpp @@ -319,11 +319,11 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") delete stream2; } - SECTION("packets get retransmitted as long as they don't exceed MaxRetransmissionDelayMs") + SECTION("packets get retransmitted as long as they don't exceed MaxRetransmissionDelayForVideoMs") { uint32_t clockRate = 90000; uint32_t firstTs = 1533790901; - uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayMs * clockRate / 1000; + uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayForVideoMs * clockRate / 1000; uint32_t secondTs = firstTs + diffTs; auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); @@ -371,11 +371,11 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") delete stream; } - SECTION("packets don't get retransmitted if MaxRetransmissionDelayMs is exceeded") + SECTION("packets don't get retransmitted if MaxRetransmissionDelayForVideoMs is exceeded") { uint32_t clockRate = 90000; uint32_t firstTs = 1533790901; - uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayMs * clockRate / 1000; + uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayForVideoMs * clockRate / 1000; uint32_t secondTs = firstTs + diffTs; auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); From 89e83e7d52fc5538246b5a3824257317c7568e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 24 Feb 2023 14:17:57 +0100 Subject: [PATCH 025/525] Update NPM deps --- package-lock.json | 28 ++++++++++++++-------------- package.json | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4f41b3662f..65380cfba1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,8 +18,8 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.14.0", - "@types/uuid": "^9.0.0", + "@types/node": "^18.14.1", + "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.53.0", "@typescript-eslint/parser": "^5.53.0", "eslint": "^8.34.0", @@ -1308,9 +1308,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", - "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==", + "version": "18.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz", + "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1338,9 +1338,9 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==", "dev": true }, "node_modules/@types/yargs": { @@ -6738,9 +6738,9 @@ "dev": true }, "@types/node": { - "version": "18.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", - "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==", + "version": "18.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz", + "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==", "dev": true }, "@types/normalize-package-data": { @@ -6768,9 +6768,9 @@ "dev": true }, "@types/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==", "dev": true }, "@types/yargs": { diff --git a/package.json b/package.json index 55507c2f2e..5c9cf0c376 100644 --- a/package.json +++ b/package.json @@ -93,8 +93,8 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.14.0", - "@types/uuid": "^9.0.0", + "@types/node": "^18.14.1", + "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.53.0", "@typescript-eslint/parser": "^5.53.0", "eslint": "^8.34.0", From ffb756d1a84f335f3a19600ad446d26ebe8642b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 24 Feb 2023 14:19:16 +0100 Subject: [PATCH 026/525] 3.11.11 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 65380cfba1..bc47afcd26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.10", + "version": "3.11.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.10", + "version": "3.11.11", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 5c9cf0c376..1950b0b9d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.10", + "version": "3.11.11", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From d47f59504a7749d0816c1d954d8d79efcfd2eead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 24 Feb 2023 14:37:42 +0100 Subject: [PATCH 027/525] Fix CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b12e0aef6..57c6288dc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.11.11 * Add support for RTCP NACK in OPUS ([PR #1015](https://github.com/versatica/mediasoup/pull/1015)). * Update NPM deps. From 0b93b9d48bd83be96d6d35aee476d835f8d3f584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 2 Mar 2023 12:24:34 +0100 Subject: [PATCH 028/525] Update NPM deps --- CHANGELOG.md | 5 + package-lock.json | 277 ++++++++++++++++++++++++---------------------- package.json | 8 +- 3 files changed, 156 insertions(+), 134 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57c6288dc6..13e6216f15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* Update NPM deps. + + ### 3.11.11 * Add support for RTCP NACK in OPUS ([PR #1015](https://github.com/versatica/mediasoup/pull/1015)). diff --git a/package-lock.json b/package-lock.json index bc47afcd26..6b92de8150 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,11 +18,11 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.14.1", + "@types/node": "^18.14.4", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.53.0", - "@typescript-eslint/parser": "^5.53.0", - "eslint": "^8.34.0", + "@typescript-eslint/eslint-plugin": "^5.54.0", + "@typescript-eslint/parser": "^5.54.0", + "eslint": "^8.35.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.4.3", "open-cli": "^7.1.0", @@ -643,9 +643,9 @@ "dev": true }, "node_modules/@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", + "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -665,6 +665,15 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/js": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", + "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -1308,9 +1317,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz", - "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==", + "version": "18.14.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.4.tgz", + "integrity": "sha512-VhCw7I7qO2X49+jaKcAUwi3rR+hbxT5VcYF493+Z5kMLI0DL568b7JI4IDJaxWFH0D/xwmGJNoXisyX+w7GH/g==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1359,14 +1368,14 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.53.0.tgz", - "integrity": "sha512-alFpFWNucPLdUOySmXCJpzr6HKC3bu7XooShWM+3w/EL6J2HIoB2PFxpLnq4JauWVk6DiVeNKzQlFEaE+X9sGw==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", + "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/type-utils": "5.53.0", - "@typescript-eslint/utils": "5.53.0", + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/type-utils": "5.54.0", + "@typescript-eslint/utils": "5.54.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1393,14 +1402,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz", - "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.0.tgz", + "integrity": "sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/typescript-estree": "5.54.0", "debug": "^4.3.4" }, "engines": { @@ -1420,13 +1429,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz", - "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", + "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0" + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1437,13 +1446,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.53.0.tgz", - "integrity": "sha512-HO2hh0fmtqNLzTAme/KnND5uFNwbsdYhCZghK2SoxGp3Ifn2emv+hi0PBUjzzSh0dstUIFqOj3bp0AwQlK4OWw==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", + "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.53.0", - "@typescript-eslint/utils": "5.53.0", + "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/utils": "5.54.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1464,9 +1473,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz", - "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", + "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1477,13 +1486,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz", - "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", + "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1504,16 +1513,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.53.0.tgz", - "integrity": "sha512-VUOOtPv27UNWLxFwQK/8+7kvxVC+hPHNsJjzlJyotlaHjLSIgOCKj9I0DBUjwOOA64qjBwx5afAPjksqOxMO0g==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", + "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/typescript-estree": "5.54.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -1530,12 +1539,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz", - "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", + "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/types": "5.54.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1547,9 +1556,9 @@ } }, "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2278,12 +2287,13 @@ } }, "node_modules/eslint": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", - "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", + "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.4.1", + "@eslint/eslintrc": "^2.0.0", + "@eslint/js": "8.35.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2297,7 +2307,7 @@ "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", "espree": "^9.4.0", - "esquery": "^1.4.0", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", @@ -2459,9 +2469,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -2837,9 +2847,9 @@ } }, "node_modules/globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -4622,9 +4632,9 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, "engines": { "node": ">=6" @@ -6190,9 +6200,9 @@ "dev": true }, "@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", + "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -6206,6 +6216,12 @@ "strip-json-comments": "^3.1.1" } }, + "@eslint/js": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", + "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "dev": true + }, "@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -6738,9 +6754,9 @@ "dev": true }, "@types/node": { - "version": "18.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz", - "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==", + "version": "18.14.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.4.tgz", + "integrity": "sha512-VhCw7I7qO2X49+jaKcAUwi3rR+hbxT5VcYF493+Z5kMLI0DL568b7JI4IDJaxWFH0D/xwmGJNoXisyX+w7GH/g==", "dev": true }, "@types/normalize-package-data": { @@ -6789,14 +6805,14 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.53.0.tgz", - "integrity": "sha512-alFpFWNucPLdUOySmXCJpzr6HKC3bu7XooShWM+3w/EL6J2HIoB2PFxpLnq4JauWVk6DiVeNKzQlFEaE+X9sGw==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", + "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/type-utils": "5.53.0", - "@typescript-eslint/utils": "5.53.0", + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/type-utils": "5.54.0", + "@typescript-eslint/utils": "5.54.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -6807,53 +6823,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz", - "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.0.tgz", + "integrity": "sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/typescript-estree": "5.54.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz", - "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", + "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0" + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0" } }, "@typescript-eslint/type-utils": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.53.0.tgz", - "integrity": "sha512-HO2hh0fmtqNLzTAme/KnND5uFNwbsdYhCZghK2SoxGp3Ifn2emv+hi0PBUjzzSh0dstUIFqOj3bp0AwQlK4OWw==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", + "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.53.0", - "@typescript-eslint/utils": "5.53.0", + "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/utils": "5.54.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz", - "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", + "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz", - "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", + "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -6862,35 +6878,35 @@ } }, "@typescript-eslint/utils": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.53.0.tgz", - "integrity": "sha512-VUOOtPv27UNWLxFwQK/8+7kvxVC+hPHNsJjzlJyotlaHjLSIgOCKj9I0DBUjwOOA64qjBwx5afAPjksqOxMO0g==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", + "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/typescript-estree": "5.54.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz", - "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==", + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", + "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/types": "5.54.0", "eslint-visitor-keys": "^3.3.0" } }, "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true }, "acorn-jsx": { @@ -7408,12 +7424,13 @@ "dev": true }, "eslint": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", - "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", + "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.4.1", + "@eslint/eslintrc": "^2.0.0", + "@eslint/js": "8.35.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7427,7 +7444,7 @@ "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", "espree": "^9.4.0", - "esquery": "^1.4.0", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", @@ -7532,9 +7549,9 @@ "dev": true }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -7822,9 +7839,9 @@ } }, "globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -9145,9 +9162,9 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true }, "queue-microtask": { diff --git a/package.json b/package.json index 1950b0b9d6..d117e819b3 100644 --- a/package.json +++ b/package.json @@ -93,11 +93,11 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.14.1", + "@types/node": "^18.14.4", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.53.0", - "@typescript-eslint/parser": "^5.53.0", - "eslint": "^8.34.0", + "@typescript-eslint/eslint-plugin": "^5.54.0", + "@typescript-eslint/parser": "^5.54.0", + "eslint": "^8.35.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.4.3", "open-cli": "^7.1.0", From 9101f456ded4fd1f14989fc82609f108f6fe45cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 3 Mar 2023 15:45:44 +0100 Subject: [PATCH 029/525] Fix jitter calculation (#1019) --- CHANGELOG.md | 1 + package-lock.json | 14 +++++++------- package.json | 2 +- worker/src/RTC/RtpStreamRecv.cpp | 5 +++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13e6216f15..77d195a7ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT +* Fix jitter calculation ([PR #1019](https://github.com/versatica/mediasoup/pull/1019), credits to @alexciarlillo and @snnz). * Update NPM deps. diff --git a/package-lock.json b/package-lock.json index 6b92de8150..14c5187fa9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.14.4", + "@types/node": "^18.14.5", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.54.0", "@typescript-eslint/parser": "^5.54.0", @@ -1317,9 +1317,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.14.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.4.tgz", - "integrity": "sha512-VhCw7I7qO2X49+jaKcAUwi3rR+hbxT5VcYF493+Z5kMLI0DL568b7JI4IDJaxWFH0D/xwmGJNoXisyX+w7GH/g==", + "version": "18.14.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.5.tgz", + "integrity": "sha512-CRT4tMK/DHYhw1fcCEBwME9CSaZNclxfzVMe7GsO6ULSwsttbj70wSiX6rZdIjGblu93sTJxLdhNIT85KKI7Qw==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -6754,9 +6754,9 @@ "dev": true }, "@types/node": { - "version": "18.14.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.4.tgz", - "integrity": "sha512-VhCw7I7qO2X49+jaKcAUwi3rR+hbxT5VcYF493+Z5kMLI0DL568b7JI4IDJaxWFH0D/xwmGJNoXisyX+w7GH/g==", + "version": "18.14.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.5.tgz", + "integrity": "sha512-CRT4tMK/DHYhw1fcCEBwME9CSaZNclxfzVMe7GsO6ULSwsttbj70wSiX6rZdIjGblu93sTJxLdhNIT85KKI7Qw==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index d117e819b3..5b110414df 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.14.4", + "@types/node": "^18.14.5", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.54.0", "@typescript-eslint/parser": "^5.54.0", diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index 532e3f1bb0..1d41be1629 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -645,8 +645,9 @@ namespace RTC if (this->params.clockRate == 0u) return; - auto transit = - static_cast(DepLibUV::GetTimeMs() - (rtpTimestamp * 1000 / this->params.clockRate)); + // NOTE: Based on https://github.com/versatica/mediasoup/issues/1018. + auto transit = static_cast( + DepLibUV::GetTimeMs() - (static_cast(rtpTimestamp) * 1000 / this->params.clockRate)); int d = transit - this->transit; // First transit calculation, save and return. From b1abd0a722686d4f1f2a8cb70c1ceebdb8189ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 3 Mar 2023 17:45:42 +0100 Subject: [PATCH 030/525] 3.11.12 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77d195a7ce..1506fb8755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.11.12 * Fix jitter calculation ([PR #1019](https://github.com/versatica/mediasoup/pull/1019), credits to @alexciarlillo and @snnz). * Update NPM deps. diff --git a/package-lock.json b/package-lock.json index 14c5187fa9..50501e6879 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.11", + "version": "3.11.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.11", + "version": "3.11.12", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 5b110414df..48d65befa2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.11", + "version": "3.11.12", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 37d542f0a38a98f824039ccf5010290eba80990f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 5 Mar 2023 20:19:22 +0100 Subject: [PATCH 031/525] Update NPM deps --- CHANGELOG.md | 5 +++++ package-lock.json | 14 +++++++------- package.json | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1506fb8755..3489c454a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +* Update NPM deps. + + ### 3.11.12 * Fix jitter calculation ([PR #1019](https://github.com/versatica/mediasoup/pull/1019), credits to @alexciarlillo and @snnz). diff --git a/package-lock.json b/package-lock.json index 50501e6879..7c6668c798 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.14.5", + "@types/node": "^18.14.6", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.54.0", "@typescript-eslint/parser": "^5.54.0", @@ -1317,9 +1317,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.14.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.5.tgz", - "integrity": "sha512-CRT4tMK/DHYhw1fcCEBwME9CSaZNclxfzVMe7GsO6ULSwsttbj70wSiX6rZdIjGblu93sTJxLdhNIT85KKI7Qw==", + "version": "18.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", + "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -6754,9 +6754,9 @@ "dev": true }, "@types/node": { - "version": "18.14.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.5.tgz", - "integrity": "sha512-CRT4tMK/DHYhw1fcCEBwME9CSaZNclxfzVMe7GsO6ULSwsttbj70wSiX6rZdIjGblu93sTJxLdhNIT85KKI7Qw==", + "version": "18.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", + "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 48d65befa2..63764028b0 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.4.0", - "@types/node": "^18.14.5", + "@types/node": "^18.14.6", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.54.0", "@typescript-eslint/parser": "^5.54.0", From f383e28a23b39ab1a9a164e2a7a43908ab7b6107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 6 Mar 2023 13:09:05 +0100 Subject: [PATCH 032/525] AudioLevelObserver: use multimap rather than map to avoid conflict (#1021) --- CHANGELOG.md | 1 + worker/src/RTC/AudioLevelObserver.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3489c454a8..83da8dde55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Next +* `AudioLevelObserver`: Use multimap rather than map to avoid conflict if various Producers generate same audio level ([PR #1021](https://github.com/versatica/mediasoup/pull/1021), issue reported by @buptlsp). * Update NPM deps. diff --git a/worker/src/RTC/AudioLevelObserver.cpp b/worker/src/RTC/AudioLevelObserver.cpp index 5fece66d50..4339e49d16 100644 --- a/worker/src/RTC/AudioLevelObserver.cpp +++ b/worker/src/RTC/AudioLevelObserver.cpp @@ -156,7 +156,7 @@ namespace RTC { MS_TRACE(); - absl::btree_map mapDBovsProducer; + absl::btree_multimap mapDBovsProducer; for (auto& kv : this->mapProducerDBovs) { @@ -164,12 +164,16 @@ namespace RTC auto& dBovs = kv.second; if (dBovs.count < 10) + { continue; + } auto avgDBov = -1 * static_cast(std::lround(dBovs.totalSum / dBovs.count)); if (avgDBov >= this->threshold) - mapDBovsProducer[avgDBov] = producer; + { + mapDBovsProducer.insert({ avgDBov, producer }); + } } // Clear the map. @@ -198,7 +202,6 @@ namespace RTC else if (!this->silence) { this->silence = true; - this->shared->channelNotifier->Emit(this->id, "silence"); } } From e09058756d85983836bc61e9c00b4d0bd1404c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 6 Mar 2023 13:11:05 +0100 Subject: [PATCH 033/525] 3.11.13 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83da8dde55..561945fcbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.11.13 * `AudioLevelObserver`: Use multimap rather than map to avoid conflict if various Producers generate same audio level ([PR #1021](https://github.com/versatica/mediasoup/pull/1021), issue reported by @buptlsp). * Update NPM deps. diff --git a/package-lock.json b/package-lock.json index 7c6668c798..6967ed4163 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.12", + "version": "3.11.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.12", + "version": "3.11.13", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 63764028b0..396d7def0f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.12", + "version": "3.11.13", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 06ac778e53f29042a98e6e2917e4a040f275e77b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 10 Mar 2023 10:03:16 +0100 Subject: [PATCH 034/525] cosmetic --- worker/src/RTC/RtpStreamSend.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index f849d84c9d..16239edb96 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -95,7 +95,9 @@ namespace RTC // Packets can arrive out of order, add blank slots. for (uint16_t i{ 1 }; i < addToBack; ++i) + { this->buffer.push_back(nullptr); + } this->buffer.push_back(storageItem); } @@ -109,7 +111,9 @@ namespace RTC // Packets can arrive out of order, add blank slots. for (uint16_t i{ 1 }; i < addToFront; ++i) + { this->buffer.push_front(nullptr); + } this->buffer.push_front(storageItem); this->startSeq = seq; @@ -304,12 +308,18 @@ namespace RTC switch (messageType) { case RTC::RTCP::FeedbackPs::MessageType::PLI: + { this->pliCount++; + break; + } case RTC::RTCP::FeedbackPs::MessageType::FIR: + { this->firCount++; + break; + } default:; } From 181ce8a1976bf5d50b3125da81d785f2d99dd363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 10 Mar 2023 10:49:23 +0100 Subject: [PATCH 035/525] cosmetic --- worker/src/RTC/RtpStreamSend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 16239edb96..78ce2533b3 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -83,7 +83,7 @@ namespace RTC // Packet arrived out of order, so we already have a slot allocated for it. if (idx <= static_cast(this->buffer.size() - 1)) { - MS_ASSERT(this->buffer[idx] == nullptr, "Must insert into empty slot"); + MS_ASSERT(this->buffer[idx] == nullptr, "must insert into empty slot"); this->buffer[idx] = storageItem; } From a6857b629171cbd35cc378f99d33502724e199cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 20 Mar 2023 17:18:21 +0100 Subject: [PATCH 036/525] Refactor RTP retransmission buffer in a separate and testable RTC::RetransmissionBuffer class (#1023) --- CHANGELOG.md | 6 + worker/include/RTC/RetransmissionBuffer.hpp | 68 +++ worker/include/RTC/RtpStream.hpp | 33 +- worker/include/RTC/RtpStreamRecv.hpp | 31 +- worker/include/RTC/RtpStreamSend.hpp | 68 +-- worker/include/common.hpp | 19 +- worker/meson.build | 2 + worker/src/RTC/RetransmissionBuffer.cpp | 544 ++++++++++++++++++ worker/src/RTC/RtpStreamRecv.cpp | 62 ++ worker/src/RTC/RtpStreamSend.cpp | 376 ++---------- worker/src/handles/Timer.cpp | 28 + .../test/src/RTC/TestRetransmissionBuffer.cpp | 232 ++++++++ worker/test/src/RTC/TestRtpStreamSend.cpp | 7 +- worker/test/src/tests.cpp | 13 + 14 files changed, 1086 insertions(+), 403 deletions(-) create mode 100644 worker/include/RTC/RetransmissionBuffer.hpp create mode 100644 worker/src/RTC/RetransmissionBuffer.cpp create mode 100644 worker/test/src/RTC/TestRetransmissionBuffer.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 561945fcbc..7f156759aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Changelog +### 3.11.14 + +* Refactor RTP retransmission buffer in a separate and testable `RTC::RetransmissionBuffer` class ([PR #1023](https://github.com/versatica/mediasoup/pull/1023). +* Update NPM deps. + + ### 3.11.13 * `AudioLevelObserver`: Use multimap rather than map to avoid conflict if various Producers generate same audio level ([PR #1021](https://github.com/versatica/mediasoup/pull/1021), issue reported by @buptlsp). diff --git a/worker/include/RTC/RetransmissionBuffer.hpp b/worker/include/RTC/RetransmissionBuffer.hpp new file mode 100644 index 0000000000..66e451d9dc --- /dev/null +++ b/worker/include/RTC/RetransmissionBuffer.hpp @@ -0,0 +1,68 @@ +#ifndef MS_RTC_RTP_RETRANSMISSION_BUFFER_HPP +#define MS_RTC_RTP_RETRANSMISSION_BUFFER_HPP + +#include "common.hpp" +#include "RTC/RtpPacket.hpp" +#include + +namespace RTC +{ + // Special container that stores `Item`* elements addressable by their `uint16_t` + // sequence number, while only taking as little memory as necessary to store + // the range covering a maximum of `MaxRetransmissionDelayForVideoMs` or + // `MaxRetransmissionDelayForAudioMs` ms. + class RetransmissionBuffer + { + public: + struct Item + { + void Reset(); + + // Original packet. + std::shared_ptr packet{ nullptr }; + // Correct SSRC since original packet may not have the same. + uint32_t ssrc{ 0u }; + // Correct sequence number since original packet may not have the same. + uint16_t sequenceNumber{ 0u }; + // Correct timestamp since original packet may not have the same. + uint32_t timestamp{ 0u }; + // Last time this packet was resent. + uint64_t resentAtMs{ 0u }; + // Number of times this packet was resent. + uint8_t sentTimes{ 0u }; + }; + + public: + RetransmissionBuffer(uint16_t maxItems, uint32_t maxRetransmissionDelayMs, uint32_t clockRate); + ~RetransmissionBuffer(); + + Item* Get(uint16_t seq) const; + void Insert(RTC::RtpPacket* packet, std::shared_ptr& sharedPacket); + void Clear(); + void Dump() const; + + private: + Item* GetOldest() const; + Item* GetNewest() const; + void RemoveOldest(); + void RemoveOldest(uint16_t numItems); + void ClearTooOld(); + bool IsTooOld(uint32_t timestamp, uint32_t newestTimestamp) const; + Item* FillItem( + Item* item, RTC::RtpPacket* packet, std::shared_ptr& sharedPacket) const; + + protected: + // Make buffer protected for testing purposes. + std::deque buffer; + + private: + // Given as argument. + uint16_t maxItems; + uint32_t maxRetransmissionDelayMs; + uint32_t clockRate; + // Others. + uint16_t startSeq{ 0u }; + }; +} // namespace RTC + +#endif diff --git a/worker/include/RTC/RtpStream.hpp b/worker/include/RTC/RtpStream.hpp index 45cbac96e5..de4b70949b 100644 --- a/worker/include/RTC/RtpStream.hpp +++ b/worker/include/RTC/RtpStream.hpp @@ -13,6 +13,7 @@ #include "RTC/RTCP/XrDelaySinceLastRr.hpp" #include "RTC/RTCP/XrReceiverReferenceTime.hpp" #include "RTC/RtpDictionaries.hpp" +#include "RTC/RtpPacket.hpp" #include "RTC/RtxStream.hpp" #include #include @@ -180,12 +181,18 @@ namespace RTC Params params; // Others. // https://tools.ietf.org/html/rfc3550#appendix-A.1 stuff. - uint16_t maxSeq{ 0u }; // Highest seq. number seen. - uint32_t cycles{ 0u }; // Shifted count of seq. number cycles. - uint32_t baseSeq{ 0u }; // Base seq number. - uint32_t badSeq{ 0u }; // Last 'bad' seq number + 1. - uint32_t maxPacketTs{ 0u }; // Highest timestamp seen. - uint64_t maxPacketMs{ 0u }; // When the packet with highest timestammp was seen. + // Highest seq. number seen. + uint16_t maxSeq{ 0u }; + // Shifted count of seq. number cycles. + uint32_t cycles{ 0u }; + // Base seq number. + uint32_t baseSeq{ 0u }; + // Last 'bad' seq number + 1. + uint32_t badSeq{ 0u }; + // Highest timestamp seen. + uint32_t maxPacketTs{ 0u }; + // When the packet with highest timestammp was seen. + uint64_t maxPacketMs{ 0u }; uint32_t packetsLost{ 0u }; uint8_t fractionLost{ 0u }; size_t packetsDiscarded{ 0u }; @@ -195,12 +202,14 @@ namespace RTC size_t nackPacketCount{ 0u }; size_t pliCount{ 0u }; size_t firCount{ 0u }; - size_t repairedPriorScore{ 0u }; // Packets repaired at last interval for score calculation. - size_t retransmittedPriorScore{ - 0u - }; // Packets retransmitted at last interval for score calculation. - uint64_t lastSenderReportNtpMs{ 0u }; // NTP timestamp in last Sender Report (in ms). - uint32_t lastSenderReportTs{ 0u }; // RTP timestamp in last Sender Report. + // Packets repaired at last interval for score calculation. + size_t repairedPriorScore{ 0u }; + // Packets retransmitted at last interval for score calculation. + size_t retransmittedPriorScore{ 0u }; + // NTP timestamp in last Sender Report (in ms). + uint64_t lastSenderReportNtpMs{ 0u }; + // RTP timestamp in last Sender Report. + uint32_t lastSenderReportTs{ 0u }; float rtt{ 0 }; bool hasRtt{ false }; // Instance of RtxStream. diff --git a/worker/include/RTC/RtpStreamRecv.hpp b/worker/include/RTC/RtpStreamRecv.hpp index e71e85e6e3..594a47e5f3 100644 --- a/worker/include/RTC/RtpStreamRecv.hpp +++ b/worker/include/RTC/RtpStreamRecv.hpp @@ -93,24 +93,31 @@ namespace RTC // Passed by argument. unsigned int sendNackDelayMs{ 0u }; // Others. - uint32_t expectedPrior{ 0u }; // Packets expected at last interval. - uint32_t expectedPriorScore{ 0u }; // Packets expected at last interval for score calculation. - uint32_t receivedPrior{ 0u }; // Packets received at last interval. - uint32_t receivedPriorScore{ 0u }; // Packets received at last interval for score calculation. - uint32_t lastSrTimestamp{ 0u }; // The middle 32 bits out of 64 in the NTP - // timestamp received in the most recent - // sender report. - uint64_t lastSrReceived{ 0u }; // Wallclock time representing the most recent - // sender report arrival. - int32_t transit{ 0u }; // Relative transit time for prev packet. + // Packets expected at last interval. + uint32_t expectedPrior{ 0u }; + // Packets expected at last interval for score calculation. + uint32_t expectedPriorScore{ 0u }; + // Packets received at last interval. + uint32_t receivedPrior{ 0u }; + // Packets received at last interval for score calculation. + uint32_t receivedPriorScore{ 0u }; + // The middle 32 bits out of 64 in the NTP timestamp received in the most + // recent sender report. + uint32_t lastSrTimestamp{ 0u }; + // Wallclock time representing the most recent sender report arrival. + uint64_t lastSrReceived{ 0u }; + // Relative transit time for prev packet. + int32_t transit{ 0u }; uint32_t jitter{ 0u }; uint8_t firSeqNumber{ 0u }; uint32_t reportedPacketLost{ 0u }; std::unique_ptr nackGenerator; Timer* inactivityCheckPeriodicTimer{ nullptr }; bool inactive{ false }; - TransmissionCounter transmissionCounter; // Valid media + valid RTX. - RTC::RtpDataCounter mediaTransmissionCounter; // Just valid media. + // Valid media + valid RTX. + TransmissionCounter transmissionCounter; + // Just valid media. + RTC::RtpDataCounter mediaTransmissionCounter; }; } // namespace RTC diff --git a/worker/include/RTC/RtpStreamSend.hpp b/worker/include/RTC/RtpStreamSend.hpp index da7ab48634..6f619d0447 100644 --- a/worker/include/RTC/RtpStreamSend.hpp +++ b/worker/include/RTC/RtpStreamSend.hpp @@ -2,16 +2,14 @@ #define MS_RTC_RTP_STREAM_SEND_HPP #include "RTC/RateCalculator.hpp" +#include "RTC/RetransmissionBuffer.hpp" #include "RTC/RtpStream.hpp" -#include namespace RTC { class RtpStreamSend : public RTC::RtpStream { public: - // Minimum retransmission buffer size (ms). - const static uint32_t MinRetransmissionDelayMs; // Maximum retransmission buffer size for video (ms). const static uint32_t MaxRetransmissionDelayForVideoMs; // Maximum retransmission buffer size for audio (ms). @@ -25,47 +23,6 @@ namespace RTC RTC::RtpStreamSend* rtpStream, RTC::RtpPacket* packet) = 0; }; - public: - struct StorageItem - { - void Reset(); - - // Original packet. - std::shared_ptr packet{ nullptr }; - // Correct SSRC since original packet may not have the same. - uint32_t ssrc{ 0 }; - // Correct sequence number since original packet may not have the same. - uint16_t sequenceNumber{ 0 }; - // Correct timestamp since original packet may not have the same. - uint32_t timestamp{ 0 }; - // Last time this packet was resent. - uint64_t resentAtMs{ 0u }; - // Number of times this packet was resent. - uint8_t sentTimes{ 0u }; - }; - - private: - // Special container that stores `StorageItem*` elements addressable by - // their `uint16_t` sequence number, while only taking as little memory as - // necessary to store the range covering a maximum of - // MaxRetransmissionDelayForVideoMs or MaxRetransmissionDelayForAudioMs ms. - class StorageItemBuffer - { - public: - ~StorageItemBuffer(); - - StorageItem* GetFirst() const; - StorageItem* Get(uint16_t seq) const; - size_t GetBufferSize() const; - void Insert(uint16_t seq, StorageItem* storageItem); - void RemoveFirst(); - void Clear(); - - private: - uint16_t startSeq{ 0 }; - std::deque buffer; - }; - public: RtpStreamSend( RTC::RtpStreamSend::Listener* listener, RTC::RtpStream::Params& params, std::string& mid); @@ -93,25 +50,24 @@ namespace RTC private: void StorePacket(RTC::RtpPacket* packet, std::shared_ptr& sharedPacket); - void ClearOldPackets(const RtpPacket* packet); - void ClearBuffer(); void FillRetransmissionContainer(uint16_t seq, uint16_t bitmask); void UpdateScore(RTC::RTCP::ReceiverReport* report); private: - uint32_t lostPriorScore{ 0u }; // Packets lost at last interval for score calculation. - uint32_t sentPriorScore{ 0u }; // Packets sent at last interval for score calculation. - StorageItemBuffer storageItemBuffer; + // Packets lost at last interval for score calculation. + uint32_t lostPriorScore{ 0u }; + // Packets sent at last interval for score calculation. + uint32_t sentPriorScore{ 0u }; std::string mid; - uint32_t maxRetransmissionDelayMs; - uint32_t retransmissionBufferSize; uint16_t rtxSeq{ 0u }; RTC::RtpDataCounter transmissionCounter; - uint32_t lastRrTimestamp{ 0u }; // The middle 32 bits out of 64 in the NTP - // timestamp received in the most recent - // receiver reference timestamp. - uint64_t lastRrReceivedMs{ 0u }; // Wallclock time representing the most recent - // receiver reference timestamp arrival. + RTC::RetransmissionBuffer* retransmissionBuffer{ nullptr }; + // The middle 32 bits out of 64 in the NTP timestamp received in the most + // recent receiver reference timestamp. + uint32_t lastRrTimestamp{ 0u }; + // Wallclock time representing the most recent receiver reference timestamp + // arrival. + uint64_t lastRrReceivedMs{ 0u }; }; } // namespace RTC diff --git a/worker/include/common.hpp b/worker/include/common.hpp index 1662579563..f019dd411c 100644 --- a/worker/include/common.hpp +++ b/worker/include/common.hpp @@ -9,7 +9,7 @@ #include // std::addressof() #ifdef _WIN32 #include -// avoid uv/win.h: error C2628 'intptr_t' followed by 'int' is illegal. +// Avoid uv/win.h: error C2628 'intptr_t' followed by 'int' is illegal. #if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) #include typedef SSIZE_T ssize_t; @@ -25,15 +25,17 @@ typedef SSIZE_T ssize_t; using ChannelReadCtx = void*; using ChannelReadFreeFn = void (*)(uint8_t*, uint32_t, size_t); -// Returns `ChannelReadFree` on successful read that must be used to free `message`. +// Returns `ChannelReadFree` on successful read that must be used to free +// `message`. using ChannelReadFn = ChannelReadFreeFn (*)( uint8_t** /* message */, uint32_t* /* messageLen */, size_t* /* messageCtx */, - // This is `uv_async_t` handle that can be called later with `uv_async_send()` when there is more - // data to read. + // This is `uv_async_t` handle that can be called later with `uv_async_send()` + // when there is more data to read. const void* /* handle */, - ChannelReadCtx /* ctx */); + ChannelReadCtx /* ctx */ +); using ChannelWriteCtx = void*; using ChannelWriteFn = @@ -41,7 +43,8 @@ using ChannelWriteFn = using PayloadChannelReadCtx = void*; using PayloadChannelReadFreeFn = void (*)(uint8_t*, uint32_t, size_t); -// Returns `PayloadChannelReadFree` on successful read that must be used to free `message` and `payload`. +// Returns `PayloadChannelReadFree` on successful read that must be used to free +// `message` and `payload`. using PayloadChannelReadFn = PayloadChannelReadFreeFn (*)( uint8_t** /* message */, uint32_t* /* messageLen */, @@ -49,8 +52,8 @@ using PayloadChannelReadFn = PayloadChannelReadFreeFn (*)( uint8_t** /* payload */, uint32_t* /* payloadLen */, size_t* /* payloadCapacity */, - // This is `uv_async_t` handle that can be called later with `uv_async_send()` when there is more - // data to read. + // This is `uv_async_t` handle that can be called later with `uv_async_send()` + // when there is more data to read. const void* /* handle */, PayloadChannelReadCtx /* ctx */); diff --git a/worker/meson.build b/worker/meson.build index ef6e6a9597..d86ccbc39f 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -84,6 +84,7 @@ common_sources = [ 'src/RTC/PortManager.cpp', 'src/RTC/Producer.cpp', 'src/RTC/RateCalculator.cpp', + 'src/RTC/RetransmissionBuffer.cpp', 'src/RTC/Router.cpp', 'src/RTC/RtpListener.cpp', 'src/RTC/RtpObserver.cpp', @@ -287,6 +288,7 @@ mediasoup_worker_test = executable( 'test/src/RTC/TestKeyFrameRequestManager.cpp', 'test/src/RTC/TestNackGenerator.cpp', 'test/src/RTC/TestRateCalculator.cpp', + 'test/src/RTC/TestRetransmissionBuffer.cpp', 'test/src/RTC/TestRtpPacket.cpp', 'test/src/RTC/TestRtpPacketH264Svc.cpp', 'test/src/RTC/TestRtpStreamSend.cpp', diff --git a/worker/src/RTC/RetransmissionBuffer.cpp b/worker/src/RTC/RetransmissionBuffer.cpp new file mode 100644 index 0000000000..fce2fe8010 --- /dev/null +++ b/worker/src/RTC/RetransmissionBuffer.cpp @@ -0,0 +1,544 @@ +#define MS_CLASS "RTC::RetransmissionBuffer" +// #define MS_LOG_DEV_LEVEL 3 + +#include "RTC/RetransmissionBuffer.hpp" +#include "Logger.hpp" +#include "RTC/SeqManager.hpp" + +namespace RTC +{ + /* Instance methods. */ + + RetransmissionBuffer::RetransmissionBuffer( + uint16_t maxItems, uint32_t maxRetransmissionDelayMs, uint32_t clockRate) + : maxItems(maxItems), maxRetransmissionDelayMs(maxRetransmissionDelayMs), clockRate(clockRate) + { + MS_TRACE(); + + MS_ASSERT(maxItems > 0u, "maxItems must be greater than 0"); + } + + RetransmissionBuffer::~RetransmissionBuffer() + { + MS_TRACE(); + + Clear(); + } + + RetransmissionBuffer::Item* RetransmissionBuffer::Get(uint16_t seq) const + { + MS_TRACE(); + + if (this->buffer.empty()) + { + return nullptr; + } + + if (RTC::SeqManager::IsSeqLowerThan(seq, this->startSeq)) + { + return nullptr; + } + + auto idx = static_cast(seq - this->startSeq); + + if (idx > static_cast(this->buffer.size() - 1)) + { + return nullptr; + } + + return this->buffer.at(idx); + } + + /** + * This method tries to insert given packet into the buffer. Here we assume + * that packet seq number is legitimate according to the content of the buffer. + * We discard the packet if too old and also discard it if its timestamp does + * not properly fit (by ensuring that elements in the buffer are not only + * ordered by increasing seq but also that their timestamp are incremental). + */ + void RetransmissionBuffer::Insert(RTC::RtpPacket* packet, std::shared_ptr& sharedPacket) + { + MS_TRACE(); + + auto ssrc = packet->GetSsrc(); + auto seq = packet->GetSequenceNumber(); + auto timestamp = packet->GetTimestamp(); + + MS_DEBUG_DEV("packet [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", seq, timestamp); + + // Buffer is empty, so just insert new item. + if (this->buffer.empty()) + { + MS_DEBUG_DEV("buffer empty [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", seq, timestamp); + + auto* item = new Item(); + + this->buffer.push_back(FillItem(item, packet, sharedPacket)); + + // Packet's seq number becomes startSeq. + this->startSeq = seq; + + return; + } + + // Clear too old packets in the buffer. + ClearTooOld(); + + auto* oldestItem = GetOldest(); + auto* newestItem = GetNewest(); + + MS_ASSERT(oldestItem != nullptr, "oldest item doesn't exist"); + MS_ASSERT(newestItem != nullptr, "newest item doesn't exist"); + + // Packet arrived in order (its seq is higher than seq of the newest stored + // packet) so will become the newest one in the buffer. + if (RTC::SeqManager::IsSeqHigherThan(seq, newestItem->sequenceNumber)) + { + MS_DEBUG_DEV("packet in order [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", seq, timestamp); + + // Ensure that the timestamp of the packet is equal or higher than the + // timestamp of the newest stored packet. + if (RTC::SeqManager::IsSeqLowerThan(timestamp, newestItem->timestamp)) + { + MS_WARN_TAG( + rtp, + "packet has higher seq but less timestamp than newest packet in the buffer, discarding it [ssrc:%" PRIu32 + ", seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + ssrc, + seq, + timestamp); + + return; + } + + // Calculate how many blank slots it would be necessary to add when + // pushing new item to the back of the buffer. + auto numBlankSlots = static_cast(seq - newestItem->sequenceNumber - 1); + + // We may have to remove oldest items not to exceed the maximum size of + // the buffer. + if (this->buffer.size() + numBlankSlots + 1 > this->maxItems) + { + auto numItemsToRemove = + static_cast(this->buffer.size() + numBlankSlots + 1 - this->maxItems); + + // If num of items to be removed exceed buffer size minus one (needed to + // allocate current packet) then we must clear the entire buffer. + if (numItemsToRemove > this->buffer.size() - 1) + { + MS_WARN_TAG( + rtp, + "packet has too high seq and forces buffer emptying [ssrc:%" PRIu32 ", seq:%" PRIu16 + ", timestamp:%" PRIu32 "]", + ssrc, + seq, + timestamp); + + numBlankSlots = 0u; + Clear(); + } + else + { + MS_DEBUG_DEV( + "calling RemoveOldest(%" PRIu16 ") [bufferSize:%zu, numBlankSlots:%" PRIu16 + ", maxItems:%" PRIu16 "]", + numItemsToRemove, + this->buffer.size(), + numBlankSlots, + this->maxItems); + + RemoveOldest(numItemsToRemove); + } + } + + // Push blank slots to the back. + for (uint16_t i{ 0u }; i < numBlankSlots; ++i) + { + this->buffer.push_back(nullptr); + } + + // Push the packet, which becomes the newest one in the buffer. + auto* item = new Item(); + + this->buffer.push_back(FillItem(item, packet, sharedPacket)); + } + // Packet arrived out order and its seq is less than seq of the oldest + // stored packet, so will become the oldest one in the buffer. + else if (RTC::SeqManager::IsSeqLowerThan(seq, oldestItem->sequenceNumber)) + { + MS_DEBUG_DEV( + "packet out of order and older than oldest packet in the buffer [seq:%" PRIu16 + ", timestamp:%" PRIu32 "]", + seq, + timestamp); + + // Ensure that packet is not too old to be stored. + if (IsTooOld(timestamp, newestItem->timestamp)) + { + MS_WARN_DEV( + "packet too old, discarding it [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", seq, timestamp); + + return; + } + + // Ensure that the timestamp of the packet is equal or less than the + // timestamp of the oldest stored packet. + if (RTC::SeqManager::IsSeqHigherThan(timestamp, oldestItem->timestamp)) + { + MS_WARN_TAG( + rtp, + "packet has less seq but higher timestamp than oldest packet in the buffer, discarding it [ssrc:%" PRIu32 + ", seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + ssrc, + seq, + timestamp); + + return; + } + + // Calculate how many blank slots it would be necessary to add when + // pushing new item to the fton of the buffer. + auto numBlankSlots = static_cast(oldestItem->sequenceNumber - seq - 1); + + // If adding this packet (and needed blank slots) to the front makes the + // buffer exceed its max size, discard this packet. + if (this->buffer.size() + numBlankSlots + 1 > this->maxItems) + { + MS_WARN_TAG( + rtp, + "discarding received old packet to not exceed max buffer size [ssrc:%" PRIu32 + ", seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + ssrc, + seq, + timestamp); + + return; + } + + // Push blank slots to the front. + for (uint16_t i{ 0u }; i < numBlankSlots; ++i) + { + this->buffer.push_front(nullptr); + } + + // Insert the packet, which becomes the oldest one in the buffer. + auto* item = new Item(); + + this->buffer.push_front(FillItem(item, packet, sharedPacket)); + + // Packet's seq number becomes startSeq. + this->startSeq = seq; + } + // Otherwise packet must be inserted between oldest and newest stored items + // so there is already an allocated slot for it. + else + { + MS_DEBUG_DEV( + "packet out of order and in between oldest and newest packets in the buffer [seq:%" PRIu16 + ", timestamp:%" PRIu32 "]", + seq, + timestamp); + + // Let's check if an item already exist in same position. If so, assume + // it's duplicated. + auto* item = Get(seq); + + if (item) + { + MS_DEBUG_DEV( + "packet already in the buffer, discarding [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + seq, + timestamp); + + return; + } + + // idx is the intended position of the received packet in the buffer. + auto idx = static_cast(seq - this->startSeq); + + // Validate that packet timestamp is equal or higher than the timestamp of + // the immediate older packet (if any). + for (auto idx2 = static_cast(idx - 1); idx2 >= 0; --idx2) + { + auto* olderItem = this->buffer.at(idx2); + + // Blank slot, continue. + if (!olderItem) + { + continue; + } + + // We are done. + if (timestamp >= olderItem->timestamp) + { + break; + } + else + { + MS_WARN_TAG( + rtp, + "packet timestamp is less than timestamp of immediate older packet in the buffer, discarding it [ssrc:%" PRIu32 + ", seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + ssrc, + seq, + timestamp); + + return; + } + } + + // Validate that packet timestamp is equal or less than the timestamp of + // the immediate newer packet (if any). + for (auto idx2 = static_cast(idx + 1); idx2 < this->buffer.size(); ++idx2) + { + auto* newerItem = this->buffer.at(idx2); + + // Blank slot, continue. + if (!newerItem) + { + continue; + } + + // We are done. + if (timestamp <= newerItem->timestamp) + { + break; + } + else + { + MS_WARN_TAG( + rtp, + "packet timestamp is higher than timestamp of immediate newer packet in the buffer, discarding it [ssrc:%" PRIu32 + ", seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + ssrc, + seq, + timestamp); + + return; + } + } + + // Store the packet. + item = new Item(); + + this->buffer[idx] = FillItem(item, packet, sharedPacket); + } + + MS_ASSERT( + this->buffer.size() <= this->maxItems, + "buffer contains %zu items (more than %" PRIu16 " max items)", + this->buffer.size(), + this->maxItems); + } + + void RetransmissionBuffer::Clear() + { + MS_TRACE(); + + for (auto* item : this->buffer) + { + if (!item) + { + continue; + } + + // Reset the stored item (decrease RTP packet shared pointer counter). + item->Reset(); + + delete item; + } + + this->buffer.clear(); + this->startSeq = 0u; + } + + void RetransmissionBuffer::Dump() const + { + MS_TRACE(); + + MS_DUMP(""); + MS_DUMP(" buffer [size:%zu, maxSize:%" PRIu16 "]", this->buffer.size(), this->maxItems); + if (this->buffer.size() > 0) + { + const auto* oldestItem = GetOldest(); + const auto* newestItem = GetNewest(); + + MS_DUMP( + " oldest item [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + oldestItem->sequenceNumber, + oldestItem->timestamp); + MS_DUMP( + " newest item [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + newestItem->sequenceNumber, + newestItem->timestamp); + MS_DUMP( + " buffer window: %" PRIu32 "ms", + static_cast(newestItem->timestamp * 1000 / this->clockRate) - + static_cast(oldestItem->timestamp * 1000 / this->clockRate)); + } + MS_DUMP(""); + } + + RetransmissionBuffer::Item* RetransmissionBuffer::GetOldest() const + { + MS_TRACE(); + + return this->Get(this->startSeq); + } + + RetransmissionBuffer::Item* RetransmissionBuffer::GetNewest() const + { + MS_TRACE(); + + return this->Get(this->startSeq + this->buffer.size() - 1); + } + + void RetransmissionBuffer::RemoveOldest() + { + MS_TRACE(); + + if (this->buffer.empty()) + { + return; + } + + auto* item = this->buffer.at(0); + + // Reset the stored item (decrease RTP packet shared pointer counter). + item->Reset(); + + delete item; + + this->buffer.pop_front(); + this->startSeq++; + + MS_DEBUG_DEV("removed 1 item from the front"); + + // Remove all nullptr elements from the beginning of the buffer. + // NOTE: Calling front on an empty container is undefined. + size_t numItemsRemoved{ 0u }; + + while (!this->buffer.empty() && this->buffer.front() == nullptr) + { + this->buffer.pop_front(); + this->startSeq++; + + ++numItemsRemoved; + } + + if (numItemsRemoved) + { + MS_DEBUG_DEV("removed 1 blank slot from the front"); + } + + // If we emptied the full buffer, reset startSeq. + if (this->buffer.empty()) + { + this->startSeq = 0u; + } + } + + void RetransmissionBuffer::RemoveOldest(uint16_t numItems) + { + MS_TRACE(); + + MS_ASSERT( + numItems <= this->buffer.size(), + "attempting to remove more items than current buffer size [numItems:%" PRIu16 + ", bufferSize:%zu]", + numItems, + this->buffer.size()); + + auto intendedBufferSize = this->buffer.size() - numItems; + + while (this->buffer.size() > intendedBufferSize) + { + RemoveOldest(); + } + } + + void RetransmissionBuffer::ClearTooOld() + { + MS_TRACE(); + + const auto* newestItem = GetNewest(); + + if (!newestItem) + { + return; + } + + RetransmissionBuffer::Item* oldestItem{ nullptr }; + + // Go through all buffer items starting with the first and free all items + // that contain too old packets. + while ((oldestItem = GetOldest())) + { + if (IsTooOld(oldestItem->timestamp, newestItem->timestamp)) + { + RemoveOldest(); + } + // If current oldest stored packet is not too old, exit the loop since we + // know that packets stored after it are guaranteed to be newer. + else + { + break; + } + } + } + + bool RetransmissionBuffer::IsTooOld(uint32_t timestamp, uint32_t newestTimestamp) const + { + MS_TRACE(); + + if (RTC::SeqManager::IsSeqHigherThan(timestamp, newestTimestamp)) + { + return false; + } + + const int64_t diffTs = newestTimestamp - timestamp; + + return static_cast(diffTs * 1000 / this->clockRate) > this->maxRetransmissionDelayMs; + } + + RetransmissionBuffer::Item* RetransmissionBuffer::FillItem( + RetransmissionBuffer::Item* item, + RTC::RtpPacket* packet, + std::shared_ptr& sharedPacket) const + { + MS_TRACE(); + + // Store original packet into the item. Only clone once and only if + // necessary. + // + // NOTE: This must be done BEFORE assigning item->packet = sharedPacket, + // otherwise the value being copied in item->packet will remain nullptr. + // This is because we are copying an **empty** shared_ptr into another + // shared_ptr (item->packet), so future value assigned via reset() in the + // former doesn't update the value in the copy. + if (!sharedPacket.get()) + { + sharedPacket.reset(packet->Clone()); + } + + // Store original packet and some extra info into the item. + item->packet = sharedPacket; + item->ssrc = packet->GetSsrc(); + item->sequenceNumber = packet->GetSequenceNumber(); + item->timestamp = packet->GetTimestamp(); + + return item; + } + + void RetransmissionBuffer::Item::Reset() + { + MS_TRACE(); + + this->packet.reset(); + this->ssrc = 0u; + this->sequenceNumber = 0u; + this->timestamp = 0u; + this->resentAtMs = 0u; + this->sentTimes = 0u; + } +} // namespace RTC diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index 1d41be1629..c74051f5d4 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -41,11 +41,15 @@ namespace RTC // Sanity check. Do not allow spatial layers higher than defined. if (spatialLayer > this->spatialLayerCounters.size() - 1) + { spatialLayer = this->spatialLayerCounters.size() - 1; + } // Sanity check. Do not allow temporal layers higher than defined. if (temporalLayer > this->spatialLayerCounters[0].size() - 1) + { temporalLayer = this->spatialLayerCounters[0].size() - 1; + } auto& counter = this->spatialLayerCounters[spatialLayer][temporalLayer]; @@ -82,7 +86,9 @@ namespace RTC auto& counter = this->spatialLayerCounters[spatialLayer][temporalLayer]; if (counter.GetBitrate(nowMs) == 0) + { return 0u; + } uint32_t rate{ 0u }; @@ -191,7 +197,9 @@ namespace RTC MS_TRACE(); if (this->params.useNack) + { this->nackGenerator.reset(new RTC::NackGenerator(this, this->sendNackDelayMs)); + } // Run the RTP inactivity periodic timer (use a different timeout if DTX is // enabled). @@ -199,9 +207,13 @@ namespace RTC this->inactive = false; if (!this->params.useDtx) + { this->inactivityCheckPeriodicTimer->Start(InactivityCheckInterval); + } else + { this->inactivityCheckPeriodicTimer->Start(InactivityCheckIntervalWithDtx); + } } RtpStreamRecv::~RtpStreamRecv() @@ -256,7 +268,9 @@ namespace RTC // Process the packet at codec level. if (packet->GetPayloadType() == GetPayloadType()) + { RTC::Codecs::Tools::ProcessRtpPacket(packet, GetMimeType()); + } // Pass the packet to the NackGenerator. if (this->params.useNack) @@ -295,7 +309,9 @@ namespace RTC // Restart the inactivityCheckPeriodicTimer. if (this->inactivityCheckPeriodicTimer) + { this->inactivityCheckPeriodicTimer->Restart(); + } return true; } @@ -376,7 +392,9 @@ namespace RTC // Process the packet at codec level. if (packet->GetPayloadType() == GetPayloadType()) + { RTC::Codecs::Tools::ProcessRtpPacket(packet, GetMimeType()); + } // Mark the packet as retransmitted. RTC::RtpStream::PacketRetransmitted(packet); @@ -401,7 +419,9 @@ namespace RTC // Restart the inactivityCheckPeriodicTimer. if (this->inactivityCheckPeriodicTimer) + { this->inactivityCheckPeriodicTimer->Restart(); + } return true; } @@ -422,7 +442,9 @@ namespace RTC ->OnRtpStreamNeedWorstRemoteFractionLost(this, worstRemoteFractionLost); if (worstRemoteFractionLost > 0) + { MS_DEBUG_TAG(rtcp, "using worst remote fraction lost:%" PRIu8, worstRemoteFractionLost); + } } auto* report = new RTC::RTCP::ReceiverReport(); @@ -435,9 +457,13 @@ namespace RTC auto expected = GetExpectedPackets(); if (expected > this->mediaTransmissionCounter.GetPacketCount()) + { this->packetsLost = expected - this->mediaTransmissionCounter.GetPacketCount(); + } else + { this->packetsLost = 0u; + } // Calculate Fraction Lost. const uint32_t expectedInterval = expected - this->expectedPrior; @@ -452,9 +478,13 @@ namespace RTC const int32_t lostInterval = expectedInterval - receivedInterval; if (expectedInterval == 0 || lostInterval <= 0) + { this->fractionLost = 0; + } else + { this->fractionLost = std::round((static_cast(lostInterval << 8) / expectedInterval)); + } // Worst remote fraction lost is not worse than local one. if (worstRemoteFractionLost <= this->fractionLost) @@ -505,7 +535,9 @@ namespace RTC MS_TRACE(); if (HasRtx()) + { return this->rtxStream->GetRtcpReceiverReport(); + } return nullptr; } @@ -536,7 +568,9 @@ namespace RTC MS_TRACE(); if (HasRtx()) + { this->rtxStream->ReceiveRtcpSenderReport(report); + } } void RtpStreamRecv::ReceiveRtcpXrDelaySinceLastRr(RTC::RTCP::DelaySinceLastRr::SsrcInfo* ssrcInfo) @@ -563,18 +597,24 @@ namespace RTC // If no Receiver Extended Report was received by the remote endpoint yet, // ignore lastRr and dlrr values in the Sender Extended Report. if (lastRr && dlrr && (compactNtp > dlrr + lastRr)) + { rtt = compactNtp - dlrr - lastRr; + } // RTT in milliseconds. this->rtt = static_cast(rtt >> 16) * 1000; this->rtt += (static_cast(rtt & 0x0000FFFF) / 65536) * 1000; if (this->rtt > 0.0f) + { this->hasRtt = true; + } // Tell it to the NackGenerator. if (this->params.useNack) + { this->nackGenerator->UpdateRtt(static_cast(this->rtt)); + } } void RtpStreamRecv::RequestKeyFrame() @@ -620,10 +660,14 @@ namespace RTC MS_TRACE(); if (this->inactivityCheckPeriodicTimer) + { this->inactivityCheckPeriodicTimer->Stop(); + } if (this->params.useNack) + { this->nackGenerator->Reset(); + } // Reset jitter. this->transit = 0; @@ -635,7 +679,9 @@ namespace RTC MS_TRACE(); if (this->inactivityCheckPeriodicTimer && !this->inactive) + { this->inactivityCheckPeriodicTimer->Restart(); + } } void RtpStreamRecv::CalculateJitter(uint32_t rtpTimestamp) @@ -643,7 +689,9 @@ namespace RTC MS_TRACE(); if (this->params.clockRate == 0u) + { return; + } // NOTE: Based on https://github.com/versatica/mediasoup/issues/1018. auto transit = static_cast( @@ -661,7 +709,9 @@ namespace RTC this->transit = transit; if (d < 0) + { d = -d; + } this->jitter += (1. / 16.) * (static_cast(d) - this->jitter); } @@ -686,9 +736,13 @@ namespace RTC uint32_t lost; if (expected < received) + { lost = 0; + } else + { lost = expected - received; + } // Calculate number of packets repaired in this interval. const auto totalRepaired = this->packetsRepaired; @@ -703,7 +757,9 @@ namespace RTC this->retransmittedPriorScore = totatRetransmitted; if (this->inactive) + { return; + } // We didn't expect more packets to come. if (expected == 0) @@ -714,7 +770,9 @@ namespace RTC } if (lost > received) + { lost = received; + } if (repaired > lost) { @@ -754,7 +812,9 @@ namespace RTC MS_ASSERT(retransmitted >= repaired, "repaired packets cannot be more than retransmitted ones"); if (retransmitted > 0) + { repairedWeight *= static_cast(repaired) / retransmitted; + } lost -= repaired * repairedWeight; @@ -826,7 +886,9 @@ namespace RTC uint16_t shift = *it - seq - 1; if (shift > 15) + { break; + } bitmask |= (1 << shift); ++it; diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 78ce2533b3..2f8e02eb70 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -11,163 +11,19 @@ namespace RTC { /* Static. */ + // Limit retransmission buffer max size to 2500 items. + static constexpr size_t RetransmissionBufferMaxItems{ 2500u }; // 17: 16 bit mask + the initial sequence number. static constexpr size_t MaxRequestedPackets{ 17u }; - thread_local static std::vector RetransmissionContainer( + thread_local static std::vector RetransmissionContainer( MaxRequestedPackets + 1); static constexpr uint32_t DefaultRtt{ 100u }; - static constexpr uint16_t MaxSeq = std::numeric_limits::max(); /* Class Static. */ - const uint32_t RtpStreamSend::MinRetransmissionDelayMs{ 200u }; const uint32_t RtpStreamSend::MaxRetransmissionDelayForVideoMs{ 2000u }; const uint32_t RtpStreamSend::MaxRetransmissionDelayForAudioMs{ 1000u }; - void RtpStreamSend::StorageItem::Reset() - { - MS_TRACE(); - - this->packet.reset(); - this->ssrc = 0; - this->sequenceNumber = 0; - this->timestamp = 0; - this->resentAtMs = 0; - this->sentTimes = 0; - } - - RtpStreamSend::StorageItem* RtpStreamSend::StorageItemBuffer::GetFirst() const - { - auto* storageItem = this->Get(this->startSeq); - - MS_ASSERT(storageItem, "first storage item is missing"); - MS_ASSERT(storageItem->packet, "storage item does not contain original packet"); - - return storageItem; - } - - RtpStreamSend::StorageItem* RtpStreamSend::StorageItemBuffer::Get(uint16_t seq) const - { - if (RTC::SeqManager::IsSeqLowerThan(seq, this->startSeq)) - { - return nullptr; - } - - auto idx{ static_cast(seq - this->startSeq) }; - - if (this->buffer.empty() || idx > static_cast(this->buffer.size() - 1)) - { - return nullptr; - } - - return this->buffer.at(idx); - } - - size_t RtpStreamSend::StorageItemBuffer::GetBufferSize() const - { - return this->buffer.size(); - } - - void RtpStreamSend::StorageItemBuffer::Insert(uint16_t seq, StorageItem* storageItem) - { - if (this->buffer.empty()) - { - this->startSeq = seq; - this->buffer.push_back(storageItem); - } - // Packet sequence number is higher than startSeq. - else if (RTC::SeqManager::IsSeqHigherThan(seq, this->startSeq)) - { - auto idx{ static_cast(seq - this->startSeq) }; - - // Packet arrived out of order, so we already have a slot allocated for it. - if (idx <= static_cast(this->buffer.size() - 1)) - { - MS_ASSERT(this->buffer[idx] == nullptr, "must insert into empty slot"); - - this->buffer[idx] = storageItem; - } - else - { - // Calculate how many elements would it be necessary to add when pushing new item - // to the back of the deque. - auto addToBack = static_cast(seq - (this->startSeq + this->buffer.size() - 1)); - - // Packets can arrive out of order, add blank slots. - for (uint16_t i{ 1 }; i < addToBack; ++i) - { - this->buffer.push_back(nullptr); - } - - this->buffer.push_back(storageItem); - } - } - // Packet sequence number is the same or lower than startSeq. - else - { - // Calculate how many elements would it be necessary to add when pushing new item - // to the front of the deque. - auto addToFront = static_cast(this->startSeq - seq); - - // Packets can arrive out of order, add blank slots. - for (uint16_t i{ 1 }; i < addToFront; ++i) - { - this->buffer.push_front(nullptr); - } - - this->buffer.push_front(storageItem); - this->startSeq = seq; - } - - MS_ASSERT( - this->buffer.size() <= MaxSeq, - "StorageItemBuffer contains more than %" PRIu16 " entries", - MaxSeq); - } - - void RtpStreamSend::StorageItemBuffer::RemoveFirst() - { - MS_ASSERT(!this->buffer.empty(), "buffer is empty"); - - auto* storageItem = this->buffer[0]; - - delete storageItem; - - this->buffer[0] = nullptr; - - // Remove all `nullptr` elements from the beginning of the buffer. - // NOTE: Calling front on an empty container is undefined. - while (!this->buffer.empty() && this->buffer.front() == nullptr) - { - this->buffer.pop_front(); - this->startSeq++; - } - } - - void RtpStreamSend::StorageItemBuffer::Clear() - { - for (auto* storageItem : this->buffer) - { - if (!storageItem) - { - continue; - } - - // Reset the storage item (decrease RTP packet shared pointer counter). - storageItem->Reset(); - - delete storageItem; - } - - this->buffer.clear(); - this->startSeq = 0; - } - - RtpStreamSend::StorageItemBuffer::~StorageItemBuffer() - { - Clear(); - } - /* Instance methods. */ RtpStreamSend::RtpStreamSend( @@ -176,28 +32,34 @@ namespace RTC { MS_TRACE(); - switch (params.mimeType.type) + if (this->params.useNack) { - case RTC::RtpCodecMimeType::Type::VIDEO: + uint32_t maxRetransmissionDelayMs; + + switch (params.mimeType.type) { - this->maxRetransmissionDelayMs = RtpStreamSend::MaxRetransmissionDelayForVideoMs; - this->retransmissionBufferSize = RtpStreamSend::MaxRetransmissionDelayForVideoMs; + case RTC::RtpCodecMimeType::Type::VIDEO: + { + maxRetransmissionDelayMs = RtpStreamSend::MaxRetransmissionDelayForVideoMs; - break; - } + break; + } - case RTC::RtpCodecMimeType::Type::AUDIO: - { - this->maxRetransmissionDelayMs = RtpStreamSend::MaxRetransmissionDelayForAudioMs; - this->retransmissionBufferSize = RtpStreamSend::MaxRetransmissionDelayForAudioMs; + case RTC::RtpCodecMimeType::Type::AUDIO: + { + maxRetransmissionDelayMs = RtpStreamSend::MaxRetransmissionDelayForAudioMs; - break; - } + break; + } - case RTC::RtpCodecMimeType::Type::UNSET: - { - MS_ABORT("codec mimeType not set"); + case RTC::RtpCodecMimeType::Type::UNSET: + { + MS_ABORT("codec mimeType not set"); + } } + + this->retransmissionBuffer = new RTC::RetransmissionBuffer( + RetransmissionBufferMaxItems, maxRetransmissionDelayMs, params.clockRate); } } @@ -205,8 +67,9 @@ namespace RTC { MS_TRACE(); - // Clear the RTP buffer. - ClearBuffer(); + // Delete retransmission buffer. + delete this->retransmissionBuffer; + this->retransmissionBuffer = nullptr; } void RtpStreamSend::FillJsonStats(json& jsonObject) @@ -236,6 +99,9 @@ namespace RTC { MS_TRACE(); + MS_ASSERT( + packet->GetSsrc() == this->params.ssrc, "RTP packet SSRC does not match the encodings SSRC"); + // Call the parent method. if (!RtpStream::ReceiveStreamPacket(packet)) { @@ -243,7 +109,7 @@ namespace RTC } // If NACK is enabled, store the packet into the buffer. - if (this->params.useNack) + if (this->retransmissionBuffer) { StorePacket(packet, sharedPacket); } @@ -268,16 +134,16 @@ namespace RTC FillRetransmissionContainer(item->GetPacketId(), item->GetLostPacketBitmask()); - for (auto* storageItem : RetransmissionContainer) + for (auto* item : RetransmissionContainer) { - if (!storageItem) + if (!item) { break; } // Note that this is an already RTX encoded packet if RTX is used // (FillRetransmissionContainer() did it). - auto packet = storageItem->packet; + auto packet = item->packet; // Retransmit the packet. static_cast(this->listener) @@ -287,7 +153,7 @@ namespace RTC RTC::RtpStream::PacketRetransmitted(packet.get()); // Mark the packet as repaired (only if this is the first retransmission). - if (storageItem->sentTimes == 1) + if (item->sentTimes == 1) { RTC::RtpStream::PacketRepaired(packet.get()); } @@ -295,7 +161,7 @@ namespace RTC if (HasRtx()) { // Restore the packet. - packet->RtxDecode(RtpStream::GetPayloadType(), storageItem->ssrc); + packet->RtxDecode(RtpStream::GetPayloadType(), item->ssrc); } } } @@ -362,15 +228,6 @@ namespace RTC this->hasRtt = true; } - // Smoothly change retransmission buffer size towards RTT + 100ms, but not - // more than this->maxRetransmissionDelayMs. - auto newRetransmissionBufferSize = static_cast(this->rtt + 100.0); - auto avgRetransmissionBufferSize = - (this->retransmissionBufferSize * 7 + newRetransmissionBufferSize) / 8; - this->retransmissionBufferSize = std::max( - std::min(avgRetransmissionBufferSize, this->maxRetransmissionDelayMs), - RtpStreamSend::MinRetransmissionDelayMs); - this->packetsLost = report->GetTotalLost(); this->fractionLost = report->GetFractionLost(); @@ -460,7 +317,11 @@ namespace RTC { MS_TRACE(); - ClearBuffer(); + // Clear retransmission buffer. + if (this->retransmissionBuffer) + { + this->retransmissionBuffer->Clear(); + } } void RtpStreamSend::Resume() @@ -495,9 +356,6 @@ namespace RTC { MS_TRACE(); - MS_ASSERT( - packet->GetSsrc() == this->params.ssrc, "RTP packet SSRC does not match the encodings SSRC"); - if (packet->GetSize() > RTC::MtuSize) { MS_WARN_TAG( @@ -510,101 +368,7 @@ namespace RTC return; } - // Check if RTP packet is too old to be stored. - if (this->storageItemBuffer.GetBufferSize() > 0) - { - auto* storageItem = this->storageItemBuffer.GetFirst(); - - // Processing RTP packet is older than first one. - if (RTC::SeqManager::IsSeqLowerThan(packet->GetTimestamp(), storageItem->timestamp)) - { - const uint32_t diffTs{ storageItem->timestamp - packet->GetTimestamp() }; - - // RTP packet is older than the retransmission buffer size. - if (static_cast(diffTs * 1000 / this->params.clockRate) >= this->retransmissionBufferSize) - { - return; - } - } - } - - this->ClearOldPackets(packet); - - auto seq = packet->GetSequenceNumber(); - auto* storageItem = this->storageItemBuffer.Get(seq); - - // The buffer item is already used. Check whether we should replace its - // storage with the new packet or just ignore it (if duplicated packet). - if (storageItem) - { - if (packet->GetTimestamp() == storageItem->timestamp) - { - return; - } - - // Reset the storage item. - storageItem->Reset(); - } - // Allocate new buffer item. - else - { - // Allocate a new storage item. - storageItem = new StorageItem(); - - this->storageItemBuffer.Insert(seq, storageItem); - } - - // Only clone once and only if necessary. - if (!sharedPacket.get()) - { - sharedPacket.reset(packet->Clone()); - } - - // Store original packet and some extra info into the storage item. - storageItem->packet = sharedPacket; - storageItem->ssrc = packet->GetSsrc(); - storageItem->sequenceNumber = packet->GetSequenceNumber(); - storageItem->timestamp = packet->GetTimestamp(); - } - - void RtpStreamSend::ClearOldPackets(const RtpPacket* packet) - { - MS_TRACE(); - - auto clockRate{ this->params.clockRate }; - - const auto bufferSize = this->storageItemBuffer.GetBufferSize(); - - // Go through all buffer items starting with the first and free all storage - // items that contain packets older than this->maxRetransmissionDelayMs. - for (size_t i{ 0 }; i < bufferSize && this->storageItemBuffer.GetBufferSize() != 0; ++i) - { - auto* storageItem = this->storageItemBuffer.GetFirst(); - const uint32_t diffTs{ packet->GetTimestamp() - storageItem->timestamp }; - - // Processing RTP packet is older than first one. - if (RTC::SeqManager::IsSeqLowerThan(packet->GetTimestamp(), storageItem->timestamp)) - { - break; - } - - // First RTP packet is recent enough. - if (static_cast(diffTs * 1000 / clockRate) < this->retransmissionBufferSize) - { - break; - } - - // Unfill the buffer start item. - this->storageItemBuffer.RemoveFirst(); - } - } - - void RtpStreamSend::ClearBuffer() - { - MS_TRACE(); - - // Reset buffer. - this->storageItemBuffer.Clear(); + this->retransmissionBuffer->Insert(packet, sharedPacket); } // This method looks for the requested RTP packets and inserts them into the @@ -612,6 +376,12 @@ namespace RTC // // If RTX is used the stored packet will be RTX encoded now (if not already // encoded in a previous resend). + // + // NOTE: This method doesn't verify whether requested stored packet is too + // old, why? Because, if we verified it, we would do it by comparing its + // timestamp with the newest one in the retransmission buffer. However we + // already clean old packets upon receipt of any new packet (see Insert() + // method in RetransmissionBuffer class). void RtpStreamSend::FillRetransmissionContainer(uint16_t seq, uint16_t bitmask) { MS_TRACE(); @@ -620,7 +390,7 @@ namespace RTC RetransmissionContainer[0] = nullptr; // If NACK is not supported, exit. - if (!this->params.useNack) + if (!this->retransmissionBuffer) { MS_WARN_TAG(rtx, "NACK not supported"); @@ -640,7 +410,6 @@ namespace RTC bool isFirstPacket{ true }; bool firstPacketSent{ false }; uint8_t bitmaskCounter{ 0 }; - bool tooOldPacketFound{ false }; while (requested || bitmask != 0) { @@ -648,57 +417,36 @@ namespace RTC if (requested) { - auto* storageItem = this->storageItemBuffer.Get(currentSeq); + auto* item = this->retransmissionBuffer->Get(currentSeq); std::shared_ptr packet{ nullptr }; - uint32_t diffMs; // Calculate the elapsed time between the max timestamp seen and the // requested packet's timestamp (in ms). - if (storageItem) + if (item) { - packet = storageItem->packet; + packet = item->packet; // Put correct info into the packet. - packet->SetSsrc(storageItem->ssrc); - packet->SetSequenceNumber(storageItem->sequenceNumber); - packet->SetTimestamp(storageItem->timestamp); + packet->SetSsrc(item->ssrc); + packet->SetSequenceNumber(item->sequenceNumber); + packet->SetTimestamp(item->timestamp); // Update MID RTP extension value. if (!this->mid.empty()) { packet->UpdateMid(mid); } - - const uint32_t diffTs = this->maxPacketTs - packet->GetTimestamp(); - - diffMs = diffTs * 1000 / this->params.clockRate; } // Packet not found. - if (!storageItem) + if (!item) { // Do nothing. } - // Don't resend the packet if older than this->maxRetransmissionDelayMs ms. - else if (diffMs > this->maxRetransmissionDelayMs) - { - if (!tooOldPacketFound) - { - MS_WARN_TAG( - rtx, - "ignoring retransmission for too old packet " - "[seq:%" PRIu16 ", max age:%" PRIu32 "ms, packet age:%" PRIu32 "ms]", - packet->GetSequenceNumber(), - this->maxRetransmissionDelayMs, - diffMs); - - tooOldPacketFound = true; - } - } // Don't resent the packet if it was resent in the last RTT ms. // clang-format off else if ( - storageItem->resentAtMs != 0u && - nowMs - storageItem->resentAtMs <= static_cast(rtt) + item->resentAtMs != 0u && + nowMs - item->resentAtMs <= static_cast(rtt) ) // clang-format on { @@ -722,13 +470,13 @@ namespace RTC } // Save when this packet was resent. - storageItem->resentAtMs = nowMs; + item->resentAtMs = nowMs; // Increase the number of times this packet was sent. - storageItem->sentTimes++; + item->sentTimes++; - // Store the storage item in the container and then increment its index. - RetransmissionContainer[containerIdx++] = storageItem; + // Store the item in the container and then increment its index. + RetransmissionContainer[containerIdx++] = item; sent = true; diff --git a/worker/src/handles/Timer.cpp b/worker/src/handles/Timer.cpp index f46cbfe345..ce6bad6264 100644 --- a/worker/src/handles/Timer.cpp +++ b/worker/src/handles/Timer.cpp @@ -43,7 +43,9 @@ Timer::~Timer() MS_TRACE(); if (!this->closed) + { Close(); + } } void Timer::Close() @@ -51,7 +53,9 @@ void Timer::Close() MS_TRACE(); if (this->closed) + { return; + } this->closed = true; @@ -63,18 +67,24 @@ void Timer::Start(uint64_t timeout, uint64_t repeat) MS_TRACE(); if (this->closed) + { MS_THROW_ERROR("closed"); + } this->timeout = timeout; this->repeat = repeat; if (uv_is_active(reinterpret_cast(this->uvHandle)) != 0) + { Stop(); + } const int err = uv_timer_start(this->uvHandle, static_cast(onTimer), timeout, repeat); if (err != 0) + { MS_THROW_ERROR("uv_timer_start() failed: %s", uv_strerror(err)); + } } void Timer::Stop() @@ -82,12 +92,16 @@ void Timer::Stop() MS_TRACE(); if (this->closed) + { MS_THROW_ERROR("closed"); + } const int err = uv_timer_stop(this->uvHandle); if (err != 0) + { MS_THROW_ERROR("uv_timer_stop() failed: %s", uv_strerror(err)); + } } void Timer::Reset() @@ -95,19 +109,27 @@ void Timer::Reset() MS_TRACE(); if (this->closed) + { MS_THROW_ERROR("closed"); + } if (uv_is_active(reinterpret_cast(this->uvHandle)) == 0) + { return; + } if (this->repeat == 0u) + { return; + } const int err = uv_timer_start(this->uvHandle, static_cast(onTimer), this->repeat, this->repeat); if (err != 0) + { MS_THROW_ERROR("uv_timer_start() failed: %s", uv_strerror(err)); + } } void Timer::Restart() @@ -115,16 +137,22 @@ void Timer::Restart() MS_TRACE(); if (this->closed) + { MS_THROW_ERROR("closed"); + } if (uv_is_active(reinterpret_cast(this->uvHandle)) != 0) + { Stop(); + } const int err = uv_timer_start(this->uvHandle, static_cast(onTimer), this->timeout, this->repeat); if (err != 0) + { MS_THROW_ERROR("uv_timer_start() failed: %s", uv_strerror(err)); + } } inline void Timer::OnUvTimer() diff --git a/worker/test/src/RTC/TestRetransmissionBuffer.cpp b/worker/test/src/RTC/TestRetransmissionBuffer.cpp new file mode 100644 index 0000000000..579930b7aa --- /dev/null +++ b/worker/test/src/RTC/TestRetransmissionBuffer.cpp @@ -0,0 +1,232 @@ +#include "common.hpp" +#include "RTC/RetransmissionBuffer.hpp" +#include "RTC/RtpPacket.hpp" +#include +#include + +using namespace RTC; + +// Class inheriting from RetransmissionBuffer so we can access its protected +// buffer member. +class MyRetransmissionBuffer : public RetransmissionBuffer +{ +public: + struct VerificationItem + { + bool isPresent; + uint16_t sequenceNumber; + uint32_t timestamp; + }; + +public: + MyRetransmissionBuffer(uint16_t maxItems, uint32_t maxRetransmissionDelayMs, uint32_t clockRate) + : RetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate) + { + } + +public: + void Insert(uint16_t seq, uint32_t timestamp) + { + // clang-format off + uint8_t rtpBuffer[] = + { + 0b10000000, 0b01111011, 0b01010010, 0b00001110, + 0b01011011, 0b01101011, 0b11001010, 0b10110101, + 0, 0, 0, 2 + }; + // clang-format on + + auto* packet = RtpPacket::Parse(rtpBuffer, sizeof(rtpBuffer)); + + packet->SetSequenceNumber(seq); + packet->SetTimestamp(timestamp); + + std::shared_ptr sharedPacket; + + RetransmissionBuffer::Insert(packet, sharedPacket); + } + + void AssertBuffer(std::vector verificationBuffer) + { + REQUIRE(verificationBuffer.size() == this->buffer.size()); + + for (size_t idx{ 0u }; idx < verificationBuffer.size(); ++idx) + { + auto& verificationItem = verificationBuffer.at(idx); + auto* item = this->buffer.at(idx); + + REQUIRE(verificationItem.isPresent == !!item); + + if (item) + { + REQUIRE(verificationItem.sequenceNumber == item->sequenceNumber); + REQUIRE(verificationItem.timestamp == item->timestamp); + } + } + } +}; + +SCENARIO("RetransmissionBuffer", "[rtp][rtx]") +{ + SECTION("proper packets received in order") + { + uint16_t maxItems{ 4 }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + + myRetransmissionBuffer.Insert(10001, 1000000000); + myRetransmissionBuffer.Insert(10002, 1000000000); + myRetransmissionBuffer.Insert(10003, 1000000200); + myRetransmissionBuffer.Insert(10004, 1000000200); + + // clang-format off + myRetransmissionBuffer.AssertBuffer( + { + { true, 10001, 1000000000 }, + { true, 10002, 1000000000 }, + { true, 10003, 1000000200 }, + { true, 10004, 1000000200 } + } + ); + // clang-format on + } + + SECTION("proper packets received out of order") + { + uint16_t maxItems{ 4 }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + + myRetransmissionBuffer.Insert(20004, 2000000200); + myRetransmissionBuffer.Insert(20001, 2000000000); + myRetransmissionBuffer.Insert(20003, 2000000200); + myRetransmissionBuffer.Insert(20002, 2000000000); + + // clang-format off + myRetransmissionBuffer.AssertBuffer( + { + { true, 20001, 2000000000 }, + { true, 20002, 2000000000 }, + { true, 20003, 2000000200 }, + { true, 20004, 2000000200 } + } + ); + // clang-format on + } + + SECTION("packet with too new sequence number produces buffer emptying") + { + uint16_t maxItems{ 4 }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + + myRetransmissionBuffer.Insert(30001, 3000000000); + myRetransmissionBuffer.Insert(30002, 3000000000); + myRetransmissionBuffer.Insert(30003, 3000000200); + myRetransmissionBuffer.Insert(40000, 3000003000); + + // clang-format off + myRetransmissionBuffer.AssertBuffer( + { + { true, 40000, 3000003000 } + } + ); + // clang-format on + } + + SECTION("blank slots are properly created") + { + uint16_t maxItems{ 10 }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + + myRetransmissionBuffer.Insert(40002, 4000000002); + // Packet must be discarded since its timestamp is lower than in seq 40002. + myRetransmissionBuffer.Insert(40003, 4000000001); + // Must produce 1 blank slot. + myRetransmissionBuffer.Insert(40004, 4000000004); + // Discarded (duplicated). + myRetransmissionBuffer.Insert(40002, 4000000002); + // Must produce 4 blank slot. + myRetransmissionBuffer.Insert(40008, 4000000008); + myRetransmissionBuffer.Insert(40006, 4000000006); + // Must produce 1 blank slot at the front. + myRetransmissionBuffer.Insert(40000, 4000000000); + + // clang-format off + myRetransmissionBuffer.AssertBuffer( + { + { true, 40000, 4000000000 }, + { false, 0, 0 }, + { true, 40002, 4000000002 }, + { false, 0, 0 }, + { true, 40004, 4000000004 }, + { false, 0, 0 }, + { true, 40006, 4000000006 }, + { false, 0, 0 }, + { true, 40008, 4000000008 } + } + ); + // clang-format on + } + + SECTION("packet with too old sequence number is discarded") + { + uint16_t maxItems{ 4 }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + + myRetransmissionBuffer.Insert(10001, 1000000001); + myRetransmissionBuffer.Insert(10002, 1000000002); + myRetransmissionBuffer.Insert(10003, 1000000003); + // Too old seq. + myRetransmissionBuffer.Insert(40000, 1000000000); + + // clang-format off + myRetransmissionBuffer.AssertBuffer( + { + { true, 10001, 1000000001 }, + { true, 10002, 1000000002 }, + { true, 10003, 1000000003 } + } + ); + // clang-format on + } + + SECTION("packet with too old timestamp is discarded") + { + uint16_t maxItems{ 4 }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + + auto maxDiffTs = static_cast(maxRetransmissionDelayMs * clockRate / 1000); + + myRetransmissionBuffer.Insert(10001, 1000000001); + myRetransmissionBuffer.Insert(10002, 1000000002); + myRetransmissionBuffer.Insert(10003, 1000000003); + // Too old timestamp (subtract 100 to avoid math issues). + myRetransmissionBuffer.Insert(10000, 1000000003 - maxDiffTs - 100); + + // clang-format off + myRetransmissionBuffer.AssertBuffer( + { + { true, 10001, 1000000001 }, + { true, 10002, 1000000002 }, + { true, 10003, 1000000003 } + } + ); + // clang-format on + } +} diff --git a/worker/test/src/RTC/TestRtpStreamSend.cpp b/worker/test/src/RTC/TestRtpStreamSend.cpp index 2ff6996357..58ea00adb7 100644 --- a/worker/test/src/RTC/TestRtpStreamSend.cpp +++ b/worker/test/src/RTC/TestRtpStreamSend.cpp @@ -376,10 +376,14 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") uint32_t clockRate = 90000; uint32_t firstTs = 1533790901; uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayForVideoMs * clockRate / 1000; - uint32_t secondTs = firstTs + diffTs; + // Make second packet arrive more than MaxRetransmissionDelayForVideoMs later. + uint32_t secondTs = firstTs + diffTs + 100; + // Send a third packet so it will clean old packets from the buffer. + uint32_t thirdTs = firstTs + (2 * diffTs); auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, secondTs); + auto* packet3 = CreateRtpPacket(rtpBuffer3, 21008, thirdTs); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener1; @@ -397,6 +401,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") // Receive all the packets. SendRtpPacket({ { stream, params1.ssrc } }, packet1); SendRtpPacket({ { stream, params1.ssrc } }, packet2); + SendRtpPacket({ { stream, params1.ssrc } }, packet3); // Create a NACK item that request for all the packets. RTCP::FeedbackRtpNackPacket nackPacket(0, params1.ssrc); diff --git a/worker/test/src/tests.cpp b/worker/test/src/tests.cpp index 17241b8f7d..e7b960fc54 100644 --- a/worker/test/src/tests.cpp +++ b/worker/test/src/tests.cpp @@ -19,15 +19,28 @@ int main(int argc, char* argv[]) if (std::getenv("MS_TEST_LOG_LEVEL")) { if (std::string(std::getenv("MS_TEST_LOG_LEVEL")) == "debug") + { logLevel = LogLevel::LOG_DEBUG; + } else if (std::string(std::getenv("MS_TEST_LOG_LEVEL")) == "warn") + { logLevel = LogLevel::LOG_WARN; + } else if (std::string(std::getenv("MS_TEST_LOG_LEVEL")) == "error") + { logLevel = LogLevel::LOG_ERROR; + } } Settings::configuration.logLevel = logLevel; + // Fill logTags based by reading ENVs. + // TODO: Add more on demand. + if (std::getenv("MS_TEST_LOG_TAG_RTP")) + { + Settings::configuration.logTags.rtp = true; + } + // Initialize static stuff. DepLibUV::ClassInit(); DepOpenSSL::ClassInit(); From 7c6c87bd46c28b3a362bb61bec36f6ad0c16f6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 20 Mar 2023 17:25:05 +0100 Subject: [PATCH 037/525] update deps --- package-lock.json | 2562 ++++++++++++++++++++++++++++----------------- package.json | 14 +- 2 files changed, 1585 insertions(+), 991 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6967ed4163..4141b29a39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,15 +17,15 @@ }, "devDependencies": { "@types/debug": "^4.1.7", - "@types/jest": "^29.4.0", - "@types/node": "^18.14.6", + "@types/jest": "^29.5.0", + "@types/node": "^18.15.3", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.54.0", - "@typescript-eslint/parser": "^5.54.0", - "eslint": "^8.35.0", + "@typescript-eslint/eslint-plugin": "^5.55.0", + "@typescript-eslint/parser": "^5.55.0", + "eslint": "^8.36.0", "eslint-plugin-jest": "^27.2.1", - "jest": "^29.4.3", - "open-cli": "^7.1.0", + "jest": "^29.5.0", + "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.0.5", @@ -642,15 +642,39 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", + "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", - "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", + "espree": "^9.5.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -666,9 +690,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", - "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -816,16 +840,16 @@ } }, "node_modules/@jest/console": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.3.tgz", - "integrity": "sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", + "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0" }, "engines": { @@ -833,37 +857,37 @@ } }, "node_modules/@jest/core": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.3.tgz", - "integrity": "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", + "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", "dev": true, "dependencies": { - "@jest/console": "^29.4.3", - "@jest/reporters": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/reporters": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.4.3", - "jest-config": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-message-util": "^29.4.3", + "jest-changed-files": "^29.5.0", + "jest-config": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-resolve-dependencies": "^29.4.3", - "jest-runner": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", - "jest-watcher": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-resolve-dependencies": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", + "jest-watcher": "^29.5.0", "micromatch": "^4.0.4", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -880,37 +904,37 @@ } }, "node_modules/@jest/environment": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.3.tgz", - "integrity": "sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", + "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^29.4.3" + "jest-mock": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.3.tgz", - "integrity": "sha512-iktRU/YsxEtumI9zsPctYUk7ptpC+AVLLk1Ax3AsA4g1C+8OOnKDkIQBDHtD5hA/+VtgMd5AWI5gNlcAlt2vxQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", "dev": true, "dependencies": { - "expect": "^29.4.3", - "jest-snapshot": "^29.4.3" + "expect": "^29.5.0", + "jest-snapshot": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.3.tgz", - "integrity": "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3" @@ -920,48 +944,48 @@ } }, "node_modules/@jest/fake-timers": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.3.tgz", - "integrity": "sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", + "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.4.3", - "jest-mock": "^29.4.3", - "jest-util": "^29.4.3" + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.3.tgz", - "integrity": "sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", + "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.3", - "@jest/expect": "^29.4.3", - "@jest/types": "^29.4.3", - "jest-mock": "^29.4.3" + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/types": "^29.5.0", + "jest-mock": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.3.tgz", - "integrity": "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", + "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", @@ -974,9 +998,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", - "jest-worker": "^29.4.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -1021,13 +1045,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.3.tgz", - "integrity": "sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", + "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", "dev": true, "dependencies": { - "@jest/console": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/types": "^29.5.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1036,14 +1060,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.3.tgz", - "integrity": "sha512-yi/t2nES4GB4G0mjLc0RInCq/cNr9dNwJxcGg8sslajua5Kb4kmozAc+qPLzplhBgfw1vLItbjyHzUN92UXicw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", + "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", "dev": true, "dependencies": { - "@jest/test-result": "^29.4.3", + "@jest/test-result": "^29.5.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "slash": "^3.0.0" }, "engines": { @@ -1051,22 +1075,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.3.tgz", - "integrity": "sha512-8u0+fBGWolDshsFgPQJESkDa72da/EVwvL+II0trN2DR66wMwiQ9/CihaGfHdlLGFzbBZwMykFtxuwFdZqlKwg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", + "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1077,9 +1101,9 @@ } }, "node_modules/@jest/types": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.3.tgz", - "integrity": "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, "dependencies": { "@jest/schemas": "^29.4.3", @@ -1289,9 +1313,9 @@ } }, "node_modules/@types/jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz", - "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", + "integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1317,9 +1341,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.14.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", - "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==", + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1368,19 +1392,19 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", - "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", + "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/type-utils": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/type-utils": "5.55.0", + "@typescript-eslint/utils": "5.55.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" }, @@ -1402,14 +1426,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.0.tgz", - "integrity": "sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", + "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", "debug": "^4.3.4" }, "engines": { @@ -1429,13 +1453,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", - "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", + "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0" + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1446,13 +1470,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", - "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", + "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/utils": "5.55.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1473,9 +1497,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", + "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1486,13 +1510,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", - "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", + "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1513,18 +1537,18 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", - "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", + "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", "dev": true, "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" }, "engines": { @@ -1539,12 +1563,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", + "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/types": "5.55.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1681,15 +1705,15 @@ } }, "node_modules/babel-jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.3.tgz", - "integrity": "sha512-o45Wyn32svZE+LnMVWv/Z4x0SwtLbh4FyGcYtR20kIWd+rdrDZ9Fzq8Ml3MYLD+mZvEdzCjZsCnYZ2jpJyQ+Nw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", + "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", "dev": true, "dependencies": { - "@jest/transform": "^29.4.3", + "@jest/transform": "^29.5.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.4.3", + "babel-preset-jest": "^29.5.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -1718,9 +1742,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.3.tgz", - "integrity": "sha512-mB6q2q3oahKphy5V7CpnNqZOCkxxZ9aokf1eh82Dy3jQmg4xvM1tGrh5y6BQUJh4a3Pj9+eLfwvAZ7VNKg7H8Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", + "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -1756,12 +1780,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.3.tgz", - "integrity": "sha512-gWx6COtSuma6n9bw+8/F+2PCXrIgxV/D1TJFnp6OyBK2cxPWg0K9p/sriNYeifKjpUkMViWQ09DSWtzJQRETsw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", + "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.4.3", + "babel-plugin-jest-hoist": "^29.5.0", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -1777,6 +1801,27 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1854,6 +1899,21 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1873,42 +1933,42 @@ } }, "node_modules/camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-8.0.2.tgz", + "integrity": "sha512-qMKdlOfsjlezMqxkUGGMaWWs17i2HoL15tM+wtx8ld4nLrUwU58TFdvyGOz/piNP842KeO8yXvggVQSdQ828NA==", "dev": true, "dependencies": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" + "camelcase": "^7.0.0", + "map-obj": "^4.3.0", + "quick-lru": "^6.1.1", + "type-fest": "^2.13.0" }, "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/camelcase-keys/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2065,6 +2125,45 @@ "node": ">= 8" } }, + "node_modules/cross-spawn-async": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", + "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", + "deprecated": "cross-spawn no longer requires a build toolchain, use it instead", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.0", + "which": "^1.2.8" + } + }, + "node_modules/cross-spawn-async/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/cross-spawn-async/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/cross-spawn-async/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + }, "node_modules/crypto-random-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", @@ -2109,12 +2208,12 @@ } }, "node_modules/decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", "dev": true, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2167,21 +2266,58 @@ "dev": true }, "node_modules/deepmerge": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", - "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/default-browser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", + "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^5.0.0", + "xdg-default-browser": "^2.1.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/detect-newline": { @@ -2287,13 +2423,15 @@ } }, "node_modules/eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", - "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^2.0.0", - "@eslint/js": "8.35.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2304,9 +2442,8 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", + "espree": "^9.5.0", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2328,7 +2465,6 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -2380,33 +2516,6 @@ "node": ">=8.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-visitor-keys": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", @@ -2439,9 +2548,9 @@ } }, "node_modules/espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", "dev": true, "dependencies": { "acorn": "^8.8.0", @@ -2576,16 +2685,16 @@ } }, "node_modules/expect": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.3.tgz", - "integrity": "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.4.3", + "@jest/expect-utils": "^29.5.0", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3" + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2668,9 +2777,9 @@ } }, "node_modules/file-type": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", - "integrity": "sha512-jjMwFpnW8PKofLE/4ohlhqwDk5k0NC6iy0UHAJFKoY1fQeGMN0GDdLgHQrvCbSpMwbqzoCZhRI5dETCZna5qVA==", + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", + "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", "dev": true, "dependencies": { "readable-web-to-node-stream": "^3.0.2", @@ -2935,15 +3044,24 @@ } }, "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", + "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.5.1" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" } }, "node_modules/html-escaper": { @@ -3087,15 +3205,15 @@ } }, "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "bin": { "is-docker": "cli.js" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3140,6 +3258,24 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -3191,6 +3327,21 @@ "node": ">=8" } }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3294,15 +3445,15 @@ } }, "node_modules/jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.3.tgz", - "integrity": "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", + "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", "dev": true, "dependencies": { - "@jest/core": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/core": "^29.5.0", + "@jest/types": "^29.5.0", "import-local": "^3.0.2", - "jest-cli": "^29.4.3" + "jest-cli": "^29.5.0" }, "bin": { "jest": "bin/jest.js" @@ -3320,9 +3471,9 @@ } }, "node_modules/jest-changed-files": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.3.tgz", - "integrity": "sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", + "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", "dev": true, "dependencies": { "execa": "^5.0.0", @@ -3333,28 +3484,29 @@ } }, "node_modules/jest-circus": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.3.tgz", - "integrity": "sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", + "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.3", - "@jest/expect": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", + "jest-each": "^29.5.0", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", "p-limit": "^3.1.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3363,21 +3515,21 @@ } }, "node_modules/jest-cli": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.3.tgz", - "integrity": "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", + "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", "dev": true, "dependencies": { - "@jest/core": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/core": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-config": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -3397,31 +3549,31 @@ } }, "node_modules/jest-config": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.3.tgz", - "integrity": "sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", + "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.4.3", - "@jest/types": "^29.4.3", - "babel-jest": "^29.4.3", + "@jest/test-sequencer": "^29.5.0", + "@jest/types": "^29.5.0", + "babel-jest": "^29.5.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.4.3", - "jest-environment-node": "^29.4.3", + "jest-circus": "^29.5.0", + "jest-environment-node": "^29.5.0", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-runner": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3442,15 +3594,15 @@ } }, "node_modules/jest-diff": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.3.tgz", - "integrity": "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3469,33 +3621,33 @@ } }, "node_modules/jest-each": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.3.tgz", - "integrity": "sha512-1ElHNAnKcbJb/b+L+7j0/w7bDvljw4gTv1wL9fYOczeJrbTbkMGQ5iQPFJ3eFQH19VPTx1IyfePdqSpePKss7Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", + "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.4.3", - "pretty-format": "^29.4.3" + "jest-util": "^29.5.0", + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.3.tgz", - "integrity": "sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", + "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.3", - "@jest/fake-timers": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^29.4.3", - "jest-util": "^29.4.3" + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3511,20 +3663,20 @@ } }, "node_modules/jest-haste-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.3.tgz", - "integrity": "sha512-eZIgAS8tvm5IZMtKlR8Y+feEOMfo2pSQkmNbufdbMzMSn9nitgGxF1waM/+LbryO3OkMcKS98SUb+j/cQxp/vQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", + "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.4.3", - "jest-worker": "^29.4.3", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3536,46 +3688,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.3.tgz", - "integrity": "sha512-9yw4VC1v2NspMMeV3daQ1yXPNxMgCzwq9BocCwYrRgXe4uaEJPAN0ZK37nFBhcy3cUwEVstFecFLaTHpF7NiGA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", + "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz", - "integrity": "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", + "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.4.3", + "jest-diff": "^29.5.0", "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.3.tgz", - "integrity": "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", + "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3584,14 +3736,14 @@ } }, "node_modules/jest-mock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.3.tgz", - "integrity": "sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", + "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-util": "^29.4.3" + "jest-util": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3624,17 +3776,17 @@ } }, "node_modules/jest-resolve": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.3.tgz", - "integrity": "sha512-GPokE1tzguRyT7dkxBim4wSx6E45S3bOQ7ZdKEG+Qj0Oac9+6AwJPCk0TZh5Vu0xzeX4afpb+eDmgbmZFFwpOw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", + "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -3644,43 +3796,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.3.tgz", - "integrity": "sha512-uvKMZAQ3nmXLH7O8WAOhS5l0iWyT3WmnJBdmIHiV5tBbdaDZ1wqtNX04FONGoaFvSOSHBJxnwAVnSn1WHdGVaw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", + "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.4.3" + "jest-snapshot": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.3.tgz", - "integrity": "sha512-GWPTEiGmtHZv1KKeWlTX9SIFuK19uLXlRQU43ceOQ2hIfA5yPEJC7AMkvFKpdCHx6pNEdOD+2+8zbniEi3v3gA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", + "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", "dev": true, "dependencies": { - "@jest/console": "^29.4.3", - "@jest/environment": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/environment": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-leak-detector": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-util": "^29.4.3", - "jest-watcher": "^29.4.3", - "jest-worker": "^29.4.3", + "jest-environment-node": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-leak-detector": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-resolve": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-util": "^29.5.0", + "jest-watcher": "^29.5.0", + "jest-worker": "^29.5.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -3689,31 +3841,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.3.tgz", - "integrity": "sha512-F5bHvxSH+LvLV24vVB3L8K467dt3y3dio6V3W89dUz9nzvTpqd/HcT9zfYKL2aZPvD63vQFgLvaUX/UpUhrP6Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", + "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.3", - "@jest/fake-timers": "^29.4.3", - "@jest/globals": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/globals": "^29.5.0", "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-mock": "^29.4.3", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -3722,9 +3874,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.3.tgz", - "integrity": "sha512-NGlsqL0jLPDW91dz304QTM/SNO99lpcSYYAjNiX0Ou+sSGgkanKBcSjCfp/pqmiiO1nQaOyLp6XQddAzRcx3Xw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", + "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -3733,23 +3885,22 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/expect-utils": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.4.3", + "expect": "^29.5.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.4.3", + "jest-diff": "^29.5.0", "jest-get-type": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "semver": "^7.3.5" }, "engines": { @@ -3757,12 +3908,12 @@ } }, "node_modules/jest-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.3.tgz", - "integrity": "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", + "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3774,17 +3925,17 @@ } }, "node_modules/jest-validate": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.3.tgz", - "integrity": "sha512-J3u5v7aPQoXPzaar6GndAVhdQcZr/3osWSgTeKg5v574I9ybX/dTyH0AJFb5XgXIB7faVhf+rS7t4p3lL9qFaw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", + "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3803,18 +3954,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.3.tgz", - "integrity": "sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", + "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "string-length": "^4.0.1" }, "engines": { @@ -3822,13 +3973,13 @@ } }, "node_modules/jest-worker": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.3.tgz", - "integrity": "sha512-GLHN/GTAAMEy5BFdvpUfzr9Dr80zQqBrh0fz1mtRMe05hqP45+HfQltu7oTBfduD0UeZs09d+maFtFYAXFWvAA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", + "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4069,38 +4220,38 @@ "dev": true }, "node_modules/meow": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", - "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", + "integrity": "sha512-Cl0yeeIrko6d94KpUo1M+0X1sB14ikoaqlIGuTH1fW4I+E3+YljL54/hb/BWmVfrV9tTV9zU04+xjw08Fh2WkA==", "dev": true, "dependencies": { "@types/minimist": "^1.2.2", - "camelcase-keys": "^7.0.0", - "decamelize": "^5.0.0", + "camelcase-keys": "^8.0.2", + "decamelize": "^6.0.0", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.2", - "read-pkg-up": "^8.0.0", + "normalize-package-data": "^4.0.1", + "read-pkg-up": "^9.1.0", "redent": "^4.0.0", "trim-newlines": "^4.0.2", - "type-fest": "^1.2.2", - "yargs-parser": "^20.2.9" + "type-fest": "^3.1.0", + "yargs-parser": "^21.1.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/meow/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.1.tgz", + "integrity": "sha512-htXWckxlT6U4+ilVgweNliPqlsVSSucbxVexRYllyMVJDtf5rTjv6kF/s+qAd4QSL1BZcnJPEJavYBPQiWuZDA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4214,18 +4365,18 @@ "dev": true }, "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", + "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", "dev": true, "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/normalize-path": { @@ -4249,6 +4400,15 @@ "node": ">=8" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4274,32 +4434,33 @@ } }, "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", + "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", "dev": true, "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", + "default-browser": "^3.1.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", "is-wsl": "^2.2.0" }, "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/open-cli": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.1.0.tgz", - "integrity": "sha512-Xnn/B7WY9ygV47oK+LlYp5WU8xr0tEL6SEw9jMX8n6ceElOs2AzVXFXI87/O0+b+LwLokQBZVxBMzGZHCYVppw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.2.0.tgz", + "integrity": "sha512-1ANJc8oJ92FiaNZ0o2Hw4WBvDJoXs1P74aFMtpAvlbkIPV4uPcQvDz7V6kMOrsZkmB4tglrHVMlLQaafuUuxXg==", "dev": true, "dependencies": { - "file-type": "^18.0.0", + "file-type": "^18.2.1", "get-stdin": "^9.0.0", - "meow": "^10.1.5", - "open": "^8.4.0", + "meow": "^11.0.0", + "open": "^9.0.0", "tempy": "^3.0.0" }, "bin": { @@ -4578,9 +4739,9 @@ } }, "node_modules/pretty-format": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", - "integrity": "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "dev": true, "dependencies": { "@jest/schemas": "^29.4.3", @@ -4631,6 +4792,12 @@ "node": ">= 0.10" } }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -4640,6 +4807,22 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.1.tgz", + "integrity": "sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4661,12 +4844,12 @@ ] }, "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.1.tgz", + "integrity": "sha512-S27GBT+F0NTRiehtbrgaSE1idUAJ5bX8dPAQTdylEyNlrdcH5X4Lz7Edz3DYzecbsCluD5zO8ZNEe04z3D3u6Q==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4679,68 +4862,177 @@ "dev": true }, "node_modules/read-pkg": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", - "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", + "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", "dev": true, "dependencies": { - "@types/normalize-package-data": "^2.4.0", + "@types/normalize-package-data": "^2.4.1", "normalize-package-data": "^3.0.2", "parse-json": "^5.2.0", - "type-fest": "^1.0.1" + "type-fest": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/read-pkg-up": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", - "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", + "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", "dev": true, "dependencies": { - "find-up": "^5.0.0", - "read-pkg": "^6.0.0", - "type-fest": "^1.0.1" + "find-up": "^6.3.0", + "read-pkg": "^7.1.0", + "type-fest": "^2.5.0" }, "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "node_modules/read-pkg-up/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, "engines": { "node": ">=10" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { "inherits": "^2.0.3", @@ -4783,18 +5075,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4852,9 +5132,9 @@ } }, "node_modules/resolve.exports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.0.tgz", - "integrity": "sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.1.tgz", + "integrity": "sha512-OEJWVeimw8mgQuj3HfkNl4KqRevH7lzeQNaWRPfx0PPse7Jk6ozcsG4FKVgtzDsC1KUF+YlTHh17NcgHOPykLw==", "dev": true, "engines": { "node": ">=10" @@ -4885,6 +5165,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5019,9 +5314,9 @@ } }, "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -5045,9 +5340,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, "node_modules/split": { @@ -5164,6 +5459,15 @@ "node": ">=8" } }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -5317,6 +5621,15 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "node_modules/titleize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", + "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -5416,15 +5729,6 @@ } } }, - "node_modules/ts-jest/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/tsc-watch": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.0.tgz", @@ -5528,6 +5832,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", @@ -5676,6 +5989,56 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/xdg-default-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", + "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", + "dev": true, + "dependencies": { + "execa": "^0.2.2", + "titleize": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/xdg-default-browser/node_modules/execa": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", + "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", + "dev": true, + "dependencies": { + "cross-spawn-async": "^2.1.1", + "npm-run-path": "^1.0.0", + "object-assign": "^4.0.1", + "path-key": "^1.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/xdg-default-browser/node_modules/npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", + "dev": true, + "dependencies": { + "path-key": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xdg-default-browser/node_modules/path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -5692,9 +6055,9 @@ "dev": true }, "node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "dev": true, "dependencies": { "cliui": "^8.0.1", @@ -5710,15 +6073,6 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", @@ -6199,15 +6553,30 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@eslint-community/eslint-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", + "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "dev": true + }, "@eslint/eslintrc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", - "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", + "espree": "^9.5.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -6217,9 +6586,9 @@ } }, "@eslint/js": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", - "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", "dev": true }, "@humanwhocodes/config-array": { @@ -6329,123 +6698,123 @@ "dev": true }, "@jest/console": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.3.tgz", - "integrity": "sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", + "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.3.tgz", - "integrity": "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", + "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", "dev": true, "requires": { - "@jest/console": "^29.4.3", - "@jest/reporters": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/reporters": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.4.3", - "jest-config": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-message-util": "^29.4.3", + "jest-changed-files": "^29.5.0", + "jest-config": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-resolve-dependencies": "^29.4.3", - "jest-runner": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", - "jest-watcher": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-resolve-dependencies": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", + "jest-watcher": "^29.5.0", "micromatch": "^4.0.4", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.3.tgz", - "integrity": "sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", + "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", "dev": true, "requires": { - "@jest/fake-timers": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^29.4.3" + "jest-mock": "^29.5.0" } }, "@jest/expect": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.3.tgz", - "integrity": "sha512-iktRU/YsxEtumI9zsPctYUk7ptpC+AVLLk1Ax3AsA4g1C+8OOnKDkIQBDHtD5hA/+VtgMd5AWI5gNlcAlt2vxQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", "dev": true, "requires": { - "expect": "^29.4.3", - "jest-snapshot": "^29.4.3" + "expect": "^29.5.0", + "jest-snapshot": "^29.5.0" } }, "@jest/expect-utils": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.3.tgz", - "integrity": "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", "dev": true, "requires": { "jest-get-type": "^29.4.3" } }, "@jest/fake-timers": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.3.tgz", - "integrity": "sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", + "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.4.3", - "jest-mock": "^29.4.3", - "jest-util": "^29.4.3" + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" } }, "@jest/globals": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.3.tgz", - "integrity": "sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", + "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", "dev": true, "requires": { - "@jest/environment": "^29.4.3", - "@jest/expect": "^29.4.3", - "@jest/types": "^29.4.3", - "jest-mock": "^29.4.3" + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/types": "^29.5.0", + "jest-mock": "^29.5.0" } }, "@jest/reporters": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.3.tgz", - "integrity": "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", + "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", @@ -6458,9 +6827,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", - "jest-worker": "^29.4.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -6488,46 +6857,46 @@ } }, "@jest/test-result": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.3.tgz", - "integrity": "sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", + "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", "dev": true, "requires": { - "@jest/console": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/types": "^29.5.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.3.tgz", - "integrity": "sha512-yi/t2nES4GB4G0mjLc0RInCq/cNr9dNwJxcGg8sslajua5Kb4kmozAc+qPLzplhBgfw1vLItbjyHzUN92UXicw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", + "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", "dev": true, "requires": { - "@jest/test-result": "^29.4.3", + "@jest/test-result": "^29.5.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.3.tgz", - "integrity": "sha512-8u0+fBGWolDshsFgPQJESkDa72da/EVwvL+II0trN2DR66wMwiQ9/CihaGfHdlLGFzbBZwMykFtxuwFdZqlKwg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", + "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -6535,9 +6904,9 @@ } }, "@jest/types": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.3.tgz", - "integrity": "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, "requires": { "@jest/schemas": "^29.4.3", @@ -6726,9 +7095,9 @@ } }, "@types/jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz", - "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", + "integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", "dev": true, "requires": { "expect": "^29.0.0", @@ -6754,9 +7123,9 @@ "dev": true }, "@types/node": { - "version": "18.14.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", - "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==", + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", "dev": true }, "@types/normalize-package-data": { @@ -6805,71 +7174,71 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", - "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", + "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/type-utils": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/type-utils": "5.55.0", + "@typescript-eslint/utils": "5.55.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "@typescript-eslint/parser": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.0.tgz", - "integrity": "sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", + "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", - "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", + "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0" + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0" } }, "@typescript-eslint/type-utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", - "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", + "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/utils": "5.55.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", + "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", - "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", + "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -6878,28 +7247,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", - "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", + "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", "dev": true, "requires": { + "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", + "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/types": "5.55.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -6989,15 +7358,15 @@ "dev": true }, "babel-jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.3.tgz", - "integrity": "sha512-o45Wyn32svZE+LnMVWv/Z4x0SwtLbh4FyGcYtR20kIWd+rdrDZ9Fzq8Ml3MYLD+mZvEdzCjZsCnYZ2jpJyQ+Nw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", + "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", "dev": true, "requires": { - "@jest/transform": "^29.4.3", + "@jest/transform": "^29.5.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.4.3", + "babel-preset-jest": "^29.5.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -7017,9 +7386,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.3.tgz", - "integrity": "sha512-mB6q2q3oahKphy5V7CpnNqZOCkxxZ9aokf1eh82Dy3jQmg4xvM1tGrh5y6BQUJh4a3Pj9+eLfwvAZ7VNKg7H8Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", + "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -7049,12 +7418,12 @@ } }, "babel-preset-jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.3.tgz", - "integrity": "sha512-gWx6COtSuma6n9bw+8/F+2PCXrIgxV/D1TJFnp6OyBK2cxPWg0K9p/sriNYeifKjpUkMViWQ09DSWtzJQRETsw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", + "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^29.4.3", + "babel-plugin-jest-hoist": "^29.5.0", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -7064,6 +7433,21 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true + }, + "bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "requires": { + "big-integer": "^1.6.44" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -7119,6 +7503,15 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "requires": { + "run-applescript": "^5.0.0" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -7132,27 +7525,27 @@ "dev": true }, "camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-8.0.2.tgz", + "integrity": "sha512-qMKdlOfsjlezMqxkUGGMaWWs17i2HoL15tM+wtx8ld4nLrUwU58TFdvyGOz/piNP842KeO8yXvggVQSdQ828NA==", "dev": true, "requires": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" + "camelcase": "^7.0.0", + "map-obj": "^4.3.0", + "quick-lru": "^6.1.1", + "type-fest": "^2.13.0" }, "dependencies": { "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", "dev": true }, "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true } } @@ -7269,6 +7662,43 @@ "which": "^2.0.1" } }, + "cross-spawn-async": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", + "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", + "dev": true, + "requires": { + "lru-cache": "^4.0.0", + "which": "^1.2.8" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + } + } + }, "crypto-random-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", @@ -7295,9 +7725,9 @@ } }, "decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", "dev": true }, "decamelize-keys": { @@ -7337,15 +7767,37 @@ "dev": true }, "deepmerge": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", - "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true }, + "default-browser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", + "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", + "dev": true, + "requires": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^5.0.0", + "xdg-default-browser": "^2.1.0" + } + }, + "default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "requires": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + } + }, "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true }, "detect-newline": { @@ -7424,13 +7876,15 @@ "dev": true }, "eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", - "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", "dev": true, "requires": { - "@eslint/eslintrc": "^2.0.0", - "@eslint/js": "8.35.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7441,9 +7895,8 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", + "espree": "^9.5.0", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -7465,7 +7918,6 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -7508,23 +7960,6 @@ "estraverse": "^4.1.1" } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, "eslint-visitor-keys": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", @@ -7532,9 +7967,9 @@ "dev": true }, "espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", "dev": true, "requires": { "acorn": "^8.8.0", @@ -7633,16 +8068,16 @@ "dev": true }, "expect": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.3.tgz", - "integrity": "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", "dev": true, "requires": { - "@jest/expect-utils": "^29.4.3", + "@jest/expect-utils": "^29.5.0", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3" + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" } }, "fast-deep-equal": { @@ -7715,9 +8150,9 @@ } }, "file-type": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", - "integrity": "sha512-jjMwFpnW8PKofLE/4ohlhqwDk5k0NC6iy0UHAJFKoY1fQeGMN0GDdLgHQrvCbSpMwbqzoCZhRI5dETCZna5qVA==", + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", + "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", "dev": true, "requires": { "readable-web-to-node-stream": "^3.0.2", @@ -7903,12 +8338,20 @@ "dev": true }, "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", + "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.5.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + } } }, "html-escaper": { @@ -8005,9 +8448,9 @@ } }, "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true }, "is-extglob": { @@ -8037,6 +8480,15 @@ "is-extglob": "^2.1.1" } }, + "is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "requires": { + "is-docker": "^3.0.0" + } + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -8068,6 +8520,14 @@ "dev": true, "requires": { "is-docker": "^2.0.0" + }, + "dependencies": { + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + } } }, "isexe": { @@ -8153,21 +8613,21 @@ } }, "jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.3.tgz", - "integrity": "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", + "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", "dev": true, "requires": { - "@jest/core": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/core": "^29.5.0", + "@jest/types": "^29.5.0", "import-local": "^3.0.2", - "jest-cli": "^29.4.3" + "jest-cli": "^29.5.0" } }, "jest-changed-files": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.3.tgz", - "integrity": "sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", + "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", "dev": true, "requires": { "execa": "^5.0.0", @@ -8175,92 +8635,93 @@ } }, "jest-circus": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.3.tgz", - "integrity": "sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", + "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", "dev": true, "requires": { - "@jest/environment": "^29.4.3", - "@jest/expect": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", + "jest-each": "^29.5.0", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", "p-limit": "^3.1.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.3.tgz", - "integrity": "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", + "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", "dev": true, "requires": { - "@jest/core": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/core": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-config": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "prompts": "^2.0.1", "yargs": "^17.3.1" } }, "jest-config": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.3.tgz", - "integrity": "sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", + "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.4.3", - "@jest/types": "^29.4.3", - "babel-jest": "^29.4.3", + "@jest/test-sequencer": "^29.5.0", + "@jest/types": "^29.5.0", + "babel-jest": "^29.5.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.4.3", - "jest-environment-node": "^29.4.3", + "jest-circus": "^29.5.0", + "jest-environment-node": "^29.5.0", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-runner": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" } }, "jest-diff": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.3.tgz", - "integrity": "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", "dev": true, "requires": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" } }, "jest-docblock": { @@ -8273,30 +8734,30 @@ } }, "jest-each": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.3.tgz", - "integrity": "sha512-1ElHNAnKcbJb/b+L+7j0/w7bDvljw4gTv1wL9fYOczeJrbTbkMGQ5iQPFJ3eFQH19VPTx1IyfePdqSpePKss7Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", + "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.4.3", - "pretty-format": "^29.4.3" + "jest-util": "^29.5.0", + "pretty-format": "^29.5.0" } }, "jest-environment-node": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.3.tgz", - "integrity": "sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", + "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", "dev": true, "requires": { - "@jest/environment": "^29.4.3", - "@jest/fake-timers": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^29.4.3", - "jest-util": "^29.4.3" + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" } }, "jest-get-type": { @@ -8306,12 +8767,12 @@ "dev": true }, "jest-haste-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.3.tgz", - "integrity": "sha512-eZIgAS8tvm5IZMtKlR8Y+feEOMfo2pSQkmNbufdbMzMSn9nitgGxF1waM/+LbryO3OkMcKS98SUb+j/cQxp/vQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", + "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", @@ -8319,60 +8780,60 @@ "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.4.3", - "jest-worker": "^29.4.3", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "jest-leak-detector": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.3.tgz", - "integrity": "sha512-9yw4VC1v2NspMMeV3daQ1yXPNxMgCzwq9BocCwYrRgXe4uaEJPAN0ZK37nFBhcy3cUwEVstFecFLaTHpF7NiGA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", + "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", "dev": true, "requires": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" } }, "jest-matcher-utils": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz", - "integrity": "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", + "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.4.3", + "jest-diff": "^29.5.0", "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" } }, "jest-message-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.3.tgz", - "integrity": "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", + "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.3.tgz", - "integrity": "sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", + "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-util": "^29.4.3" + "jest-util": "^29.5.0" } }, "jest-pnp-resolver": { @@ -8389,95 +8850,95 @@ "dev": true }, "jest-resolve": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.3.tgz", - "integrity": "sha512-GPokE1tzguRyT7dkxBim4wSx6E45S3bOQ7ZdKEG+Qj0Oac9+6AwJPCk0TZh5Vu0xzeX4afpb+eDmgbmZFFwpOw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", + "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.3.tgz", - "integrity": "sha512-uvKMZAQ3nmXLH7O8WAOhS5l0iWyT3WmnJBdmIHiV5tBbdaDZ1wqtNX04FONGoaFvSOSHBJxnwAVnSn1WHdGVaw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", + "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", "dev": true, "requires": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.4.3" + "jest-snapshot": "^29.5.0" } }, "jest-runner": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.3.tgz", - "integrity": "sha512-GWPTEiGmtHZv1KKeWlTX9SIFuK19uLXlRQU43ceOQ2hIfA5yPEJC7AMkvFKpdCHx6pNEdOD+2+8zbniEi3v3gA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", + "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", "dev": true, "requires": { - "@jest/console": "^29.4.3", - "@jest/environment": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/environment": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-leak-detector": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-util": "^29.4.3", - "jest-watcher": "^29.4.3", - "jest-worker": "^29.4.3", + "jest-environment-node": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-leak-detector": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-resolve": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-util": "^29.5.0", + "jest-watcher": "^29.5.0", + "jest-worker": "^29.5.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.3.tgz", - "integrity": "sha512-F5bHvxSH+LvLV24vVB3L8K467dt3y3dio6V3W89dUz9nzvTpqd/HcT9zfYKL2aZPvD63vQFgLvaUX/UpUhrP6Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", + "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", "dev": true, "requires": { - "@jest/environment": "^29.4.3", - "@jest/fake-timers": "^29.4.3", - "@jest/globals": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/globals": "^29.5.0", "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-mock": "^29.4.3", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.3.tgz", - "integrity": "sha512-NGlsqL0jLPDW91dz304QTM/SNO99lpcSYYAjNiX0Ou+sSGgkanKBcSjCfp/pqmiiO1nQaOyLp6XQddAzRcx3Xw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", + "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -8486,33 +8947,32 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/expect-utils": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.4.3", + "expect": "^29.5.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.4.3", + "jest-diff": "^29.5.0", "jest-get-type": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "semver": "^7.3.5" } }, "jest-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.3.tgz", - "integrity": "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", + "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -8521,17 +8981,17 @@ } }, "jest-validate": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.3.tgz", - "integrity": "sha512-J3u5v7aPQoXPzaar6GndAVhdQcZr/3osWSgTeKg5v574I9ybX/dTyH0AJFb5XgXIB7faVhf+rS7t4p3lL9qFaw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", + "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" }, "dependencies": { "camelcase": { @@ -8543,29 +9003,29 @@ } }, "jest-watcher": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.3.tgz", - "integrity": "sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", + "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", "dev": true, "requires": { - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.3.tgz", - "integrity": "sha512-GLHN/GTAAMEy5BFdvpUfzr9Dr80zQqBrh0fz1mtRMe05hqP45+HfQltu7oTBfduD0UeZs09d+maFtFYAXFWvAA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", + "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -8747,29 +9207,29 @@ "dev": true }, "meow": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", - "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", + "integrity": "sha512-Cl0yeeIrko6d94KpUo1M+0X1sB14ikoaqlIGuTH1fW4I+E3+YljL54/hb/BWmVfrV9tTV9zU04+xjw08Fh2WkA==", "dev": true, "requires": { "@types/minimist": "^1.2.2", - "camelcase-keys": "^7.0.0", - "decamelize": "^5.0.0", + "camelcase-keys": "^8.0.2", + "decamelize": "^6.0.0", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.2", - "read-pkg-up": "^8.0.0", + "normalize-package-data": "^4.0.1", + "read-pkg-up": "^9.1.0", "redent": "^4.0.0", "trim-newlines": "^4.0.2", - "type-fest": "^1.2.2", - "yargs-parser": "^20.2.9" + "type-fest": "^3.1.0", + "yargs-parser": "^21.1.1" }, "dependencies": { "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.1.tgz", + "integrity": "sha512-htXWckxlT6U4+ilVgweNliPqlsVSSucbxVexRYllyMVJDtf5rTjv6kF/s+qAd4QSL1BZcnJPEJavYBPQiWuZDA==", "dev": true } } @@ -8864,15 +9324,15 @@ "dev": true }, "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", + "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" } }, "normalize-path": { @@ -8890,6 +9350,12 @@ "path-key": "^3.0.0" } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8909,26 +9375,27 @@ } }, "open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", + "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", "dev": true, "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", + "default-browser": "^3.1.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", "is-wsl": "^2.2.0" } }, "open-cli": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.1.0.tgz", - "integrity": "sha512-Xnn/B7WY9ygV47oK+LlYp5WU8xr0tEL6SEw9jMX8n6ceElOs2AzVXFXI87/O0+b+LwLokQBZVxBMzGZHCYVppw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.2.0.tgz", + "integrity": "sha512-1ANJc8oJ92FiaNZ0o2Hw4WBvDJoXs1P74aFMtpAvlbkIPV4uPcQvDz7V6kMOrsZkmB4tglrHVMlLQaafuUuxXg==", "dev": true, "requires": { - "file-type": "^18.0.0", + "file-type": "^18.2.1", "get-stdin": "^9.0.0", - "meow": "^10.1.5", - "open": "^8.4.0", + "meow": "^11.0.0", + "open": "^9.0.0", "tempy": "^3.0.0" } }, @@ -9124,9 +9591,9 @@ "dev": true }, "pretty-format": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", - "integrity": "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "dev": true, "requires": { "@jest/schemas": "^29.4.3", @@ -9161,12 +9628,24 @@ "event-stream": "=3.3.4" } }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, "punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true }, + "pure-rand": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.1.tgz", + "integrity": "sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==", + "dev": true + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -9174,9 +9653,9 @@ "dev": true }, "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.1.tgz", + "integrity": "sha512-S27GBT+F0NTRiehtbrgaSE1idUAJ5bX8dPAQTdylEyNlrdcH5X4Lz7Edz3DYzecbsCluD5zO8ZNEe04z3D3u6Q==", "dev": true }, "react-is": { @@ -9186,48 +9665,118 @@ "dev": true }, "read-pkg": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", - "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", + "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", "dev": true, "requires": { - "@types/normalize-package-data": "^2.4.0", + "@types/normalize-package-data": "^2.4.1", "normalize-package-data": "^3.0.2", "parse-json": "^5.2.0", - "type-fest": "^1.0.1" + "type-fest": "^2.0.0" }, "dependencies": { + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } + }, "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true } } }, "read-pkg-up": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", - "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", + "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", "dev": true, "requires": { - "find-up": "^5.0.0", - "read-pkg": "^6.0.0", - "type-fest": "^1.0.1" + "find-up": "^6.3.0", + "read-pkg": "^7.1.0", + "type-fest": "^2.5.0" }, "dependencies": { + "find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "requires": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + } + }, + "locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "requires": { + "p-locate": "^6.0.0" + } + }, + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "requires": { + "p-limit": "^4.0.0" + } + }, + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true + }, "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "dev": true } } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -9254,12 +9803,6 @@ "strip-indent": "^4.0.0" } }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -9301,9 +9844,9 @@ "dev": true }, "resolve.exports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.0.tgz", - "integrity": "sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.1.tgz", + "integrity": "sha512-OEJWVeimw8mgQuj3HfkNl4KqRevH7lzeQNaWRPfx0PPse7Jk6ozcsG4FKVgtzDsC1KUF+YlTHh17NcgHOPykLw==", "dev": true }, "reusify": { @@ -9321,6 +9864,15 @@ "glob": "^7.1.3" } }, + "run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "requires": { + "execa": "^5.0.0" + } + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -9406,9 +9958,9 @@ } }, "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -9432,9 +9984,9 @@ } }, "spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, "split": { @@ -9529,6 +10081,12 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true + }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -9626,6 +10184,12 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "titleize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", + "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", + "dev": true + }, "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -9677,14 +10241,6 @@ "make-error": "1.x", "semver": "7.x", "yargs-parser": "^21.0.1" - }, - "dependencies": { - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } } }, "tsc-watch": { @@ -9750,6 +10306,12 @@ "crypto-random-string": "^4.0.0" } }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, "update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", @@ -9860,6 +10422,46 @@ "signal-exit": "^3.0.7" } }, + "xdg-default-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", + "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", + "dev": true, + "requires": { + "execa": "^0.2.2", + "titleize": "^1.0.0" + }, + "dependencies": { + "execa": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", + "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", + "dev": true, + "requires": { + "cross-spawn-async": "^2.1.1", + "npm-run-path": "^1.0.0", + "object-assign": "^4.0.1", + "path-key": "^1.0.0", + "strip-eof": "^1.0.0" + } + }, + "npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", + "dev": true, + "requires": { + "path-key": "^1.0.0" + } + }, + "path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", + "dev": true + } + } + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -9873,9 +10475,9 @@ "dev": true }, "yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "dev": true, "requires": { "cliui": "^8.0.1", @@ -9885,20 +10487,12 @@ "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" - }, - "dependencies": { - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } } }, "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true }, "yocto-queue": { diff --git a/package.json b/package.json index 396d7def0f..c1363a2eff 100644 --- a/package.json +++ b/package.json @@ -92,15 +92,15 @@ }, "devDependencies": { "@types/debug": "^4.1.7", - "@types/jest": "^29.4.0", - "@types/node": "^18.14.6", + "@types/jest": "^29.5.0", + "@types/node": "^18.15.3", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.54.0", - "@typescript-eslint/parser": "^5.54.0", - "eslint": "^8.35.0", + "@typescript-eslint/eslint-plugin": "^5.55.0", + "@typescript-eslint/parser": "^5.55.0", + "eslint": "^8.36.0", "eslint-plugin-jest": "^27.2.1", - "jest": "^29.4.3", - "open-cli": "^7.1.0", + "jest": "^29.5.0", + "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.0.5", From 7200507d6c4dbe2352835501aedcbe2705dc31fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 20 Mar 2023 17:29:53 +0100 Subject: [PATCH 038/525] 3.11.14 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4141b29a39..f27ff3e754 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.13", + "version": "3.11.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.13", + "version": "3.11.14", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index c1363a2eff..5442a62b22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.13", + "version": "3.11.14", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 6a7920e3b7b21ac9552ee3c4317f1f27eaafd0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Mar 2023 19:21:41 +0100 Subject: [PATCH 039/525] cosmetic --- worker/fuzzer/src/FuzzerUtils.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/worker/fuzzer/src/FuzzerUtils.cpp b/worker/fuzzer/src/FuzzerUtils.cpp index 10ef166519..7ed8565d27 100644 --- a/worker/fuzzer/src/FuzzerUtils.cpp +++ b/worker/fuzzer/src/FuzzerUtils.cpp @@ -12,10 +12,13 @@ void Fuzzer::Utils::Fuzz(const uint8_t* data, size_t len) /* IP class. */ std::string ip; + ip = std::string(reinterpret_cast(data2), INET6_ADDRSTRLEN / 2); ::Utils::IP::GetFamily(ip); + ip = std::string(reinterpret_cast(data2), INET6_ADDRSTRLEN); ::Utils::IP::GetFamily(ip); + ip = std::string(reinterpret_cast(data2), INET6_ADDRSTRLEN * 2); ::Utils::IP::GetFamily(ip); @@ -23,6 +26,7 @@ void Fuzzer::Utils::Fuzz(const uint8_t* data, size_t len) try { auto ip = std::string(reinterpret_cast(data2), len); + ::Utils::IP::NormalizeIp(ip); } catch (const MediaSoupError& error) @@ -60,6 +64,7 @@ void Fuzzer::Utils::Fuzz(const uint8_t* data, size_t len) try { size_t outLen; + ::Utils::String::Base64Encode(data2, len); ::Utils::String::Base64Decode(data2, len, outLen); } @@ -70,6 +75,7 @@ void Fuzzer::Utils::Fuzz(const uint8_t* data, size_t len) /* Time class. */ auto ntp = ::Utils::Time::TimeMs2Ntp(static_cast(len)); + ::Utils::Time::Ntp2TimeMs(ntp); ::Utils::Time::IsNewerTimestamp(static_cast(len), static_cast(len * len)); ::Utils::Time::IsNewerTimestamp(static_cast(len * len), static_cast(len)); From 626d3d906d8f1531a0a844d974f2d766f025894e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Mar 2023 19:32:01 +0100 Subject: [PATCH 040/525] Update NPM deps --- CHANGELOG.md | 5 ++ package-lock.json | 178 +++++++++++++++++++++++----------------------- package.json | 6 +- 3 files changed, 97 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f156759aa..747635842b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* Update NPM deps. + + ### 3.11.14 * Refactor RTP retransmission buffer in a separate and testable `RTC::RetransmissionBuffer` class ([PR #1023](https://github.com/versatica/mediasoup/pull/1023). diff --git a/package-lock.json b/package-lock.json index f27ff3e754..fe28003ca9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,10 +18,10 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.5.0", - "@types/node": "^18.15.3", + "@types/node": "^18.15.5", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.55.0", - "@typescript-eslint/parser": "^5.55.0", + "@typescript-eslint/eslint-plugin": "^5.56.0", + "@typescript-eslint/parser": "^5.56.0", "eslint": "^8.36.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", @@ -1341,9 +1341,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.15.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", - "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", + "version": "18.15.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", + "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1392,15 +1392,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", - "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.56.0.tgz", + "integrity": "sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/type-utils": "5.55.0", - "@typescript-eslint/utils": "5.55.0", + "@typescript-eslint/scope-manager": "5.56.0", + "@typescript-eslint/type-utils": "5.56.0", + "@typescript-eslint/utils": "5.56.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1426,14 +1426,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", - "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.56.0.tgz", + "integrity": "sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/scope-manager": "5.56.0", + "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/typescript-estree": "5.56.0", "debug": "^4.3.4" }, "engines": { @@ -1453,13 +1453,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", - "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz", + "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0" + "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/visitor-keys": "5.56.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1470,13 +1470,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", - "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.56.0.tgz", + "integrity": "sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.55.0", - "@typescript-eslint/utils": "5.55.0", + "@typescript-eslint/typescript-estree": "5.56.0", + "@typescript-eslint/utils": "5.56.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1497,9 +1497,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", - "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", + "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1510,13 +1510,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", - "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz", + "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0", + "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/visitor-keys": "5.56.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1537,17 +1537,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", - "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.56.0.tgz", + "integrity": "sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/scope-manager": "5.56.0", + "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/typescript-estree": "5.56.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1563,12 +1563,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", - "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", + "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/types": "5.56.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -7123,9 +7123,9 @@ "dev": true }, "@types/node": { - "version": "18.15.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", - "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", + "version": "18.15.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", + "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==", "dev": true }, "@types/normalize-package-data": { @@ -7174,15 +7174,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", - "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.56.0.tgz", + "integrity": "sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/type-utils": "5.55.0", - "@typescript-eslint/utils": "5.55.0", + "@typescript-eslint/scope-manager": "5.56.0", + "@typescript-eslint/type-utils": "5.56.0", + "@typescript-eslint/utils": "5.56.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7192,53 +7192,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", - "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.56.0.tgz", + "integrity": "sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/scope-manager": "5.56.0", + "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/typescript-estree": "5.56.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", - "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz", + "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0" + "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/visitor-keys": "5.56.0" } }, "@typescript-eslint/type-utils": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", - "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.56.0.tgz", + "integrity": "sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.55.0", - "@typescript-eslint/utils": "5.55.0", + "@typescript-eslint/typescript-estree": "5.56.0", + "@typescript-eslint/utils": "5.56.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", - "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", + "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", - "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz", + "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0", + "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/visitor-keys": "5.56.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7247,28 +7247,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", - "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.56.0.tgz", + "integrity": "sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/scope-manager": "5.56.0", + "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/typescript-estree": "5.56.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", - "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", + "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", "dev": true, "requires": { - "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/types": "5.56.0", "eslint-visitor-keys": "^3.3.0" } }, diff --git a/package.json b/package.json index 5442a62b22..b544e6bf95 100644 --- a/package.json +++ b/package.json @@ -93,10 +93,10 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.5.0", - "@types/node": "^18.15.3", + "@types/node": "^18.15.5", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.55.0", - "@typescript-eslint/parser": "^5.55.0", + "@typescript-eslint/eslint-plugin": "^5.56.0", + "@typescript-eslint/parser": "^5.56.0", "eslint": "^8.36.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", From ce7751e2797d76a8fabbe436c71b97da7a80ec7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Mar 2023 19:32:36 +0100 Subject: [PATCH 041/525] Rename RetransmissionBuffer to RtpRetransmissionBuffer --- ...Buffer.hpp => RtpRetransmissionBuffer.hpp} | 6 +-- worker/include/RTC/RtpStreamSend.hpp | 4 +- worker/meson.build | 4 +- ...Buffer.cpp => RtpRetransmissionBuffer.cpp} | 41 ++++++++++--------- worker/src/RTC/RtpStreamSend.cpp | 4 +- ...er.cpp => TestRtpRetransmissionBuffer.cpp} | 26 ++++++------ 6 files changed, 43 insertions(+), 42 deletions(-) rename worker/include/RTC/{RetransmissionBuffer.hpp => RtpRetransmissionBuffer.hpp} (91%) rename worker/src/RTC/{RetransmissionBuffer.cpp => RtpRetransmissionBuffer.cpp} (91%) rename worker/test/src/RTC/{TestRetransmissionBuffer.cpp => TestRtpRetransmissionBuffer.cpp} (83%) diff --git a/worker/include/RTC/RetransmissionBuffer.hpp b/worker/include/RTC/RtpRetransmissionBuffer.hpp similarity index 91% rename from worker/include/RTC/RetransmissionBuffer.hpp rename to worker/include/RTC/RtpRetransmissionBuffer.hpp index 66e451d9dc..4519ba653c 100644 --- a/worker/include/RTC/RetransmissionBuffer.hpp +++ b/worker/include/RTC/RtpRetransmissionBuffer.hpp @@ -11,7 +11,7 @@ namespace RTC // sequence number, while only taking as little memory as necessary to store // the range covering a maximum of `MaxRetransmissionDelayForVideoMs` or // `MaxRetransmissionDelayForAudioMs` ms. - class RetransmissionBuffer + class RtpRetransmissionBuffer { public: struct Item @@ -33,8 +33,8 @@ namespace RTC }; public: - RetransmissionBuffer(uint16_t maxItems, uint32_t maxRetransmissionDelayMs, uint32_t clockRate); - ~RetransmissionBuffer(); + RtpRetransmissionBuffer(uint16_t maxItems, uint32_t maxRetransmissionDelayMs, uint32_t clockRate); + ~RtpRetransmissionBuffer(); Item* Get(uint16_t seq) const; void Insert(RTC::RtpPacket* packet, std::shared_ptr& sharedPacket); diff --git a/worker/include/RTC/RtpStreamSend.hpp b/worker/include/RTC/RtpStreamSend.hpp index 6f619d0447..7f041c9b21 100644 --- a/worker/include/RTC/RtpStreamSend.hpp +++ b/worker/include/RTC/RtpStreamSend.hpp @@ -2,7 +2,7 @@ #define MS_RTC_RTP_STREAM_SEND_HPP #include "RTC/RateCalculator.hpp" -#include "RTC/RetransmissionBuffer.hpp" +#include "RTC/RtpRetransmissionBuffer.hpp" #include "RTC/RtpStream.hpp" namespace RTC @@ -61,7 +61,7 @@ namespace RTC std::string mid; uint16_t rtxSeq{ 0u }; RTC::RtpDataCounter transmissionCounter; - RTC::RetransmissionBuffer* retransmissionBuffer{ nullptr }; + RTC::RtpRetransmissionBuffer* retransmissionBuffer{ nullptr }; // The middle 32 bits out of 64 in the NTP timestamp received in the most // recent receiver reference timestamp. uint32_t lastRrTimestamp{ 0u }; diff --git a/worker/meson.build b/worker/meson.build index d86ccbc39f..51e123c51b 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -84,12 +84,12 @@ common_sources = [ 'src/RTC/PortManager.cpp', 'src/RTC/Producer.cpp', 'src/RTC/RateCalculator.cpp', - 'src/RTC/RetransmissionBuffer.cpp', 'src/RTC/Router.cpp', 'src/RTC/RtpListener.cpp', 'src/RTC/RtpObserver.cpp', 'src/RTC/RtpPacket.cpp', 'src/RTC/RtpProbationGenerator.cpp', + 'src/RTC/RtpRetransmissionBuffer.cpp', 'src/RTC/RtpStream.cpp', 'src/RTC/RtpStreamRecv.cpp', 'src/RTC/RtpStreamSend.cpp', @@ -288,9 +288,9 @@ mediasoup_worker_test = executable( 'test/src/RTC/TestKeyFrameRequestManager.cpp', 'test/src/RTC/TestNackGenerator.cpp', 'test/src/RTC/TestRateCalculator.cpp', - 'test/src/RTC/TestRetransmissionBuffer.cpp', 'test/src/RTC/TestRtpPacket.cpp', 'test/src/RTC/TestRtpPacketH264Svc.cpp', + 'test/src/RTC/TestRtpRetransmissionBuffer.cpp', 'test/src/RTC/TestRtpStreamSend.cpp', 'test/src/RTC/TestRtpStreamRecv.cpp', 'test/src/RTC/TestSeqManager.cpp', diff --git a/worker/src/RTC/RetransmissionBuffer.cpp b/worker/src/RTC/RtpRetransmissionBuffer.cpp similarity index 91% rename from worker/src/RTC/RetransmissionBuffer.cpp rename to worker/src/RTC/RtpRetransmissionBuffer.cpp index fce2fe8010..426d275dac 100644 --- a/worker/src/RTC/RetransmissionBuffer.cpp +++ b/worker/src/RTC/RtpRetransmissionBuffer.cpp @@ -1,7 +1,7 @@ -#define MS_CLASS "RTC::RetransmissionBuffer" +#define MS_CLASS "RTC::RtpRetransmissionBuffer" // #define MS_LOG_DEV_LEVEL 3 -#include "RTC/RetransmissionBuffer.hpp" +#include "RTC/RtpRetransmissionBuffer.hpp" #include "Logger.hpp" #include "RTC/SeqManager.hpp" @@ -9,7 +9,7 @@ namespace RTC { /* Instance methods. */ - RetransmissionBuffer::RetransmissionBuffer( + RtpRetransmissionBuffer::RtpRetransmissionBuffer( uint16_t maxItems, uint32_t maxRetransmissionDelayMs, uint32_t clockRate) : maxItems(maxItems), maxRetransmissionDelayMs(maxRetransmissionDelayMs), clockRate(clockRate) { @@ -18,14 +18,14 @@ namespace RTC MS_ASSERT(maxItems > 0u, "maxItems must be greater than 0"); } - RetransmissionBuffer::~RetransmissionBuffer() + RtpRetransmissionBuffer::~RtpRetransmissionBuffer() { MS_TRACE(); Clear(); } - RetransmissionBuffer::Item* RetransmissionBuffer::Get(uint16_t seq) const + RtpRetransmissionBuffer::Item* RtpRetransmissionBuffer::Get(uint16_t seq) const { MS_TRACE(); @@ -56,7 +56,8 @@ namespace RTC * not properly fit (by ensuring that elements in the buffer are not only * ordered by increasing seq but also that their timestamp are incremental). */ - void RetransmissionBuffer::Insert(RTC::RtpPacket* packet, std::shared_ptr& sharedPacket) + void RtpRetransmissionBuffer::Insert( + RTC::RtpPacket* packet, std::shared_ptr& sharedPacket) { MS_TRACE(); @@ -331,7 +332,7 @@ namespace RTC this->maxItems); } - void RetransmissionBuffer::Clear() + void RtpRetransmissionBuffer::Clear() { MS_TRACE(); @@ -352,11 +353,11 @@ namespace RTC this->startSeq = 0u; } - void RetransmissionBuffer::Dump() const + void RtpRetransmissionBuffer::Dump() const { MS_TRACE(); - MS_DUMP(""); + MS_DUMP(""); MS_DUMP(" buffer [size:%zu, maxSize:%" PRIu16 "]", this->buffer.size(), this->maxItems); if (this->buffer.size() > 0) { @@ -376,24 +377,24 @@ namespace RTC static_cast(newestItem->timestamp * 1000 / this->clockRate) - static_cast(oldestItem->timestamp * 1000 / this->clockRate)); } - MS_DUMP(""); + MS_DUMP(""); } - RetransmissionBuffer::Item* RetransmissionBuffer::GetOldest() const + RtpRetransmissionBuffer::Item* RtpRetransmissionBuffer::GetOldest() const { MS_TRACE(); return this->Get(this->startSeq); } - RetransmissionBuffer::Item* RetransmissionBuffer::GetNewest() const + RtpRetransmissionBuffer::Item* RtpRetransmissionBuffer::GetNewest() const { MS_TRACE(); return this->Get(this->startSeq + this->buffer.size() - 1); } - void RetransmissionBuffer::RemoveOldest() + void RtpRetransmissionBuffer::RemoveOldest() { MS_TRACE(); @@ -438,7 +439,7 @@ namespace RTC } } - void RetransmissionBuffer::RemoveOldest(uint16_t numItems) + void RtpRetransmissionBuffer::RemoveOldest(uint16_t numItems) { MS_TRACE(); @@ -457,7 +458,7 @@ namespace RTC } } - void RetransmissionBuffer::ClearTooOld() + void RtpRetransmissionBuffer::ClearTooOld() { MS_TRACE(); @@ -468,7 +469,7 @@ namespace RTC return; } - RetransmissionBuffer::Item* oldestItem{ nullptr }; + RtpRetransmissionBuffer::Item* oldestItem{ nullptr }; // Go through all buffer items starting with the first and free all items // that contain too old packets. @@ -487,7 +488,7 @@ namespace RTC } } - bool RetransmissionBuffer::IsTooOld(uint32_t timestamp, uint32_t newestTimestamp) const + bool RtpRetransmissionBuffer::IsTooOld(uint32_t timestamp, uint32_t newestTimestamp) const { MS_TRACE(); @@ -501,8 +502,8 @@ namespace RTC return static_cast(diffTs * 1000 / this->clockRate) > this->maxRetransmissionDelayMs; } - RetransmissionBuffer::Item* RetransmissionBuffer::FillItem( - RetransmissionBuffer::Item* item, + RtpRetransmissionBuffer::Item* RtpRetransmissionBuffer::FillItem( + RtpRetransmissionBuffer::Item* item, RTC::RtpPacket* packet, std::shared_ptr& sharedPacket) const { @@ -530,7 +531,7 @@ namespace RTC return item; } - void RetransmissionBuffer::Item::Reset() + void RtpRetransmissionBuffer::Item::Reset() { MS_TRACE(); diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 2f8e02eb70..c73b826717 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -15,7 +15,7 @@ namespace RTC static constexpr size_t RetransmissionBufferMaxItems{ 2500u }; // 17: 16 bit mask + the initial sequence number. static constexpr size_t MaxRequestedPackets{ 17u }; - thread_local static std::vector RetransmissionContainer( + thread_local static std::vector RetransmissionContainer( MaxRequestedPackets + 1); static constexpr uint32_t DefaultRtt{ 100u }; @@ -58,7 +58,7 @@ namespace RTC } } - this->retransmissionBuffer = new RTC::RetransmissionBuffer( + this->retransmissionBuffer = new RTC::RtpRetransmissionBuffer( RetransmissionBufferMaxItems, maxRetransmissionDelayMs, params.clockRate); } } diff --git a/worker/test/src/RTC/TestRetransmissionBuffer.cpp b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp similarity index 83% rename from worker/test/src/RTC/TestRetransmissionBuffer.cpp rename to worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp index 579930b7aa..c3a092203f 100644 --- a/worker/test/src/RTC/TestRetransmissionBuffer.cpp +++ b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp @@ -1,14 +1,14 @@ #include "common.hpp" -#include "RTC/RetransmissionBuffer.hpp" #include "RTC/RtpPacket.hpp" +#include "RTC/RtpRetransmissionBuffer.hpp" #include #include using namespace RTC; -// Class inheriting from RetransmissionBuffer so we can access its protected +// Class inheriting from RtpRetransmissionBuffer so we can access its protected // buffer member. -class MyRetransmissionBuffer : public RetransmissionBuffer +class RtpMyRetransmissionBuffer : public RtpRetransmissionBuffer { public: struct VerificationItem @@ -19,8 +19,8 @@ class MyRetransmissionBuffer : public RetransmissionBuffer }; public: - MyRetransmissionBuffer(uint16_t maxItems, uint32_t maxRetransmissionDelayMs, uint32_t clockRate) - : RetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate) + RtpMyRetransmissionBuffer(uint16_t maxItems, uint32_t maxRetransmissionDelayMs, uint32_t clockRate) + : RtpRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate) { } @@ -43,7 +43,7 @@ class MyRetransmissionBuffer : public RetransmissionBuffer std::shared_ptr sharedPacket; - RetransmissionBuffer::Insert(packet, sharedPacket); + RtpRetransmissionBuffer::Insert(packet, sharedPacket); } void AssertBuffer(std::vector verificationBuffer) @@ -66,7 +66,7 @@ class MyRetransmissionBuffer : public RetransmissionBuffer } }; -SCENARIO("RetransmissionBuffer", "[rtp][rtx]") +SCENARIO("RtpRetransmissionBuffer", "[rtp][rtx]") { SECTION("proper packets received in order") { @@ -74,7 +74,7 @@ SCENARIO("RetransmissionBuffer", "[rtp][rtx]") uint32_t maxRetransmissionDelayMs{ 2000u }; uint32_t clockRate{ 90000 }; - MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + RtpMyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); myRetransmissionBuffer.Insert(10001, 1000000000); myRetransmissionBuffer.Insert(10002, 1000000000); @@ -99,7 +99,7 @@ SCENARIO("RetransmissionBuffer", "[rtp][rtx]") uint32_t maxRetransmissionDelayMs{ 2000u }; uint32_t clockRate{ 90000 }; - MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + RtpMyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); myRetransmissionBuffer.Insert(20004, 2000000200); myRetransmissionBuffer.Insert(20001, 2000000000); @@ -124,7 +124,7 @@ SCENARIO("RetransmissionBuffer", "[rtp][rtx]") uint32_t maxRetransmissionDelayMs{ 2000u }; uint32_t clockRate{ 90000 }; - MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + RtpMyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); myRetransmissionBuffer.Insert(30001, 3000000000); myRetransmissionBuffer.Insert(30002, 3000000000); @@ -146,7 +146,7 @@ SCENARIO("RetransmissionBuffer", "[rtp][rtx]") uint32_t maxRetransmissionDelayMs{ 2000u }; uint32_t clockRate{ 90000 }; - MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + RtpMyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); myRetransmissionBuffer.Insert(40002, 4000000002); // Packet must be discarded since its timestamp is lower than in seq 40002. @@ -184,7 +184,7 @@ SCENARIO("RetransmissionBuffer", "[rtp][rtx]") uint32_t maxRetransmissionDelayMs{ 2000u }; uint32_t clockRate{ 90000 }; - MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + RtpMyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); myRetransmissionBuffer.Insert(10001, 1000000001); myRetransmissionBuffer.Insert(10002, 1000000002); @@ -209,7 +209,7 @@ SCENARIO("RetransmissionBuffer", "[rtp][rtx]") uint32_t maxRetransmissionDelayMs{ 2000u }; uint32_t clockRate{ 90000 }; - MyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + RtpMyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); auto maxDiffTs = static_cast(maxRetransmissionDelayMs * clockRate / 1000); From db61631913d8b99bba6d78d2ce5fabd1e152e8a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Mar 2023 20:00:21 +0100 Subject: [PATCH 042/525] cosmetic --- worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp | 4 +++ worker/fuzzer/src/RTC/FuzzerStunPacket.cpp | 4 +++ worker/fuzzer/src/fuzzer.cpp | 42 +++++++++++----------- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp b/worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp index 4167e371d5..8375a4e627 100644 --- a/worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp +++ b/worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp @@ -7,7 +7,9 @@ void Fuzzer::RTC::RtpPacket::Fuzz(const uint8_t* data, size_t len) { if (!::RTC::RtpPacket::IsRtp(data, len)) + { return; + } // We need to clone the given data into a separate buffer because setters // below will try to write into packet memory. @@ -31,7 +33,9 @@ void Fuzzer::RTC::RtpPacket::Fuzz(const uint8_t* data, size_t len) ::RTC::RtpPacket* packet = ::RTC::RtpPacket::Parse(data2, len); if (!packet) + { return; + } // packet->Dump(); packet->GetData(); diff --git a/worker/fuzzer/src/RTC/FuzzerStunPacket.cpp b/worker/fuzzer/src/RTC/FuzzerStunPacket.cpp index 177a530673..2110f8f0e1 100644 --- a/worker/fuzzer/src/RTC/FuzzerStunPacket.cpp +++ b/worker/fuzzer/src/RTC/FuzzerStunPacket.cpp @@ -4,12 +4,16 @@ void Fuzzer::RTC::StunPacket::Fuzz(const uint8_t* data, size_t len) { if (!::RTC::StunPacket::IsStun(data, len)) + { return; + } ::RTC::StunPacket* packet = ::RTC::StunPacket::Parse(data, len); if (!packet) + { return; + } // packet->Dump(); packet->GetClass(); diff --git a/worker/fuzzer/src/fuzzer.cpp b/worker/fuzzer/src/fuzzer.cpp index eaad253255..974a924711 100644 --- a/worker/fuzzer/src/fuzzer.cpp +++ b/worker/fuzzer/src/fuzzer.cpp @@ -19,11 +19,10 @@ #include #include -bool fuzzStun = false; -bool fuzzRtp = false; -bool fuzzRtcp = false; -bool fuzzRtpStream = false; -bool fuzzUtils = false; +bool fuzzStun = false; +bool fuzzRtp = false; +bool fuzzRtcp = false; +bool fuzzUtils = false; int Init(); @@ -36,16 +35,20 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) unused++; if (fuzzStun) + { Fuzzer::RTC::StunPacket::Fuzz(data, len); + } if (fuzzRtp) + { Fuzzer::RTC::RtpPacket::Fuzz(data, len); + Fuzzer::RTC::RtpStreamSend::Fuzz(data, len); + } if (fuzzRtcp) + { Fuzzer::RTC::RTCP::Packet::Fuzz(data, len); - - if (fuzzRtpStream) - Fuzzer::RTC::RtpStreamSend::Fuzz(data, len); + } if (fuzzUtils) { @@ -64,11 +67,17 @@ int Init() if (std::getenv("MS_FUZZ_LOG_LEVEL")) { if (std::string(std::getenv("MS_FUZZ_LOG_LEVEL")) == "debug") + { logLevel = LogLevel::LOG_DEBUG; + } else if (std::string(std::getenv("MS_FUZZ_LOG_LEVEL")) == "warn") + { logLevel = LogLevel::LOG_WARN; + } else if (std::string(std::getenv("MS_FUZZ_LOG_LEVEL")) == "error") + { logLevel = LogLevel::LOG_ERROR; + } } // Select what to fuzz. @@ -90,27 +99,20 @@ int Init() fuzzRtcp = true; } - if (std::getenv("MS_FUZZ_RTP_STREAM") && std::string(std::getenv("MS_FUZZ_RTP_STREAM")) == "1") - { - std::cout << "[fuzzer] RTP Stream fuzzers enabled" << std::endl; - - fuzzRtpStream = true; - } if (std::getenv("MS_FUZZ_UTILS") && std::string(std::getenv("MS_FUZZ_UTILS")) == "1") { std::cout << "[fuzzer] Utils fuzzers enabled" << std::endl; fuzzUtils = true; } - if (!fuzzUtils && !fuzzStun && !fuzzRtcp && !fuzzRtp && !fuzzRtpStream) + if (!fuzzUtils && !fuzzStun && !fuzzRtcp && !fuzzRtp) { std::cout << "[fuzzer] all fuzzers enabled" << std::endl; - fuzzStun = true; - fuzzRtp = true; - fuzzRtcp = true; - fuzzRtpStream = true; - fuzzUtils = true; + fuzzStun = true; + fuzzRtp = true; + fuzzRtcp = true; + fuzzUtils = true; } Settings::configuration.logLevel = logLevel; From 7ebffcc01bc8c5c0c08220ebf5a0229f66a75b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Mar 2023 21:29:14 +0100 Subject: [PATCH 043/525] Add fuzzer for RtpRetransmissionBuffer and fix crash (#1028) --- CHANGELOG.md | 1 + .../RTC/FuzzerRtpRetransmissionBuffer.hpp | 17 +++++++ ...h-2d204ea940d313bbdb69874f035ec5e7664b7181 | Bin 0 -> 4 bytes .../src/RTC/FuzzerRtpRetransmissionBuffer.cpp | 44 ++++++++++++++++++ worker/fuzzer/src/RTC/FuzzerRtpStreamSend.cpp | 2 +- worker/fuzzer/src/fuzzer.cpp | 2 + worker/meson.build | 1 + worker/src/RTC/RtpRetransmissionBuffer.cpp | 10 +++- .../src/RTC/TestRtpRetransmissionBuffer.cpp | 40 ++++++++++++++++ 9 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 worker/fuzzer/include/RTC/FuzzerRtpRetransmissionBuffer.hpp create mode 100644 worker/fuzzer/reports/crash-2d204ea940d313bbdb69874f035ec5e7664b7181 create mode 100644 worker/fuzzer/src/RTC/FuzzerRtpRetransmissionBuffer.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 747635842b..e0974e85e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT +* `RtpRetransmissionBuffer.cpp`: Fix crash and add fuzzer ([PR #1028](https://github.com/versatica/mediasoup/pull/1028). * Update NPM deps. diff --git a/worker/fuzzer/include/RTC/FuzzerRtpRetransmissionBuffer.hpp b/worker/fuzzer/include/RTC/FuzzerRtpRetransmissionBuffer.hpp new file mode 100644 index 0000000000..2a084b7960 --- /dev/null +++ b/worker/fuzzer/include/RTC/FuzzerRtpRetransmissionBuffer.hpp @@ -0,0 +1,17 @@ +#ifndef MS_FUZZER_RTC_RTP_RETRANSMISSION_BUFFER_HPP +#define MS_FUZZER_RTC_RTP_RETRANSMISSION_BUFFER_HPP + +#include "common.hpp" + +namespace Fuzzer +{ + namespace RTC + { + namespace RtpRetransmissionBuffer + { + void Fuzz(const uint8_t* data, size_t len); + } + } // namespace RTC +} // namespace Fuzzer + +#endif diff --git a/worker/fuzzer/reports/crash-2d204ea940d313bbdb69874f035ec5e7664b7181 b/worker/fuzzer/reports/crash-2d204ea940d313bbdb69874f035ec5e7664b7181 new file mode 100644 index 0000000000000000000000000000000000000000..7e768a24a66fb24c9684488d6a4988692d159926 GIT binary patch literal 4 LcmYdH_{{(S1fBuC literal 0 HcmV?d00001 diff --git a/worker/fuzzer/src/RTC/FuzzerRtpRetransmissionBuffer.cpp b/worker/fuzzer/src/RTC/FuzzerRtpRetransmissionBuffer.cpp new file mode 100644 index 0000000000..1bc6af4bca --- /dev/null +++ b/worker/fuzzer/src/RTC/FuzzerRtpRetransmissionBuffer.cpp @@ -0,0 +1,44 @@ +#include "RTC/FuzzerRtpRetransmissionBuffer.hpp" +#include "Utils.hpp" +#include "RTC/RtpPacket.hpp" +#include "RTC/RtpRetransmissionBuffer.hpp" + +void Fuzzer::RTC::RtpRetransmissionBuffer::Fuzz(const uint8_t* data, size_t len) +{ + uint16_t maxItems{ 2500u }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + // Trick to initialize our stuff just once (use static). + static ::RTC::RtpRetransmissionBuffer retransmissionBuffer( + maxItems, maxRetransmissionDelayMs, clockRate); + + // clang-format off + uint8_t buffer[] = + { + 0b10000000, 0b01111011, 0b01010010, 0b00001110, + 0b01011011, 0b01101011, 0b11001010, 0b10110101, + 0, 0, 0, 2 + }; + // clang-format on + + // Create base RtpPacket instance. + auto* packet = ::RTC::RtpPacket::Parse(buffer, 12); + size_t offset{ 0u }; + + while (len >= 4u) + { + std::shared_ptr<::RTC::RtpPacket> sharedPacket; + + // Set 'random' sequence number and timestamp. + packet->SetSequenceNumber(Utils::Byte::Get2Bytes(data, offset)); + packet->SetTimestamp(Utils::Byte::Get4Bytes(data, offset)); + + retransmissionBuffer.Insert(packet, sharedPacket); + + len -= 4u; + offset += 4; + } + + delete packet; +} diff --git a/worker/fuzzer/src/RTC/FuzzerRtpStreamSend.cpp b/worker/fuzzer/src/RTC/FuzzerRtpStreamSend.cpp index 88f8a806fb..d5f52b55e6 100644 --- a/worker/fuzzer/src/RTC/FuzzerRtpStreamSend.cpp +++ b/worker/fuzzer/src/RTC/FuzzerRtpStreamSend.cpp @@ -27,7 +27,6 @@ void Fuzzer::RTC::RtpStreamSend::Fuzz(const uint8_t* data, size_t len) // Create base RtpPacket instance. auto* packet = ::RTC::RtpPacket::Parse(buffer, 12); - size_t offset{ 0u }; // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -44,6 +43,7 @@ void Fuzzer::RTC::RtpStreamSend::Fuzz(const uint8_t* data, size_t len) std::string mid; auto* stream = new ::RTC::RtpStreamSend(&testRtpStreamListener, params, mid); + size_t offset{ 0u }; while (len >= 4u) { diff --git a/worker/fuzzer/src/fuzzer.cpp b/worker/fuzzer/src/fuzzer.cpp index 974a924711..f6f6bf4d1e 100644 --- a/worker/fuzzer/src/fuzzer.cpp +++ b/worker/fuzzer/src/fuzzer.cpp @@ -10,6 +10,7 @@ #include "Settings.hpp" #include "Utils.hpp" #include "RTC/FuzzerRtpPacket.hpp" +#include "RTC/FuzzerRtpRetransmissionBuffer.hpp" #include "RTC/FuzzerRtpStreamSend.hpp" #include "RTC/FuzzerStunPacket.hpp" #include "RTC/FuzzerTrendCalculator.hpp" @@ -43,6 +44,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { Fuzzer::RTC::RtpPacket::Fuzz(data, len); Fuzzer::RTC::RtpStreamSend::Fuzz(data, len); + Fuzzer::RTC::RtpRetransmissionBuffer::Fuzz(data, len); } if (fuzzRtcp) diff --git a/worker/meson.build b/worker/meson.build index 51e123c51b..ce6bf4eb20 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -354,6 +354,7 @@ executable( 'fuzzer/src/FuzzerUtils.cpp', 'fuzzer/src/RTC/FuzzerStunPacket.cpp', 'fuzzer/src/RTC/FuzzerRtpPacket.cpp', + 'fuzzer/src/RTC/FuzzerRtpRetransmissionBuffer.cpp', 'fuzzer/src/RTC/FuzzerRtpStreamSend.cpp', 'fuzzer/src/RTC/FuzzerTrendCalculator.cpp', 'fuzzer/src/RTC/RTCP/FuzzerBye.cpp', diff --git a/worker/src/RTC/RtpRetransmissionBuffer.cpp b/worker/src/RTC/RtpRetransmissionBuffer.cpp index 426d275dac..543af5b1c8 100644 --- a/worker/src/RTC/RtpRetransmissionBuffer.cpp +++ b/worker/src/RTC/RtpRetransmissionBuffer.cpp @@ -136,7 +136,11 @@ namespace RTC timestamp); numBlankSlots = 0u; + Clear(); + + // After clearing the buffer, update startSeq. + this->startSeq = seq; } else { @@ -358,7 +362,11 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" buffer [size:%zu, maxSize:%" PRIu16 "]", this->buffer.size(), this->maxItems); + MS_DUMP( + " buffer [size:%zu, maxSize:%" PRIu16 ", startSeq:%" PRIu16 "]", + this->buffer.size(), + this->maxItems, + this->startSeq); if (this->buffer.size() > 0) { const auto* oldestItem = GetOldest(); diff --git a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp index c3a092203f..1d11c5364b 100644 --- a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp +++ b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp @@ -229,4 +229,44 @@ SCENARIO("RtpRetransmissionBuffer", "[rtp][rtx]") ); // clang-format on } + + SECTION("fuzzer generated packets") + { + uint16_t maxItems{ 2500u }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + RtpMyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + + // These packets reproduce an already fixed crash reported here: + // https://github.com/versatica/mediasoup/issues/1027#issuecomment-1478464584 + // I've commented first packets and just left those that produce the crash. + + // myRetransmissionBuffer.Insert(14906, 976891962); + // myRetransmissionBuffer.Insert(14906, 976891962); + // myRetransmissionBuffer.Insert(14906, 976892730); + // myRetransmissionBuffer.Insert(13157, 862283031); + // myRetransmissionBuffer.Insert(13114, 859453491); + // myRetransmissionBuffer.Insert(14906, 976892264); + // myRetransmissionBuffer.Insert(14906, 976897098); + // myRetransmissionBuffer.Insert(13114, 859464290); + // myRetransmissionBuffer.Insert(14906, 976889088); + // myRetransmissionBuffer.Insert(13056, 855638184); + // myRetransmissionBuffer.Insert(14906, 976891950); + // myRetransmissionBuffer.Insert(17722, 1161443894); + // myRetransmissionBuffer.Insert(12846, 841888049); + // myRetransmissionBuffer.Insert(14906, 976905830); + // myRetransmissionBuffer.Insert(15677, 1027420485); + // myRetransmissionBuffer.Insert(33742, 2211317269); + // myRetransmissionBuffer.Insert(14906, 976892672); + // myRetransmissionBuffer.Insert(13102, 858665774); + // myRetransmissionBuffer.Insert(12850, 842150702); + // myRetransmissionBuffer.Insert(14906, 976891941); + // myRetransmissionBuffer.Insert(15677, 1027423549); + // myRetransmissionBuffer.Insert(12346, 809120580); + // myRetransmissionBuffer.Insert(12645, 828715313); + myRetransmissionBuffer.Insert(12645, 828702743); + myRetransmissionBuffer.Insert(33998, 2228092928); + myRetransmissionBuffer.Insert(33998, 2228092928); + } } From 5be8faa840fac2c702535aee7dd725d5d3418898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Mar 2023 21:30:38 +0100 Subject: [PATCH 044/525] 3.11.15 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0974e85e7..f5b9c283fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.11.15 * `RtpRetransmissionBuffer.cpp`: Fix crash and add fuzzer ([PR #1028](https://github.com/versatica/mediasoup/pull/1028). * Update NPM deps. diff --git a/package-lock.json b/package-lock.json index fe28003ca9..b0d1d6e572 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.14", + "version": "3.11.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.14", + "version": "3.11.15", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index b544e6bf95..ca4add311b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.14", + "version": "3.11.15", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 9ae56538e1e699fe37d969b826ed6c99b31f5f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 22 Mar 2023 13:26:56 +0100 Subject: [PATCH 045/525] RtpRetransmissionBuffer: get rid of startSeq private member (#1029) --- CHANGELOG.md | 7 +- .../include/RTC/RtpRetransmissionBuffer.hpp | 2 - worker/src/RTC/RtpRetransmissionBuffer.cpp | 70 ++++++++----------- 3 files changed, 36 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5b9c283fb..01c4058c5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,14 @@ # Changelog +### NEXT + +* `RtpRetransmissionBuffer`: Get rid of not necessary `startSeq` private member ([PR #1029](https://github.com/versatica/mediasoup/pull/1029). + + ### 3.11.15 -* `RtpRetransmissionBuffer.cpp`: Fix crash and add fuzzer ([PR #1028](https://github.com/versatica/mediasoup/pull/1028). +* `RtpRetransmissionBuffer`: Fix crash and add fuzzer ([PR #1028](https://github.com/versatica/mediasoup/pull/1028). * Update NPM deps. diff --git a/worker/include/RTC/RtpRetransmissionBuffer.hpp b/worker/include/RTC/RtpRetransmissionBuffer.hpp index 4519ba653c..059879d546 100644 --- a/worker/include/RTC/RtpRetransmissionBuffer.hpp +++ b/worker/include/RTC/RtpRetransmissionBuffer.hpp @@ -60,8 +60,6 @@ namespace RTC uint16_t maxItems; uint32_t maxRetransmissionDelayMs; uint32_t clockRate; - // Others. - uint16_t startSeq{ 0u }; }; } // namespace RTC diff --git a/worker/src/RTC/RtpRetransmissionBuffer.cpp b/worker/src/RTC/RtpRetransmissionBuffer.cpp index 543af5b1c8..dd3e33f294 100644 --- a/worker/src/RTC/RtpRetransmissionBuffer.cpp +++ b/worker/src/RTC/RtpRetransmissionBuffer.cpp @@ -29,17 +29,19 @@ namespace RTC { MS_TRACE(); - if (this->buffer.empty()) + const auto* oldestItem = GetOldest(); + + if (!oldestItem) { return nullptr; } - if (RTC::SeqManager::IsSeqLowerThan(seq, this->startSeq)) + if (RTC::SeqManager::IsSeqLowerThan(seq, oldestItem->sequenceNumber)) { return nullptr; } - auto idx = static_cast(seq - this->startSeq); + const auto idx = static_cast(seq - oldestItem->sequenceNumber); if (idx > static_cast(this->buffer.size() - 1)) { @@ -61,9 +63,9 @@ namespace RTC { MS_TRACE(); - auto ssrc = packet->GetSsrc(); - auto seq = packet->GetSequenceNumber(); - auto timestamp = packet->GetTimestamp(); + const auto ssrc = packet->GetSsrc(); + const auto seq = packet->GetSequenceNumber(); + const auto timestamp = packet->GetTimestamp(); MS_DEBUG_DEV("packet [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", seq, timestamp); @@ -76,17 +78,14 @@ namespace RTC this->buffer.push_back(FillItem(item, packet, sharedPacket)); - // Packet's seq number becomes startSeq. - this->startSeq = seq; - return; } // Clear too old packets in the buffer. ClearTooOld(); - auto* oldestItem = GetOldest(); - auto* newestItem = GetNewest(); + const auto* oldestItem = GetOldest(); + const auto* newestItem = GetNewest(); MS_ASSERT(oldestItem != nullptr, "oldest item doesn't exist"); MS_ASSERT(newestItem != nullptr, "newest item doesn't exist"); @@ -120,7 +119,7 @@ namespace RTC // the buffer. if (this->buffer.size() + numBlankSlots + 1 > this->maxItems) { - auto numItemsToRemove = + const auto numItemsToRemove = static_cast(this->buffer.size() + numBlankSlots + 1 - this->maxItems); // If num of items to be removed exceed buffer size minus one (needed to @@ -138,9 +137,6 @@ namespace RTC numBlankSlots = 0u; Clear(); - - // After clearing the buffer, update startSeq. - this->startSeq = seq; } else { @@ -203,7 +199,7 @@ namespace RTC // Calculate how many blank slots it would be necessary to add when // pushing new item to the fton of the buffer. - auto numBlankSlots = static_cast(oldestItem->sequenceNumber - seq - 1); + const auto numBlankSlots = static_cast(oldestItem->sequenceNumber - seq - 1); // If adding this packet (and needed blank slots) to the front makes the // buffer exceed its max size, discard this packet. @@ -230,9 +226,6 @@ namespace RTC auto* item = new Item(); this->buffer.push_front(FillItem(item, packet, sharedPacket)); - - // Packet's seq number becomes startSeq. - this->startSeq = seq; } // Otherwise packet must be inserted between oldest and newest stored items // so there is already an allocated slot for it. @@ -259,13 +252,13 @@ namespace RTC } // idx is the intended position of the received packet in the buffer. - auto idx = static_cast(seq - this->startSeq); + const auto idx = static_cast(seq - oldestItem->sequenceNumber); // Validate that packet timestamp is equal or higher than the timestamp of // the immediate older packet (if any). for (auto idx2 = static_cast(idx - 1); idx2 >= 0; --idx2) { - auto* olderItem = this->buffer.at(idx2); + const auto* olderItem = this->buffer.at(idx2); // Blank slot, continue. if (!olderItem) @@ -296,7 +289,7 @@ namespace RTC // the immediate newer packet (if any). for (auto idx2 = static_cast(idx + 1); idx2 < this->buffer.size(); ++idx2) { - auto* newerItem = this->buffer.at(idx2); + const auto* newerItem = this->buffer.at(idx2); // Blank slot, continue. if (!newerItem) @@ -354,7 +347,6 @@ namespace RTC } this->buffer.clear(); - this->startSeq = 0u; } void RtpRetransmissionBuffer::Dump() const @@ -362,11 +354,7 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP( - " buffer [size:%zu, maxSize:%" PRIu16 ", startSeq:%" PRIu16 "]", - this->buffer.size(), - this->maxItems, - this->startSeq); + MS_DUMP(" buffer [size:%zu, maxSize:%" PRIu16 "]", this->buffer.size(), this->maxItems); if (this->buffer.size() > 0) { const auto* oldestItem = GetOldest(); @@ -392,14 +380,24 @@ namespace RTC { MS_TRACE(); - return this->Get(this->startSeq); + if (this->buffer.empty()) + { + return nullptr; + } + + return this->buffer.front(); } RtpRetransmissionBuffer::Item* RtpRetransmissionBuffer::GetNewest() const { MS_TRACE(); - return this->Get(this->startSeq + this->buffer.size() - 1); + if (this->buffer.empty()) + { + return nullptr; + } + + return this->buffer.back(); } void RtpRetransmissionBuffer::RemoveOldest() @@ -411,7 +409,7 @@ namespace RTC return; } - auto* item = this->buffer.at(0); + auto* item = this->buffer.front(); // Reset the stored item (decrease RTP packet shared pointer counter). item->Reset(); @@ -419,7 +417,6 @@ namespace RTC delete item; this->buffer.pop_front(); - this->startSeq++; MS_DEBUG_DEV("removed 1 item from the front"); @@ -430,7 +427,6 @@ namespace RTC while (!this->buffer.empty() && this->buffer.front() == nullptr) { this->buffer.pop_front(); - this->startSeq++; ++numItemsRemoved; } @@ -439,12 +435,6 @@ namespace RTC { MS_DEBUG_DEV("removed 1 blank slot from the front"); } - - // If we emptied the full buffer, reset startSeq. - if (this->buffer.empty()) - { - this->startSeq = 0u; - } } void RtpRetransmissionBuffer::RemoveOldest(uint16_t numItems) @@ -458,7 +448,7 @@ namespace RTC numItems, this->buffer.size()); - auto intendedBufferSize = this->buffer.size() - numItems; + const auto intendedBufferSize = this->buffer.size() - numItems; while (this->buffer.size() > intendedBufferSize) { From 6b9a91a827832db929b7a6a7d966a61dbe3684f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 23 Mar 2023 15:49:07 +0100 Subject: [PATCH 046/525] Upgrade TypeScript to 5.0.2 --- CHANGELOG.md | 1 + package-lock.json | 16 ++++++++-------- package.json | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c4058c5f..e15d0a2eb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### NEXT * `RtpRetransmissionBuffer`: Get rid of not necessary `startSeq` private member ([PR #1029](https://github.com/versatica/mediasoup/pull/1029). +* Node: Upgrade TypeScript to 5.0.2. ### 3.11.15 diff --git a/package-lock.json b/package-lock.json index b0d1d6e572..39a6520578 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.0.5", "tsc-watch": "^6.0.0", - "typescript": "^4.9.5" + "typescript": "^5.0.2" }, "engines": { "node": ">=16" @@ -5805,16 +5805,16 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=12.20" } }, "node_modules/unique-string": { @@ -10292,9 +10292,9 @@ "dev": true }, "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index ca4add311b..f8776f8f03 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.0.5", "tsc-watch": "^6.0.0", - "typescript": "^4.9.5" + "typescript": "^5.0.2" } } From 727d17367731a73f10d3de5668943ae21e668bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 27 Mar 2023 19:01:53 +0200 Subject: [PATCH 047/525] Fix SeqManager (#1032) --- CHANGELOG.md | 5 +- worker/include/RTC/SeqManager.hpp | 4 +- worker/src/RTC/SeqManager.cpp | 105 +++++++++++++++++-------- worker/test/src/RTC/TestSeqManager.cpp | 56 +++++++++++-- 4 files changed, 127 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e15d0a2eb0..cef484a8cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ### NEXT -* `RtpRetransmissionBuffer`: Get rid of not necessary `startSeq` private member ([PR #1029](https://github.com/versatica/mediasoup/pull/1029). +* Fix `SeqManager`: Properly consider previous cycle dropped inputs ([PR #1032](https://github.com/versatica/mediasoup/pull/1032)). +* `RtpRetransmissionBuffer`: Get rid of not necessary `startSeq` private member ([PR #1029](https://github.com/versatica/mediasoup/pull/1029)). * Node: Upgrade TypeScript to 5.0.2. @@ -15,7 +16,7 @@ ### 3.11.14 -* Refactor RTP retransmission buffer in a separate and testable `RTC::RetransmissionBuffer` class ([PR #1023](https://github.com/versatica/mediasoup/pull/1023). +* Refactor RTP retransmission buffer in a separate and testable `RTC::RetransmissionBuffer` class ([PR #1023](https://github.com/versatica/mediasoup/pull/1023)). * Update NPM deps. diff --git a/worker/include/RTC/SeqManager.hpp b/worker/include/RTC/SeqManager.hpp index 3bf0e74dc8..5d4eb17654 100644 --- a/worker/include/RTC/SeqManager.hpp +++ b/worker/include/RTC/SeqManager.hpp @@ -29,7 +29,6 @@ namespace RTC private: static const SeqLowerThan isSeqLowerThan; static const SeqHigherThan isSeqHigherThan; - static T Delta(const T lhs, const T rhs); public: static bool IsSeqLowerThan(const T lhs, const T rhs); @@ -46,6 +45,9 @@ namespace RTC T GetMaxInput() const; T GetMaxOutput() const; + private: + void ClearDropped(); + private: T base{ 0 }; T maxOutput{ 0 }; diff --git a/worker/src/RTC/SeqManager.cpp b/worker/src/RTC/SeqManager.cpp index d2e8558ca3..73d21a431c 100644 --- a/worker/src/RTC/SeqManager.cpp +++ b/worker/src/RTC/SeqManager.cpp @@ -39,14 +39,6 @@ namespace RTC return isSeqHigherThan(lhs, rhs); } - template - T SeqManager::Delta(const T lhs, const T rhs) - { - T value = (lhs > rhs) ? (lhs - rhs) : (MaxValue - rhs + lhs); - - return value & MaxValue; - } - template void SeqManager::Sync(T input) { @@ -84,48 +76,55 @@ namespace RTC // There are dropped inputs. Synchronize. if (!this->dropped.empty()) { - // Delete dropped inputs older than input - MaxValue/2. - size_t droppedCount = this->dropped.size(); - const size_t threshold = (input - MaxValue / 2) & MaxValue; - auto it = this->dropped.lower_bound(threshold); - this->dropped.erase(this->dropped.begin(), it); - this->base = (this->base - (droppedCount - this->dropped.size())) & MaxValue; - - // Count dropped entries before 'input' in order to adapt the base. - droppedCount = this->dropped.size(); - it = this->dropped.lower_bound(input); - - if (it != this->dropped.end()) + // Check whether this input was dropped. + if (this->dropped.find(input) != this->dropped.end()) { - // Check whether this input was dropped. - if (*it == input) - { - MS_DEBUG_DEV("trying to send a dropped input"); + MS_DEBUG_DEV("trying to send a dropped input"); - return false; - } + return false; + } - droppedCount -= std::distance(it, this->dropped.end()); + // Dropped entries count that must be considered for the output. + size_t count{ 0 }; + + /* + * Consider values lower than input and those higher that input + * which belong to a previous cycle. + */ + for (const auto& value : this->dropped) + { + // clang-format off + if + ( + IsSeqLowerThan(value, input) || + ( + (value > input && (value - input > MaxValue / 3)) || + (value < input && (input - value > MaxValue / 3)) + ) + ) + // clang-format on + { + count++; + } } - base = (this->base - droppedCount) & MaxValue; + base = (this->base - count) & MaxValue; } output = (input + base) & MaxValue; - T idelta = SeqManager::Delta(input, this->maxInput); - T odelta = SeqManager::Delta(output, this->maxOutput); - // New input is higher than the maximum seen. But less than acceptable units higher. // Keep it as the maximum seen. See Drop(). - if (idelta < MaxValue / 2) + if (IsSeqHigherThan(input, this->maxInput)) this->maxInput = input; // New output is higher than the maximum seen. But less than acceptable units higher. // Keep it as the maximum seen. See Sync(). - if (odelta < MaxValue / 2) + if (IsSeqHigherThan(output, this->maxOutput)) this->maxOutput = output; + ClearDropped(); + return true; } @@ -141,8 +140,48 @@ namespace RTC return this->maxOutput; } + /* + * Delete droped inputs greater than maxInput that belong to a previous + * cycle. + */ + template + void SeqManager::ClearDropped() + { + // Cleanup dropped values. + if (this->dropped.empty()) + { + return; + } + + const size_t threshold = (this->maxInput + MaxValue / 3) & MaxValue; + const size_t previousDroppedSize = this->dropped.size(); + const auto it1 = this->dropped.upper_bound(this->maxInput); + const auto it2 = this->dropped.lower_bound(threshold); + + // There is no dropped value greater than this->maxInput. + if (it1 == this->dropped.end()) + { + return; + } + + // There is a single value in the range. + if (it1 == it2) + { + this->dropped.erase(it1); + } + // There are many values in the range. + else + { + this->dropped.erase(it1, it2); + } + + // Adapt base. + this->base = (this->base - (previousDroppedSize - this->dropped.size())) & MaxValue; + } + // Explicit instantiation to have all SeqManager definitions in this file. template class SeqManager; + template class SeqManager; // For testing. template class SeqManager; template class SeqManager; // For PictureID (15 bits). template class SeqManager; diff --git a/worker/test/src/RTC/TestSeqManager.cpp b/worker/test/src/RTC/TestSeqManager.cpp index 5c4624fe6d..c59641c62c 100644 --- a/worker/test/src/RTC/TestSeqManager.cpp +++ b/worker/test/src/RTC/TestSeqManager.cpp @@ -56,7 +56,7 @@ void validate(SeqManager& seqManager, std::vector>& } } -SCENARIO("SeqManager", "[rtc]") +SCENARIO("SeqManager", "[rtc][SeqMananger]") { SECTION("0 is greater than 65000") { @@ -577,10 +577,10 @@ SCENARIO("SeqManager", "[rtc]") { { 0, 1, true, false, 0, 0 }, }; - for (uint16_t j = 0; j < 100; ++j) { + for (uint16_t j = 0; j < 3; ++j) { for (uint16_t i = 1; i < std::numeric_limits::max(); ++i) { - uint16_t output = i + 1; - inputs.push_back({ i, output, false, false, 0, i }); + const uint16_t output = i + 1; + inputs.emplace_back( i, output, false, false, 0, i ); } } // clang-format on @@ -596,10 +596,10 @@ SCENARIO("SeqManager", "[rtc]") { { 0, 1, true, false, 0, 0 }, }; - for (uint16_t j = 0; j < 100; ++j) { + for (uint16_t j = 0; j < 3; ++j) { for (uint16_t i = 1; i < kMaxNumberFor15Bits; ++i) { - uint16_t output = i + 1; - inputs.push_back({ i, output, false, false, 0, i }); + const uint16_t output = i + 1; + inputs.emplace_back( i, output, false, false, 0, i ); } } // clang-format on @@ -607,4 +607,46 @@ SCENARIO("SeqManager", "[rtc]") SeqManager seqManager; validate(seqManager, inputs); } + + SECTION("should produce same output for same old input before drop (15 bits range)") + { + // clang-format off + std::vector> inputs = + { + { 10, 1, true, false }, // sync. + { 11, 2, false, false }, + { 12, 3, false, false }, + { 13, 4, false, false }, + { 14, 0, false, true }, // drop. + { 15, 5, false, false }, + { 12, 3, false, false } + }; + // clang-format on + + SeqManager seqManager; + validate(seqManager, inputs); + } + + SECTION("should properly clean previous cycle drops") + { + // clang-format off + std::vector> inputs = + { + { 1, 1, false, false, 0 }, + { 2, 0, false, true, 0 }, // Drop. + { 3, 2, false, false, 0 }, + { 4, 3, false, false, 0 }, + { 5, 4, false, false, 0 }, + { 6, 5, false, false, 0 }, + { 7, 6, false, false, 0 }, + { 0, 7, false, false, 0 }, + { 1, 0, false, false, 0 }, + { 2, 1, false, false, 0 }, + { 3, 2, false, false, 0 } + }; + // clang-format on + + SeqManager seqManager; + validate(seqManager, inputs); + } } From d6c9edf6cdae8404b3cfb105373e7bd26f0404a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 27 Mar 2023 19:04:54 +0200 Subject: [PATCH 048/525] Update NPM deps and fix CHANGELOG links --- CHANGELOG.md | 3 ++- package-lock.json | 14 +++++++------- package.json | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cef484a8cc..d12878cb9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,12 @@ * Fix `SeqManager`: Properly consider previous cycle dropped inputs ([PR #1032](https://github.com/versatica/mediasoup/pull/1032)). * `RtpRetransmissionBuffer`: Get rid of not necessary `startSeq` private member ([PR #1029](https://github.com/versatica/mediasoup/pull/1029)). * Node: Upgrade TypeScript to 5.0.2. +* Update NPM deps. ### 3.11.15 -* `RtpRetransmissionBuffer`: Fix crash and add fuzzer ([PR #1028](https://github.com/versatica/mediasoup/pull/1028). +* `RtpRetransmissionBuffer`: Fix crash and add fuzzer ([PR #1028](https://github.com/versatica/mediasoup/pull/1028)). * Update NPM deps. diff --git a/package-lock.json b/package-lock.json index 39a6520578..e4657515a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.5.0", - "@types/node": "^18.15.5", + "@types/node": "^18.15.10", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", @@ -1341,9 +1341,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.15.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", - "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==", + "version": "18.15.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz", + "integrity": "sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -7123,9 +7123,9 @@ "dev": true }, "@types/node": { - "version": "18.15.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", - "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==", + "version": "18.15.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz", + "integrity": "sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index f8776f8f03..fb07e8cd2f 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.5.0", - "@types/node": "^18.15.5", + "@types/node": "^18.15.10", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", From 7bbe1eb8bfd4e8eff8a2d7069ee9fccfe1744de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 27 Mar 2023 19:06:28 +0200 Subject: [PATCH 049/525] 3.11.16 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d12878cb9b..14e25d287f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.11.16 * Fix `SeqManager`: Properly consider previous cycle dropped inputs ([PR #1032](https://github.com/versatica/mediasoup/pull/1032)). * `RtpRetransmissionBuffer`: Get rid of not necessary `startSeq` private member ([PR #1029](https://github.com/versatica/mediasoup/pull/1029)). diff --git a/package-lock.json b/package-lock.json index e4657515a0..efec896fbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.15", + "version": "3.11.16", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.15", + "version": "3.11.16", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index fb07e8cd2f..8ae5482137 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.15", + "version": "3.11.16", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 6a44fc39f61ec342c5e8af000c38c98d92cab839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Tue, 28 Mar 2023 11:13:43 +0200 Subject: [PATCH 050/525] Github workflow: remove deprecated Ubuntu 18.04 (#1033) --- .github/workflows/mediasoup-worker.yaml | 6 ------ CHANGELOG.md | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 3ef8fa58c9..489e6bb741 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -8,12 +8,6 @@ jobs: fail-fast: false matrix: build: - - os: ubuntu-18.04 - cc: gcc - cxx: g++ - - os: ubuntu-18.04 - cc: clang - cxx: clang++ - os: ubuntu-20.04 cc: gcc cxx: g++ diff --git a/CHANGELOG.md b/CHANGELOG.md index 14e25d287f..59df0a6f91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +* Github workflow: Remove deprecated Ubuntu version 18.04 ([PR #1033](https://github.com/versatica/mediasoup/pull/1033)). + ### 3.11.16 From 6a671aab0123266a35647142cebb371263d96e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 28 Mar 2023 12:25:39 +0200 Subject: [PATCH 051/525] GitHub CI: Cancel in progress workflows (#1034) --- .github/workflows/mediasoup-node.yaml | 8 +++++++- .github/workflows/mediasoup-rust.yaml | 6 ++++++ .github/workflows/mediasoup-worker.yaml | 9 ++++++++- .github/workflows/pull-request-stats.yml | 3 ++- CHANGELOG.md | 3 ++- 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index eef5549b6a..a925d6dc69 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -2,11 +2,17 @@ name: mediasoup-node on: [push, pull_request] +concurrency: + # Cancel a currently running workflow from the same PR, branch or tag when a + # new workflow is triggered. + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: ci: strategy: matrix: - # Different Node versions on Ubuntu, the latest Node on other platforms + # Different Node versions on Ubuntu, the latest Node on other platforms. ci: - os: ubuntu-22.04 node: 16 diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index 424113a365..e3304d29a7 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -2,6 +2,12 @@ name: mediasoup-rust on: [push, pull_request] +concurrency: + # Cancel a currently running workflow from the same PR, branch or tag when a + # new workflow is triggered. + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 489e6bb741..20474fe075 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -2,6 +2,12 @@ name: mediasoup-worker on: [push, pull_request] +concurrency: + # Cancel a currently running workflow from the same PR, branch or tag when a + # new workflow is triggered. + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: ci: strategy: @@ -31,7 +37,7 @@ jobs: cxx: cl # A single Node.js version should be fine for C++. node: - - 16 + - 18 runs-on: ${{ matrix.build.os }} @@ -66,4 +72,5 @@ jobs: - run: npm run worker:build - run: npm run test:worker + # TODO: Maybe fix this one day. if: runner.os != 'Windows' diff --git a/.github/workflows/pull-request-stats.yml b/.github/workflows/pull-request-stats.yml index 1035c0188b..af1e612f02 100644 --- a/.github/workflows/pull-request-stats.yml +++ b/.github/workflows/pull-request-stats.yml @@ -1,8 +1,9 @@ name: Pull Request Stats on: + # Run it every Monday at 1PM UTC. schedule: - - cron: "0 13 * * 1" # Run it every Monday at 1PM UTC. + - cron: "0 13 * * 1" jobs: stats: diff --git a/CHANGELOG.md b/CHANGELOG.md index 59df0a6f91..c80498b2e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ### NEXT -* Github workflow: Remove deprecated Ubuntu version 18.04 ([PR #1033](https://github.com/versatica/mediasoup/pull/1033)). +* GitHub CI: Remove deprecated Ubuntu version 18.04 ([PR #1033](https://github.com/versatica/mediasoup/pull/1033)). +* GitHub CI: Cancel in progress workflows ([PR #1034](https://github.com/versatica/mediasoup/pull/1034)). ### 3.11.16 From d6841c364e599ebb4aaba7c6f6cc3f9b224f3f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 28 Mar 2023 12:39:26 +0200 Subject: [PATCH 052/525] Remove useless entries in CHANGELOG --- CHANGELOG.md | 90 ++++--------------------- package-lock.json | 164 +++++++++++++++++++++++----------------------- package.json | 4 +- 3 files changed, 96 insertions(+), 162 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c80498b2e3..c7787263c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,47 +1,36 @@ # Changelog -### NEXT - -* GitHub CI: Remove deprecated Ubuntu version 18.04 ([PR #1033](https://github.com/versatica/mediasoup/pull/1033)). -* GitHub CI: Cancel in progress workflows ([PR #1034](https://github.com/versatica/mediasoup/pull/1034)). - ### 3.11.16 * Fix `SeqManager`: Properly consider previous cycle dropped inputs ([PR #1032](https://github.com/versatica/mediasoup/pull/1032)). * `RtpRetransmissionBuffer`: Get rid of not necessary `startSeq` private member ([PR #1029](https://github.com/versatica/mediasoup/pull/1029)). * Node: Upgrade TypeScript to 5.0.2. -* Update NPM deps. ### 3.11.15 * `RtpRetransmissionBuffer`: Fix crash and add fuzzer ([PR #1028](https://github.com/versatica/mediasoup/pull/1028)). -* Update NPM deps. ### 3.11.14 * Refactor RTP retransmission buffer in a separate and testable `RTC::RetransmissionBuffer` class ([PR #1023](https://github.com/versatica/mediasoup/pull/1023)). -* Update NPM deps. ### 3.11.13 * `AudioLevelObserver`: Use multimap rather than map to avoid conflict if various Producers generate same audio level ([PR #1021](https://github.com/versatica/mediasoup/pull/1021), issue reported by @buptlsp). -* Update NPM deps. ### 3.11.12 * Fix jitter calculation ([PR #1019](https://github.com/versatica/mediasoup/pull/1019), credits to @alexciarlillo and @snnz). -* Update NPM deps. ### 3.11.11 * Add support for RTCP NACK in OPUS ([PR #1015](https://github.com/versatica/mediasoup/pull/1015)). -* Update NPM deps. ### 3.11.10 @@ -53,34 +42,29 @@ * Allow simulcast with a single encoding (and N temporal layers) ([PR #1013](https://github.com/versatica/mediasoup/pull/1013)). * Update libsrtp to 2.5.0. -* Update NPM deps. ### 3.11.8 * `SimulcastConsumer::GetDesiredBitrate()`: Choose the highest bitrate among all Producer streams ([PR #992](https://github.com/versatica/mediasoup/pull/992)). * `SimulcastConsumer`: Fix frozen video when syncing keyframe is discarded due to too high RTP timestamp extra offset needed ([PR #999](https://github.com/versatica/mediasoup/pull/999), thanks to @satoren for properly reporting the issue and helping with the solution). -* Update NPM deps. ### 3.11.7 * libwebrtc: Fix crash due to invalid `arrival_time` value ([PR #985](https://github.com/versatica/mediasoup/pull/985) by @ggarber). * libwebrtc: Replace `MS_ASSERT()` with `MS_ERROR()` ([PR #988](https://github.com/versatica/mediasoup/pull/988)). -* Update NPM deps. ### 3.11.6 * Fix wrong `PictureID` rolling over in VP9 and VP8 ([PR #984](https://github.com/versatica/mediasoup/pull/984) by @jcague). -* Update NPM deps. ### 3.11.5 * Require Node.js >= 16 ([PR #973](https://github.com/versatica/mediasoup/pull/973)). * Fix wrong `Consumer` bandwidth estimation under `Producer` packet loss ([PR #962](https://github.com/versatica/mediasoup/pull/962) by @ggarber). -* Update NPM deps. ### 3.11.4 @@ -89,7 +73,6 @@ * Node: Remove compiled JavaScript from repository and compile TypeScript code on NPM `prepare` script on demand when installed via git ([PR #954](https://github.com/versatica/mediasoup/pull/954)). * `Worker`: Add `RTC::Shared` singleton for RTC entities ([PR #953](https://github.com/versatica/mediasoup/pull/953)). * Update OpenSSL to 3.0.7. -* Update NPM deps. ### 3.11.3 @@ -116,14 +99,12 @@ * `ActiveSpeakerObserver`: Fix memory leak ([PR #942](https://github.com/versatica/mediasoup/pull/942)). * Fix some libwebrtc issues ([PR #944](https://github.com/versatica/mediasoup/pull/944)). * Tests: Normalize hexadecimal data representation ([PR #945](https://github.com/versatica/mediasoup/pull/945)). -* Update NPM deps. * `SctpAssociation`: Fix memory violation ([PR #943](https://github.com/versatica/mediasoup/pull/943)). ### 3.10.12 * Fix worker crash due to `std::out_of_range` exception ([PR #933](https://github.com/versatica/mediasoup/pull/933)). -* Update NPM deps. ### 3.10.11 @@ -134,7 +115,6 @@ ### 3.10.10 * Fix the JSON serialization for the payload channel `rtp` event ([PR #926](https://github.com/versatica/mediasoup/pull/926) by @mhammo). -* Update NPM deps. ### 3.10.9 @@ -154,7 +134,6 @@ ### 3.10.7 * Forward `abs-capture-time` RTP extension also for audio packets ([PR #911](https://github.com/versatica/mediasoup/pull/911)). -* Update NPM deps. ### 3.10.6 @@ -165,7 +144,6 @@ * New C++ `ChannelMessageHandlers` class ([PR #894](https://github.com/versatica/mediasoup/pull/894)). * Fix Rust support after recent changes ([PR #898](https://github.com/versatica/mediasoup/pull/898)). * Modify `FeedbackRtpTransport` and tests to be compliant with latest libwebrtc code, make reference time to be unsigned ([PR #899](https://github.com/versatica/mediasoup/pull/899) by @penguinol and @sarumjanuch). -* Update NPM deps. ### 3.10.5 @@ -176,8 +154,7 @@ ### 3.10.4 * Do not clone RTP packets if not needed ([PR #850](https://github.com/versatica/mediasoup/pull/850)). -* Fix DTLS related crash ([PR #867](https://github.com/versatica/mediasoup/pull/867)). -* Update NPM deps. +* Fix DTLS related crash ([PR #867](https://github.com/versatica/mediasoup/pull/867)). ### 3.10.3 @@ -196,7 +173,6 @@ * `RtpStreamSend`: Memory optimizations ([PR #840](https://github.com/versatica/mediasoup/pull/840)). Extracted from #675, by @nazar-pc. * `SimpleConsumer`: Opus DTX ignore capabilities ([PR #846](https://github.com/versatica/mediasoup/pull/846)). * Update `libuv` to 1.44.1: Fixes `libuv` build ([PR #857](https://github.com/versatica/mediasoup/pull/857)). -* Update NPM deps. ### 3.10.0 @@ -205,19 +181,19 @@ * More SRTP crypto suites ([PR #837](https://github.com/versatica/mediasoup/pull/837)). * Improve `EnhancedEventEmitter` ([PR #836](https://github.com/versatica/mediasoup/pull/836)). * `TransportCongestionControlClient`: Allow setting max outgoing bitrate before `tccClient` is created ([PR #833](https://github.com/versatica/mediasoup/pull/833)). -* Update NPM deps and TypeScript version. +* Update TypeScript version. ### 3.9.17 * `RateCalculator`: Fix old buffer items cleanup ([PR #830](https://github.com/versatica/mediasoup/pull/830) by @dsdolzhenko). -* Update NPM deps and TypeScript version. +* Update TypeScript version. ### 3.9.16 * `SimulcastConsumer`: Fix spatial layer switch with unordered packets ([PR #823](https://github.com/versatica/mediasoup/pull/823) by @jcague). -* Update NPM deps and TypeScript version. +* Update TypeScript version. ### 3.9.15 @@ -235,25 +211,24 @@ * `DirectTransport`: Create a buffer to process RTP packets ([PR #730](https://github.com/versatica/mediasoup/pull/730) by @rtctt). * Node: Improve `appData` TypeScript syntax and initialization. * Allow setting max outgoing bitrate below the initial value ([PR #826](https://github.com/versatica/mediasoup/pull/826) by @ggarber). -* Update NPM deps and TypeScript version. +* Update TypeScript version. ### 3.9.13 * `VP8`: Do not discard `TL0PICIDX` from Temporal Layers higher than 0 (PR @817 by @jcague). -* Update NPM deps and TypeScript version. +* Update TypeScript version. ### 3.9.12 * `DtlsTransport`: Make DTLS negotiation run immediately ([PR #815](https://github.com/versatica/mediasoup/pull/815)). -* Update NPM deps and TypeScript version. +* Update TypeScript version. ### 3.9.11 * Modify `SimulcastConsumer` to keep using layers without good scores ([PR #804](https://github.com/versatica/mediasoup/pull/804) by @ggarber). -* Update NPM deps. ### 3.9.10 @@ -264,7 +239,7 @@ * nlohmann_json 3.10.5. * usrsctp snapshot 4e06feb01cadcd127d119486b98a4bd3d64aa1e7. * wingetopt 1.00. -* Update NPM deps and TypeScript version. +* Update TypeScript version. * Fix RTP marker bit not being reseted after mangling in each `Consumer` ([PR #811](https://github.com/versatica/mediasoup/pull/811) by @ggarber). @@ -280,40 +255,35 @@ * Fix VP9 kSVC forwarding logic to not forward lower unneded layers ([PR #778](https://github.com/versatica/mediasoup/pull/778) by @ggarber). * Fix update bandwidth estimation configuration and available bitrate when updating max outgoing bitrate ([PR #779](https://github.com/versatica/mediasoup/pull/779) by @ggarber). * Replace outdated `random-numbers` package by native `crypto.randomInt()` ([PR #776](https://github.com/versatica/mediasoup/pull/776) by @piranna). -* Update NPM deps and TypeScript version. +* Update TypeScript version. ### 3.9.7 * Typing event emitters in mediasoup Node ([PR #764](https://github.com/versatica/mediasoup/pull/764) by @unao). -* Update NPM deps. ### 3.9.6 * TCC client optimizations for faster and more stable BWE ([PR #712](https://github.com/versatica/mediasoup/pull/712) by @ggarber). * Added support for RTP abs-capture-time header ([PR #761](https://github.com/versatica/mediasoup/pull/761) by @oto313). -* Update NPM deps. ### 3.9.5 * ICE renomination support ([PR #756](https://github.com/versatica/mediasoup/pull/756)). * Update `libuv` to 1.43.0. -* Update NPM deps. ### 3.9.4 * `Worker`: Fix bad printing of error messages from Worker ([PR #750](https://github.com/versatica/mediasoup/pull/750) by @j1elo). -* Update NPM deps. ### 3.9.3 * Single H264/H265 codec configuration in `supportedRtpCapabilities` ([PR #718](https://github.com/versatica/mediasoup/pull/718)). * Improve Windows support by not requiring MSVC configuration ([PR #741](https://github.com/versatica/mediasoup/pull/741)). -* Update NPM deps. ### 3.9.2 @@ -323,7 +293,6 @@ * Update TypeScript version to 4.X.X and use `target: "esnext"` so transpilation of ECMAScript private fields (`#xxxxx`) don't use `WeakMaps` tricks but use standard syntax instead. * Use more than one core for compilation on Windows ([PR #709](https://github.com/versatica/mediasoup/pull/709)). * `Consumer`: Modification of bitrate allocation algorithm ([PR #708](https://github.com/versatica/mediasoup/pull/708)). -* Update NPM deps. ### 3.9.1 @@ -334,7 +303,6 @@ * Update `libuv` to 1.42.0. * Improve Windows support ([PR #692](https://github.com/versatica/mediasoup/pull/692)). * Avoid build commands when MEDIASOUP_WORKER_BIN is set ([PR #695](https://github.com/versatica/mediasoup/pull/695)). -* Update NPM deps. ### 3.9.0 @@ -352,7 +320,6 @@ * Add `packetLoss` stats to transport ([PR #648](https://github.com/versatica/mediasoup/pull/648) by @ggarber). * Fixes for active speaker observer ([PR #655](https://github.com/versatica/mediasoup/pull/655) by @ggarber). * Fix big endian issues ([PR #639](https://github.com/versatica/mediasoup/pull/639)). -* Update NPM deps. ### 3.8.3 @@ -363,13 +330,11 @@ ### 3.8.2 * `ActiveSpeakerObserver`: Fix crash due to a `nullptr` ([PR #634](https://github.com/versatica/mediasoup/pull/634)). -* Update NPM deps. ### 3.8.1 * `SimulcastConsumer`: Fix RTP timestamp when switching layers ([PR #626](https://github.com/versatica/mediasoup/pull/626) by @penguinol). -* Update NPM deps. ### 3.8.0 @@ -378,13 +343,11 @@ * Use non-ASM OpenSSL on Windows ([PR #614](https://github.com/versatica/mediasoup/pull/614)). * Fix minor memory leak caused by non-virtual destructor ([PR #625](https://github.com/versatica/mediasoup/pull/625)). * Dominant Speaker Event ([PR #603](https://github.com/versatica/mediasoup/pull/603) by @SteveMcFarlin). -* Update NPM deps. ### 3.7.19 * Update `libuv` to 1.41.0. -* Update NPM deps. * C++: - Move header includes ([PR #608](https://github.com/versatica/mediasoup/pull/608)). - Enhance debugging on channel request/notification error ([PR #607](https://github.com/versatica/mediasoup/pull/607)). @@ -397,7 +360,6 @@ - OpenSSL upgraded to version 1.1.1k. - Enable the compilation of assembly extensions for OpenSSL. - Optimize the worker build (`-O3`) and disable the debug flag (`-g`). -* Update NPM deps. ### 3.7.17 @@ -409,7 +371,6 @@ ### 3.7.16 * Add `mid` option in `ConsumerOptions` to provide way to override MID ([PR #586](https://github.com/versatica/mediasoup/pull/586) by @mstyura). -* Update NPM deps. ### 3.7.15 @@ -421,7 +382,6 @@ ### 3.7.14 * Update `usrsctp` to include a "possible use after free bug" fix (commit [here](https://github.com/sctplab/usrsctp/commit/0f8d58300b1fdcd943b4a9dd3fbd830825390d4d)). -* Update NPM deps. ### 3.7.13 @@ -432,13 +392,11 @@ ### 3.7.12 * `mediasoup-worker`: Fix memory leaks on error exit ([PR #581](https://github.com/versatica/mediasoup/pull/581)). -* Update NPM deps. ### 3.7.11 * Fix `DepUsrSCTP::Checker::timer` not being freed on `Worker` close ([PR #576](https://github.com/versatica/mediasoup/pull/576)). Thanks @nazar-pc for discovering this. -* Update NPM deps. ### 3.7.10 @@ -461,7 +419,6 @@ * Thread and memory safety fixes needed for mediasoup-rust ([PR #562](https://github.com/versatica/mediasoup/pull/562) by @nazar-pc). * mediasoup-rust support on macOS ([PR #567](https://github.com/versatica/mediasoup/pull/567) by @nazar-pc). * mediasoup-rust release 0.7.2. -* Update NPM deps. ### 3.7.6 @@ -470,7 +427,6 @@ * `SctpAssociation`: Don't warn if SCTP send buffer is full. * Rust: Update modules structure and other minor improvements for Rust version ([PR #558](https://github.com/versatica/mediasoup/pull/558)). * `mediasoup-worker`: Avoid duplicated basenames so that libmediasoup-worker is compilable on macOS ([PR #557](https://github.com/versatica/mediasoup/pull/557)). -* Update NPM deps. ### 3.7.5 @@ -481,7 +437,6 @@ ### 3.7.4 * Improve `RateCalculator` ([PR #547](https://github.com/versatica/mediasoup/pull/547) by @vpalmisano). -* Update NPM deps. ### 3.7.3 @@ -492,21 +447,17 @@ ### 3.7.2 * `RateCalculator` optimization ([PR #538](https://github.com/versatica/mediasoup/pull/538) by @vpalmisano). -* Update `Catch` to 2.13.5. -* Update NPM deps. ### 3.7.1 * `SimulcastConsumer`: Fix miscalculation when increasing layer ([PR #541](https://github.com/versatica/mediasoup/pull/541) by @penguinol). * Rust version with thread-based worker ([PR #540](https://github.com/versatica/mediasoup/pull/540)). -* Update NPM deps. ### 3.7.0 * Welcome to `mediasoup-rust`! Authored by @nazar-pc (PRs #518 and #533). -* Update NPM deps. * Update `usrsctp`. @@ -522,7 +473,6 @@ ### 3.6.35 * `XxxxConsumer.hpp`: make `IsActive()` return `true` (even if `Producer`'s score is 0) when DTX is enabled ([PR #534](https://github.com/versatica/mediasoup/pull/534) due to issue #532). -* Update NPM deps. ### 3.6.34 @@ -536,7 +486,6 @@ * `router.pipeToRouter()`: Fix possible inconsistency in `pipeProducer.paused` status (as discussed in this [thread](https://mediasoup.discourse.group/t/concurrency-architecture/2515/) in the mediasoup forum). * Update `nlohmann/json` to 3.9.1. * Update `usrsctp`. -* Update NPM deps. * Enhance Jitter calculation. @@ -548,7 +497,6 @@ ### 3.6.31 * Move `bufferedAmount` from `dataConsumer.dump()` to `dataConsumer.getStats()`. -* Update NPM deps. ### 3.6.30 @@ -556,10 +504,8 @@ * Add `pipe` option to `transport.consume()`([PR #494](https://github.com/versatica/mediasoup/pull/494)). - So the receiver will get all streams from the `Producer`. - It works for any kind of transport (but `PipeTransport` which is always like this). -* Update NPM deps. * Add `LICENSE` and `PATENTS` files in `libwebrtc` dependency (issue #495). * Added `worker/src/Utils/README_BASE64_UTILS` (issue #497). -* Update `Catch` to 2.13.4. * Update `usrsctp`. @@ -573,27 +519,22 @@ ### 3.6.28 * Fix replacement of `__MEDIASOUP_VERSION__` in `lib/index.d.ts` (issue #483). -* Update NPM deps. * `worker/scripts/configure.py`: Handle 'mips64' ([PR #485](https://github.com/versatica/mediasoup/pull/485)). ### 3.6.27 -* Update NPM deps. * Allow the `mediasoup-worker` process to inherit all environment variables (issue #480). ### 3.6.26 * BWE tweaks and debug logs. -* Update NPM deps. ### 3.6.25 -* Update `Catch` to 2.13.2. -* Update NPM deps. -* sctp fixes #479. +* SCTP fixes ([PR #479](https://github.com/versatica/mediasoup/pull/479)). ### 3.6.24 @@ -604,7 +545,6 @@ ### 3.6.23 * Fix yet another memory leak in Node.js layer due to `PayloadChannel` event listener not being removed. -* Update NPM deps. ### 3.6.22 @@ -665,9 +605,8 @@ * Fix `usrsctp` vulnerability ([PR #439](https://github.com/versatica/mediasoup/pull/439)). * Fix issue #435 (thanks to @penguinol for reporting). * `TransportCongestionControlClient.cpp`: Enable periodic ALR probing to recover faster from network issues. -* Update NPM deps. + * Update `nlohmann::json` C++ dep to 3.9.0. -* Update `Catch` to 2.13.0. ### 3.6.13 @@ -693,16 +632,12 @@ * `Transport`: Implement `maxSctpSendBufferSize`. * Update `libuv` to 1.38.1. -* Update `Catch` to 2.12.4. -* Update NPM deps. ### 3.6.9 * `Transport::ReceiveRtpPacket()`: Call `RecvStreamClosed(packet->GetSsrc())` if received RTP packet does not match any `Producer`. * `Transport::HandleRtcpPacket()`: Ensure `Consumer` is found for received NACK Feedback packets. -* Update NPM deps. -* Update C++ `Catch` dep. * Fix issue #408. @@ -713,7 +648,6 @@ - Credits to credits to @penguinol for reporting and initial work at [PR #427](https://github.com/versatica/mediasoup/pull/427). * Update `nlohmann::json` C++ dep to 3.8.0. * C++: Enhance `const` correctness. -* Update NPM deps. ### 3.6.7 @@ -965,7 +899,7 @@ * Add `worker.getResourceUsage()` API. * Update OpenSSL to 1.1.1d. * Update `libuv` to 1.34.0. -* Update TypeScript and ESLint NPM dependencies. +* Update TypeScript version. ### 3.3.8 diff --git a/package-lock.json b/package-lock.json index efec896fbb..e1e5628598 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,8 @@ "@types/jest": "^29.5.0", "@types/node": "^18.15.10", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.56.0", - "@typescript-eslint/parser": "^5.56.0", + "@typescript-eslint/eslint-plugin": "^5.57.0", + "@typescript-eslint/parser": "^5.57.0", "eslint": "^8.36.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", @@ -1392,15 +1392,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.56.0.tgz", - "integrity": "sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.0.tgz", + "integrity": "sha512-itag0qpN6q2UMM6Xgk6xoHa0D0/P+M17THnr4SVgqn9Rgam5k/He33MA7/D7QoJcdMxHFyX7U9imaBonAX/6qA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/type-utils": "5.56.0", - "@typescript-eslint/utils": "5.56.0", + "@typescript-eslint/scope-manager": "5.57.0", + "@typescript-eslint/type-utils": "5.57.0", + "@typescript-eslint/utils": "5.57.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1426,14 +1426,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.56.0.tgz", - "integrity": "sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.0.tgz", + "integrity": "sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/typescript-estree": "5.56.0", + "@typescript-eslint/scope-manager": "5.57.0", + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/typescript-estree": "5.57.0", "debug": "^4.3.4" }, "engines": { @@ -1453,13 +1453,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz", - "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.0.tgz", + "integrity": "sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0" + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/visitor-keys": "5.57.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1470,13 +1470,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.56.0.tgz", - "integrity": "sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.0.tgz", + "integrity": "sha512-kxXoq9zOTbvqzLbdNKy1yFrxLC6GDJFE2Yuo3KqSwTmDOFjUGeWSakgoXT864WcK5/NAJkkONCiKb1ddsqhLXQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.56.0", - "@typescript-eslint/utils": "5.56.0", + "@typescript-eslint/typescript-estree": "5.57.0", + "@typescript-eslint/utils": "5.57.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1497,9 +1497,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", - "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.0.tgz", + "integrity": "sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1510,13 +1510,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz", - "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.0.tgz", + "integrity": "sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0", + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/visitor-keys": "5.57.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1537,17 +1537,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.56.0.tgz", - "integrity": "sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.0.tgz", + "integrity": "sha512-ps/4WohXV7C+LTSgAL5CApxvxbMkl9B9AUZRtnEFonpIxZDIT7wC1xfvuJONMidrkB9scs4zhtRyIwHh4+18kw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/typescript-estree": "5.56.0", + "@typescript-eslint/scope-manager": "5.57.0", + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/typescript-estree": "5.57.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1563,12 +1563,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", - "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.0.tgz", + "integrity": "sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/types": "5.57.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -7174,15 +7174,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.56.0.tgz", - "integrity": "sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.0.tgz", + "integrity": "sha512-itag0qpN6q2UMM6Xgk6xoHa0D0/P+M17THnr4SVgqn9Rgam5k/He33MA7/D7QoJcdMxHFyX7U9imaBonAX/6qA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/type-utils": "5.56.0", - "@typescript-eslint/utils": "5.56.0", + "@typescript-eslint/scope-manager": "5.57.0", + "@typescript-eslint/type-utils": "5.57.0", + "@typescript-eslint/utils": "5.57.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7192,53 +7192,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.56.0.tgz", - "integrity": "sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.0.tgz", + "integrity": "sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/typescript-estree": "5.56.0", + "@typescript-eslint/scope-manager": "5.57.0", + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/typescript-estree": "5.57.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz", - "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.0.tgz", + "integrity": "sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0" + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/visitor-keys": "5.57.0" } }, "@typescript-eslint/type-utils": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.56.0.tgz", - "integrity": "sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.0.tgz", + "integrity": "sha512-kxXoq9zOTbvqzLbdNKy1yFrxLC6GDJFE2Yuo3KqSwTmDOFjUGeWSakgoXT864WcK5/NAJkkONCiKb1ddsqhLXQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.56.0", - "@typescript-eslint/utils": "5.56.0", + "@typescript-eslint/typescript-estree": "5.57.0", + "@typescript-eslint/utils": "5.57.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", - "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.0.tgz", + "integrity": "sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz", - "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.0.tgz", + "integrity": "sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0", + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/visitor-keys": "5.57.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7247,28 +7247,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.56.0.tgz", - "integrity": "sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.0.tgz", + "integrity": "sha512-ps/4WohXV7C+LTSgAL5CApxvxbMkl9B9AUZRtnEFonpIxZDIT7wC1xfvuJONMidrkB9scs4zhtRyIwHh4+18kw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/typescript-estree": "5.56.0", + "@typescript-eslint/scope-manager": "5.57.0", + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/typescript-estree": "5.57.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", - "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.0.tgz", + "integrity": "sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==", "dev": true, "requires": { - "@typescript-eslint/types": "5.56.0", + "@typescript-eslint/types": "5.57.0", "eslint-visitor-keys": "^3.3.0" } }, diff --git a/package.json b/package.json index 8ae5482137..f96c7b0aa9 100644 --- a/package.json +++ b/package.json @@ -95,8 +95,8 @@ "@types/jest": "^29.5.0", "@types/node": "^18.15.10", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.56.0", - "@typescript-eslint/parser": "^5.56.0", + "@typescript-eslint/eslint-plugin": "^5.57.0", + "@typescript-eslint/parser": "^5.57.0", "eslint": "^8.36.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", From f8e6238d282ca42bd33614dce77990799acdfe89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 29 Mar 2023 12:22:14 +0200 Subject: [PATCH 053/525] RTC::RetransmissionBuffer: Increase RetransmissionBufferMaxItems from 2500 to 5000 --- CHANGELOG.md | 5 +++++ worker/src/RTC/RtpStreamSend.cpp | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7787263c0..72acec627f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* `RTC::RetransmissionBuffer`: Increase `RetransmissionBufferMaxItems` from 2500 to 5000. + + ### 3.11.16 * Fix `SeqManager`: Properly consider previous cycle dropped inputs ([PR #1032](https://github.com/versatica/mediasoup/pull/1032)). diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index c73b826717..67231d14df 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -11,8 +11,8 @@ namespace RTC { /* Static. */ - // Limit retransmission buffer max size to 2500 items. - static constexpr size_t RetransmissionBufferMaxItems{ 2500u }; + // Limit max number of items in the retransmission buffer. + static constexpr size_t RetransmissionBufferMaxItems{ 5000u }; // 17: 16 bit mask + the initial sequence number. static constexpr size_t MaxRequestedPackets{ 17u }; thread_local static std::vector RetransmissionContainer( From 2744b4ca7dceb2a3929667aa11e086ddb4481474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 29 Mar 2023 15:11:43 +0200 Subject: [PATCH 054/525] Add transport.setMinOutgoingBitrate() (2) (#1038) Same PR than https://github.com/versatica/mediasoup/pull/1035/files by @jcague (all credits to him) with some additions such as the ability to reset min/max limits by calling the methods with argument 0 and more tests. --- CHANGELOG.md | 1 + node/src/DirectTransport.ts | 10 + node/src/Transport.ts | 17 +- node/src/tests/test-WebRtcTransport.ts | 62 +++++- rust/src/messages.rs | 6 + rust/src/router/transport.rs | 8 +- rust/src/router/webrtc_transport.rs | 8 + rust/tests/integration/webrtc_transport.rs | 110 ++++++++++- worker/include/Channel/ChannelRequest.hpp | 1 + worker/include/RTC/Transport.hpp | 1 + .../RTC/TransportCongestionControlClient.hpp | 5 +- worker/include/Utils.hpp | 26 ++- worker/src/Channel/ChannelRequest.cpp | 1 + worker/src/RTC/Transport.cpp | 185 +++++++++++++++++- .../RTC/TransportCongestionControlClient.cpp | 29 ++- 15 files changed, 450 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72acec627f..73aa7e2f65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT +* Add `transport.setMinOutgoingBitrate()` method ([PR #1038](https://github.com/versatica/mediasoup/pull/1038), credits to @ jcague). * `RTC::RetransmissionBuffer`: Increase `RetransmissionBufferMaxItems` from 2500 to 5000. diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 34ac3789ca..4a6fc7bea7 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -166,6 +166,16 @@ export class DirectTransport extends 'setMaxOutgoingBitrate() not implemented in DirectTransport'); } + /** + * @override + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async setMinOutgoingBitrate(bitrate: number): Promise + { + throw new UnsupportedError( + 'setMinOutgoingBitrate() not implemented in DirectTransport'); + } + /** * Send RTCP packet. */ diff --git a/node/src/Transport.ts b/node/src/Transport.ts index fb65f2e4d2..5463b547a6 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -86,8 +86,8 @@ export type TransportTraceEventData = export type SctpState = 'new' | 'connecting' | 'connected' | 'failed' | 'closed'; -export type TransportEvents = -{ +export type TransportEvents = +{ routerclose: []; listenserverclose: []; trace: [TransportTraceEventData]; @@ -523,6 +523,19 @@ export class Transport + { + logger.debug('setMinOutgoingBitrate() [bitrate:%s]', bitrate); + + const reqData = { bitrate }; + + await this.channel.request( + 'transport.setMinOutgoingBitrate', this.internal.transportId, reqData); + } + /** * Create a Producer. */ diff --git a/node/src/tests/test-WebRtcTransport.ts b/node/src/tests/test-WebRtcTransport.ts index 2ad1b9f1ad..bc49b9a168 100644 --- a/node/src/tests/test-WebRtcTransport.ts +++ b/node/src/tests/test-WebRtcTransport.ts @@ -340,14 +340,68 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => { - await expect(transport.setMaxIncomingBitrate(100000)) + await expect(transport.setMaxIncomingBitrate(1000000)) + .resolves + .toBeUndefined(); + + // Remove limit. + await expect(transport.setMaxIncomingBitrate(0)) .resolves .toBeUndefined(); }, 2000); test('webRtcTransport.setMaxOutgoingBitrate() succeeds', async () => { - await expect(transport.setMaxIncomingBitrate(100000)) + await expect(transport.setMaxOutgoingBitrate(2000000)) + .resolves + .toBeUndefined(); + + // Remove limit. + await expect(transport.setMaxOutgoingBitrate(0)) + .resolves + .toBeUndefined(); +}, 2000); + +test('webRtcTransport.setMinOutgoingBitrate() succeeds', async () => +{ + await expect(transport.setMinOutgoingBitrate(100000)) + .resolves + .toBeUndefined(); + + // Remove limit. + await expect(transport.setMinOutgoingBitrate(0)) + .resolves + .toBeUndefined(); +}, 2000); + +test('webRtcTransport.setMaxOutgoingBitrate() fails if value is lower than current min limit', async () => +{ + await expect(transport.setMinOutgoingBitrate(3000000)) + .resolves + .toBeUndefined(); + + await expect(transport.setMaxOutgoingBitrate(2000000)) + .rejects + .toThrow(Error); + + // Remove limit. + await expect(transport.setMinOutgoingBitrate(0)) + .resolves + .toBeUndefined(); +}, 2000); + +test('webRtcTransport.setMinOutgoingBitrate() fails if value is higher than current max limit', async () => +{ + await expect(transport.setMaxOutgoingBitrate(2000000)) + .resolves + .toBeUndefined(); + + await expect(transport.setMinOutgoingBitrate(3000000)) + .rejects + .toThrow(Error); + + // Remove limit. + await expect(transport.setMaxOutgoingBitrate(0)) .resolves .toBeUndefined(); }, 2000); @@ -500,6 +554,10 @@ test('WebRtcTransport methods reject if closed', async () => .rejects .toThrow(Error); + await expect(transport.setMinOutgoingBitrate(100000)) + .rejects + .toThrow(Error); + await expect(transport.restartIce()) .rejects .toThrow(Error); diff --git a/rust/src/messages.rs b/rust/src/messages.rs index f933c18290..865954b592 100644 --- a/rust/src/messages.rs +++ b/rust/src/messages.rs @@ -595,6 +595,12 @@ request_response!( TransportSetMaxOutgoingBitrateRequest { bitrate: u32 }, ); +request_response!( + TransportId, + "transport.setMinOutgoingBitrate", + TransportSetMinOutgoingBitrateRequest { bitrate: u32 }, +); + request_response!( TransportId, "transport.restartIce", diff --git a/rust/src/router/transport.rs b/rust/src/router/transport.rs index 5ab9362558..5e7eca730b 100644 --- a/rust/src/router/transport.rs +++ b/rust/src/router/transport.rs @@ -6,7 +6,7 @@ use crate::messages::{ TransportConsumeDataRequest, TransportConsumeRequest, TransportDumpRequest, TransportEnableTraceEventRequest, TransportGetStatsRequest, TransportProduceDataRequest, TransportProduceRequest, TransportSetMaxIncomingBitrateRequest, - TransportSetMaxOutgoingBitrateRequest, + TransportSetMaxOutgoingBitrateRequest, TransportSetMinOutgoingBitrateRequest, }; pub use crate::ortc::{ ConsumerRtpParametersError, RtpCapabilitiesError, RtpParametersError, RtpParametersMappingError, @@ -396,6 +396,12 @@ pub(super) trait TransportImpl: TransportGeneric { .await } + async fn set_min_outgoing_bitrate_impl(&self, bitrate: u32) -> Result<(), RequestError> { + self.channel() + .request(self.id(), TransportSetMinOutgoingBitrateRequest { bitrate }) + .await + } + async fn produce_impl( &self, producer_options: ProducerOptions, diff --git a/rust/src/router/webrtc_transport.rs b/rust/src/router/webrtc_transport.rs index 0ea5f47cdd..53a1ac08ca 100644 --- a/rust/src/router/webrtc_transport.rs +++ b/rust/src/router/webrtc_transport.rs @@ -794,6 +794,14 @@ impl WebRtcTransport { self.set_max_outgoing_bitrate_impl(bitrate).await } + /// Set minimum outgoing bitrate for media streams sent by the remote endpoint over this + /// transport. + pub async fn set_min_outgoing_bitrate(&self, bitrate: u32) -> Result<(), RequestError> { + debug!("set_min_outgoing_bitrate() [bitrate:{}]", bitrate); + + self.set_min_outgoing_bitrate_impl(bitrate).await + } + /// Local ICE role. Due to the mediasoup ICE Lite design, this is always `Controlled`. #[must_use] pub fn ice_role(&self) -> IceRole { diff --git a/rust/tests/integration/webrtc_transport.rs b/rust/tests/integration/webrtc_transport.rs index bf12e3ae49..f50bae6a28 100644 --- a/rust/tests/integration/webrtc_transport.rs +++ b/rust/tests/integration/webrtc_transport.rs @@ -436,9 +436,15 @@ fn set_max_incoming_bitrate_succeeds() { .expect("Failed to create WebRTC transport"); transport - .set_max_incoming_bitrate(100000) + .set_max_incoming_bitrate(1000000) .await .expect("Failed to set max incoming bitrate on WebRTC transport"); + + // Remove limit. + transport + .set_max_incoming_bitrate(0) + .await + .expect("Failed to remove limit in max incoming bitrate on WebRTC transport"); }); } @@ -458,9 +464,109 @@ fn set_max_outgoing_bitrate_succeeds() { .expect("Failed to create WebRTC transport"); transport - .set_max_outgoing_bitrate(100000) + .set_max_outgoing_bitrate(2000000) .await .expect("Failed to set max outgoing bitrate on WebRTC transport"); + + // Remove limit. + transport + .set_max_outgoing_bitrate(0) + .await + .expect("Failed to remove limit in max outgoing bitrate on WebRTC transport"); + }); +} + +#[test] +fn set_min_outgoing_bitrate_succeeds() { + future::block_on(async move { + let (_worker, router) = init().await; + + let transport = router + .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( + ListenIp { + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: Some("9.9.9.1".parse().unwrap()), + }, + ))) + .await + .expect("Failed to create WebRTC transport"); + + transport + .set_min_outgoing_bitrate(100000) + .await + .expect("Failed to set min outgoing bitrate on WebRTC transport"); + + // Remove limit. + transport + .set_min_outgoing_bitrate(0) + .await + .expect("Failed to remove limit in min outgoing bitrate on WebRTC transport"); + }); +} + +#[test] +fn set_max_outgoing_bitrate_fails_if_value_is_lower_than_current_min_limit() { + future::block_on(async move { + let (_worker, router) = init().await; + + let transport = router + .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( + ListenIp { + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: Some("9.9.9.1".parse().unwrap()), + }, + ))) + .await + .expect("Failed to create WebRTC transport"); + + transport + .set_min_outgoing_bitrate(3000000) + .await + .expect("Failed to set min outgoing bitrate on WebRTC transport"); + + assert!(matches!( + transport.set_max_outgoing_bitrate(2000000).await, + Err(RequestError::Response { .. }), + )); + + // Remove limit. + transport + .set_min_outgoing_bitrate(0) + .await + .expect("Failed to remove limit in min outgoing bitrate on WebRTC transport"); + }); +} + +#[test] +fn set_min_outgoing_bitrate_fails_if_value_is_higher_than_current_max_limit() { + future::block_on(async move { + let (_worker, router) = init().await; + + let transport = router + .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( + ListenIp { + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: Some("9.9.9.1".parse().unwrap()), + }, + ))) + .await + .expect("Failed to create WebRTC transport"); + + transport + .set_max_outgoing_bitrate(2000000) + .await + .expect("Failed to set max outgoing bitrate on WebRTC transport"); + + assert!(matches!( + transport.set_min_outgoing_bitrate(3000000).await, + Err(RequestError::Response { .. }), + )); + + // Remove limit. + transport + .set_max_outgoing_bitrate(0) + .await + .expect("Failed to remove limit in max outgoing bitrate on WebRTC transport"); }); } diff --git a/worker/include/Channel/ChannelRequest.hpp b/worker/include/Channel/ChannelRequest.hpp index be10df42a6..7381c94d7e 100644 --- a/worker/include/Channel/ChannelRequest.hpp +++ b/worker/include/Channel/ChannelRequest.hpp @@ -43,6 +43,7 @@ namespace Channel TRANSPORT_CONNECT, TRANSPORT_SET_MAX_INCOMING_BITRATE, TRANSPORT_SET_MAX_OUTGOING_BITRATE, + TRANSPORT_SET_MIN_OUTGOING_BITRATE, TRANSPORT_RESTART_ICE, TRANSPORT_PRODUCE, TRANSPORT_CONSUME, diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index c52a197616..87e5e81909 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -329,6 +329,7 @@ namespace RTC uint32_t initialAvailableOutgoingBitrate{ 600000u }; uint32_t maxIncomingBitrate{ 0u }; uint32_t maxOutgoingBitrate{ 0u }; + uint32_t minOutgoingBitrate{ 0u }; struct TraceEventTypes traceEventTypes; }; } // namespace RTC diff --git a/worker/include/RTC/TransportCongestionControlClient.hpp b/worker/include/RTC/TransportCongestionControlClient.hpp index 17f7684f04..dd58ed943c 100644 --- a/worker/include/RTC/TransportCongestionControlClient.hpp +++ b/worker/include/RTC/TransportCongestionControlClient.hpp @@ -56,7 +56,8 @@ namespace RTC RTC::TransportCongestionControlClient::Listener* listener, RTC::BweType bweType, uint32_t initialAvailableBitrate, - uint32_t maxOutgoingBitrate); + uint32_t maxOutgoingBitrate, + uint32_t minOutgoingBitrate); virtual ~TransportCongestionControlClient(); public: @@ -74,6 +75,7 @@ namespace RTC void ReceiveRtcpTransportFeedback(const RTC::RTCP::FeedbackRtpTransportPacket* feedback); void SetDesiredBitrate(uint32_t desiredBitrate, bool force); void SetMaxOutgoingBitrate(uint32_t maxBitrate); + void SetMinOutgoingBitrate(uint32_t minBitrate); const Bitrates& GetBitrates() const { return this->bitrates; @@ -118,6 +120,7 @@ namespace RTC RTC::BweType bweType; uint32_t initialAvailableBitrate{ 0u }; uint32_t maxOutgoingBitrate{ 0u }; + uint32_t minOutgoingBitrate{ 0u }; Bitrates bitrates; bool availableBitrateEventCalled{ false }; uint64_t lastAvailableBitrateEventAtMs{ 0u }; diff --git a/worker/include/Utils.hpp b/worker/include/Utils.hpp index b19415c346..d41ecb6551 100644 --- a/worker/include/Utils.hpp +++ b/worker/include/Utils.hpp @@ -172,18 +172,26 @@ namespace Utils { // If size is not multiple of 32 bits then pad it. if (size & 0x03) + { return (size & 0xFFFC) + 4; + } else + { return size; + } } static uint32_t PadTo4Bytes(uint32_t size) { // If size is not multiple of 32 bits then pad it. if (size & 0x03) + { return (size & 0xFFFFFFFC) + 4; + } else + { return size; + } } }; @@ -213,10 +221,14 @@ namespace Utils // Special case. if (max == 4294967295) + { --max; + } if (min > max) + { min = max; + } return (((Crypto::seed >> 4) & 0x7FFF7FFF) % (max - min + 1)) + min; } @@ -229,7 +241,9 @@ namespace Utils 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; if (len > 64) + { len = 64; + } for (size_t i{ 0 }; i < len; ++i) { @@ -323,10 +337,12 @@ namespace Utils // IsNewer(t2,t1)=false // rather than having IsNewer(t1,t2) = IsNewer(t2,t1) = false. if (static_cast(timestamp - prevTimestamp) == 0x80000000) + { return timestamp > prevTimestamp; + } - return timestamp != prevTimestamp && - static_cast(timestamp - prevTimestamp) < 0x80000000; + return ( + timestamp != prevTimestamp && static_cast(timestamp - prevTimestamp) < 0x80000000); } static uint32_t LatestTimestamp(uint32_t timestamp1, uint32_t timestamp2) @@ -346,11 +362,17 @@ namespace Utils static bool IsPositiveInteger(const json& value) { if (value.is_number_unsigned()) + { return true; + } else if (value.is_number_integer()) + { return value.get() >= 0; + } else + { return false; + } } }; } // namespace Utils diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index 8ed466a22d..d107b39329 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -37,6 +37,7 @@ namespace Channel { "transport.connect", ChannelRequest::MethodId::TRANSPORT_CONNECT }, { "transport.setMaxIncomingBitrate", ChannelRequest::MethodId::TRANSPORT_SET_MAX_INCOMING_BITRATE }, { "transport.setMaxOutgoingBitrate", ChannelRequest::MethodId::TRANSPORT_SET_MAX_OUTGOING_BITRATE }, + { "transport.setMinOutgoingBitrate", ChannelRequest::MethodId::TRANSPORT_SET_MIN_OUTGOING_BITRATE }, { "transport.restartIce", ChannelRequest::MethodId::TRANSPORT_RESTART_ICE }, { "transport.produce", ChannelRequest::MethodId::TRANSPORT_PRODUCE }, { "transport.consume", ChannelRequest::MethodId::TRANSPORT_CONSUME }, diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 9aef0f78cc..079b3a5055 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -69,7 +69,9 @@ namespace RTC if (jsonInitialAvailableOutgoingBitrateIt != data.end()) { if (!Utils::Json::IsPositiveInteger(*jsonInitialAvailableOutgoingBitrateIt)) + { MS_THROW_TYPE_ERROR("wrong initialAvailableOutgoingBitrate (not a number)"); + } this->initialAvailableOutgoingBitrate = jsonInitialAvailableOutgoingBitrateIt->get(); } @@ -163,7 +165,9 @@ namespace RTC bool isDataChannel{ false }; if (jsonIsDataChannelIt != data.end() && jsonIsDataChannelIt->is_boolean()) + { isDataChannel = jsonIsDataChannelIt->get(); + } // This may throw. this->sctpAssociation = new RTC::SctpAssociation( @@ -382,20 +386,30 @@ namespace RTC auto jsonRtpHeaderExtensionsIt = jsonObject.find("recvRtpHeaderExtensions"); if (this->recvRtpHeaderExtensionIds.mid != 0u) + { (*jsonRtpHeaderExtensionsIt)["mid"] = this->recvRtpHeaderExtensionIds.mid; + } if (this->recvRtpHeaderExtensionIds.rid != 0u) + { (*jsonRtpHeaderExtensionsIt)["rid"] = this->recvRtpHeaderExtensionIds.rid; + } if (this->recvRtpHeaderExtensionIds.rrid != 0u) + { (*jsonRtpHeaderExtensionsIt)["rrid"] = this->recvRtpHeaderExtensionIds.rrid; + } if (this->recvRtpHeaderExtensionIds.absSendTime != 0u) + { (*jsonRtpHeaderExtensionsIt)["absSendTime"] = this->recvRtpHeaderExtensionIds.absSendTime; + } if (this->recvRtpHeaderExtensionIds.transportWideCc01 != 0u) + { (*jsonRtpHeaderExtensionsIt)["transportWideCc01"] = this->recvRtpHeaderExtensionIds.transportWideCc01; + } // Add rtpListener. this->rtpListener.FillJson(jsonObject["rtpListener"]); @@ -437,9 +451,14 @@ namespace RTC std::ostringstream traceEventTypesStream; if (this->traceEventTypes.probation) + { traceEventTypes.emplace_back("probation"); + } + if (this->traceEventTypes.bwe) + { traceEventTypes.emplace_back("bwe"); + } if (!traceEventTypes.empty()) { @@ -535,23 +554,33 @@ namespace RTC // Add availableOutgoingBitrate. if (this->tccClient) + { jsonObject["availableOutgoingBitrate"] = this->tccClient->GetAvailableBitrate(); + } // Add availableIncomingBitrate. if (this->tccServer && this->tccServer->GetAvailableBitrate() != 0u) + { jsonObject["availableIncomingBitrate"] = this->tccServer->GetAvailableBitrate(); + } // Add maxIncomingBitrate. if (this->maxIncomingBitrate != 0u) + { jsonObject["maxIncomingBitrate"] = this->maxIncomingBitrate; + } // Add packetLossReceived. if (this->tccServer) + { jsonObject["rtpPacketLossReceived"] = this->tccServer->GetPacketLoss(); + } // Add packetLossSent. if (this->tccClient) + { jsonObject["rtpPacketLossSent"] = this->tccClient->GetPacketLoss(); + } } void Transport::HandleRequest(Channel::ChannelRequest* request) @@ -603,7 +632,9 @@ namespace RTC request->Accept(); if (this->tccServer) + { this->tccServer->SetMaxIncomingBitrate(this->maxIncomingBitrate); + } break; } @@ -624,10 +655,17 @@ namespace RTC const uint32_t bitrate = jsonBitrateIt->get(); - if (bitrate < RTC::TransportCongestionControlMinOutgoingBitrate) + if (bitrate > 0u && bitrate < RTC::TransportCongestionControlMinOutgoingBitrate) { MS_THROW_TYPE_ERROR( - "bitrate must be >= %" PRIu32 " bps", RTC::TransportCongestionControlMinOutgoingBitrate); + "bitrate must be >= %" PRIu32 " or 0 (unlimited)", + RTC::TransportCongestionControlMinOutgoingBitrate); + } + else if (bitrate > 0u && bitrate < this->minOutgoingBitrate) + { + MS_THROW_TYPE_ERROR( + "bitrate must be >= current min outgoing bitrate (%" PRIu32 ") or 0 (unlimited)", + this->minOutgoingBitrate); } if (this->tccClient) @@ -651,6 +689,56 @@ namespace RTC break; } + case Channel::ChannelRequest::MethodId::TRANSPORT_SET_MIN_OUTGOING_BITRATE: + { + auto jsonBitrateIt = request->data.find("bitrate"); + + // clang-format off + if ( + jsonBitrateIt == request->data.end() || + !Utils::Json::IsPositiveInteger(*jsonBitrateIt) + ) + // clang-format on + { + MS_THROW_TYPE_ERROR("missing bitrate"); + } + + const uint32_t bitrate = jsonBitrateIt->get(); + + if (bitrate > 0u && bitrate < RTC::TransportCongestionControlMinOutgoingBitrate) + { + MS_THROW_TYPE_ERROR( + "bitrate must be >= %" PRIu32 " or 0 (unlimited)", + RTC::TransportCongestionControlMinOutgoingBitrate); + } + else if (bitrate > 0u && this->maxOutgoingBitrate > 0 && bitrate > this->maxOutgoingBitrate) + { + MS_THROW_TYPE_ERROR( + "bitrate must be <= current max outgoing bitrate (%" PRIu32 ") or 0 (unlimited)", + this->maxOutgoingBitrate); + } + + if (this->tccClient) + { + // NOTE: This may throw so don't update things before calling this + // method. + this->tccClient->SetMinOutgoingBitrate(bitrate); + this->minOutgoingBitrate = bitrate; + + MS_DEBUG_TAG(bwe, "minimum outgoing bitrate set to %" PRIu32, this->minOutgoingBitrate); + + ComputeOutgoingDesiredBitrate(); + } + else + { + this->minOutgoingBitrate = bitrate; + } + + request->Accept(); + + break; + } + case Channel::ChannelRequest::MethodId::TRANSPORT_PRODUCE: { std::string producerId; @@ -799,10 +887,14 @@ namespace RTC std::make_shared(this, bweType, RTC::MtuSize); if (this->maxIncomingBitrate != 0u) + { this->tccServer->SetMaxIncomingBitrate(this->maxIncomingBitrate); + } if (IsConnected()) + { this->tccServer->TransportConnected(); + } } } @@ -828,7 +920,9 @@ namespace RTC auto jsonTypeIt = request->data.find("type"); if (jsonTypeIt == request->data.end() || !jsonTypeIt->is_string()) + { MS_THROW_TYPE_ERROR("missing type"); + } // This may throw. auto type = RTC::RtpParameters::GetType(jsonTypeIt->get()); @@ -1002,17 +1096,25 @@ namespace RTC }; this->tccClient = std::make_shared( - this, bweType, this->initialAvailableOutgoingBitrate, this->maxOutgoingBitrate); + this, + bweType, + this->initialAvailableOutgoingBitrate, + this->maxOutgoingBitrate, + this->minOutgoingBitrate); if (IsConnected()) + { this->tccClient->TransportConnected(); + } } } // If applicable, tell the new Consumer that we are gonna manage its // bitrate. if (this->tccClient) + { consumer->SetExternallyManagedBitrate(); + } #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR // Create SenderBandwidthEstimator if: @@ -1052,17 +1154,23 @@ namespace RTC this, this->initialAvailableOutgoingBitrate); if (IsConnected()) + { this->senderBwe->TransportConnected(); + } } // If applicable, tell the new Consumer that we are gonna manage its // bitrate. if (this->senderBwe) + { consumer->SetExternallyManagedBitrate(); + } #endif if (IsConnected()) + { consumer->TransportConnected(); + } break; } @@ -1255,7 +1363,9 @@ namespace RTC request->Accept(data); if (IsConnected()) + { dataConsumer->TransportConnected(); + } if (dataConsumer->GetType() == RTC::DataConsumer::Type::SCTP) { @@ -1277,7 +1387,9 @@ namespace RTC // Disable all if no entries. if (jsonTypesIt == request->data.end() || !jsonTypesIt->is_array()) + { MS_THROW_TYPE_ERROR("wrong types (not an array)"); + } // Reset traceEventTypes. struct TraceEventTypes newTraceEventTypes; @@ -1285,14 +1397,20 @@ namespace RTC for (const auto& type : *jsonTypesIt) { if (!type.is_string()) + { MS_THROW_TYPE_ERROR("wrong type (not a string)"); + } const std::string typeStr = type.get(); if (typeStr == "probation") + { newTraceEventTypes.probation = true; + } if (typeStr == "bwe") + { newTraceEventTypes.bwe = true; + } } this->traceEventTypes = newTraceEventTypes; @@ -1321,7 +1439,9 @@ namespace RTC RecvStreamClosed(rtpStream->GetSsrc()); if (rtpStream->HasRtx()) + { RecvStreamClosed(rtpStream->GetRtxSsrc()); + } } // Notify the listener. @@ -1371,9 +1491,12 @@ namespace RTC request->Accept(); - // This may be the latest active Consumer with BWE. If so we have to stop probation. + // This may be the latest active Consumer with BWE. If so we have to stop + // probation. if (this->tccClient) + { ComputeOutgoingDesiredBitrate(/*forceBitrate*/ true); + } break; } @@ -1493,23 +1616,31 @@ namespace RTC // Tell the SctpAssociation. if (this->sctpAssociation) + { this->sctpAssociation->TransportConnected(); + } // Start the RTCP timer. this->rtcpTimer->Start(static_cast(RTC::RTCP::MaxVideoIntervalMs / 2)); // Tell the TransportCongestionControlClient. if (this->tccClient) + { this->tccClient->TransportConnected(); + } // Tell the TransportCongestionControlServer. if (this->tccServer) + { this->tccServer->TransportConnected(); + } #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR // Tell the SenderBandwidthEstimator. if (this->senderBwe) + { this->senderBwe->TransportConnected(); + } #endif } @@ -1538,16 +1669,22 @@ namespace RTC // Tell the TransportCongestionControlClient. if (this->tccClient) + { this->tccClient->TransportDisconnected(); + } // Tell the TransportCongestionControlServer. if (this->tccServer) + { this->tccServer->TransportDisconnected(); + } #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR // Tell the SenderBandwidthEstimator. if (this->senderBwe) + { this->senderBwe->TransportDisconnected(); + } #endif } @@ -1566,7 +1703,9 @@ namespace RTC // Feed the TransportCongestionControlServer. if (this->tccServer) + { this->tccServer->IncomingPacket(nowMs, packet); + } // Get the associated Producer. RTC::Producer* producer = this->rtpListener.GetProducer(packet); @@ -1679,7 +1818,9 @@ namespace RTC auto it = this->mapProducers.find(jsonProducerIdIt->get()); if (it == this->mapProducers.end()) + { MS_THROW_ERROR("Producer not found"); + } RTC::Producer* producer = it->second; @@ -1719,7 +1860,9 @@ namespace RTC auto it = this->mapConsumers.find(jsonConsumerIdIt->get()); if (it == this->mapConsumers.end()) + { MS_THROW_ERROR("Consumer not found"); + } RTC::Consumer* consumer = it->second; @@ -1733,7 +1876,9 @@ namespace RTC auto mapSsrcConsumerIt = this->mapSsrcConsumer.find(ssrc); if (mapSsrcConsumerIt == this->mapSsrcConsumer.end()) + { return nullptr; + } auto* consumer = mapSsrcConsumerIt->second; @@ -1747,7 +1892,9 @@ namespace RTC auto mapRtxSsrcConsumerIt = this->mapRtxSsrcConsumer.find(ssrc); if (mapRtxSsrcConsumerIt == this->mapRtxSsrcConsumer.end()) + { return nullptr; + } auto* consumer = mapRtxSsrcConsumerIt->second; @@ -1787,7 +1934,9 @@ namespace RTC auto it = this->mapDataProducers.find(jsonDataProducerIdIt->get()); if (it == this->mapDataProducers.end()) + { MS_THROW_ERROR("DataProducer not found"); + } RTC::DataProducer* dataProducer = it->second; @@ -1827,7 +1976,9 @@ namespace RTC auto it = this->mapDataConsumers.find(jsonDataConsumerIdIt->get()); if (it == this->mapDataConsumers.end()) + { MS_THROW_ERROR("DataConsumer not found"); + } RTC::DataConsumer* dataConsumer = it->second; @@ -2085,12 +2236,16 @@ namespace RTC auto* feedback = static_cast(packet); if (this->tccClient) + { this->tccClient->ReceiveRtcpTransportFeedback(feedback); + } #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR // Pass it to the SenderBandwidthEstimator client. if (this->senderBwe) + { this->senderBwe->ReceiveRtcpTransportFeedback(feedback); + } #endif break; @@ -2176,7 +2331,9 @@ namespace RTC // SSRC should be filled in the sub-block. if (ssrcInfo->GetSsrc() == 0) + { ssrcInfo->SetSsrc(xr->GetSsrc()); + } auto* producer = this->rtpListener.GetProducer(ssrcInfo->GetSsrc()); @@ -2293,12 +2450,16 @@ namespace RTC auto priority = consumer->GetBitratePriority(); if (priority > 0u) + { multimapPriorityConsumer.emplace(priority, consumer); + } } // Nobody wants bitrate. Exit. if (multimapPriorityConsumer.empty()) + { return; + } bool baseAllocation = true; uint32_t availableBitrate = this->tccClient->GetAvailableBitrate(); @@ -2334,13 +2495,17 @@ namespace RTC // Exit the loop fast if used bitrate is 0. if (usedBitrate == 0u) + { break; + } } } // If no Consumer used bitrate, exit the loop. if (availableBitrate == previousAvailableBitrate) + { break; + } baseAllocation = false; } @@ -2382,7 +2547,9 @@ namespace RTC MS_TRACE(); if (!this->traceEventTypes.probation) + { return; + } json data = json::object(); @@ -2401,7 +2568,9 @@ namespace RTC MS_TRACE(); if (!this->traceEventTypes.bwe) + { return; + } json data = json::object(); @@ -2740,7 +2909,9 @@ namespace RTC // This may be the latest active Consumer with BWE. If so we have to stop probation. if (this->tccClient) + { ComputeOutgoingDesiredBitrate(/*forceBitrate*/ true); + } } inline void Transport::OnDataProducerMessageReceived( @@ -2870,10 +3041,14 @@ namespace RTC // its destructor is called first and then the parent Transport's destructor, // and we would end here calling SendSctpData() which is an abstract method. if (this->destroying) + { return; + } if (this->sctpAssociation) + { SendSctpData(data, len); + } } inline void Transport::OnSctpAssociationMessageReceived( @@ -2916,7 +3091,9 @@ namespace RTC auto* dataConsumer = kv.second; if (dataConsumer->GetType() == RTC::DataConsumer::Type::SCTP) + { dataConsumer->SctpAssociationBufferedAmount(bufferedAmount); + } } } diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index f555bdf7a5..7a782c9739 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -27,11 +27,12 @@ namespace RTC RTC::TransportCongestionControlClient::Listener* listener, RTC::BweType bweType, uint32_t initialAvailableBitrate, - uint32_t maxOutgoingBitrate) + uint32_t maxOutgoingBitrate, + uint32_t minOutgoingBitrate) : listener(listener), bweType(bweType), initialAvailableBitrate(std::max( initialAvailableBitrate, RTC::TransportCongestionControlMinOutgoingBitrate)), - maxOutgoingBitrate(maxOutgoingBitrate) + maxOutgoingBitrate(maxOutgoingBitrate), minOutgoingBitrate(minOutgoingBitrate) { MS_TRACE(); @@ -281,6 +282,16 @@ namespace RTC } } + void TransportCongestionControlClient::SetMinOutgoingBitrate(uint32_t minBitrate) + { + this->minOutgoingBitrate = minBitrate; + + ApplyBitrateUpdates(); + + this->bitrates.minBitrate = std::max( + this->minOutgoingBitrate, RTC::TransportCongestionControlMinOutgoingBitrate); + } + void TransportCongestionControlClient::SetDesiredBitrate(uint32_t desiredBitrate, bool force) { MS_TRACE(); @@ -305,7 +316,9 @@ namespace RTC this->bitrates.effectiveDesiredBitrate = desiredBitrate; #endif - this->bitrates.minBitrate = RTC::TransportCongestionControlMinOutgoingBitrate; + this->bitrates.minBitrate = std::max( + this->minOutgoingBitrate, RTC::TransportCongestionControlMinOutgoingBitrate); + // NOTE: Setting 'startBitrate' to 'availableBitrate' has proven to generate // more stable values. this->bitrates.startBitrate = std::max( @@ -333,9 +346,10 @@ namespace RTC this->bitrates.desiredBitrate * MaxBitrateIncrementFactor); #endif - // If max bitrate requested didn't change by more than a small % keep the previous settings - // to avoid constant small fluctuations requiring extra probing and making the estimation - // less stable (requires constant redistribution of bitrate accross consumers). + // If max bitrate requested didn't change by more than a small % keep the + // previous settings to avoid constant small fluctuations requiring extra + // probing and making the estimation less stable (requires constant + // redistribution of bitrate accross consumers). auto maxBitrateMargin = newMaxBitrate * MaxBitrateMarginFactor; if (currentMaxBitrate > newMaxBitrate - maxBitrateMargin && currentMaxBitrate < newMaxBitrate + maxBitrateMargin) { @@ -358,6 +372,9 @@ namespace RTC this->bitrates.maxBitrate = newMaxBitrate; } + this->bitrates.minBitrate = std::max( + this->minOutgoingBitrate, RTC::TransportCongestionControlMinOutgoingBitrate); + MS_DEBUG_DEV( "[desiredBitrate:%" PRIu32 ", desiredBitrateTrend:%" PRIu32 ", startBitrate:%" PRIu32 ", minBitrate:%" PRIu32 ", maxBitrate:%" PRIu32 ", maxPaddingBitrate:%" PRIu32 "]", From 3235e06673ddc5f1d6d06f0d5b7e9bef3f6a76b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 29 Mar 2023 15:12:31 +0200 Subject: [PATCH 055/525] Update NPM deps --- package-lock.json | 103 ++++++++++++++++++++++++---------------------- package.json | 4 +- 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index e1e5628598..b990e728b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,11 +18,11 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.5.0", - "@types/node": "^18.15.10", + "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", - "eslint": "^8.36.0", + "eslint": "^8.37.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", "open-cli": "^7.2.0", @@ -667,14 +667,14 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", + "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.0", + "espree": "^9.5.1", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -690,9 +690,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", + "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1341,9 +1341,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.15.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz", - "integrity": "sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ==", + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -2423,15 +2423,15 @@ } }, "node_modules/eslint": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", - "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", + "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.1", - "@eslint/js": "8.36.0", + "@eslint/eslintrc": "^2.0.2", + "@eslint/js": "8.37.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2442,8 +2442,8 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.5.0", + "eslint-visitor-keys": "^3.4.0", + "espree": "^9.5.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2517,12 +2517,15 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-scope": { @@ -2548,14 +2551,14 @@ } }, "node_modules/espree": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", - "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", + "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", "dev": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -6569,14 +6572,14 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", + "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.0", + "espree": "^9.5.1", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -6586,9 +6589,9 @@ } }, "@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", + "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", "dev": true }, "@humanwhocodes/config-array": { @@ -7123,9 +7126,9 @@ "dev": true }, "@types/node": { - "version": "18.15.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz", - "integrity": "sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ==", + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", "dev": true }, "@types/normalize-package-data": { @@ -7876,15 +7879,15 @@ "dev": true }, "eslint": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", - "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", + "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.1", - "@eslint/js": "8.36.0", + "@eslint/eslintrc": "^2.0.2", + "@eslint/js": "8.37.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7895,8 +7898,8 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.5.0", + "eslint-visitor-keys": "^3.4.0", + "espree": "^9.5.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -7961,20 +7964,20 @@ } }, "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true }, "espree": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", - "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", + "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", "dev": true, "requires": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.0" } }, "esprima": { diff --git a/package.json b/package.json index f96c7b0aa9..f53be03c33 100644 --- a/package.json +++ b/package.json @@ -93,11 +93,11 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/jest": "^29.5.0", - "@types/node": "^18.15.10", + "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", - "eslint": "^8.36.0", + "eslint": "^8.37.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", "open-cli": "^7.2.0", From e30d5f7e54874bac777566cdeb8445965ad08109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 29 Mar 2023 15:15:35 +0200 Subject: [PATCH 056/525] 3.11.17 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73aa7e2f65..195fb87df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.11.17 * Add `transport.setMinOutgoingBitrate()` method ([PR #1038](https://github.com/versatica/mediasoup/pull/1038), credits to @ jcague). * `RTC::RetransmissionBuffer`: Increase `RetransmissionBufferMaxItems` from 2500 to 5000. diff --git a/package-lock.json b/package-lock.json index b990e728b0..8d667e6aae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.16", + "version": "3.11.17", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.16", + "version": "3.11.17", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index f53be03c33..59e5b083d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.16", + "version": "3.11.17", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From cb039ec4458959dba35a63504182dd5cac0ee402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 29 Mar 2023 17:11:36 +0200 Subject: [PATCH 057/525] fix typo --- worker/src/RTC/RtpStream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/RtpStream.cpp b/worker/src/RTC/RtpStream.cpp index b8e123c6af..72e8bc859d 100644 --- a/worker/src/RTC/RtpStream.cpp +++ b/worker/src/RTC/RtpStream.cpp @@ -193,7 +193,7 @@ namespace RTC this->maxSeq = seq; } // Too old packet received (older than the allowed misorder). - // Or to new packet (more than acceptable dropout). + // Or too new packet (more than acceptable dropout). else if (udelta <= RtpSeqMod - MaxMisorder) { // The sequence number made a very large jump. If two sequential packets From 5823632a1dbae6abe0d08fd31cfee7393a7f3c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 29 Mar 2023 18:31:06 +0200 Subject: [PATCH 058/525] RtpRetransmissionBuffer: consider the case of packet with newest timestamp but "old" seq number (#1039) Fixes #1037 - We must consider the case in which, due for example to huge packet loss, received packet has higher timestamp but "older" seq than the newest packet in the buffer and, if so, use it to clear too old packets rather than the newest packet in the buffer. - Bonus track: restore buffer size to 2500 since increasing it didn't indeed help (it shouldn't help as proven). --- CHANGELOG.md | 5 ++ .../include/RTC/RtpRetransmissionBuffer.hpp | 2 +- worker/src/RTC/RtpRetransmissionBuffer.cpp | 52 ++++++++++++++----- worker/src/RTC/RtpStreamSend.cpp | 2 +- .../src/RTC/TestRtpRetransmissionBuffer.cpp | 23 ++++++++ 5 files changed, 70 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 195fb87df5..e84cbfeb8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* `RtpRetransmissionBuffer`: Consider the case of packet with newest timestamp but "old" seq number ([PR #1039](https://github.com/versatica/mediasoup/pull/1039)). + + ### 3.11.17 * Add `transport.setMinOutgoingBitrate()` method ([PR #1038](https://github.com/versatica/mediasoup/pull/1038), credits to @ jcague). diff --git a/worker/include/RTC/RtpRetransmissionBuffer.hpp b/worker/include/RTC/RtpRetransmissionBuffer.hpp index 059879d546..b893b7966e 100644 --- a/worker/include/RTC/RtpRetransmissionBuffer.hpp +++ b/worker/include/RTC/RtpRetransmissionBuffer.hpp @@ -46,7 +46,7 @@ namespace RTC Item* GetNewest() const; void RemoveOldest(); void RemoveOldest(uint16_t numItems); - void ClearTooOld(); + bool ClearTooOld(uint32_t newestTimestamp); bool IsTooOld(uint32_t timestamp, uint32_t newestTimestamp) const; Item* FillItem( Item* item, RTC::RtpPacket* packet, std::shared_ptr& sharedPacket) const; diff --git a/worker/src/RTC/RtpRetransmissionBuffer.cpp b/worker/src/RTC/RtpRetransmissionBuffer.cpp index dd3e33f294..1342372100 100644 --- a/worker/src/RTC/RtpRetransmissionBuffer.cpp +++ b/worker/src/RTC/RtpRetransmissionBuffer.cpp @@ -81,11 +81,41 @@ namespace RTC return; } + auto* oldestItem = GetOldest(); + auto* newestItem = GetNewest(); + // Clear too old packets in the buffer. - ClearTooOld(); + // NOTE: Here we must consider the case in which, due for example to huge + // packet loss, received packet has higher timestamp but "older" seq number + // than the newest packet in the buffer and, if so, use it to clear too old + // packets rather than the newest packet in the buffer. + auto newestTimestamp = + RTC::SeqManager::IsSeqHigherThan(timestamp, newestItem->timestamp) + ? timestamp + : newestItem->timestamp; + + // ClearTooOld() returns true if at least one packet has been removed from + // the front. + if (ClearTooOld(newestTimestamp)) + { + // Buffer content has been modified so we must check it again. + if (this->buffer.empty()) + { + MS_DEBUG_DEV( + "buffer empty after clearing too old packets [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + seq, + timestamp); - const auto* oldestItem = GetOldest(); - const auto* newestItem = GetNewest(); + auto* item = new Item(); + + this->buffer.push_back(FillItem(item, packet, sharedPacket)); + + return; + } + + oldestItem = GetOldest(); + newestItem = GetNewest(); + } MS_ASSERT(oldestItem != nullptr, "oldest item doesn't exist"); MS_ASSERT(newestItem != nullptr, "newest item doesn't exist"); @@ -456,26 +486,22 @@ namespace RTC } } - void RtpRetransmissionBuffer::ClearTooOld() + bool RtpRetransmissionBuffer::ClearTooOld(uint32_t newestTimestamp) { MS_TRACE(); - const auto* newestItem = GetNewest(); - - if (!newestItem) - { - return; - } - RtpRetransmissionBuffer::Item* oldestItem{ nullptr }; + bool itemsRemoved{ false }; // Go through all buffer items starting with the first and free all items // that contain too old packets. while ((oldestItem = GetOldest())) { - if (IsTooOld(oldestItem->timestamp, newestItem->timestamp)) + if (IsTooOld(oldestItem->timestamp, newestTimestamp)) { RemoveOldest(); + + itemsRemoved = true; } // If current oldest stored packet is not too old, exit the loop since we // know that packets stored after it are guaranteed to be newer. @@ -484,6 +510,8 @@ namespace RTC break; } } + + return itemsRemoved; } bool RtpRetransmissionBuffer::IsTooOld(uint32_t timestamp, uint32_t newestTimestamp) const diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 67231d14df..0103492e06 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -12,7 +12,7 @@ namespace RTC /* Static. */ // Limit max number of items in the retransmission buffer. - static constexpr size_t RetransmissionBufferMaxItems{ 5000u }; + static constexpr size_t RetransmissionBufferMaxItems{ 2500u }; // 17: 16 bit mask + the initial sequence number. static constexpr size_t MaxRequestedPackets{ 17u }; thread_local static std::vector RetransmissionContainer( diff --git a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp index 1d11c5364b..3c24ae15d0 100644 --- a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp +++ b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp @@ -230,6 +230,29 @@ SCENARIO("RtpRetransmissionBuffer", "[rtp][rtx]") // clang-format on } + SECTION("packet with very newest timestamp is inserted as newest item despite its seq is old") + { + uint16_t maxItems{ 4 }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + RtpMyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + + // Scenario based on https://github.com/versatica/mediasoup/issues/1037. + + myRetransmissionBuffer.Insert(24816, 1024930187); + myRetransmissionBuffer.Insert(24980, 1025106407); + myRetransmissionBuffer.Insert(18365, 1026593387); + + // clang-format off + myRetransmissionBuffer.AssertBuffer( + { + { true, 18365, 1026593387 } + } + ); + // clang-format on + } + SECTION("fuzzer generated packets") { uint16_t maxItems{ 2500u }; From b6c3190916afdd2500635aa73443222cf1d48d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 29 Mar 2023 18:33:50 +0200 Subject: [PATCH 059/525] 3.11.18 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e84cbfeb8f..56de09b421 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.11.18 * `RtpRetransmissionBuffer`: Consider the case of packet with newest timestamp but "old" seq number ([PR #1039](https://github.com/versatica/mediasoup/pull/1039)). diff --git a/package-lock.json b/package-lock.json index 8d667e6aae..4a932f76be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.17", + "version": "3.11.18", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.17", + "version": "3.11.18", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 59e5b083d9..ef5deb00fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.17", + "version": "3.11.18", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From f9e9c6451d299cce6bd363ff86fd22b8cc364565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 30 Mar 2023 11:44:19 +0200 Subject: [PATCH 060/525] Fix false -Wmaybe-uninitialized when using old GCC versions Fixes #1040 --- worker/src/RTC/RtpStreamSend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 0103492e06..a0540a6fe4 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -52,7 +52,7 @@ namespace RTC break; } - case RTC::RtpCodecMimeType::Type::UNSET: + default: { MS_ABORT("codec mimeType not set"); } From eafca69f60bddbf141cbc737c3fba4bdec560274 Mon Sep 17 00:00:00 2001 From: Vittorio Palmisano Date: Thu, 30 Mar 2023 11:56:15 +0200 Subject: [PATCH 061/525] Properly handle ksvc bandwidth allocation (#1036) --- worker/src/RTC/SvcConsumer.cpp | 49 ++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index f9a84da769..c2278ba556 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -426,6 +426,28 @@ namespace RTC requiredBitrate = this->producerRtpStream->GetLayerBitrate(nowMs, spatialLayer, temporalLayer); + // When using K-SVC we must subtract the bitrate of the current used layer + // if the new layer is the temporal layer 0 of an higher spatial layer. + // + // clang-format off + if ( + this->encodingContext->IsKSvc() && + requiredBitrate && + temporalLayer == 0 && + this->provisionalTargetSpatialLayer > -1 && + spatialLayer > this->provisionalTargetSpatialLayer + ) + // clang-format on + { + auto provisionalRequiredBitrate = this->producerRtpStream->GetBitrate( + nowMs, this->provisionalTargetSpatialLayer, this->provisionalTargetTemporalLayer); + + if (requiredBitrate > provisionalRequiredBitrate) + requiredBitrate -= provisionalRequiredBitrate; + else + requiredBitrate = 1u; // Don't set 0 since it would be ignored. + } + MS_DEBUG_DEV( "testing layers %" PRIi16 ":%" PRIi16 " [virtual bitrate:%" PRIu32 ", required bitrate:%" PRIu32 "]", @@ -531,8 +553,31 @@ namespace RTC if (!IsActive()) return 0u; - auto nowMs = DepLibUV::GetTimeMs(); - uint32_t desiredBitrate = this->producerRtpStream->GetBitrate(nowMs); + auto nowMs = DepLibUV::GetTimeMs(); + uint32_t desiredBitrate{ 0u }; + + // When using K-SVC each spatial layer is independent of the others. + if (this->encodingContext->IsKSvc()) + { + // Let's iterate all spatial layers of the Producer (from highest to lowest) and + // obtain their bitrate. Choose the highest one. + // NOTE: When the Producer enables a higher spatial layer, initially the bitrate + // oft could be less than the bitrate of a lower one. That's why we iterate all + // spatial layers here anyway. + for (auto spatialLayer{ this->producerRtpStream->GetSpatialLayers() - 1 }; spatialLayer >= 0; + --spatialLayer) + { + auto spatialLayerBitrate = + this->producerRtpStream->GetSpatialLayerBitrate(nowMs, spatialLayer); + + if (spatialLayerBitrate > desiredBitrate) + desiredBitrate = spatialLayerBitrate; + } + } + else + { + desiredBitrate = this->producerRtpStream->GetBitrate(nowMs); + } // If consumer.rtpParameters.encodings[0].maxBitrate was given and it's // greater than computed one, then use it. From ddecc7fb9efceb4a4dd74ac4a2d130a9fe0177a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 30 Mar 2023 11:59:17 +0200 Subject: [PATCH 062/525] 3.11.19 --- CHANGELOG.md | 5 +++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56de09b421..df1cbabff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.11.19 + +* `SvcConsumer`: Properly handle VP9 K-SVC bandwidth allocation ([PR #1036](https://github.com/versatica/mediasoup/pull/1036) by @vpalmisano). + + ### 3.11.18 * `RtpRetransmissionBuffer`: Consider the case of packet with newest timestamp but "old" seq number ([PR #1039](https://github.com/versatica/mediasoup/pull/1039)). diff --git a/package-lock.json b/package-lock.json index 4a932f76be..a8fb2a85ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.18", + "version": "3.11.19", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.18", + "version": "3.11.19", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index ef5deb00fb..d87644db13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.18", + "version": "3.11.19", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 1b579f59e3b39758e1cb4ec4629b40ac531d63a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 30 Mar 2023 17:15:00 +0200 Subject: [PATCH 063/525] Reset RTP retransmission buffer upon RTP sequence number reset (#1041) --- CHANGELOG.md | 5 ++ worker/include/RTC/RtpStream.hpp | 4 ++ worker/include/RTC/RtpStreamRecv.hpp | 4 ++ worker/include/RTC/RtpStreamSend.hpp | 4 ++ worker/src/RTC/RtpStream.cpp | 4 ++ worker/src/RTC/RtpStreamRecv.cpp | 7 ++ worker/src/RTC/RtpStreamSend.cpp | 11 +++ worker/test/src/RTC/TestRtpStreamSend.cpp | 83 +++++++++++++++++------ 8 files changed, 103 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df1cbabff8..0124b42a6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* `RtpStreamSend`: Reset RTP retransmission buffer upon RTP sequence number reset ([PR #1041](https://github.com/versatica/mediasoup/pull/1041)). + + ### 3.11.19 * `SvcConsumer`: Properly handle VP9 K-SVC bandwidth allocation ([PR #1036](https://github.com/versatica/mediasoup/pull/1036) by @vpalmisano). diff --git a/worker/include/RTC/RtpStream.hpp b/worker/include/RTC/RtpStream.hpp index de4b70949b..9a0ca8daa6 100644 --- a/worker/include/RTC/RtpStream.hpp +++ b/worker/include/RTC/RtpStream.hpp @@ -175,6 +175,10 @@ namespace RTC private: void InitSeq(uint16_t seq); + /* Pure virtual method that must be implemented by the subclass. */ + protected: + virtual void UserOnSequenceNumberReset() = 0; + protected: // Given as argument. RTC::RtpStream::Listener* listener{ nullptr }; diff --git a/worker/include/RTC/RtpStreamRecv.hpp b/worker/include/RTC/RtpStreamRecv.hpp index 594a47e5f3..4457e38205 100644 --- a/worker/include/RTC/RtpStreamRecv.hpp +++ b/worker/include/RTC/RtpStreamRecv.hpp @@ -80,6 +80,10 @@ namespace RTC void CalculateJitter(uint32_t rtpTimestamp); void UpdateScore(); + /* Pure virtual methods inherited from RTC::RtpStream. */ + public: + void UserOnSequenceNumberReset() override; + /* Pure virtual methods inherited from Timer. */ protected: void OnTimer(Timer* timer) override; diff --git a/worker/include/RTC/RtpStreamSend.hpp b/worker/include/RTC/RtpStreamSend.hpp index 7f041c9b21..9c59c897dd 100644 --- a/worker/include/RTC/RtpStreamSend.hpp +++ b/worker/include/RTC/RtpStreamSend.hpp @@ -53,6 +53,10 @@ namespace RTC void FillRetransmissionContainer(uint16_t seq, uint16_t bitmask); void UpdateScore(RTC::RTCP::ReceiverReport* report); + /* Pure virtual methods inherited from RTC::RtpStream. */ + public: + void UserOnSequenceNumberReset() override; + private: // Packets lost at last interval for score calculation. uint32_t lostPriorScore{ 0u }; diff --git a/worker/src/RTC/RtpStream.cpp b/worker/src/RTC/RtpStream.cpp index 72e8bc859d..85b6850b81 100644 --- a/worker/src/RTC/RtpStream.cpp +++ b/worker/src/RTC/RtpStream.cpp @@ -28,6 +28,7 @@ namespace RTC MS_TRACE(); delete this->rtxStream; + this->rtxStream = nullptr; } void RtpStream::FillJson(json& jsonObject) const @@ -212,6 +213,9 @@ namespace RTC this->maxPacketTs = packet->GetTimestamp(); this->maxPacketMs = DepLibUV::GetTimeMs(); + + // Notify the subclass about it. + UserOnSequenceNumberReset(); } else { diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index c74051f5d4..240e260e69 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -836,6 +836,13 @@ namespace RTC RtpStream::UpdateScore(score); } + void RtpStreamRecv::UserOnSequenceNumberReset() + { + MS_TRACE(); + + // Nothing to do. + } + inline void RtpStreamRecv::OnTimer(Timer* timer) { MS_TRACE(); diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index a0540a6fe4..b8949a37ff 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -627,4 +627,15 @@ namespace RTC RtpStream::UpdateScore(score); } + + void RtpStreamSend::UserOnSequenceNumberReset() + { + MS_TRACE(); + + // Clear retransmission buffer. + if (this->retransmissionBuffer) + { + this->retransmissionBuffer->Clear(); + } + } } // namespace RTC diff --git a/worker/test/src/RTC/TestRtpStreamSend.cpp b/worker/test/src/RTC/TestRtpStreamSend.cpp index 58ea00adb7..b1182ca4e0 100644 --- a/worker/test/src/RTC/TestRtpStreamSend.cpp +++ b/worker/test/src/RTC/TestRtpStreamSend.cpp @@ -123,11 +123,11 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") REQUIRE(testRtpStreamListener.retransmittedPackets.size() == 5); - auto rtxPacket1 = testRtpStreamListener.retransmittedPackets[0]; - auto rtxPacket2 = testRtpStreamListener.retransmittedPackets[1]; - auto rtxPacket3 = testRtpStreamListener.retransmittedPackets[2]; - auto rtxPacket4 = testRtpStreamListener.retransmittedPackets[3]; - auto rtxPacket5 = testRtpStreamListener.retransmittedPackets[4]; + auto* rtxPacket1 = testRtpStreamListener.retransmittedPackets[0]; + auto* rtxPacket2 = testRtpStreamListener.retransmittedPackets[1]; + auto* rtxPacket3 = testRtpStreamListener.retransmittedPackets[2]; + auto* rtxPacket4 = testRtpStreamListener.retransmittedPackets[3]; + auto* rtxPacket5 = testRtpStreamListener.retransmittedPackets[4]; testRtpStreamListener.retransmittedPackets.clear(); @@ -294,8 +294,8 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") REQUIRE(testRtpStreamListener1.retransmittedPackets.size() == 2); - auto rtxPacket1 = testRtpStreamListener1.retransmittedPackets[0]; - auto rtxPacket2 = testRtpStreamListener1.retransmittedPackets[1]; + auto* rtxPacket1 = testRtpStreamListener1.retransmittedPackets[0]; + auto* rtxPacket2 = testRtpStreamListener1.retransmittedPackets[1]; testRtpStreamListener1.retransmittedPackets.clear(); @@ -330,7 +330,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, secondTs - 1); // Create a RtpStreamSend instance. - TestRtpStreamListener testRtpStreamListener1; + TestRtpStreamListener testRtpStreamListener; RtpStream::Params params1; @@ -340,7 +340,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - auto* stream = new RtpStreamSend(&testRtpStreamListener1, params1, mid); + auto* stream = new RtpStreamSend(&testRtpStreamListener, params1, mid); // Receive all the packets. SendRtpPacket({ { stream, params1.ssrc } }, packet1); @@ -358,12 +358,12 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") // Process the NACK packet on stream1. stream->ReceiveNack(&nackPacket); - REQUIRE(testRtpStreamListener1.retransmittedPackets.size() == 2); + REQUIRE(testRtpStreamListener.retransmittedPackets.size() == 2); - auto rtxPacket1 = testRtpStreamListener1.retransmittedPackets[0]; - auto rtxPacket2 = testRtpStreamListener1.retransmittedPackets[1]; + auto* rtxPacket1 = testRtpStreamListener.retransmittedPackets[0]; + auto* rtxPacket2 = testRtpStreamListener.retransmittedPackets[1]; - testRtpStreamListener1.retransmittedPackets.clear(); + testRtpStreamListener.retransmittedPackets.clear(); CheckRtxPacket(rtxPacket1, packet1->GetSequenceNumber(), packet1->GetTimestamp()); CheckRtxPacket(rtxPacket2, packet2->GetSequenceNumber(), packet2->GetTimestamp()); @@ -386,7 +386,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") auto* packet3 = CreateRtpPacket(rtpBuffer3, 21008, thirdTs); // Create a RtpStreamSend instance. - TestRtpStreamListener testRtpStreamListener1; + TestRtpStreamListener testRtpStreamListener; RtpStream::Params params1; @@ -396,14 +396,14 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - auto* stream = new RtpStreamSend(&testRtpStreamListener1, params1, mid); + auto* stream = new RtpStreamSend(&testRtpStreamListener, params1, mid); // Receive all the packets. SendRtpPacket({ { stream, params1.ssrc } }, packet1); SendRtpPacket({ { stream, params1.ssrc } }, packet2); SendRtpPacket({ { stream, params1.ssrc } }, packet3); - // Create a NACK item that request for all the packets. + // Create a NACK item that requests for all packets. RTCP::FeedbackRtpNackPacket nackPacket(0, params1.ssrc); auto* nackItem = new RTCP::FeedbackRtpNackItem(21006, 0b0000000000000001); @@ -415,17 +415,62 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") // Process the NACK packet on stream1. stream->ReceiveNack(&nackPacket); - REQUIRE(testRtpStreamListener1.retransmittedPackets.size() == 1); + REQUIRE(testRtpStreamListener.retransmittedPackets.size() == 1); - auto rtxPacket2 = testRtpStreamListener1.retransmittedPackets[0]; + auto* rtxPacket2 = testRtpStreamListener.retransmittedPackets[0]; - testRtpStreamListener1.retransmittedPackets.clear(); + testRtpStreamListener.retransmittedPackets.clear(); CheckRtxPacket(rtxPacket2, packet2->GetSequenceNumber(), packet2->GetTimestamp()); delete stream; } + SECTION("packets get removed from the retransmission buffer if seq number of the stream is reset") + { + // This scenario reproduce the "too bad sequence number" and "bad sequence + // number" scenarios in RtpStream::UpdateSeq(). + auto* packet1 = CreateRtpPacket(rtpBuffer1, 50001, 1000001); + auto* packet2 = CreateRtpPacket(rtpBuffer2, 50002, 1000002); + // Third packet has bad sequence number (its seq is more than MaxDropout=3000 + // older than current max seq) and will be dropped. + auto* packet3 = CreateRtpPacket(rtpBuffer3, 40003, 1000003); + // Forth packet has seq=badSeq+1 so will be accepted and will trigger a + // stream reset. + auto* packet4 = CreateRtpPacket(rtpBuffer4, 40004, 1000004); + + // Create a RtpStreamSend instance. + TestRtpStreamListener testRtpStreamListener; + + RtpStream::Params params1; + + params1.ssrc = 1111; + params1.clockRate = 90000; + params1.useNack = true; + params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; + + std::string mid; + auto* stream = new RtpStreamSend(&testRtpStreamListener, params1, mid); + + SendRtpPacket({ { stream, params1.ssrc } }, packet1); + SendRtpPacket({ { stream, params1.ssrc } }, packet2); + SendRtpPacket({ { stream, params1.ssrc } }, packet3); + SendRtpPacket({ { stream, params1.ssrc } }, packet4); + + // Create a NACK item that requests for packets 1 and 2. + RTCP::FeedbackRtpNackPacket nackPacket2(0, params1.ssrc); + auto* nackItem2 = new RTCP::FeedbackRtpNackItem(50001, 0b0000000000000001); + + nackPacket2.AddItem(nackItem2); + + // Process the NACK packet on stream1. + stream->ReceiveNack(&nackPacket2); + + REQUIRE(testRtpStreamListener.retransmittedPackets.size() == 0); + + delete stream; + } + #ifdef PERFORMANCE_TEST SECTION("Performance") { From 4b0d5be98d33eb452670a5ebe12e8d6c90175017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 30 Mar 2023 19:08:50 +0200 Subject: [PATCH 064/525] worker/Makefile: move a Windows related comment so it's not printed in OS != Windows --- worker/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/Makefile b/worker/Makefile index 4547ae13d4..3e8fc4eac7 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -216,9 +216,9 @@ format: test: setup $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-test +ifeq ($(OS),Windows_NT) # On Windows lcov doesn't work (at least not yet) and we need to add `.exe` to # the binary path. -ifeq ($(OS),Windows_NT) $(BUILD_DIR)/mediasoup-worker-test.exe --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS) else $(LCOV) --directory ./ --zerocounters From 752883bc61a741bc97072fdc15a3c217000262b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 30 Mar 2023 20:10:27 +0200 Subject: [PATCH 065/525] RtpRetransmissionBuffer: improve methods' name and logs --- .../include/RTC/RtpRetransmissionBuffer.hpp | 4 ++-- worker/src/RTC/RtpRetransmissionBuffer.cpp | 24 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/worker/include/RTC/RtpRetransmissionBuffer.hpp b/worker/include/RTC/RtpRetransmissionBuffer.hpp index b893b7966e..dee6894876 100644 --- a/worker/include/RTC/RtpRetransmissionBuffer.hpp +++ b/worker/include/RTC/RtpRetransmissionBuffer.hpp @@ -46,8 +46,8 @@ namespace RTC Item* GetNewest() const; void RemoveOldest(); void RemoveOldest(uint16_t numItems); - bool ClearTooOld(uint32_t newestTimestamp); - bool IsTooOld(uint32_t timestamp, uint32_t newestTimestamp) const; + bool ClearTooOldByTimestamp(uint32_t newestTimestamp); + bool IsTooOldTimestamp(uint32_t timestamp, uint32_t newestTimestamp) const; Item* FillItem( Item* item, RTC::RtpPacket* packet, std::shared_ptr& sharedPacket) const; diff --git a/worker/src/RTC/RtpRetransmissionBuffer.cpp b/worker/src/RTC/RtpRetransmissionBuffer.cpp index 1342372100..1e61043465 100644 --- a/worker/src/RTC/RtpRetransmissionBuffer.cpp +++ b/worker/src/RTC/RtpRetransmissionBuffer.cpp @@ -94,9 +94,9 @@ namespace RTC ? timestamp : newestItem->timestamp; - // ClearTooOld() returns true if at least one packet has been removed from - // the front. - if (ClearTooOld(newestTimestamp)) + // ClearTooOldByTimestamp() returns true if at least one packet has been + // removed from the front. + if (ClearTooOldByTimestamp(newestTimestamp)) { // Buffer content has been modified so we must check it again. if (this->buffer.empty()) @@ -132,7 +132,7 @@ namespace RTC { MS_WARN_TAG( rtp, - "packet has higher seq but less timestamp than newest packet in the buffer, discarding it [ssrc:%" PRIu32 + "packet has higher seq but lower timestamp than newest packet in the buffer, discarding it [ssrc:%" PRIu32 ", seq:%" PRIu16 ", timestamp:%" PRIu32 "]", ssrc, seq, @@ -204,10 +204,12 @@ namespace RTC timestamp); // Ensure that packet is not too old to be stored. - if (IsTooOld(timestamp, newestItem->timestamp)) + if (IsTooOldTimestamp(timestamp, newestItem->timestamp)) { MS_WARN_DEV( - "packet too old, discarding it [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", seq, timestamp); + "packet's timestamp too old, discarding it [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + seq, + timestamp); return; } @@ -218,7 +220,7 @@ namespace RTC { MS_WARN_TAG( rtp, - "packet has less seq but higher timestamp than oldest packet in the buffer, discarding it [ssrc:%" PRIu32 + "packet has lower seq but higher timestamp than oldest packet in the buffer, discarding it [ssrc:%" PRIu32 ", seq:%" PRIu16 ", timestamp:%" PRIu32 "]", ssrc, seq, @@ -305,7 +307,7 @@ namespace RTC { MS_WARN_TAG( rtp, - "packet timestamp is less than timestamp of immediate older packet in the buffer, discarding it [ssrc:%" PRIu32 + "packet timestamp is lower than timestamp of immediate older packet in the buffer, discarding it [ssrc:%" PRIu32 ", seq:%" PRIu16 ", timestamp:%" PRIu32 "]", ssrc, seq, @@ -486,7 +488,7 @@ namespace RTC } } - bool RtpRetransmissionBuffer::ClearTooOld(uint32_t newestTimestamp) + bool RtpRetransmissionBuffer::ClearTooOldByTimestamp(uint32_t newestTimestamp) { MS_TRACE(); @@ -497,7 +499,7 @@ namespace RTC // that contain too old packets. while ((oldestItem = GetOldest())) { - if (IsTooOld(oldestItem->timestamp, newestTimestamp)) + if (IsTooOldTimestamp(oldestItem->timestamp, newestTimestamp)) { RemoveOldest(); @@ -514,7 +516,7 @@ namespace RTC return itemsRemoved; } - bool RtpRetransmissionBuffer::IsTooOld(uint32_t timestamp, uint32_t newestTimestamp) const + bool RtpRetransmissionBuffer::IsTooOldTimestamp(uint32_t timestamp, uint32_t newestTimestamp) const { MS_TRACE(); From 97e3fd62ded36fdcf1007d48373afe7ea02c2610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 31 Mar 2023 10:40:53 +0200 Subject: [PATCH 066/525] RTC::RtpRetransmissionBuffer: Handle corner case in which received packet has lower seq than newest packet in the buffer but higher timestamp (#1044) --- CHANGELOG.md | 1 + package-lock.json | 14 +++++----- package.json | 2 +- worker/src/RTC/RtpRetransmissionBuffer.cpp | 26 ++++++++++++++++++- .../src/RTC/TestRtpRetransmissionBuffer.cpp | 24 +++++++++++++++++ 5 files changed, 58 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0124b42a6e..e4cc3c1266 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### NEXT * `RtpStreamSend`: Reset RTP retransmission buffer upon RTP sequence number reset ([PR #1041](https://github.com/versatica/mediasoup/pull/1041)). +* `RtpRetransmissionBuffer`: Handle corner case in which received packet has lower seq than newest packet in the buffer but higher timestamp ([PR #1044](https://github.com/versatica/mediasoup/pull/1044)). ### 3.11.19 diff --git a/package-lock.json b/package-lock.json index a8fb2a85ab..79bf288a9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.0.5", "tsc-watch": "^6.0.0", - "typescript": "^5.0.2" + "typescript": "^5.0.3" }, "engines": { "node": ">=16" @@ -5808,9 +5808,9 @@ } }, "node_modules/typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", + "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -10295,9 +10295,9 @@ "dev": true }, "typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", + "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index d87644db13..ff814f5cc5 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.0.5", "tsc-watch": "^6.0.0", - "typescript": "^5.0.2" + "typescript": "^5.0.3" } } diff --git a/worker/src/RTC/RtpRetransmissionBuffer.cpp b/worker/src/RTC/RtpRetransmissionBuffer.cpp index 1e61043465..2ddbc2a028 100644 --- a/worker/src/RTC/RtpRetransmissionBuffer.cpp +++ b/worker/src/RTC/RtpRetransmissionBuffer.cpp @@ -84,6 +84,29 @@ namespace RTC auto* oldestItem = GetOldest(); auto* newestItem = GetNewest(); + // Special case: Received packet has lower seq than newest packet in the + // buffer, however its timestamp is higher. If so, clear the whole buffer. + if ( + RTC::SeqManager::IsSeqLowerThan(seq, newestItem->sequenceNumber) && + RTC::SeqManager::IsSeqHigherThan(timestamp, newestItem->timestamp)) + { + MS_WARN_TAG( + rtp, + "packet has lower seq but higher timestamp than newest packet in the buffer, emptying the buffer [ssrc:%" PRIu32 + ", seq:%" PRIu16 ", timestamp:%" PRIu32 "]", + ssrc, + seq, + timestamp); + + Clear(); + + auto* item = new Item(); + + this->buffer.push_back(FillItem(item, packet, sharedPacket)); + + return; + } + // Clear too old packets in the buffer. // NOTE: Here we must consider the case in which, due for example to huge // packet loss, received packet has higher timestamp but "older" seq number @@ -101,7 +124,8 @@ namespace RTC // Buffer content has been modified so we must check it again. if (this->buffer.empty()) { - MS_DEBUG_DEV( + MS_WARN_TAG( + rtp, "buffer empty after clearing too old packets [seq:%" PRIu16 ", timestamp:%" PRIu32 "]", seq, timestamp); diff --git a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp index 3c24ae15d0..74d2628b44 100644 --- a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp +++ b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp @@ -253,6 +253,30 @@ SCENARIO("RtpRetransmissionBuffer", "[rtp][rtx]") // clang-format on } + SECTION( + "packet with lower seq than newest packet in the buffer and higher timestamp forces buffer emptying") + { + uint16_t maxItems{ 4 }; + uint32_t maxRetransmissionDelayMs{ 2000u }; + uint32_t clockRate{ 90000 }; + + RtpMyRetransmissionBuffer myRetransmissionBuffer(maxItems, maxRetransmissionDelayMs, clockRate); + + myRetransmissionBuffer.Insert(33331, 1000000001); + myRetransmissionBuffer.Insert(33332, 1000000002); + myRetransmissionBuffer.Insert(33330, 1000000003); + + myRetransmissionBuffer.Dump(); + + // clang-format off + myRetransmissionBuffer.AssertBuffer( + { + { true, 33330, 1000000003 } + } + ); + // clang-format on + } + SECTION("fuzzer generated packets") { uint16_t maxItems{ 2500u }; From b6d23b72df91c78182f82edef950a80b08611da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 31 Mar 2023 13:27:13 +0200 Subject: [PATCH 067/525] mediasoup-node: Make appData TS typed and writable (#1046) --- CHANGELOG.md | 1 + node/.eslintrc.js | 4 +- node/src/ActiveSpeakerObserver.ts | 13 ++-- node/src/AudioLevelObserver.ts | 13 ++-- node/src/Consumer.ts | 22 +++--- node/src/DataConsumer.ts | 22 +++--- node/src/DataProducer.ts | 22 +++--- node/src/DirectTransport.ts | 20 +++--- node/src/PipeTransport.ts | 33 +++++---- node/src/PlainTransport.ts | 20 +++--- node/src/Producer.ts | 22 +++--- node/src/Router.ts | 70 ++++++++++--------- node/src/RtpObserver.ts | 25 ++++--- node/src/Transport.ts | 57 ++++++++------- node/src/WebRtcServer.ts | 44 ++++++------ node/src/WebRtcTransport.ts | 25 ++++--- node/src/Worker.ts | 38 +++++----- node/src/index.ts | 9 +-- node/src/ortc.ts | 5 +- node/src/tests/test-Router.ts | 8 ++- node/src/tests/test-WebRtcServer.ts | 2 +- node/src/tests/test-Worker.ts | 6 +- node/src/types.ts | 5 ++ .../src/RTC/TestRtpRetransmissionBuffer.cpp | 2 - 24 files changed, 270 insertions(+), 218 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4cc3c1266..0bb31b2e6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * `RtpStreamSend`: Reset RTP retransmission buffer upon RTP sequence number reset ([PR #1041](https://github.com/versatica/mediasoup/pull/1041)). * `RtpRetransmissionBuffer`: Handle corner case in which received packet has lower seq than newest packet in the buffer but higher timestamp ([PR #1044](https://github.com/versatica/mediasoup/pull/1044)). +* Node: Make `appData` TS typed and writable ([PR #1046](https://github.com/versatica/mediasoup/pull/1046), credits to @mango-martin). ### 3.11.19 diff --git a/node/.eslintrc.js b/node/.eslintrc.js index f681e15d1c..ca8e7cefc4 100644 --- a/node/.eslintrc.js +++ b/node/.eslintrc.js @@ -75,10 +75,10 @@ const eslintConfig = beforeLineComment : false } ], - 'max-len' : [ 2, 90, + 'max-len' : [ 2, 100, { tabWidth : 2, - comments : 90, + comments : 84, ignoreUrls : true, ignoreStrings : true, ignoreTemplateLiterals : true, diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index f5ebd29337..a9af22c569 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -7,15 +7,16 @@ import { RtpObserverConstructorOptions } from './RtpObserver'; import { Producer } from './Producer'; +import { AppData } from './types'; -export type ActiveSpeakerObserverOptions = +export type ActiveSpeakerObserverOptions = { interval?: number; /** * Custom application data. */ - appData?: Record; + appData?: ActiveSpeakerObserverAppData; }; export type ActiveSpeakerObserverDominantSpeaker = @@ -36,16 +37,18 @@ export type ActiveSpeakerObserverObserverEvents = RtpObserverObserverEvents & dominantspeaker: [ActiveSpeakerObserverDominantSpeaker]; }; -type RtpObserverObserverConstructorOptions = RtpObserverConstructorOptions; +type RtpObserverObserverConstructorOptions = + RtpObserverConstructorOptions; const logger = new Logger('ActiveSpeakerObserver'); -export class ActiveSpeakerObserver extends RtpObserver +export class ActiveSpeakerObserver + extends RtpObserver { /** * @private */ - constructor(options: RtpObserverObserverConstructorOptions) + constructor(options: RtpObserverObserverConstructorOptions) { super(options); diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index 0b0f8cf6c3..597e3ed882 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -7,8 +7,9 @@ import { RtpObserverConstructorOptions } from './RtpObserver'; import { Producer } from './Producer'; +import { AppData } from './types'; -export type AudioLevelObserverOptions = +export type AudioLevelObserverOptions = { /** * Maximum number of entries in the 'volumes”' event. Default 1. @@ -29,7 +30,7 @@ export type AudioLevelObserverOptions = /** * Custom application data. */ - appData?: Record; + appData?: AudioLevelObserverAppData; }; export type AudioLevelObserverVolume = @@ -58,16 +59,18 @@ export type AudioLevelObserverObserverEvents = RtpObserverObserverEvents & silence: []; }; -type AudioLevelObserverConstructorOptions = RtpObserverConstructorOptions; +type AudioLevelObserverConstructorOptions = + RtpObserverConstructorOptions; const logger = new Logger('AudioLevelObserver'); -export class AudioLevelObserver extends RtpObserver +export class AudioLevelObserver + extends RtpObserver { /** * @private */ - constructor(options: AudioLevelObserverConstructorOptions) + constructor(options: AudioLevelObserverConstructorOptions) { super(options); diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 5bf3c6d5cb..bcf09e3c20 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -9,8 +9,9 @@ import { RtpCapabilities, RtpParameters } from './RtpParameters'; +import { AppData } from './types'; -export type ConsumerOptions = +export type ConsumerOptions = { /** * The id of the Producer to consume. @@ -75,7 +76,7 @@ export type ConsumerOptions = /** * Custom application data. */ - appData?: Record; + appData?: ConsumerAppData; }; /** @@ -211,7 +212,8 @@ type ConsumerData = const logger = new Logger('Consumer'); -export class Consumer extends EnhancedEventEmitter +export class Consumer + extends EnhancedEventEmitter { // Internal data. readonly #internal: ConsumerInternal; @@ -229,7 +231,7 @@ export class Consumer extends EnhancedEventEmitter #closed = false; // Custom app data. - readonly #appData: Record; + #appData: ConsumerAppData; // Paused flag. #paused = false; @@ -272,7 +274,7 @@ export class Consumer extends EnhancedEventEmitter data: ConsumerData; channel: Channel; payloadChannel: PayloadChannel; - appData?: Record; + appData?: ConsumerAppData; paused: boolean; producerPaused: boolean; score?: ConsumerScore; @@ -287,7 +289,7 @@ export class Consumer extends EnhancedEventEmitter this.#data = data; this.#channel = channel; this.#payloadChannel = payloadChannel; - this.#appData = appData || {}; + this.#appData = appData || {} as ConsumerAppData; this.#paused = paused; this.#producerPaused = producerPaused; this.#score = score; @@ -395,17 +397,17 @@ export class Consumer extends EnhancedEventEmitter /** * App custom data. */ - get appData(): Record + get appData(): ConsumerAppData { return this.#appData; } /** - * Invalid setter. + * App custom data setter. */ - set appData(appData: Record) // eslint-disable-line no-unused-vars + set appData(appData: ConsumerAppData) { - throw new Error('cannot override appData object'); + this.#appData = appData; } /** diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 79f1742a56..a85413c38f 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -4,8 +4,9 @@ import { Channel } from './Channel'; import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; import { SctpStreamParameters } from './SctpParameters'; +import { AppData } from './types'; -export type DataConsumerOptions = +export type DataConsumerOptions = { /** * The id of the DataProducer to consume. @@ -39,7 +40,7 @@ export type DataConsumerOptions = /** * Custom application data. */ - appData?: Record; + appData?: DataConsumerAppData; }; export type DataConsumerStat = @@ -91,7 +92,8 @@ type DataConsumerData = const logger = new Logger('DataConsumer'); -export class DataConsumer extends EnhancedEventEmitter +export class DataConsumer + extends EnhancedEventEmitter { // Internal data. readonly #internal: DataConsumerInternal; @@ -109,7 +111,7 @@ export class DataConsumer extends EnhancedEventEmitter #closed = false; // Custom app data. - readonly #appData: Record; + #appData: DataConsumerAppData; // Observer instance. readonly #observer = new EnhancedEventEmitter(); @@ -130,7 +132,7 @@ export class DataConsumer extends EnhancedEventEmitter data: DataConsumerData; channel: Channel; payloadChannel: PayloadChannel; - appData?: Record; + appData?: DataConsumerAppData; } ) { @@ -142,7 +144,7 @@ export class DataConsumer extends EnhancedEventEmitter this.#data = data; this.#channel = channel; this.#payloadChannel = payloadChannel; - this.#appData = appData || {}; + this.#appData = appData || {} as DataConsumerAppData; this.handleWorkerNotifications(); } @@ -206,17 +208,17 @@ export class DataConsumer extends EnhancedEventEmitter /** * App custom data. */ - get appData(): Record + get appData(): DataConsumerAppData { return this.#appData; } /** - * Invalid setter. + * App custom data setter. */ - set appData(appData: Record) // eslint-disable-line no-unused-vars + set appData(appData: DataConsumerAppData) { - throw new Error('cannot override appData object'); + this.#appData = appData; } /** diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 7d48eb8eb9..94320ab26d 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -4,8 +4,9 @@ import { Channel } from './Channel'; import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; import { SctpStreamParameters } from './SctpParameters'; +import { AppData } from './types'; -export type DataProducerOptions = +export type DataProducerOptions = { /** * DataProducer id (just for Router.pipeToRouter() method). @@ -31,7 +32,7 @@ export type DataProducerOptions = /** * Custom application data. */ - appData?: Record; + appData?: DataProducerAppData; }; export type DataProducerStat = @@ -76,7 +77,8 @@ type DataProducerData = const logger = new Logger('DataProducer'); -export class DataProducer extends EnhancedEventEmitter +export class DataProducer + extends EnhancedEventEmitter { // Internal data. readonly #internal: DataProducerInternal; @@ -94,7 +96,7 @@ export class DataProducer extends EnhancedEventEmitter #closed = false; // Custom app data. - readonly #appData: Record; + #appData: DataProducerAppData; // Observer instance. readonly #observer = new EnhancedEventEmitter(); @@ -115,7 +117,7 @@ export class DataProducer extends EnhancedEventEmitter data: DataProducerData; channel: Channel; payloadChannel: PayloadChannel; - appData?: Record; + appData?: DataProducerAppData; } ) { @@ -127,7 +129,7 @@ export class DataProducer extends EnhancedEventEmitter this.#data = data; this.#channel = channel; this.#payloadChannel = payloadChannel; - this.#appData = appData || {}; + this.#appData = appData || {} as DataProducerAppData; this.handleWorkerNotifications(); } @@ -183,17 +185,17 @@ export class DataProducer extends EnhancedEventEmitter /** * App custom data. */ - get appData(): Record + get appData(): DataProducerAppData { return this.#appData; } /** - * Invalid setter. + * App custom data setter. */ - set appData(appData: Record) // eslint-disable-line no-unused-vars + set appData(appData: DataProducerAppData) { - throw new Error('cannot override appData object'); + this.#appData = appData; } /** diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 4a6fc7bea7..f4bc0be37a 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -8,8 +8,9 @@ import { TransportConstructorOptions } from './Transport'; import { SctpParameters } from './SctpParameters'; +import { AppData } from './types'; -export type DirectTransportOptions = +export type DirectTransportOptions = { /** * Maximum allowed size for direct messages sent from DataProducers. @@ -20,7 +21,7 @@ export type DirectTransportOptions = /** * Custom application data. */ - appData?: Record; + appData?: DirectTransportAppData; }; export type DirectTransportStat = @@ -58,10 +59,11 @@ export type DirectTransportObserverEvents = TransportObserverEvents & rtcp: [Buffer]; }; -type DirectTransportConstructorOptions = TransportConstructorOptions & -{ - data: DirectTransportData; -}; +type DirectTransportConstructorOptions = + TransportConstructorOptions & + { + data: DirectTransportData; + }; export type DirectTransportData = { @@ -70,8 +72,8 @@ export type DirectTransportData = const logger = new Logger('DirectTransport'); -export class DirectTransport extends - Transport +export class DirectTransport + extends Transport { // DirectTransport data. readonly #data: DirectTransportData; @@ -79,7 +81,7 @@ export class DirectTransport extends /** * @private */ - constructor(options: DirectTransportConstructorOptions) + constructor(options: DirectTransportConstructorOptions) { super(options); diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index 3aced3c836..f312a79ec6 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -14,8 +14,9 @@ import { import { Consumer, ConsumerType } from './Consumer'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; import { SrtpParameters } from './SrtpParameters'; +import { AppData } from './types'; -export type PipeTransportOptions = +export type PipeTransportOptions = { /** * Listening IP address. @@ -67,7 +68,7 @@ export type PipeTransportOptions = /** * Custom application data. */ - appData?: Record; + appData?: PipeTransportAppData; }; export type PipeTransportStat = @@ -98,7 +99,7 @@ export type PipeTransportStat = tuple: TransportTuple; }; -export type PipeConsumerOptions = +export type PipeConsumerOptions = { /** * The id of the Producer to consume. @@ -108,7 +109,7 @@ export type PipeConsumerOptions = /** * Custom application data. */ - appData?: Record; + appData?: ConsumerAppData; }; export type PipeTransportEvents = TransportEvents & @@ -121,10 +122,11 @@ export type PipeTransportObserverEvents = TransportObserverEvents & sctpstatechange: [SctpState]; }; -type PipeTransportConstructorOptions = TransportConstructorOptions & -{ - data: PipeTransportData; -}; +type PipeTransportConstructorOptions = + TransportConstructorOptions & + { + data: PipeTransportData; + }; export type PipeTransportData = { @@ -137,8 +139,8 @@ export type PipeTransportData = const logger = new Logger('PipeTransport'); -export class PipeTransport - extends Transport +export class PipeTransport + extends Transport { // PipeTransport data. readonly #data: PipeTransportData; @@ -146,7 +148,7 @@ export class PipeTransport /** * @private */ - constructor(options: PipeTransportConstructorOptions) + constructor(options: PipeTransportConstructorOptions) { super(options); @@ -285,7 +287,12 @@ export class PipeTransport * * @override */ - async consume({ producerId, appData }: PipeConsumerOptions): Promise + async consume( + { + producerId, + appData + }: PipeConsumerOptions + ): Promise> { logger.debug('consume()'); @@ -334,7 +341,7 @@ export class PipeTransport type : 'pipe' as ConsumerType }; - const consumer = new Consumer( + const consumer = new Consumer( { internal : { diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index 256d504950..23c4e266c0 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -11,8 +11,9 @@ import { } from './Transport'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; import { SrtpParameters, SrtpCryptoSuite } from './SrtpParameters'; +import { AppData } from './types'; -export type PlainTransportOptions = +export type PlainTransportOptions = { /** * Listening IP address. @@ -75,7 +76,7 @@ export type PlainTransportOptions = /** * Custom application data. */ - appData?: Record; + appData?: PlainTransportAppData; }; export type PlainTransportStat = @@ -123,10 +124,11 @@ export type PlainTransportObserverEvents = TransportObserverEvents & sctpstatechange: [SctpState]; }; -type PlainTransportConstructorOptions = TransportConstructorOptions & -{ - data: PlainTransportData; -}; +type PlainTransportConstructorOptions = + TransportConstructorOptions & + { + data: PlainTransportData; + }; export type PlainTransportData = { @@ -141,8 +143,8 @@ export type PlainTransportData = const logger = new Logger('PlainTransport'); -export class PlainTransport extends - Transport +export class PlainTransport + extends Transport { // PlainTransport data. readonly #data: PlainTransportData; @@ -150,7 +152,7 @@ export class PlainTransport extends /** * @private */ - constructor(options: PlainTransportConstructorOptions) + constructor(options: PlainTransportConstructorOptions) { super(options); diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 0046b6f672..2d152ffb40 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -4,8 +4,9 @@ import { Channel } from './Channel'; import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; import { MediaKind, RtpParameters } from './RtpParameters'; +import { AppData } from './types'; -export type ProducerOptions = +export type ProducerOptions = { /** * Producer id (just for Router.pipeToRouter() method). @@ -36,7 +37,7 @@ export type ProducerOptions = /** * Custom application data. */ - appData?: Record; + appData?: ProducerAppData; }; /** @@ -176,7 +177,8 @@ type ProducerData = const logger = new Logger('Producer'); -export class Producer extends EnhancedEventEmitter +export class Producer + extends EnhancedEventEmitter { // Internal data. readonly #internal: ProducerInternal; @@ -194,7 +196,7 @@ export class Producer extends EnhancedEventEmitter #closed = false; // Custom app data. - readonly #appData: Record; + #appData: ProducerAppData; // Paused flag. #paused = false; @@ -222,7 +224,7 @@ export class Producer extends EnhancedEventEmitter data: ProducerData; channel: Channel; payloadChannel: PayloadChannel; - appData?: Record; + appData?: ProducerAppData; paused: boolean; } ) @@ -235,7 +237,7 @@ export class Producer extends EnhancedEventEmitter this.#data = data; this.#channel = channel; this.#payloadChannel = payloadChannel; - this.#appData = appData || {}; + this.#appData = appData || {} as ProducerAppData; this.#paused = paused; this.handleWorkerNotifications(); @@ -310,17 +312,17 @@ export class Producer extends EnhancedEventEmitter /** * App custom data. */ - get appData(): Record + get appData(): ProducerAppData { return this.#appData; } /** - * Invalid setter. + * App custom data setter. */ - set appData(appData: Record) // eslint-disable-line no-unused-vars + set appData(appData: ProducerAppData) { - throw new Error('cannot override appData object'); + this.#appData = appData; } /** diff --git a/node/src/Router.ts b/node/src/Router.ts index 51a2e876da..21466d4c23 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -19,8 +19,9 @@ import { ActiveSpeakerObserver, ActiveSpeakerObserverOptions } from './ActiveSpe import { AudioLevelObserver, AudioLevelObserverOptions } from './AudioLevelObserver'; import { RtpCapabilities, RtpCodecCapability } from './RtpParameters'; import { NumSctpStreams } from './SctpParameters'; +import { AppData } from './types'; -export type RouterOptions = +export type RouterOptions = { /** * Router media codecs. @@ -30,7 +31,7 @@ export type RouterOptions = /** * Custom application data. */ - appData?: Record; + appData?: RouterAppData; }; export type PipeToRouterOptions = @@ -130,7 +131,8 @@ type RouterData = const logger = new Logger('Router'); -export class Router extends EnhancedEventEmitter +export class Router + extends EnhancedEventEmitter { // Internal data. readonly #internal: RouterInternal; @@ -148,7 +150,7 @@ export class Router extends EnhancedEventEmitter #closed = false; // Custom app data. - readonly #appData: Record; + #appData: RouterAppData; // Transports map. readonly #transports: Map = new Map(); @@ -186,7 +188,7 @@ export class Router extends EnhancedEventEmitter data: RouterData; channel: Channel; payloadChannel: PayloadChannel; - appData?: Record; + appData?: RouterAppData; } ) { @@ -198,7 +200,7 @@ export class Router extends EnhancedEventEmitter this.#data = data; this.#channel = channel; this.#payloadChannel = payloadChannel; - this.#appData = appData || {}; + this.#appData = appData || {} as RouterAppData; } /** @@ -228,17 +230,17 @@ export class Router extends EnhancedEventEmitter /** * App custom data. */ - get appData(): Record + get appData(): RouterAppData { return this.#appData; } /** - * Invalid setter. + * App custom data setter. */ - set appData(appData: Record) // eslint-disable-line no-unused-vars + set appData(appData: RouterAppData) { - throw new Error('cannot override appData object'); + this.#appData = appData; } /** @@ -358,7 +360,7 @@ export class Router extends EnhancedEventEmitter /** * Create a WebRtcTransport. */ - async createWebRtcTransport( + async createWebRtcTransport( { webRtcServer, listenIps, @@ -373,8 +375,8 @@ export class Router extends EnhancedEventEmitter maxSctpMessageSize = 262144, sctpSendBufferSize = 262144, appData - }: WebRtcTransportOptions - ): Promise + }: WebRtcTransportOptions + ): Promise> { logger.debug('createWebRtcTransport()'); @@ -431,7 +433,7 @@ export class Router extends EnhancedEventEmitter ? await this.#channel.request('router.createWebRtcTransportWithServer', this.#internal.routerId, reqData) : await this.#channel.request('router.createWebRtcTransport', this.#internal.routerId, reqData); - const transport = new WebRtcTransport( + const transport = new WebRtcTransport( { internal : { @@ -477,7 +479,7 @@ export class Router extends EnhancedEventEmitter /** * Create a PlainTransport. */ - async createPlainTransport( + async createPlainTransport( { listenIp, port, @@ -490,8 +492,8 @@ export class Router extends EnhancedEventEmitter enableSrtp = false, srtpCryptoSuite = 'AES_CM_128_HMAC_SHA1_80', appData - }: PlainTransportOptions - ): Promise + }: PlainTransportOptions + ): Promise> { logger.debug('createPlainTransport()'); @@ -540,7 +542,7 @@ export class Router extends EnhancedEventEmitter const data = await this.#channel.request('router.createPlainTransport', this.#internal.routerId, reqData); - const transport = new PlainTransport( + const transport = new PlainTransport( { internal : { @@ -581,7 +583,7 @@ export class Router extends EnhancedEventEmitter /** * Create a PipeTransport. */ - async createPipeTransport( + async createPipeTransport( { listenIp, port, @@ -592,8 +594,8 @@ export class Router extends EnhancedEventEmitter enableRtx = false, enableSrtp = false, appData - }: PipeTransportOptions - ): Promise + }: PipeTransportOptions + ): Promise> { logger.debug('createPipeTransport()'); @@ -640,7 +642,7 @@ export class Router extends EnhancedEventEmitter const data = await this.#channel.request('router.createPipeTransport', this.#internal.routerId, reqData); - const transport = new PipeTransport( + const transport = new PipeTransport( { internal : { @@ -681,15 +683,15 @@ export class Router extends EnhancedEventEmitter /** * Create a DirectTransport. */ - async createDirectTransport( + async createDirectTransport( { maxMessageSize = 262144, appData - }: DirectTransportOptions = + }: DirectTransportOptions = { maxMessageSize : 262144 } - ): Promise + ): Promise> { logger.debug('createDirectTransport()'); @@ -703,7 +705,7 @@ export class Router extends EnhancedEventEmitter const data = await this.#channel.request('router.createDirectTransport', this.#internal.routerId, reqData); - const transport = new DirectTransport( + const transport = new DirectTransport( { internal : { @@ -1065,12 +1067,12 @@ export class Router extends EnhancedEventEmitter /** * Create an ActiveSpeakerObserver */ - async createActiveSpeakerObserver( + async createActiveSpeakerObserver( { interval = 300, appData - }: ActiveSpeakerObserverOptions = {} - ): Promise + }: ActiveSpeakerObserverOptions = {} + ): Promise> { logger.debug('createActiveSpeakerObserver()'); @@ -1087,7 +1089,7 @@ export class Router extends EnhancedEventEmitter await this.#channel.request('router.createActiveSpeakerObserver', this.#internal.routerId, reqData); - const activeSpeakerObserver = new ActiveSpeakerObserver( + const activeSpeakerObserver = new ActiveSpeakerObserver( { internal : { @@ -1117,14 +1119,14 @@ export class Router extends EnhancedEventEmitter /** * Create an AudioLevelObserver. */ - async createAudioLevelObserver( + async createAudioLevelObserver( { maxEntries = 1, threshold = -80, interval = 1000, appData - }: AudioLevelObserverOptions = {} - ): Promise + }: AudioLevelObserverOptions = {} + ): Promise> { logger.debug('createAudioLevelObserver()'); @@ -1143,7 +1145,7 @@ export class Router extends EnhancedEventEmitter await this.#channel.request('router.createAudioLevelObserver', this.#internal.routerId, reqData); - const audioLevelObserver = new AudioLevelObserver( + const audioLevelObserver = new AudioLevelObserver( { internal : { diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 324fc3313f..3821d728d4 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -4,6 +4,7 @@ import { Channel } from './Channel'; import { PayloadChannel } from './PayloadChannel'; import { RouterInternal } from './Router'; import { Producer } from './Producer'; +import { AppData } from './types'; export type RtpObserverEvents = { @@ -21,12 +22,12 @@ export type RtpObserverObserverEvents = removeproducer: [Producer]; }; -export type RtpObserverConstructorOptions = +export type RtpObserverConstructorOptions = { internal: RtpObserverObserverInternal; channel: Channel; payloadChannel: PayloadChannel; - appData?: Record; + appData?: RtpObserverAppData; getProducerById: (producerId: string) => Producer | undefined; }; @@ -45,8 +46,10 @@ export type RtpObserverAddRemoveProducerOptions = producerId: string; }; -export class RtpObserver - extends EnhancedEventEmitter +export class RtpObserver + + extends EnhancedEventEmitter { // Internal data. protected readonly internal: RtpObserverObserverInternal; @@ -64,7 +67,7 @@ export class RtpObserver #paused = false; // Custom app data. - readonly #appData: Record; + #appData: RtpObserverAppData; // Method to retrieve a Producer. protected readonly getProducerById: (producerId: string) => Producer | undefined; @@ -83,7 +86,7 @@ export class RtpObserver payloadChannel, appData, getProducerById - }: RtpObserverConstructorOptions + }: RtpObserverConstructorOptions ) { super(); @@ -93,7 +96,7 @@ export class RtpObserver this.internal = internal; this.channel = channel; this.payloadChannel = payloadChannel; - this.#appData = appData || {}; + this.#appData = appData || {} as RtpObserverAppData; this.getProducerById = getProducerById; } @@ -124,17 +127,17 @@ export class RtpObserver /** * App custom data. */ - get appData(): Record + get appData(): RtpObserverAppData { return this.#appData; } /** - * Invalid setter. + * App custom data setter. */ - set appData(appData: Record) // eslint-disable-line no-unused-vars + set appData(appData: RtpObserverAppData) { - throw new Error('cannot override appData object'); + this.#appData = appData; } /** diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 5463b547a6..5d31e794ac 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -24,6 +24,7 @@ import { } from './DataConsumer'; import { RtpCapabilities } from './RtpParameters'; import { SctpStreamParameters } from './SctpParameters'; +import { AppData } from './types'; export type TransportListenIp = { @@ -110,13 +111,13 @@ export type TransportObserverEvents = trace: [TransportTraceEventData]; }; -export type TransportConstructorOptions = +export type TransportConstructorOptions = { internal: TransportInternal; data: TransportData; channel: Channel; payloadChannel: PayloadChannel; - appData?: Record; + appData?: TransportAppData; getRouterRtpCapabilities: () => RtpCapabilities; getProducerById: (producerId: string) => Producer | undefined; getDataProducerById: (dataProducerId: string) => DataProducer | undefined; @@ -135,8 +136,10 @@ type TransportData = const logger = new Logger('Transport'); -export class Transport +export class Transport + extends EnhancedEventEmitter { // Internal data. @@ -155,7 +158,7 @@ export class Transport; + #appData: TransportAppData; // Method to retrieve Router RTP capabilities. readonly #getRouterRtpCapabilities: () => RtpCapabilities; @@ -208,7 +211,7 @@ export class Transport ) { super(); @@ -219,7 +222,7 @@ export class Transport + get appData(): TransportAppData { return this.#appData; } /** - * Invalid setter. + * App custom data setter. */ - set appData(appData: Record) // eslint-disable-line no-unused-vars + set appData(appData: TransportAppData) { - throw new Error('cannot override appData object'); + this.#appData = appData; } /** @@ -539,7 +542,7 @@ export class Transport( { id = undefined, kind, @@ -547,8 +550,8 @@ export class Transport + }: ProducerOptions + ): Promise> { logger.debug('produce()'); @@ -631,7 +634,7 @@ export class Transport( { internal : { @@ -665,7 +668,7 @@ export class Transport( { producerId, rtpCapabilities, @@ -676,8 +679,8 @@ export class Transport + }: ConsumerOptions + ): Promise> { logger.debug('consume()'); @@ -766,7 +769,7 @@ export class Transport( { internal : { @@ -796,15 +799,15 @@ export class Transport( { id = undefined, sctpStreamParameters, label = '', protocol = '', appData - }: DataProducerOptions = {} - ): Promise + }: DataProducerOptions = {} + ): Promise> { logger.debug('produceData()'); @@ -851,7 +854,7 @@ export class Transport( { internal : { @@ -882,15 +885,15 @@ export class Transport( { dataProducerId, ordered, maxPacketLifeTime, maxRetransmits, appData - }: DataConsumerOptions - ): Promise + }: DataConsumerOptions + ): Promise> { logger.debug('consumeData()'); @@ -975,7 +978,7 @@ export class Transport( { internal : { diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 3c0c4eb6b3..0db3346ded 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -3,6 +3,20 @@ import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; import { TransportProtocol } from './Transport'; import { WebRtcTransport } from './WebRtcTransport'; +import { AppData } from './types'; + +export type WebRtcServerOptions = +{ + /** + * Listen infos. + */ + listenInfos: WebRtcServerListenInfo[]; + + /** + * Custom application data. + */ + appData?: WebRtcServerAppData; +}; export type WebRtcServerListenInfo = { @@ -28,19 +42,6 @@ export type WebRtcServerListenInfo = port?: number; }; -export type WebRtcServerOptions = -{ - /** - * Listen infos. - */ - listenInfos: WebRtcServerListenInfo[]; - - /** - * Custom application data. - */ - appData?: Record; -}; - export type WebRtcServerEvents = { workerclose: []; @@ -62,7 +63,8 @@ type WebRtcServerInternal = const logger = new Logger('WebRtcServer'); -export class WebRtcServer extends EnhancedEventEmitter +export class WebRtcServer + extends EnhancedEventEmitter { // Internal data. readonly #internal: WebRtcServerInternal; @@ -74,7 +76,7 @@ export class WebRtcServer extends EnhancedEventEmitter #closed = false; // Custom app data. - readonly #appData: Record; + #appData: WebRtcServerAppData; // Transports map. readonly #webRtcTransports: Map = new Map(); @@ -94,7 +96,7 @@ export class WebRtcServer extends EnhancedEventEmitter { internal: WebRtcServerInternal; channel: Channel; - appData?: Record; + appData?: WebRtcServerAppData; } ) { @@ -104,7 +106,7 @@ export class WebRtcServer extends EnhancedEventEmitter this.#internal = internal; this.#channel = channel; - this.#appData = appData || {}; + this.#appData = appData || {} as WebRtcServerAppData; } /** @@ -126,17 +128,17 @@ export class WebRtcServer extends EnhancedEventEmitter /** * App custom data. */ - get appData(): Record + get appData(): WebRtcServerAppData { return this.#appData; } /** - * Invalid setter. + * App custom data setter. */ - set appData(appData: Record) // eslint-disable-line no-unused-vars + set appData(appData: WebRtcServerAppData) { - throw new Error('cannot override appData object'); + this.#appData = appData; } /** diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 8e364fed2e..e297a5d4a1 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -13,6 +13,10 @@ import { import { WebRtcServer } from './WebRtcServer'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; import { Either } from './utils'; +import { AppData } from './types'; + +export type WebRtcTransportOptions = + WebRtcTransportOptionsBase & WebRtcTransportListen; export type WebRtcTransportListenIndividual = { @@ -40,7 +44,7 @@ export type WebRtcTransportListenServer = export type WebRtcTransportListen = Either; -export type WebRtcTransportOptionsBase = +export type WebRtcTransportOptionsBase = { /** * Listen in UDP. Default true. @@ -92,11 +96,9 @@ export type WebRtcTransportOptionsBase = /** * Custom application data. */ - appData?: Record; + appData?: WebRtcTransportAppData; }; -export type WebRtcTransportOptions = WebRtcTransportOptionsBase & WebRtcTransportListen; - export type IceParameters = { usernameFragment: string; @@ -186,10 +188,11 @@ export type WebRtcTransportObserverEvents = TransportObserverEvents & sctpstatechange: [SctpState]; }; -type WebRtcTransportConstructorOptions = TransportConstructorOptions & -{ - data: WebRtcTransportData; -}; +type WebRtcTransportConstructorOptions = + TransportConstructorOptions & + { + data: WebRtcTransportData; + }; export type WebRtcTransportData = { @@ -207,8 +210,8 @@ export type WebRtcTransportData = const logger = new Logger('WebRtcTransport'); -export class WebRtcTransport extends - Transport +export class WebRtcTransport + extends Transport { // WebRtcTransport data. readonly #data: WebRtcTransportData; @@ -216,7 +219,7 @@ export class WebRtcTransport extends /** * @private */ - constructor(options: WebRtcTransportConstructorOptions) + constructor(options: WebRtcTransportConstructorOptions) { super(options); diff --git a/node/src/Worker.ts b/node/src/Worker.ts index eefa9c8018..582a0f12b9 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -9,6 +9,7 @@ import { Channel } from './Channel'; import { PayloadChannel } from './PayloadChannel'; import { Router, RouterOptions } from './Router'; import { WebRtcServer, WebRtcServerOptions } from './WebRtcServer'; +import { AppData } from './types'; export type WorkerLogLevel = 'debug' | 'warn' | 'error' | 'none'; @@ -27,7 +28,7 @@ export type WorkerLogTag = | 'sctp' | 'message'; -export type WorkerSettings = +export type WorkerSettings = { /** * Logging level for logs generated by the media worker subprocesses (check @@ -77,10 +78,11 @@ export type WorkerSettings = /** * Custom application data. */ - appData?: Record; + appData?: WorkerAppData; }; -export type WorkerUpdateableSettings = Pick; +export type WorkerUpdateableSettings = + Pick, 'logLevel' | 'logTags'>; /** * An object with the fields of the uv_rusage_t struct. @@ -202,7 +204,8 @@ const workerBin = process.env.MEDIASOUP_WORKER_BIN const logger = new Logger('Worker'); const workerLogger = new Logger('Worker'); -export class Worker extends EnhancedEventEmitter +export class Worker + extends EnhancedEventEmitter { // mediasoup-worker child process. #child?: ChildProcess; @@ -223,7 +226,7 @@ export class Worker extends EnhancedEventEmitter #died = false; // Custom app data. - readonly #appData: Record; + #appData: WorkerAppData; // WebRtcServers set. readonly #webRtcServers: Set = new Set(); @@ -247,7 +250,7 @@ export class Worker extends EnhancedEventEmitter dtlsPrivateKeyFile, libwebrtcFieldTrials, appData - }: WorkerSettings) + }: WorkerSettings) { super(); @@ -356,7 +359,7 @@ export class Worker extends EnhancedEventEmitter consumerSocket : this.#child.stdio[6] }); - this.#appData = appData || {}; + this.#appData = appData || {} as WorkerAppData; let spawnDone = false; @@ -487,17 +490,17 @@ export class Worker extends EnhancedEventEmitter /** * App custom data. */ - get appData(): Record + get appData(): WorkerAppData { return this.#appData; } /** - * Invalid setter. + * App custom data setter. */ - set appData(appData: Record) // eslint-disable-line no-unused-vars + set appData(appData: WorkerAppData) { - throw new Error('cannot override appData object'); + this.#appData = appData; } /** @@ -603,7 +606,7 @@ export class Worker extends EnhancedEventEmitter { logLevel, logTags - }: WorkerUpdateableSettings = {} + }: WorkerUpdateableSettings = {} ): Promise { logger.debug('updateSettings()'); @@ -616,11 +619,12 @@ export class Worker extends EnhancedEventEmitter /** * Create a WebRtcServer. */ - async createWebRtcServer( + async createWebRtcServer( { listenInfos, appData - }: WebRtcServerOptions): Promise + }: WebRtcServerOptions + ): Promise> { logger.debug('createWebRtcServer()'); @@ -656,11 +660,11 @@ export class Worker extends EnhancedEventEmitter /** * Create a Router. */ - async createRouter( + async createRouter( { mediaCodecs, appData - }: RouterOptions = {}): Promise + }: RouterOptions = {}): Promise> { logger.debug('createRouter()'); @@ -677,7 +681,7 @@ export class Worker extends EnhancedEventEmitter await this.#channel.request('worker.createRouter', undefined, reqData); const data = { rtpCapabilities }; - const router = new Router( + const router = new Router( { internal : { diff --git a/node/src/index.ts b/node/src/index.ts index 83d7967760..c98d349e7b 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -5,6 +5,7 @@ import * as utils from './utils'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; import { RtpCapabilities } from './RtpParameters'; import * as types from './types'; +import { AppData } from './types'; /** * Expose all types. @@ -38,7 +39,7 @@ export { observer }; /** * Create a Worker. */ -export async function createWorker( +export async function createWorker( { logLevel = 'error', logTags, @@ -48,8 +49,8 @@ export async function createWorker( dtlsPrivateKeyFile, libwebrtcFieldTrials, appData - }: WorkerSettings = {} -): Promise + }: WorkerSettings = {} +): Promise> { logger.debug('createWorker()'); @@ -58,7 +59,7 @@ export async function createWorker( throw new TypeError('if given, appData must be an object'); } - const worker = new Worker( + const worker = new Worker( { logLevel, logTags, diff --git a/node/src/ortc.ts b/node/src/ortc.ts index 9b0995b1e3..6f229e6743 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -435,9 +435,8 @@ export function validateRtpCodecParameters(codec: RtpCodecParameters): void } /** - * Validates RtpHeaderExtensionParameteters. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. + * Validates RtpHeaderExtensionParameteters. It may modify given data by adding + * missing fields with default values. It throws if invalid. */ export function validateRtpHeaderExtensionParameters( ext: RtpHeaderExtensionParameters diff --git a/node/src/tests/test-Router.ts b/node/src/tests/test-Router.ts index c9316ee1f4..9d9941f2b4 100644 --- a/node/src/tests/test-Router.ts +++ b/node/src/tests/test-Router.ts @@ -48,7 +48,11 @@ test('worker.createRouter() succeeds', async () => worker.observer.once('newrouter', onObserverNewRouter); - const router = await worker.createRouter({ mediaCodecs, appData: { foo: 123 } }); + const router = await worker.createRouter<{ foo: number; bar?: string }>( + { + mediaCodecs, + appData : { foo: 123 } + }); expect(onObserverNewRouter).toHaveBeenCalledTimes(1); expect(onObserverNewRouter).toHaveBeenCalledWith(router); @@ -59,6 +63,8 @@ test('worker.createRouter() succeeds', async () => expect(Array.isArray(router.rtpCapabilities.headerExtensions)).toBe(true); expect(router.appData).toEqual({ foo: 123 }); + expect(() => (router.appData = { foo: 222, bar: 'BBB' })).not.toThrow(); + await expect(worker.dump()) .resolves .toEqual( diff --git a/node/src/tests/test-WebRtcServer.ts b/node/src/tests/test-WebRtcServer.ts index febdea95bf..ff28ebe26b 100644 --- a/node/src/tests/test-WebRtcServer.ts +++ b/node/src/tests/test-WebRtcServer.ts @@ -21,7 +21,7 @@ test('worker.createWebRtcServer() succeeds', async () => const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await worker.createWebRtcServer( + const webRtcServer = await worker.createWebRtcServer<{ foo?: number }>( { listenInfos : [ diff --git a/node/src/tests/test-Worker.ts b/node/src/tests/test-Worker.ts index feb0232fcc..15ab5ace52 100644 --- a/node/src/tests/test-Worker.ts +++ b/node/src/tests/test-Worker.ts @@ -32,7 +32,7 @@ test('createWorker() succeeds', async () => expect(worker.died).toBe(false); // eslint-disable-next-line require-atomic-updates - worker = await createWorker( + worker = await createWorker<{ foo: number; bar?: string }>( { logLevel : 'debug', logTags : [ 'info' ], @@ -41,13 +41,13 @@ test('createWorker() succeeds', async () => dtlsCertificateFile : path.join(__dirname, 'data', 'dtls-cert.pem'), dtlsPrivateKeyFile : path.join(__dirname, 'data', 'dtls-key.pem'), libwebrtcFieldTrials : 'WebRTC-Bwe-AlrLimitedBackoff/Disabled/', - appData : { bar: 456 } + appData : { foo: 456 } }); expect(worker.constructor.name).toBe('Worker'); expect(typeof worker.pid).toBe('number'); expect(worker.closed).toBe(false); expect(worker.died).toBe(false); - expect(worker.appData).toEqual({ bar: 456 }); + expect(worker.appData).toEqual({ foo: 456 }); worker.close(); diff --git a/node/src/types.ts b/node/src/types.ts index b3fe195f77..fe72cb95fb 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -18,3 +18,8 @@ export * from './SctpParameters'; export * from './SrtpParameters'; export * from './errors'; export { ScalabilityMode } from './scalabilityModes'; + +export type AppData = +{ + [key: string]: unknown; +}; diff --git a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp index 74d2628b44..411db9fcac 100644 --- a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp +++ b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp @@ -266,8 +266,6 @@ SCENARIO("RtpRetransmissionBuffer", "[rtp][rtx]") myRetransmissionBuffer.Insert(33332, 1000000002); myRetransmissionBuffer.Insert(33330, 1000000003); - myRetransmissionBuffer.Dump(); - // clang-format off myRetransmissionBuffer.AssertBuffer( { From 56b953dca35f45747ddbb89a50c74c870e2aebd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Fri, 31 Mar 2023 15:09:24 +0200 Subject: [PATCH 068/525] SeqManager: fix crash and add fuzzer (#1045) * SeqManager: fix crash and add fuzzer Fixes #1042 --- CHANGELOG.md | 1 + .../fuzzer/include/RTC/FuzzerSeqManager.hpp | 17 ++++ ...h-b75c1208384621922270e954b4902442592c3ca9 | 1 + worker/fuzzer/src/RTC/FuzzerSeqManager.cpp | 22 ++++++ worker/fuzzer/src/fuzzer.cpp | 2 + worker/include/RTC/SeqManager.hpp | 2 + worker/meson.build | 1 + worker/src/RTC/SeqManager.cpp | 44 ++++++++--- worker/test/src/RTC/TestSeqManager.cpp | 79 +++++++++++++++++++ 9 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 worker/fuzzer/include/RTC/FuzzerSeqManager.hpp create mode 100644 worker/fuzzer/reports/crash-b75c1208384621922270e954b4902442592c3ca9 create mode 100644 worker/fuzzer/src/RTC/FuzzerSeqManager.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bb31b2e6e..212c997260 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * `RtpStreamSend`: Reset RTP retransmission buffer upon RTP sequence number reset ([PR #1041](https://github.com/versatica/mediasoup/pull/1041)). * `RtpRetransmissionBuffer`: Handle corner case in which received packet has lower seq than newest packet in the buffer but higher timestamp ([PR #1044](https://github.com/versatica/mediasoup/pull/1044)). +* `SeqManager`: Fix crash and add fuzzer ([PR #1045](https://github.com/versatica/mediasoup/pull/1045)). * Node: Make `appData` TS typed and writable ([PR #1046](https://github.com/versatica/mediasoup/pull/1046), credits to @mango-martin). diff --git a/worker/fuzzer/include/RTC/FuzzerSeqManager.hpp b/worker/fuzzer/include/RTC/FuzzerSeqManager.hpp new file mode 100644 index 0000000000..e3644e1f1f --- /dev/null +++ b/worker/fuzzer/include/RTC/FuzzerSeqManager.hpp @@ -0,0 +1,17 @@ +#ifndef MS_FUZZER_RTC_SEQ_MANAGER_HPP +#define MS_FUZZER_RTC_SEQ_MANAGER_HPP + +#include "common.hpp" + +namespace Fuzzer +{ + namespace RTC + { + namespace SeqManager + { + void Fuzz(const uint8_t* data, size_t len); + } + } // namespace RTC +} // namespace Fuzzer + +#endif diff --git a/worker/fuzzer/reports/crash-b75c1208384621922270e954b4902442592c3ca9 b/worker/fuzzer/reports/crash-b75c1208384621922270e954b4902442592c3ca9 new file mode 100644 index 0000000000..4a61033691 --- /dev/null +++ b/worker/fuzzer/reports/crash-b75c1208384621922270e954b4902442592c3ca9 @@ -0,0 +1 @@ +dtat \ No newline at end of file diff --git a/worker/fuzzer/src/RTC/FuzzerSeqManager.cpp b/worker/fuzzer/src/RTC/FuzzerSeqManager.cpp new file mode 100644 index 0000000000..4ea5385038 --- /dev/null +++ b/worker/fuzzer/src/RTC/FuzzerSeqManager.cpp @@ -0,0 +1,22 @@ +#include "RTC/FuzzerSeqManager.hpp" +#include "Utils.hpp" +#include "RTC/SeqManager.hpp" +#include + +void Fuzzer::RTC::SeqManager::Fuzz(const uint8_t* data, size_t len) +{ + if (len < 10) + { + return; + } + + ::RTC::SeqManager seqManager; + + uint16_t output; + + for (size_t count = 0; count < 7; count++) + { + seqManager.Input(Utils::Byte::Get2Bytes(data, count), output); + seqManager.Drop(Utils::Byte::Get2Bytes(data, count + 2)); + } +} diff --git a/worker/fuzzer/src/fuzzer.cpp b/worker/fuzzer/src/fuzzer.cpp index f6f6bf4d1e..26e3ee6957 100644 --- a/worker/fuzzer/src/fuzzer.cpp +++ b/worker/fuzzer/src/fuzzer.cpp @@ -12,6 +12,7 @@ #include "RTC/FuzzerRtpPacket.hpp" #include "RTC/FuzzerRtpRetransmissionBuffer.hpp" #include "RTC/FuzzerRtpStreamSend.hpp" +#include "RTC/FuzzerSeqManager.hpp" #include "RTC/FuzzerStunPacket.hpp" #include "RTC/FuzzerTrendCalculator.hpp" #include "RTC/RTCP/FuzzerPacket.hpp" @@ -45,6 +46,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) Fuzzer::RTC::RtpPacket::Fuzz(data, len); Fuzzer::RTC::RtpStreamSend::Fuzz(data, len); Fuzzer::RTC::RtpRetransmissionBuffer::Fuzz(data, len); + Fuzzer::RTC::SeqManager::Fuzz(data, len); } if (fuzzRtcp) diff --git a/worker/include/RTC/SeqManager.hpp b/worker/include/RTC/SeqManager.hpp index 5d4eb17654..442cc0f9c9 100644 --- a/worker/include/RTC/SeqManager.hpp +++ b/worker/include/RTC/SeqManager.hpp @@ -49,6 +49,8 @@ namespace RTC void ClearDropped(); private: + // Whether at least a sequence number has been inserted. + bool started{ false }; T base{ 0 }; T maxOutput{ 0 }; T maxInput{ 0 }; diff --git a/worker/meson.build b/worker/meson.build index ce6bf4eb20..9f2bba2a91 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -356,6 +356,7 @@ executable( 'fuzzer/src/RTC/FuzzerRtpPacket.cpp', 'fuzzer/src/RTC/FuzzerRtpRetransmissionBuffer.cpp', 'fuzzer/src/RTC/FuzzerRtpStreamSend.cpp', + 'fuzzer/src/RTC/FuzzerSeqManager.cpp', 'fuzzer/src/RTC/FuzzerTrendCalculator.cpp', 'fuzzer/src/RTC/RTCP/FuzzerBye.cpp', 'fuzzer/src/RTC/RTCP/FuzzerFeedbackPs.cpp', diff --git a/worker/src/RTC/SeqManager.cpp b/worker/src/RTC/SeqManager.cpp index 73d21a431c..24b33b20ea 100644 --- a/worker/src/RTC/SeqManager.cpp +++ b/worker/src/RTC/SeqManager.cpp @@ -113,15 +113,29 @@ namespace RTC output = (input + base) & MaxValue; - // New input is higher than the maximum seen. But less than acceptable units higher. - // Keep it as the maximum seen. See Drop(). - if (IsSeqHigherThan(input, this->maxInput)) - this->maxInput = input; - - // New output is higher than the maximum seen. But less than acceptable units higher. - // Keep it as the maximum seen. See Sync(). - if (IsSeqHigherThan(output, this->maxOutput)) + if (!this->started) + { + this->started = true; + + this->maxInput = input; this->maxOutput = output; + } + else + { + // New input is higher than the maximum seen. But less than acceptable units higher. + // Keep it as the maximum seen. See Drop(). + if (IsSeqHigherThan(input, this->maxInput)) + { + this->maxInput = input; + } + + // New output is higher than the maximum seen. But less than acceptable units higher. + // Keep it as the maximum seen. See Sync(). + if (IsSeqHigherThan(output, this->maxOutput)) + { + this->maxOutput = output; + } + } ClearDropped(); @@ -172,7 +186,19 @@ namespace RTC // There are many values in the range. else { - this->dropped.erase(it1, it2); + // Measure the distance of it1 and it2 to the beggining of dropped. + auto distanceIt1 = std::distance(this->dropped.begin(), it1); + auto distanceIt2 = std::distance(this->dropped.begin(), it2); + + // it2 goes out of range, only it1 is within the range. + if (distanceIt2 < distanceIt1) + { + this->dropped.erase(it1); + } + else + { + this->dropped.erase(it1, it2); + } } // Adapt base. diff --git a/worker/test/src/RTC/TestSeqManager.cpp b/worker/test/src/RTC/TestSeqManager.cpp index c59641c62c..fa56dd077c 100644 --- a/worker/test/src/RTC/TestSeqManager.cpp +++ b/worker/test/src/RTC/TestSeqManager.cpp @@ -649,4 +649,83 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") SeqManager seqManager; validate(seqManager, inputs); } + + SECTION("dropped inputs to be removed going out of range, 1.") + { + // clang-format off + std::vector> inputs = + { + { 36964, 36964, false, false, 0 }, + { 25923, 0, false, true, 0 }, // Drop. + { 25701, 25701, false, false, 0 }, + { 17170, 0, false, true, 0 }, // Drop. + { 25923, 25923, false, false, 0 }, + { 4728, 0, false, true, 0 }, // Drop. + { 17170, 17170, false, false, 0 }, + { 30738, 0, false, true, 0 }, // Drop. + { 4728, 4728, false, false, 0 }, + { 4806, 0, false, true, 0 }, // Drop. + { 30738, 30738, false, false, 0 }, + { 50886, 0, false, true, 0 }, // Drop. + { 4806, 4805, false, false, 0 }, // Previously dropped. + { 50774, 0, false, true, 0 }, // Drop. + { 50886, 50884, false, false, 0 }, // Previously dropped. + { 22136, 0, false, true, 0 }, // Drop. + { 50774, 50884, false, false, 0 }, // Previously dropped. + { 30910, 0, false, true, 0 }, // Drop. + { 22136, 22134, false, false, 0 }, + { 48862, 0, false, true, 0 }, // Drop. + { 30910, 30909, false, false, 0 }, + { 56832, 0, false, true, 0 }, // Drop. + { 48862, 48861, false, false, 0 }, + { 2, 0, false, true, 0 }, // Drop. + { 56832, 56828, false, false, 0 }, + { 530, 0, false, true, 0 }, // Drop. + { 2, 65534, false, false, 0 }, + }; + // clang-format on + + SeqManager seqManager; + validate(seqManager, inputs); + } + + SECTION("dropped inputs to be removed go out of range, 2.") + { + // clang-format off + std::vector> inputs = + { + { 36960, 36960, false, false, 0 }, + { 3328, 0, false, true, 0 }, // Drop. + { 24589, 24588, false, false, 0 }, + { 120, 0, false, true, 0 }, // Drop. + { 3328, 3326, false, false, 0 }, + { 30848, 0, false, true, 0 }, // Drop. + { 120, 3326, false, false, 0 }, // Previously dropped. + }; + // clang-format on + + SeqManager seqManager; + validate(seqManager, inputs); + } + + SECTION("dropped inputs to be removed go out of range, 3.") + { + // clang-format off + std::vector> inputs = + { + { 36964, 36964, false, false, 0 }, + { 65396 , 0, false, true, 0 }, // Drop. + { 25855, 25854, false, false, 0 }, + { 29793 , 0, false, true, 0 }, // Drop. + { 65396, 65395, false, false, 0 }, + { 25087, 0, false, true, 0 }, // Drop. + { 29793, 29791, false, false, 0 }, + { 65535 , 0, false, true, 0 }, // Drop. + { 25087, 29791, false, false, 0 }, // Previously dropped. + }; + // clang-format on + + SeqManager seqManager; + validate(seqManager, inputs); + } } From bd809cbcb9bce9eaacd3d453ba20f6465181f229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 31 Mar 2023 15:13:53 +0200 Subject: [PATCH 069/525] 3.11.20 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 212c997260..b30972c7c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.11.20 * `RtpStreamSend`: Reset RTP retransmission buffer upon RTP sequence number reset ([PR #1041](https://github.com/versatica/mediasoup/pull/1041)). * `RtpRetransmissionBuffer`: Handle corner case in which received packet has lower seq than newest packet in the buffer but higher timestamp ([PR #1044](https://github.com/versatica/mediasoup/pull/1044)). diff --git a/package-lock.json b/package-lock.json index 79bf288a9c..d7d8008cdc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.19", + "version": "3.11.20", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.19", + "version": "3.11.20", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index ff814f5cc5..fcfa3aebc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.19", + "version": "3.11.20", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From d51ad71962d7f4d86fe5784d6c4b3739c1f4b316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 31 Mar 2023 16:37:25 +0200 Subject: [PATCH 070/525] cosmetic --- doc/Building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Building.md b/doc/Building.md index 5b273f976f..93e103b3d9 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -160,7 +160,7 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy/) and performs C++ code * [PyYAML](https://pyyaml.org/) is required. - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. -`MEDIASOUP_TIDY_CHECKS` environment variable with a comma separated list of checks overrides the checks defined in .clang-tidy file. +`MEDIASOUP_TIDY_CHECKS` environment variable with a comma separated list of checks overrides the checks defined in `.clang-tidy` file. ### `make fuzzer` From 015d5e3a1d6ed3fdd20cfddae316cdbddae904f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 31 Mar 2023 16:43:11 +0200 Subject: [PATCH 071/525] Update worker/scripts/package-lock.json --- worker/scripts/package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worker/scripts/package-lock.json b/worker/scripts/package-lock.json index 24ee1c9032..6d187c60d3 100644 --- a/worker/scripts/package-lock.json +++ b/worker/scripts/package-lock.json @@ -639,7 +639,7 @@ "node_modules/clang-tools-prebuilt": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", - "integrity": "sha1-8gINNlN2CMDPrQeuvglNmXMFkLM=", + "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -5932,7 +5932,7 @@ "clang-tools-prebuilt": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", - "integrity": "sha1-8gINNlN2CMDPrQeuvglNmXMFkLM=", + "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", "dev": true, "requires": { "home-path": "^0.1.1", From 827bdbbb2b16f594131cf6d9a9e6d1167b59da88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 31 Mar 2023 16:50:05 +0200 Subject: [PATCH 072/525] Add worker/.clang-tidy-ignore (although it just works with recent clang-tidy) --- worker/.clang-tidy-ignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 worker/.clang-tidy-ignore diff --git a/worker/.clang-tidy-ignore b/worker/.clang-tidy-ignore new file mode 100644 index 0000000000..82186c89a4 --- /dev/null +++ b/worker/.clang-tidy-ignore @@ -0,0 +1,2 @@ +# Ignore subprojects folder. +/subprojects From bb0e27d8f139c8e7a0434644f154370d5268e4b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 31 Mar 2023 17:06:21 +0200 Subject: [PATCH 073/525] Add worker/subprojects/.clang-tidy workaround to "limit" checks in worker/subprojects folder --- .gitignore | 1 + worker/subprojects/.clang-tidy | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 worker/subprojects/.clang-tidy diff --git a/.gitignore b/.gitignore index be274839a7..7f8ebf4acb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ ## Meson. /worker/subprojects/* !/worker/subprojects/*.wrap +!/worker/subprojects/.clang-tidy ## Node. /node_modules diff --git a/worker/subprojects/.clang-tidy b/worker/subprojects/.clang-tidy new file mode 100644 index 0000000000..18b170ce1f --- /dev/null +++ b/worker/subprojects/.clang-tidy @@ -0,0 +1,7 @@ +# Bad workaround to disable clang-tidy checks in worker/subprojects folder. +# Ideally we should use a modern version so worker/.clang-tidy-ignore would be +# honored. Here we should also be able to do Checks: '-*' to disable all rules +# but if we do it it fails with "Error: no checks enable". +--- +Checks: 'modernize-*' +... From 6c984ae6b3c08a4e4f36d9193765b6afca45595f Mon Sep 17 00:00:00 2001 From: Gustavo Garcia Date: Tue, 4 Apr 2023 10:38:35 +0200 Subject: [PATCH 074/525] Fix check division by zero in transport congestion control (#1049) --- worker/src/RTC/TransportCongestionControlClient.cpp | 6 +++++- worker/src/RTC/TransportCongestionControlServer.cpp | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index 7a782c9739..71f9bfa51a 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -221,8 +221,12 @@ namespace RTC { if (!result.received) lost_packets += 1; + } + + if (expected_packets > 0) + { + this->UpdatePacketLoss(static_cast(lost_packets) / expected_packets); } - this->UpdatePacketLoss(static_cast(lost_packets) / expected_packets); if (this->rtpTransportControllerSend == nullptr) { diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index d04ee93f6a..7dc95dea9f 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -240,7 +240,10 @@ namespace RTC lost_packets += 1; } - this->UpdatePacketLoss(static_cast(lost_packets) / expected_packets); + if (expected_packets > 0) + { + this->UpdatePacketLoss(static_cast(lost_packets) / expected_packets); + } // Create a new feedback packet. this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( From 2584ae44ec6a4d8fd653195be8a80aad1561eb87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 4 Apr 2023 10:42:50 +0200 Subject: [PATCH 075/525] Update NPM devs and add brackets in C++ --- package-lock.json | 180 +++++++++--------- package.json | 6 +- .../RTC/TransportCongestionControlClient.cpp | 27 ++- .../RTC/TransportCongestionControlServer.cpp | 29 ++- 4 files changed, 137 insertions(+), 105 deletions(-) diff --git a/package-lock.json b/package-lock.json index d7d8008cdc..22dd314fa9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,15 +20,15 @@ "@types/jest": "^29.5.0", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.57.0", - "@typescript-eslint/parser": "^5.57.0", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", "eslint": "^8.37.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", - "ts-jest": "^29.0.5", + "ts-jest": "^29.1.0", "tsc-watch": "^6.0.0", "typescript": "^5.0.3" }, @@ -1392,15 +1392,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.0.tgz", - "integrity": "sha512-itag0qpN6q2UMM6Xgk6xoHa0D0/P+M17THnr4SVgqn9Rgam5k/He33MA7/D7QoJcdMxHFyX7U9imaBonAX/6qA==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz", + "integrity": "sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.57.0", - "@typescript-eslint/type-utils": "5.57.0", - "@typescript-eslint/utils": "5.57.0", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/type-utils": "5.57.1", + "@typescript-eslint/utils": "5.57.1", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1426,14 +1426,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.0.tgz", - "integrity": "sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.1.tgz", + "integrity": "sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.57.0", - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/typescript-estree": "5.57.0", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", "debug": "^4.3.4" }, "engines": { @@ -1453,13 +1453,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.0.tgz", - "integrity": "sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.1.tgz", + "integrity": "sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/visitor-keys": "5.57.0" + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1470,13 +1470,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.0.tgz", - "integrity": "sha512-kxXoq9zOTbvqzLbdNKy1yFrxLC6GDJFE2Yuo3KqSwTmDOFjUGeWSakgoXT864WcK5/NAJkkONCiKb1ddsqhLXQ==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.1.tgz", + "integrity": "sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.57.0", - "@typescript-eslint/utils": "5.57.0", + "@typescript-eslint/typescript-estree": "5.57.1", + "@typescript-eslint/utils": "5.57.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1497,9 +1497,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.0.tgz", - "integrity": "sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.1.tgz", + "integrity": "sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1510,13 +1510,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.0.tgz", - "integrity": "sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.1.tgz", + "integrity": "sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/visitor-keys": "5.57.0", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1537,17 +1537,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.0.tgz", - "integrity": "sha512-ps/4WohXV7C+LTSgAL5CApxvxbMkl9B9AUZRtnEFonpIxZDIT7wC1xfvuJONMidrkB9scs4zhtRyIwHh4+18kw==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.1.tgz", + "integrity": "sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.57.0", - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/typescript-estree": "5.57.0", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1563,12 +1563,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.0.tgz", - "integrity": "sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz", + "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/types": "5.57.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -5690,9 +5690,9 @@ } }, "node_modules/ts-jest": { - "version": "29.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz", - "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==", + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", + "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -5715,7 +5715,7 @@ "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", - "typescript": ">=4.3" + "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { "@babel/core": { @@ -7177,15 +7177,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.0.tgz", - "integrity": "sha512-itag0qpN6q2UMM6Xgk6xoHa0D0/P+M17THnr4SVgqn9Rgam5k/He33MA7/D7QoJcdMxHFyX7U9imaBonAX/6qA==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz", + "integrity": "sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.57.0", - "@typescript-eslint/type-utils": "5.57.0", - "@typescript-eslint/utils": "5.57.0", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/type-utils": "5.57.1", + "@typescript-eslint/utils": "5.57.1", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7195,53 +7195,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.0.tgz", - "integrity": "sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.1.tgz", + "integrity": "sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.57.0", - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/typescript-estree": "5.57.0", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.0.tgz", - "integrity": "sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.1.tgz", + "integrity": "sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/visitor-keys": "5.57.0" + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1" } }, "@typescript-eslint/type-utils": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.0.tgz", - "integrity": "sha512-kxXoq9zOTbvqzLbdNKy1yFrxLC6GDJFE2Yuo3KqSwTmDOFjUGeWSakgoXT864WcK5/NAJkkONCiKb1ddsqhLXQ==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.1.tgz", + "integrity": "sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.57.0", - "@typescript-eslint/utils": "5.57.0", + "@typescript-eslint/typescript-estree": "5.57.1", + "@typescript-eslint/utils": "5.57.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.0.tgz", - "integrity": "sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.1.tgz", + "integrity": "sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.0.tgz", - "integrity": "sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.1.tgz", + "integrity": "sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/visitor-keys": "5.57.0", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7250,28 +7250,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.0.tgz", - "integrity": "sha512-ps/4WohXV7C+LTSgAL5CApxvxbMkl9B9AUZRtnEFonpIxZDIT7wC1xfvuJONMidrkB9scs4zhtRyIwHh4+18kw==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.1.tgz", + "integrity": "sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.57.0", - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/typescript-estree": "5.57.0", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.0.tgz", - "integrity": "sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz", + "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/types": "5.57.1", "eslint-visitor-keys": "^3.3.0" } }, @@ -10231,9 +10231,9 @@ "dev": true }, "ts-jest": { - "version": "29.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz", - "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==", + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", + "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", "dev": true, "requires": { "bs-logger": "0.x", diff --git a/package.json b/package.json index fcfa3aebc8..63f2638f02 100644 --- a/package.json +++ b/package.json @@ -95,15 +95,15 @@ "@types/jest": "^29.5.0", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.57.0", - "@typescript-eslint/parser": "^5.57.0", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", "eslint": "^8.37.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", - "ts-jest": "^29.0.5", + "ts-jest": "^29.1.0", "tsc-watch": "^6.0.0", "typescript": "^5.0.3" } diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index 71f9bfa51a..2a0d35badd 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -215,17 +215,20 @@ namespace RTC MS_TRACE(); // Update packet loss history. - const size_t expected_packets = feedback->GetPacketStatusCount(); - size_t lost_packets = 0; + const size_t expectedPackets = feedback->GetPacketStatusCount(); + size_t lostPackets = 0; + for (const auto& result : feedback->GetPacketResults()) { if (!result.received) - lost_packets += 1; - } - - if (expected_packets > 0) + { + lostPackets += 1; + } + } + + if (expectedPackets > 0) { - this->UpdatePacketLoss(static_cast(lost_packets) / expected_packets); + this->UpdatePacketLoss(static_cast(lostPackets) / expectedPackets); } if (this->rtpTransportControllerSend == nullptr) @@ -240,7 +243,9 @@ namespace RTC { // Add the score into the histogram. if (this->packetLossHistory.size() == PacketLossHistogramLength) + { this->packetLossHistory.pop_front(); + } this->packetLossHistory.push_back(packetLoss); @@ -307,9 +312,13 @@ namespace RTC // Manage it via trending and increase it a bit to avoid immediate oscillations. #ifdef USE_TREND_CALCULATOR if (!force) + { this->desiredBitrateTrend.Update(desiredBitrate, nowMs); + } else + { this->desiredBitrateTrend.ForceUpdate(desiredBitrate, nowMs); + } #endif this->bitrates.desiredBitrate = desiredBitrate; @@ -516,9 +525,13 @@ namespace RTC // Update availableBitrate. // NOTE: Just in case. if (targetTransferRate.target_rate.bps() > std::numeric_limits::max()) + { this->bitrates.availableBitrate = std::numeric_limits::max(); + } else + { this->bitrates.availableBitrate = static_cast(targetTransferRate.target_rate.bps()); + } MS_DEBUG_DEV("new available bitrate:%" PRIu32, this->bitrates.availableBitrate); diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index 7dc95dea9f..a2c4b60985 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -120,7 +120,9 @@ namespace RTC uint16_t wideSeqNumber; if (!packet->ReadTransportWideCc01(wideSeqNumber)) + { break; + } // Update the RTCP media SSRC of the ongoing Transport-CC Feedback packet. this->transportCcFeedbackSenderSsrc = 0u; @@ -186,7 +188,9 @@ namespace RTC uint32_t absSendTime; if (!packet->ReadAbsSendTime(absSendTime)) + { break; + } // NOTE: nowMs is uint64_t but we need to "convert" it to int64_t before // we give it to libwebrtc lib (althought this is implicit in the @@ -222,7 +226,9 @@ namespace RTC MS_TRACE(); if (!this->transportCcFeedbackPacket->IsSerializable()) + { return; + } auto latestWideSeqNumber = this->transportCcFeedbackPacket->GetLatestSequenceNumber(); auto latestTimestamp = this->transportCcFeedbackPacket->GetLatestTimestamp(); @@ -232,17 +238,20 @@ namespace RTC this, this->transportCcFeedbackPacket.get()); // Update packet loss history. - const size_t expected_packets = this->transportCcFeedbackPacket->GetPacketStatusCount(); - size_t lost_packets = 0; + const size_t expectedPackets = this->transportCcFeedbackPacket->GetPacketStatusCount(); + size_t lostPackets = 0; + for (const auto& result : this->transportCcFeedbackPacket->GetPacketResults()) { if (!result.received) - lost_packets += 1; + { + lostPackets += 1; + } } - if (expected_packets > 0) + if (expectedPackets > 0) { - this->UpdatePacketLoss(static_cast(lost_packets) / expected_packets); + this->UpdatePacketLoss(static_cast(lostPackets) / expectedPackets); } // Create a new feedback packet. @@ -268,7 +277,9 @@ namespace RTC // May fix unlimitedRembCounter. if (this->unlimitedRembCounter > 0u && this->maxIncomingBitrate != 0u) + { this->unlimitedRembCounter = 0u; + } // In case this is the first unlimited REMB packet, send it fast. // clang-format off @@ -298,7 +309,9 @@ namespace RTC this->limitationRembSentAtMs = nowMs; if (this->unlimitedRembCounter > 0u) + { this->unlimitedRembCounter--; + } } } @@ -306,7 +319,9 @@ namespace RTC { // Add the score into the histogram. if (this->packetLossHistory.size() == PacketLossHistogramLength) + { this->packetLossHistory.pop_front(); + } this->packetLossHistory.push_back(packetLoss); @@ -337,7 +352,9 @@ namespace RTC // Limit announced bitrate if requested via API. if (this->maxIncomingBitrate != 0u) + { availableBitrate = std::min(availableBitrate, this->maxIncomingBitrate); + } #if MS_LOG_DEV_LEVEL == 3 std::ostringstream ssrcsStream; @@ -369,6 +386,8 @@ namespace RTC MS_TRACE(); if (timer == this->transportCcFeedbackSendPeriodicTimer) + { SendTransportCcFeedback(); + } } } // namespace RTC From 0b643a4ad36a000f9784d125290c4bc67282a525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 4 Apr 2023 10:47:34 +0200 Subject: [PATCH 076/525] C++: add brackets in conditions (more) --- worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index e2cc570a35..31ba9350cb 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -48,7 +48,9 @@ namespace RTC new FeedbackRtpTransportPacket(commonHeader, len)); if (!packet->IsCorrect()) + { return nullptr; + } return packet.release(); } @@ -399,7 +401,9 @@ namespace RTC auto& packetResult = packetResults[idx]; if (!packetResult.received) + { continue; + } currentReceivedAtMs += this->deltas.at(deltaIdx) / 4; packetResult.delta = this->deltas.at(deltaIdx); @@ -418,7 +422,9 @@ namespace RTC uint16_t lost{ 0u }; if (expected == 0u) + { return 0u; + } for (auto* chunk : this->chunks) { @@ -428,7 +434,9 @@ namespace RTC // NOTE: If lost equals expected, the math below would produce 256, which // becomes 0 in uint8_t. if (lost == expected) + { return 255u; + } return (lost << 8) / expected; } @@ -487,9 +495,13 @@ namespace RTC Status status; if (delta >= 0 && delta <= 255) + { status = Status::SmallDelta; + } else + { status = Status::LargeDelta; + } // Create a long run chunk before processing this packet, if needed. // clang-format off @@ -576,7 +588,9 @@ namespace RTC { // No pending status packets. if (this->context.statuses.empty()) + { return; + } if (this->context.allSameStatus) { @@ -638,9 +652,13 @@ namespace RTC uint8_t symbolSize = data[0] & 0x40; if (symbolSize == 0) + { return new OneBitVectorChunk(bytes, count); + } else + { return new TwoBitVectorChunk(bytes, count); + } } return nullptr; @@ -717,9 +735,13 @@ namespace RTC MS_TRACE(); if (this->status == Status::SmallDelta || this->status == Status::LargeDelta) + { return this->count; + } else + { return 0u; + } } void FeedbackRtpTransportPacket::RunLengthChunk::FillResults( @@ -837,7 +859,9 @@ namespace RTC for (auto status : this->statuses) { if (status == Status::SmallDelta || status == Status::LargeDelta) + { count++; + } } return count; @@ -975,7 +999,9 @@ namespace RTC for (auto status : this->statuses) { if (status == Status::SmallDelta || status == Status::LargeDelta) + { count++; + } } return count; From 9471c4e6f2c66a32e4f44ca5ea55206690cb841a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 4 Apr 2023 10:49:02 +0200 Subject: [PATCH 077/525] cosmetic --- worker/include/RTC/RTCP/FeedbackRtpTransport.hpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp index 58cbc6f151..2d1cb7f67c 100644 --- a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp +++ b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp @@ -213,7 +213,8 @@ namespace RTC public: AddPacketResult AddPacket(uint16_t sequenceNumber, uint64_t timestamp, size_t maxRtcpPacketLen); - void Finish(); // Just for locally generated packets. + // Just for locally generated packets. + void Finish(); bool IsFull() { // NOTE: Since AddPendingChunks() is called at the end, we cannot track @@ -315,13 +316,16 @@ namespace RTC private: uint16_t baseSequenceNumber{ 0u }; uint32_t referenceTime{ 0 }; - uint16_t latestSequenceNumber{ 0u }; // Just for locally generated packets. - uint64_t latestTimestamp{ 0u }; // Just for locally generated packets. + // Just for locally generated packets. + uint16_t latestSequenceNumber{ 0u }; + // Just for locally generated packets. + uint64_t latestTimestamp{ 0u }; uint16_t packetStatusCount{ 0u }; uint8_t feedbackPacketCount{ 0u }; std::vector chunks; std::vector deltas; - Context context; // Just for locally generated packets. + // Just for locally generated packets. + Context context; size_t deltasAndChunksSize{ 0u }; size_t size{ 0 }; bool isCorrect{ true }; From e93d4f669448a4a95aebf7ffb641011eb315b95c Mon Sep 17 00:00:00 2001 From: Gustavo Garcia Date: Tue, 4 Apr 2023 10:50:23 +0200 Subject: [PATCH 078/525] Fix lost pending statuses in transport feedback (#1050) --- worker/src/RTC/TransportCongestionControlServer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index a2c4b60985..8c7a016949 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -225,6 +225,8 @@ namespace RTC { MS_TRACE(); + this->transportCcFeedbackPacket->Finish(); + if (!this->transportCcFeedbackPacket->IsSerializable()) { return; From 1ef3fea2d053f6cea2bac2487229957eb32a4af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 4 Apr 2023 10:54:18 +0200 Subject: [PATCH 079/525] 3.11.21 --- CHANGELOG.md | 6 ++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b30972c7c6..e239fbfbca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Changelog +### 3.11.21 + +* Fix check division by zero in transport congestion control ([PR #1049](https://github.com/versatica/mediasoup/pull/1049) by @ggarber). +* Fix lost pending statuses in transport CC feedback ([PR #1050](https://github.com/versatica/mediasoup/pull/1050) by @ggarber). + + ### 3.11.20 * `RtpStreamSend`: Reset RTP retransmission buffer upon RTP sequence number reset ([PR #1041](https://github.com/versatica/mediasoup/pull/1041)). diff --git a/package-lock.json b/package-lock.json index 22dd314fa9..4e09d10124 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.20", + "version": "3.11.21", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.20", + "version": "3.11.21", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 63f2638f02..16e5543a2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.20", + "version": "3.11.21", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From f78d7852c51ef361db55ed0a480ad61aa34da1c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 4 Apr 2023 11:21:20 +0200 Subject: [PATCH 080/525] Node Worker.ts: Forgot to pass to WebRtcServer --- node/src/Worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 582a0f12b9..3c6ce2d61d 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -641,7 +641,7 @@ export class Worker await this.#channel.request('worker.createWebRtcServer', undefined, reqData); - const webRtcServer = new WebRtcServer( + const webRtcServer = new WebRtcServer( { internal : { webRtcServerId: reqData.webRtcServerId }, channel : this.#channel, From feaaf20293c3714b5cb95494bbb21e9a1d2f1cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Tue, 4 Apr 2023 15:35:52 +0200 Subject: [PATCH 081/525] SeqManager: remove unused Offset method (#1051) --- worker/include/RTC/SeqManager.hpp | 1 - worker/src/RTC/SeqManager.cpp | 6 - worker/test/src/RTC/TestSeqManager.cpp | 163 ++++++++++++------------- 3 files changed, 80 insertions(+), 90 deletions(-) diff --git a/worker/include/RTC/SeqManager.hpp b/worker/include/RTC/SeqManager.hpp index 442cc0f9c9..82409d2a65 100644 --- a/worker/include/RTC/SeqManager.hpp +++ b/worker/include/RTC/SeqManager.hpp @@ -40,7 +40,6 @@ namespace RTC public: void Sync(T input); void Drop(T input); - void Offset(T offset); bool Input(const T input, T& output); T GetMaxInput() const; T GetMaxOutput() const; diff --git a/worker/src/RTC/SeqManager.cpp b/worker/src/RTC/SeqManager.cpp index 24b33b20ea..ce0e3bcf1e 100644 --- a/worker/src/RTC/SeqManager.cpp +++ b/worker/src/RTC/SeqManager.cpp @@ -62,12 +62,6 @@ namespace RTC } } - template - void SeqManager::Offset(T offset) - { - this->base = (this->base + offset) & MaxValue; - } - template bool SeqManager::Input(const T input, T& output) { diff --git a/worker/test/src/RTC/TestSeqManager.cpp b/worker/test/src/RTC/TestSeqManager.cpp index fa56dd077c..b23eb4ea80 100644 --- a/worker/test/src/RTC/TestSeqManager.cpp +++ b/worker/test/src/RTC/TestSeqManager.cpp @@ -11,9 +11,8 @@ constexpr uint16_t kMaxNumberFor15Bits = (1 << 15) - 1; template struct TestSeqManagerInput { - TestSeqManagerInput( - T input, T output, bool sync = false, bool drop = false, T offset = 0, int64_t maxInput = -1) - : input(input), output(output), sync(sync), drop(drop), offset(offset), maxInput(maxInput) + TestSeqManagerInput(T input, T output, bool sync = false, bool drop = false, int64_t maxInput = -1) + : input(input), output(output), sync(sync), drop(drop), maxInput(maxInput) { } @@ -21,7 +20,6 @@ struct TestSeqManagerInput T output{ 0 }; bool sync{ false }; bool drop{ false }; - T offset{ 0 }; int64_t maxInput{ -1 }; }; @@ -31,10 +29,9 @@ void validate(SeqManager& seqManager, std::vector>& for (auto& element : inputs) { if (element.sync) + { seqManager.Sync(element.input - 1); - - if (element.offset) - seqManager.Offset(element.offset); + } if (element.drop) { @@ -299,14 +296,14 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") // clang-format off std::vector> inputs = { - { 0, 0, false, false }, - { 1, 1, false, false }, - { 2, 2, false, false }, - { 80, 23, true, false, 20 }, - { 81, 24, false, false }, - { 82, 25, false, false }, - { 83, 26, false, false }, - { 84, 27, false, false } + { 0, 0, false, false }, + { 1, 1, false, false }, + { 2, 2, false, false }, + { 80, 3, true, false }, + { 81, 4, false, false }, + { 82, 5, false, false }, + { 83, 6, false, false }, + { 84, 7, false, false } }; // clang-format on @@ -553,16 +550,16 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") // clang-format off std::vector> inputs = { - { 32762, 1, true, false, 0, 32762 }, - { 32763, 2, false, false, 0, 32763 }, - { 32764, 3, false, false, 0, 32764 }, - { 32765, 0, false, true, 0, 32765 }, - { 32766, 0, false, true, 0, 32766 }, - { 32767, 4, false, false, 0, 32767 }, - { 0, 5, false, false, 0, 0 }, - { 1, 6, false, false, 0, 1 }, - { 2, 7, false, false, 0, 2 }, - { 3, 8, false, false, 0, 3 } + { 32762, 1, true, false, 32762 }, + { 32763, 2, false, false, 32763 }, + { 32764, 3, false, false, 32764 }, + { 32765, 0, false, true, 32765 }, + { 32766, 0, false, true, 32766 }, + { 32767, 4, false, false, 32767 }, + { 0, 5, false, false, 0 }, + { 1, 6, false, false, 1 }, + { 2, 7, false, false, 2 }, + { 3, 8, false, false, 3 } }; // clang-format on @@ -575,12 +572,12 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") // clang-format off std::vector> inputs = { - { 0, 1, true, false, 0, 0 }, + { 0, 1, true, false, 0 }, }; for (uint16_t j = 0; j < 3; ++j) { for (uint16_t i = 1; i < std::numeric_limits::max(); ++i) { const uint16_t output = i + 1; - inputs.emplace_back( i, output, false, false, 0, i ); + inputs.emplace_back( i, output, false, false, i ); } } // clang-format on @@ -594,12 +591,12 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") // clang-format off std::vector> inputs = { - { 0, 1, true, false, 0, 0 }, + { 0, 1, true, false, 0, }, }; for (uint16_t j = 0; j < 3; ++j) { for (uint16_t i = 1; i < kMaxNumberFor15Bits; ++i) { const uint16_t output = i + 1; - inputs.emplace_back( i, output, false, false, 0, i ); + inputs.emplace_back( i, output, false, false, i ); } } // clang-format on @@ -632,17 +629,17 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") // clang-format off std::vector> inputs = { - { 1, 1, false, false, 0 }, - { 2, 0, false, true, 0 }, // Drop. - { 3, 2, false, false, 0 }, - { 4, 3, false, false, 0 }, - { 5, 4, false, false, 0 }, - { 6, 5, false, false, 0 }, - { 7, 6, false, false, 0 }, - { 0, 7, false, false, 0 }, - { 1, 0, false, false, 0 }, - { 2, 1, false, false, 0 }, - { 3, 2, false, false, 0 } + { 1, 1, false, false }, + { 2, 0, false, true }, // Drop. + { 3, 2, false, false }, + { 4, 3, false, false }, + { 5, 4, false, false }, + { 6, 5, false, false }, + { 7, 6, false, false }, + { 0, 7, false, false }, + { 1, 0, false, false }, + { 2, 1, false, false }, + { 3, 2, false, false } }; // clang-format on @@ -655,33 +652,33 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") // clang-format off std::vector> inputs = { - { 36964, 36964, false, false, 0 }, - { 25923, 0, false, true, 0 }, // Drop. - { 25701, 25701, false, false, 0 }, - { 17170, 0, false, true, 0 }, // Drop. - { 25923, 25923, false, false, 0 }, - { 4728, 0, false, true, 0 }, // Drop. - { 17170, 17170, false, false, 0 }, - { 30738, 0, false, true, 0 }, // Drop. - { 4728, 4728, false, false, 0 }, - { 4806, 0, false, true, 0 }, // Drop. - { 30738, 30738, false, false, 0 }, - { 50886, 0, false, true, 0 }, // Drop. - { 4806, 4805, false, false, 0 }, // Previously dropped. - { 50774, 0, false, true, 0 }, // Drop. - { 50886, 50884, false, false, 0 }, // Previously dropped. - { 22136, 0, false, true, 0 }, // Drop. - { 50774, 50884, false, false, 0 }, // Previously dropped. - { 30910, 0, false, true, 0 }, // Drop. - { 22136, 22134, false, false, 0 }, - { 48862, 0, false, true, 0 }, // Drop. - { 30910, 30909, false, false, 0 }, - { 56832, 0, false, true, 0 }, // Drop. - { 48862, 48861, false, false, 0 }, - { 2, 0, false, true, 0 }, // Drop. - { 56832, 56828, false, false, 0 }, - { 530, 0, false, true, 0 }, // Drop. - { 2, 65534, false, false, 0 }, + { 36964, 36964, false, false }, + { 25923, 0, false, true }, // Drop. + { 25701, 25701, false, false }, + { 17170, 0, false, true }, // Drop. + { 25923, 25923, false, false }, + { 4728, 0, false, true }, // Drop. + { 17170, 17170, false, false }, + { 30738, 0, false, true }, // Drop. + { 4728, 4728, false, false }, + { 4806, 0, false, true }, // Drop. + { 30738, 30738, false, false }, + { 50886, 0, false, true }, // Drop. + { 4806, 4805, false, false }, // Previously dropped. + { 50774, 0, false, true }, // Drop. + { 50886, 50884, false, false }, // Previously dropped. + { 22136, 0, false, true }, // Drop. + { 50774, 50884, false, false }, // Previously dropped. + { 30910, 0, false, true }, // Drop. + { 22136, 22134, false, false }, + { 48862, 0, false, true }, // Drop. + { 30910, 30909, false, false }, + { 56832, 0, false, true }, // Drop. + { 48862, 48861, false, false }, + { 2, 0, false, true }, // Drop. + { 56832, 56828, false, false }, + { 530, 0, false, true }, // Drop. + { 2, 65534, false, false }, }; // clang-format on @@ -694,13 +691,13 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") // clang-format off std::vector> inputs = { - { 36960, 36960, false, false, 0 }, - { 3328, 0, false, true, 0 }, // Drop. - { 24589, 24588, false, false, 0 }, - { 120, 0, false, true, 0 }, // Drop. - { 3328, 3326, false, false, 0 }, - { 30848, 0, false, true, 0 }, // Drop. - { 120, 3326, false, false, 0 }, // Previously dropped. + { 36960, 36960, false, false }, + { 3328, 0, false, true }, // Drop. + { 24589, 24588, false, false }, + { 120, 0, false, true }, // Drop. + { 3328, 3326, false, false }, + { 30848, 0, false, true }, // Drop. + { 120, 3326, false, false }, // Previously dropped. }; // clang-format on @@ -713,15 +710,15 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") // clang-format off std::vector> inputs = { - { 36964, 36964, false, false, 0 }, - { 65396 , 0, false, true, 0 }, // Drop. - { 25855, 25854, false, false, 0 }, - { 29793 , 0, false, true, 0 }, // Drop. - { 65396, 65395, false, false, 0 }, - { 25087, 0, false, true, 0 }, // Drop. - { 29793, 29791, false, false, 0 }, - { 65535 , 0, false, true, 0 }, // Drop. - { 25087, 29791, false, false, 0 }, // Previously dropped. + { 36964, 36964, false, false }, + { 65396 , 0, false, true }, // Drop. + { 25855, 25854, false, false }, + { 29793 , 0, false, true }, // Drop. + { 65396, 65395, false, false }, + { 25087, 0, false, true }, // Drop. + { 29793, 29791, false, false }, + { 65535 , 0, false, true }, // Drop. + { 25087, 29791, false, false }, // Previously dropped. }; // clang-format on From 56eda745e2cad34fab00c998b0e47a570d838a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Wed, 5 Apr 2023 17:45:15 +0200 Subject: [PATCH 082/525] RTC Logger (#1048) RtcLogger: RtpPacket --- worker/include/RTC/RtcLogger.hpp | 58 +++++++++++++++ worker/include/RTC/RtpPacket.hpp | 4 ++ worker/meson.build | 7 ++ worker/meson_options.txt | 1 + worker/src/RTC/PipeConsumer.cpp | 15 ++++ worker/src/RTC/Producer.cpp | 10 +++ worker/src/RTC/Router.cpp | 2 + worker/src/RTC/RtcLogger.cpp | 101 +++++++++++++++++++++++++++ worker/src/RTC/RtpPacket.cpp | 9 +++ worker/src/RTC/SimpleConsumer.cpp | 17 +++++ worker/src/RTC/SimulcastConsumer.cpp | 34 +++++++++ worker/src/RTC/SvcConsumer.cpp | 19 +++++ worker/src/RTC/Transport.cpp | 7 ++ 13 files changed, 284 insertions(+) create mode 100644 worker/include/RTC/RtcLogger.hpp create mode 100644 worker/src/RTC/RtcLogger.cpp diff --git a/worker/include/RTC/RtcLogger.hpp b/worker/include/RTC/RtcLogger.hpp new file mode 100644 index 0000000000..76c1364870 --- /dev/null +++ b/worker/include/RTC/RtcLogger.hpp @@ -0,0 +1,58 @@ +#ifndef MS_RTC_RTC_LOGGER_HPP +#define MS_RTC_RTC_LOGGER_HPP + +#include "common.hpp" +#include + +namespace RTC +{ + namespace RtcLogger + { + class RtpPacket + { + public: + enum class DropReason : uint8_t + { + NONE = 0, + PRODUCER_NOT_FOUND, + RECV_RTP_STREAM_NOT_FOUND, + RECV_RTP_STREAM_DISCARDED, + CONSUMER_INACTIVE, + INVALID_TARGET_LAYER, + UNSUPPORTED_PAYLOAD_TYPE, + NOT_A_KEYFRAME, + SPATIAL_LAYER_MISMATCH, + TOO_HIGH_TIMESTAMP_EXTRA_NEEDED, + PACKET_PREVIOUS_TO_SPATIAL_LAYER_SWITCH, + DROPPED_BY_CODEC, + SEND_RTP_STREAM_DISCARDED, + }; + + static absl::flat_hash_map dropReason2String; + + RtpPacket() = default; + ~RtpPacket() = default; + void Sent(); + void Dropped(DropReason dropReason); + + private: + void Log() const; + void Clear(); + + public: + uint64_t timestamp; + std::string recvTransportId{}; + std::string sendTransportId{}; + std::string routerId{}; + std::string producerId{}; + std::string consumerId{}; + uint32_t recvRtpTimestamp; + uint32_t sendRtpTimestamp; + uint16_t recvSeqNumber; + uint16_t sendSeqNumber; + bool dropped; + DropReason dropReason{ DropReason::NONE }; + }; + }; // namespace RtcLogger +} // namespace RTC +#endif diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index 0dece98d5b..a585a3babc 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -4,6 +4,7 @@ #include "common.hpp" #include "Utils.hpp" #include "RTC/Codecs/PayloadDescriptorHandler.hpp" +#include "RTC/RtcLogger.hpp" #include #include #include @@ -606,6 +607,9 @@ namespace RTC void ShiftPayload(size_t payloadOffset, size_t shift, bool expand = true); + public: + RtcLogger::RtpPacket logger; + private: void ParseExtensions(); diff --git a/worker/meson.build b/worker/meson.build index 9f2bba2a91..4be31c0c0b 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -38,6 +38,12 @@ if get_option('ms_log_file_line') ] endif +if get_option('ms_rtc_logger_rtp') + cpp_args += [ + '-DMS_RTC_LOGGER_RTP', + ] +endif + common_sources = [ 'src/lib.cpp', 'src/DepLibSRTP.cpp', @@ -85,6 +91,7 @@ common_sources = [ 'src/RTC/Producer.cpp', 'src/RTC/RateCalculator.cpp', 'src/RTC/Router.cpp', + 'src/RTC/RtcLogger.cpp', 'src/RTC/RtpListener.cpp', 'src/RTC/RtpObserver.cpp', 'src/RTC/RtpPacket.cpp', diff --git a/worker/meson_options.txt b/worker/meson_options.txt index ec104f5197..debe84aa26 100644 --- a/worker/meson_options.txt +++ b/worker/meson_options.txt @@ -1,2 +1,3 @@ option('ms_log_trace', type : 'boolean', value : false, description : 'When enabled, logs the current method/function if current log level is "debug"') option('ms_log_file_line', type : 'boolean', value : false, description : 'When enabled, all the logging macros print more verbose information, including current file and line') +option('ms_rtc_logger_rtp', type : 'boolean', value : false, description : 'When enabled, prints a line with information for each RTP packet') diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index be42f16730..f4f1d767ef 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -201,8 +201,14 @@ namespace RTC { MS_TRACE(); + packet->logger.consumerId = this->id; + if (!IsActive()) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::CONSUMER_INACTIVE); + return; + } auto payloadType = packet->GetPayloadType(); @@ -212,6 +218,8 @@ namespace RTC { MS_DEBUG_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE); + return; } @@ -223,7 +231,11 @@ namespace RTC // If we need to sync, support key frames and this is not a key frame, ignore // the packet. if (syncRequired && this->keyFrameSupported && !packet->IsKeyFrame()) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); + return; + } // Whether this is the first packet after re-sync. const bool isSyncPacket = syncRequired; @@ -252,6 +264,9 @@ namespace RTC packet->SetSsrc(ssrc); packet->SetSequenceNumber(seq); + packet->logger.sendRtpTimestamp = packet->GetTimestamp(); + packet->logger.sendSeqNumber = seq; + if (isSyncPacket) { MS_DEBUG_TAG( diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index 18e7ef527e..768c2b6943 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -672,6 +672,8 @@ namespace RTC { MS_TRACE(); + packet->logger.producerId = this->id; + // Reset current packet. this->currentRtpPacket = nullptr; @@ -684,6 +686,8 @@ namespace RTC { MS_WARN_TAG(rtp, "no stream found for received packet [ssrc:%" PRIu32 "]", packet->GetSsrc()); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_NOT_FOUND); + return ReceiveRtpPacketResult::DISCARDED; } @@ -705,6 +709,8 @@ namespace RTC if (this->mapSsrcRtpStream.size() > numRtpStreamsBefore) NotifyNewRtpStream(rtpStream); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_DISCARDED); + return result; } } @@ -716,7 +722,11 @@ namespace RTC // Process the packet. if (!rtpStream->ReceiveRtxPacket(packet)) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_NOT_FOUND); + return result; + } } // Should not happen. else diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index 5ee105a029..b56dc1c345 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -706,6 +706,8 @@ namespace RTC { MS_TRACE(); + packet->logger.routerId = this->id; + auto& consumers = this->mapProducerConsumers.at(producer); if (!consumers.empty()) diff --git a/worker/src/RTC/RtcLogger.cpp b/worker/src/RTC/RtcLogger.cpp new file mode 100644 index 0000000000..1301fd5292 --- /dev/null +++ b/worker/src/RTC/RtcLogger.cpp @@ -0,0 +1,101 @@ +#define MS_CLASS "RTC::RtcLogger" +// #define MS_LOG_DEV_LEVEL 3 + +#include "RTC/RtcLogger.hpp" +#include "Logger.hpp" + +namespace RTC +{ + namespace RtcLogger + { + // clang-format off + absl::flat_hash_map RtpPacket::dropReason2String = { + { RtpPacket::DropReason::NONE, "None" }, + { RtpPacket::DropReason::PRODUCER_NOT_FOUND, "ProducerNotFound" }, + { RtpPacket::DropReason::RECV_RTP_STREAM_NOT_FOUND, "RecvRtpStreamNotFound" }, + { RtpPacket::DropReason::RECV_RTP_STREAM_DISCARDED, "RecvRtpStreamDiscarded" }, + { RtpPacket::DropReason::CONSUMER_INACTIVE, "ConsumerInactive" }, + { RtpPacket::DropReason::INVALID_TARGET_LAYER, "InvalidTargetLayer" }, + { RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE, "UnsupportedPayloadType" }, + { RtpPacket::DropReason::NOT_A_KEYFRAME, "NotAKeyframe" }, + { RtpPacket::DropReason::SPATIAL_LAYER_MISMATCH, "SpatialLayerMismatch" }, + { RtpPacket::DropReason::TOO_HIGH_TIMESTAMP_EXTRA_NEEDED, "TooHighTimestampExtraNeeded" }, + { RtpPacket::DropReason::PACKET_PREVIOUS_TO_SPATIAL_LAYER_SWITCH, "PacketPreviousToSpatialLayerSwitch" }, + { RtpPacket::DropReason::DROPPED_BY_CODEC, "DroppedByCodec" }, + { RtpPacket::DropReason::SEND_RTP_STREAM_DISCARDED, "SendRtpStreamDiscarded" }, + }; + // clang-format on + + void RtpPacket::Sent() + { + MS_TRACE(); + + this->dropped = false; + + Log(); + Clear(); + } + + void RtpPacket::Dropped(DropReason dropReason) + { + MS_TRACE(); + + this->dropped = true; + this->dropReason = dropReason; + + Log(); + Clear(); + } + + void RtpPacket::Log() const + { +#ifdef MS_RTC_LOGGER_RTP + MS_TRACE(); + + std::cout << "{"; + std::cout << "\"timestamp\": " << this->timestamp; + + if (!this->recvTransportId.empty()) + { + std::cout << ", \"recvTransportId\": \"" << this->recvTransportId << "\""; + } + if (!this->sendTransportId.empty()) + { + std::cout << ", \"sendTransportId\": \"" << this->sendTransportId << "\""; + } + if (!this->routerId.empty()) + { + std::cout << ", \"routerId\": \"" << this->routerId << "\""; + } + if (!this->producerId.empty()) + { + std::cout << ", \"producerId\": \"" << this->producerId << "\""; + } + if (!this->consumerId.empty()) + { + std::cout << ", \"consumerId\": \"" << this->consumerId << "\""; + } + + std::cout << ", \"recvRtpTimestamp\": " << this->recvRtpTimestamp; + std::cout << ", \"sendRtpTimestamp\": " << this->sendRtpTimestamp; + std::cout << ", \"recvSeqNumber\": " << this->recvSeqNumber; + std::cout << ", \"sendSeqNumber\": " << this->sendSeqNumber; + std::cout << ", \"dropped\": " << (this->dropped ? "true" : "false"); + std::cout << ", \"dropReason\": '" << dropReason2String[this->dropReason] << "'"; + std::cout << "}" << std::endl; +#endif + } + + void RtpPacket::Clear() + { + MS_TRACE(); + + this->sendTransportId = {}; + this->routerId = {}; + this->producerId = {}; + this->sendSeqNumber = { 0 }; + this->dropped = { false }; + this->dropReason = { DropReason::NONE }; + } + } // namespace RtcLogger +} // namespace RTC diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index b959464959..368115abed 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -2,6 +2,7 @@ // #define MS_LOG_DEV_LEVEL 3 #include "RTC/RtpPacket.hpp" +#include "DepLibUV.hpp" #include "Logger.hpp" #include // std::memcpy(), std::memmove(), std::memset() #include // std::ostream_iterator @@ -139,6 +140,14 @@ namespace RTC // Parse RFC 5285 header extension. ParseExtensions(); + +// Avoid retrieving the time if RTC logger is disabled. +#ifdef MS_RTC_LOGGER_RTP + // Initialize logger. + this->logger.timestamp = DepLibUV::GetTimeMs(); + this->logger.recvRtpTimestamp = this->GetTimestamp(); + this->logger.recvSeqNumber = this->GetSequenceNumber(); +#endif } RtpPacket::~RtpPacket() diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index 7ed5f44d2f..01da96fb0e 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -265,8 +265,14 @@ namespace RTC { MS_TRACE(); + packet->logger.consumerId = this->id; + if (!IsActive()) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::CONSUMER_INACTIVE); + return; + } auto payloadType = packet->GetPayloadType(); @@ -276,6 +282,8 @@ namespace RTC { MS_DEBUG_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE); + return; } @@ -292,13 +300,19 @@ namespace RTC this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC); + return; } // If we need to sync, support key frames and this is not a key frame, ignore // the packet. if (this->syncRequired && this->keyFrameSupported && !packet->IsKeyFrame()) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); + return; + } // Whether this is the first packet after re-sync. const bool isSyncPacket = this->syncRequired; @@ -327,6 +341,9 @@ namespace RTC packet->SetSsrc(this->rtpParameters.encodings[0].ssrc); packet->SetSequenceNumber(seq); + packet->logger.sendRtpTimestamp = packet->GetTimestamp(); + packet->logger.sendSeqNumber = seq; + if (isSyncPacket) { MS_DEBUG_TAG( diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index 81871cf2f4..44076dca1f 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -664,11 +664,21 @@ namespace RTC { MS_TRACE(); + packet->logger.consumerId = this->id; + if (!IsActive()) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::CONSUMER_INACTIVE); + return; + } if (this->targetTemporalLayer == -1) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::INVALID_TARGET_LAYER); + return; + } auto payloadType = packet->GetPayloadType(); @@ -678,6 +688,8 @@ namespace RTC { MS_DEBUG_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE); + return; } @@ -690,7 +702,11 @@ namespace RTC { // Ignore if not a key frame. if (!packet->IsKeyFrame()) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); + return; + } shouldSwitchCurrentSpatialLayer = true; @@ -702,12 +718,18 @@ namespace RTC // drop it. else if (spatialLayer != this->currentSpatialLayer) { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::SPATIAL_LAYER_MISMATCH); + return; } // If we need to sync and this is not a key frame, ignore the packet. if (this->syncRequired && !packet->IsKeyFrame()) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); + return; + } // Whether this is the first packet after re-sync. const bool isSyncPacket = this->syncRequired; @@ -814,6 +836,8 @@ namespace RTC this->syncRequired = false; this->spatialLayerToSync = -1; + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::TOO_HIGH_TIMESTAMP_EXTRA_NEEDED); + return; } @@ -854,6 +878,9 @@ namespace RTC if (SeqManager::IsSeqLowerThan( packet->GetSequenceNumber(), this->snReferenceSpatialLayer)) { + packet->logger.Dropped( + RtcLogger::RtpPacket::DropReason::PACKET_PREVIOUS_TO_SPATIAL_LAYER_SWITCH); + return; } else if (SeqManager::IsSeqHigherThan( @@ -898,6 +925,8 @@ namespace RTC { this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC); + return; } @@ -921,6 +950,9 @@ namespace RTC packet->SetSequenceNumber(seq); packet->SetTimestamp(timestamp); + packet->logger.sendRtpTimestamp = timestamp; + packet->logger.sendSeqNumber = seq; + if (isSyncPacket) { MS_DEBUG_TAG( @@ -959,6 +991,8 @@ namespace RTC origSsrc, origSeq, origTimestamp); + + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::SEND_RTP_STREAM_DISCARDED); } // Restore packet fields. diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index c2278ba556..d2b6af9566 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -593,8 +593,14 @@ namespace RTC { MS_TRACE(); + packet->logger.consumerId = this->id; + if (!IsActive()) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::CONSUMER_INACTIVE); + return; + } // clang-format off if ( @@ -603,6 +609,8 @@ namespace RTC ) // clang-format on { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::INVALID_TARGET_LAYER); + return; } @@ -614,12 +622,18 @@ namespace RTC { MS_DEBUG_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE); + return; } // If we need to sync and this is not a key frame, ignore the packet. if (this->syncRequired && !packet->IsKeyFrame()) + { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); + return; + } // Whether this is the first packet after re-sync. const bool isSyncPacket = this->syncRequired; @@ -646,6 +660,8 @@ namespace RTC { this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC); + return; } @@ -673,6 +689,9 @@ namespace RTC packet->SetSsrc(this->rtpParameters.encodings[0].ssrc); packet->SetSequenceNumber(seq); + packet->logger.sendRtpTimestamp = packet->GetTimestamp(); + packet->logger.sendSeqNumber = seq; + if (marker) { packet->SetMarker(true); diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 079b3a5055..65e0b57c73 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -1692,6 +1692,8 @@ namespace RTC { MS_TRACE(); + packet->logger.recvTransportId = this->id; + // Apply the Transport RTP header extension ids so the RTP listener can use them. packet->SetMidExtensionId(this->recvRtpHeaderExtensionIds.mid); packet->SetRidExtensionId(this->recvRtpHeaderExtensionIds.rid); @@ -1712,6 +1714,8 @@ namespace RTC if (!producer) { + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::PRODUCER_NOT_FOUND); + MS_WARN_TAG( rtp, "no suitable Producer for received RTP packet [ssrc:%" PRIu32 ", payloadType:%" PRIu8 "]", @@ -2663,6 +2667,9 @@ namespace RTC { MS_TRACE(); + packet->logger.sendTransportId = this->id; + packet->logger.Sent(); + // Update abs-send-time if present. packet->UpdateAbsSendTime(DepLibUV::GetTimeMs()); From 937bb6c832582d05ebbfa35cc38864894d683391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Thu, 13 Apr 2023 12:08:31 +0200 Subject: [PATCH 083/525] SeqManager: Properly remove dropped entries (#1054) * SeqManager: Properly remove dropped entries Fixes #1037. Keep dropped entries clean by removing those higher than this->maxInput. * Set dropped input to 'maxInput' if needed A dropped input is part of the same sequence, hence set it to 'maxInput' if the dropped value is higher than the current 'maxInput'. Without this consideration we would be wrongly erasing dropped inputs that are legitimally just the maximum input of the sequence stream. * Update CHANGELOG * Input(): Performance, do not loop over every dropped inputs Which has a linear complexity. Use lower_bound which has logarithmic complexity. --- CHANGELOG.md | 5 ++ worker/src/RTC/SeqManager.cpp | 107 +++++++++++-------------- worker/test/src/RTC/TestSeqManager.cpp | 20 ++--- 3 files changed, 63 insertions(+), 69 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e239fbfbca..e02769781a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* `SeqManager`: Properly remove old dropped entries ([PR #1054](https://github.com/versatica/mediasoup/pull/1054)). + + ### 3.11.21 * Fix check division by zero in transport congestion control ([PR #1049](https://github.com/versatica/mediasoup/pull/1049) by @ggarber). diff --git a/worker/src/RTC/SeqManager.cpp b/worker/src/RTC/SeqManager.cpp index ce0e3bcf1e..27ca6efba1 100644 --- a/worker/src/RTC/SeqManager.cpp +++ b/worker/src/RTC/SeqManager.cpp @@ -58,7 +58,10 @@ namespace RTC // Mark as dropped if 'input' is higher than anyone already processed. if (SeqManager::IsSeqHigherThan(input, this->maxInput)) { + this->maxInput = input; this->dropped.insert(input); + + ClearDropped(); } } @@ -67,44 +70,52 @@ namespace RTC { auto base = this->base; - // There are dropped inputs. Synchronize. - if (!this->dropped.empty()) + // No dropped inputs to consider. + if (this->dropped.empty()) { - // Check whether this input was dropped. - if (this->dropped.find(input) != this->dropped.end()) + goto done; + } + // Dropped inputs present, cleanup and update base. + else + { + // Set 'maxInput' here if needed before calling ClearDropped(). + if (this->started && IsSeqHigherThan(input, this->maxInput)) { - MS_DEBUG_DEV("trying to send a dropped input"); - - return false; + this->maxInput = input; } - // Dropped entries count that must be considered for the output. - size_t count{ 0 }; + ClearDropped(); + + base = this->base; + } + + // No dropped inputs to consider after cleanup. + if (this->dropped.empty()) + { + goto done; + } + // This input was dropped. + else if (this->dropped.find(input) != this->dropped.end()) + { + MS_DEBUG_DEV("trying to send a dropped input"); - /* - * Consider values lower than input and those higher that input - * which belong to a previous cycle. - */ - for (const auto& value : this->dropped) + return false; + } + // There are dropped inputs, calculate 'base' for this input. + else + { + // Get the first dropped input which is higher than or equal 'input'. + auto it = this->dropped.lower_bound(input); + + // There are dropped inputs lower than 'input'. + if (it != this->dropped.begin()) { - // clang-format off - if - ( - IsSeqLowerThan(value, input) || - ( - (value > input && (value - input > MaxValue / 3)) || - (value < input && (input - value > MaxValue / 3)) - ) - ) - // clang-format on - { - count++; - } + auto count = std::distance(this->dropped.begin(), it); + base = (this->base - count) & MaxValue; } - - base = (this->base - count) & MaxValue; } + done: output = (input + base) & MaxValue; if (!this->started) @@ -116,23 +127,19 @@ namespace RTC } else { - // New input is higher than the maximum seen. But less than acceptable units higher. - // Keep it as the maximum seen. See Drop(). + // New input is higher than the maximum seen. if (IsSeqHigherThan(input, this->maxInput)) { this->maxInput = input; } - // New output is higher than the maximum seen. But less than acceptable units higher. - // Keep it as the maximum seen. See Sync(). + // New output is higher than the maximum seen. if (IsSeqHigherThan(output, this->maxOutput)) { this->maxOutput = output; } } - ClearDropped(); - return true; } @@ -149,7 +156,7 @@ namespace RTC } /* - * Delete droped inputs greater than maxInput that belong to a previous + * Delete droped inputs greater than maxInput, which belong to a previous * cycle. */ template @@ -161,37 +168,19 @@ namespace RTC return; } - const size_t threshold = (this->maxInput + MaxValue / 3) & MaxValue; const size_t previousDroppedSize = this->dropped.size(); - const auto it1 = this->dropped.upper_bound(this->maxInput); - const auto it2 = this->dropped.lower_bound(threshold); - // There is no dropped value greater than this->maxInput. - if (it1 == this->dropped.end()) - { - return; - } - - // There is a single value in the range. - if (it1 == it2) - { - this->dropped.erase(it1); - } - // There are many values in the range. - else + for (auto it = this->dropped.begin(); it != this->dropped.end();) { - // Measure the distance of it1 and it2 to the beggining of dropped. - auto distanceIt1 = std::distance(this->dropped.begin(), it1); - auto distanceIt2 = std::distance(this->dropped.begin(), it2); + auto value = *it; - // it2 goes out of range, only it1 is within the range. - if (distanceIt2 < distanceIt1) + if (isSeqHigherThan(value, this->maxInput)) { - this->dropped.erase(it1); + it = this->dropped.erase(it); } else { - this->dropped.erase(it1, it2); + break; } } diff --git a/worker/test/src/RTC/TestSeqManager.cpp b/worker/test/src/RTC/TestSeqManager.cpp index b23eb4ea80..828f479b70 100644 --- a/worker/test/src/RTC/TestSeqManager.cpp +++ b/worker/test/src/RTC/TestSeqManager.cpp @@ -666,19 +666,19 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") { 50886, 0, false, true }, // Drop. { 4806, 4805, false, false }, // Previously dropped. { 50774, 0, false, true }, // Drop. - { 50886, 50884, false, false }, // Previously dropped. + { 50886, 4805, false, false }, // Previously dropped. { 22136, 0, false, true }, // Drop. - { 50774, 50884, false, false }, // Previously dropped. + { 50774, 50773, false, false }, { 30910, 0, false, true }, // Drop. - { 22136, 22134, false, false }, + { 22136, 50773, false, false }, // Previously dropped. { 48862, 0, false, true }, // Drop. { 30910, 30909, false, false }, { 56832, 0, false, true }, // Drop. { 48862, 48861, false, false }, { 2, 0, false, true }, // Drop. - { 56832, 56828, false, false }, + { 56832, 48861, false, false }, // Previously dropped. { 530, 0, false, true }, // Drop. - { 2, 65534, false, false }, + { 2, 48861, false, false }, // Previously dropped. }; // clang-format on @@ -695,9 +695,9 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") { 3328, 0, false, true }, // Drop. { 24589, 24588, false, false }, { 120, 0, false, true }, // Drop. - { 3328, 3326, false, false }, + { 3328, 24588, false, false }, // Previously dropped. { 30848, 0, false, true }, // Drop. - { 120, 3326, false, false }, // Previously dropped. + { 120, 120, false, false }, }; // clang-format on @@ -714,11 +714,11 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") { 65396 , 0, false, true }, // Drop. { 25855, 25854, false, false }, { 29793 , 0, false, true }, // Drop. - { 65396, 65395, false, false }, + { 65396, 25854, false, false }, // Previously dropped. { 25087, 0, false, true }, // Drop. - { 29793, 29791, false, false }, + { 29793, 25854, false, false }, // Previously dropped. { 65535 , 0, false, true }, // Drop. - { 25087, 29791, false, false }, // Previously dropped. + { 25087, 25086, false, false }, }; // clang-format on From abfd942f83270d85e3121986ad8490b7f24c1fa2 Mon Sep 17 00:00:00 2001 From: Gustavo Garcia Date: Fri, 14 Apr 2023 10:28:12 +0200 Subject: [PATCH 084/525] Upgrade trendline estimator to improve low bandwidth conditions (#1055) * Uprade trendline estimator to improve low bandwidth conditions * Missing constant change --- .../goog_cc/delay_based_bwe.cc | 4 +- .../goog_cc/trendline_estimator.cc | 219 +++++++++--------- .../goog_cc/trendline_estimator.h | 73 +++--- 3 files changed, 162 insertions(+), 134 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc index 57f4afa146..6871afae0e 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc @@ -61,7 +61,7 @@ DelayBasedBwe::DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config, network_state_predictor_(network_state_predictor), inter_arrival_(), delay_detector_( - new TrendlineEstimator(key_value_config_, network_state_predictor_)), + new TrendlineEstimator(network_state_predictor_)), last_seen_packet_(Timestamp::MinusInfinity()), uma_recorded_(false), rate_control_(key_value_config, /*send_side=*/true), @@ -127,7 +127,7 @@ void DelayBasedBwe::IncomingPacketFeedback(const PacketResult& packet_feedback, new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, kTimestampToMs, true)); delay_detector_.reset( - new TrendlineEstimator(key_value_config_, network_state_predictor_)); + new TrendlineEstimator(network_state_predictor_)); } last_seen_packet_ = at_time; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 885c6776cb..dedb33d3f9 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -13,96 +13,92 @@ #include "modules/congestion_controller/goog_cc/trendline_estimator.h" -#include "modules/remote_bitrate_estimator/include/bwe_defines.h" -#include "rtc_base/numerics/safe_minmax.h" - -#include "Logger.hpp" - -#include #include + #include #include +#include "absl/strings/match.h" +#include "absl/types/optional.h" +#include "api/network_state_predictor.h" +#include "rtc_base/numerics/safe_minmax.h" +#include "api/transport/webrtc_key_value_config.h" + +#include "Logger.hpp" + namespace webrtc { namespace { // Parameters for linear least squares fit of regression line to noisy data. -constexpr size_t kDefaultTrendlineWindowSize = 20; -constexpr double kDefaultTrendlineSmoothingCoeff = 0.6; +constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; constexpr double kDefaultTrendlineThresholdGain = 4.0; -const char kBweWindowSizeInPacketsExperiment[] = - "WebRTC-BweWindowSizeInPackets"; - -size_t ReadTrendlineFilterWindowSize( - const WebRtcKeyValueConfig* key_value_config) { - std::string experiment_string = - key_value_config->Lookup(kBweWindowSizeInPacketsExperiment); - size_t window_size; - int parsed_values = - sscanf(experiment_string.c_str(), "Enabled-%zu", &window_size); - if (parsed_values == 1) { - if (window_size > 1) - return window_size; - MS_WARN_DEV("window size must be greater than 1"); - } - MS_WARN_DEV( - "failed to parse parameters for BweWindowSizeInPackets" - " experiment from field trial string, using default"); - return kDefaultTrendlineWindowSize; -} absl::optional LinearFitSlope( - const std::deque>& points) { - //RTC_DCHECK(points.size() >= 2); + const std::deque& packets) { + // RTC_DCHECK(packets.size() >= 2); // Compute the "center of mass". double sum_x = 0; double sum_y = 0; - for (const auto& point : points) { - sum_x += point.first; - sum_y += point.second; + for (const auto& packet : packets) { + sum_x += packet.arrival_time_ms; + sum_y += packet.smoothed_delay_ms; } - double x_avg = sum_x / points.size(); - double y_avg = sum_y / points.size(); + double x_avg = sum_x / packets.size(); + double y_avg = sum_y / packets.size(); // Compute the slope k = \sum (x_i-x_avg)(y_i-y_avg) / \sum (x_i-x_avg)^2 double numerator = 0; double denominator = 0; - for (const auto& point : points) { - numerator += (point.first - x_avg) * (point.second - y_avg); - denominator += (point.first - x_avg) * (point.first - x_avg); + for (const auto& packet : packets) { + double x = packet.arrival_time_ms; + double y = packet.smoothed_delay_ms; + numerator += (x - x_avg) * (y - y_avg); + denominator += (x - x_avg) * (x - x_avg); } if (denominator == 0) return absl::nullopt; return numerator / denominator; } +absl::optional ComputeSlopeCap( + const std::deque& packets, + const TrendlineEstimatorSettings& settings) { + // RTC_DCHECK(1 <= settings.beginning_packets && + // settings.beginning_packets < packets.size()); + // RTC_DCHECK(1 <= settings.end_packets && + // settings.end_packets < packets.size()); + // RTC_DCHECK(settings.beginning_packets + settings.end_packets <= + // packets.size()); + TrendlineEstimator::PacketTiming early = packets[0]; + for (size_t i = 1; i < settings.beginning_packets; ++i) { + if (packets[i].raw_delay_ms < early.raw_delay_ms) + early = packets[i]; + } + size_t late_start = packets.size() - settings.end_packets; + TrendlineEstimator::PacketTiming late = packets[late_start]; + for (size_t i = late_start + 1; i < packets.size(); ++i) { + if (packets[i].raw_delay_ms < late.raw_delay_ms) + late = packets[i]; + } + if (late.arrival_time_ms - early.arrival_time_ms < 1) { + return absl::nullopt; + } + return (late.raw_delay_ms - early.raw_delay_ms) / + (late.arrival_time_ms - early.arrival_time_ms) + + settings.cap_uncertainty; +} + constexpr double kMaxAdaptOffsetMs = 15.0; -constexpr double kOverUsingTimeThreshold = 30; +constexpr double kOverUsingTimeThreshold = 10; constexpr int kMinNumDeltas = 60; constexpr int kDeltaCounterMax = 1000; } // namespace TrendlineEstimator::TrendlineEstimator( - const WebRtcKeyValueConfig* key_value_config, NetworkStatePredictor* network_state_predictor) - : TrendlineEstimator( - key_value_config->Lookup(kBweWindowSizeInPacketsExperiment) - .find("Enabled") == 0 - ? ReadTrendlineFilterWindowSize(key_value_config) - : kDefaultTrendlineWindowSize, - kDefaultTrendlineSmoothingCoeff, - kDefaultTrendlineThresholdGain, - network_state_predictor) {} - -TrendlineEstimator::TrendlineEstimator( - size_t window_size, - double smoothing_coef, - double threshold_gain, - NetworkStatePredictor* network_state_predictor) - : window_size_(window_size), - smoothing_coef_(smoothing_coef), - threshold_gain_(threshold_gain), + : smoothing_coef_(kDefaultTrendlineSmoothingCoeff), + threshold_gain_(kDefaultTrendlineThresholdGain), num_of_deltas_(0), first_arrival_time_ms_(-1), accumulated_delay_(0), @@ -120,63 +116,75 @@ TrendlineEstimator::TrendlineEstimator( hypothesis_(BandwidthUsage::kBwNormal), hypothesis_predicted_(BandwidthUsage::kBwNormal), network_state_predictor_(network_state_predictor) { - MS_DEBUG_DEV( - "using Trendline filter for delay change estimation with window size: %zu", - window_size_); } TrendlineEstimator::~TrendlineEstimator() {} +void TrendlineEstimator::UpdateTrendline(double recv_delta_ms, + double send_delta_ms, + int64_t send_time_ms, + int64_t arrival_time_ms) { + const double delta_ms = recv_delta_ms - send_delta_ms; + ++num_of_deltas_; + num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax); + if (first_arrival_time_ms_ == -1) + first_arrival_time_ms_ = arrival_time_ms; + + // Exponential backoff filter. + accumulated_delay_ += delta_ms; + // BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms, + // accumulated_delay_); + smoothed_delay_ = smoothing_coef_ * smoothed_delay_ + + (1 - smoothing_coef_) * accumulated_delay_; + // BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms, + // smoothed_delay_); + + // Maintain packet window + delay_hist_.emplace_back( + static_cast(arrival_time_ms - first_arrival_time_ms_), + smoothed_delay_, accumulated_delay_); + if (settings_.enable_sort) { + for (size_t i = delay_hist_.size() - 1; + i > 0 && + delay_hist_[i].arrival_time_ms < delay_hist_[i - 1].arrival_time_ms; + --i) { + std::swap(delay_hist_[i], delay_hist_[i - 1]); + } + } + if (delay_hist_.size() > settings_.window_size) + delay_hist_.pop_front(); + + // Simple linear regression. + double trend = prev_trend_; + if (delay_hist_.size() == settings_.window_size) { + // Update trend_ if it is possible to fit a line to the data. The delay + // trend can be seen as an estimate of (send_rate - capacity)/capacity. + // 0 < trend < 1 -> the delay increases, queues are filling up + // trend == 0 -> the delay does not change + // trend < 0 -> the delay decreases, queues are being emptied + trend = LinearFitSlope(delay_hist_).value_or(trend); + if (settings_.enable_cap) { + absl::optional cap = ComputeSlopeCap(delay_hist_, settings_); + // We only use the cap to filter out overuse detections, not + // to detect additional underuses. + if (trend >= 0 && cap.has_value() && trend > cap.value()) { + trend = cap.value(); + } + } + } + // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend); + + Detect(trend, send_delta_ms, arrival_time_ms); +} + void TrendlineEstimator::Update(double recv_delta_ms, double send_delta_ms, int64_t send_time_ms, int64_t arrival_time_ms, bool calculated_deltas) { if (calculated_deltas) { - const double delta_ms = recv_delta_ms - send_delta_ms; - ++num_of_deltas_; - num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax); - if (first_arrival_time_ms_ == -1) - first_arrival_time_ms_ = arrival_time_ms; - - // Exponential backoff filter. - accumulated_delay_ += delta_ms; - // BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms, - // accumulated_delay_); - // smoothed_delay_ = smoothing_coef_ * smoothed_delay_ + - // (1 - smoothing_coef_) * accumulated_delay_; - // MS_NOTE: Apply WEMA to the current delta_ms. Don't consider the - // accumulated delay. Tests show it behaves more robustly upon delta peaks. - smoothed_delay_ = smoothing_coef_ * delta_ms + - (1 - smoothing_coef_) * smoothed_delay_; - // BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms, - // smoothed_delay_); - - // Simple linear regression. - delay_hist_.push_back(std::make_pair( - static_cast(arrival_time_ms - first_arrival_time_ms_), - smoothed_delay_)); - if (delay_hist_.size() > window_size_) - delay_hist_.pop_front(); - double trend = prev_trend_; - if (delay_hist_.size() == window_size_) { - // Update trend_ if it is possible to fit a line to the data. The delay - // trend can be seen as an estimate of (send_rate - capacity)/capacity. - // 0 < trend < 1 -> the delay increases, queues are filling up - // trend == 0 -> the delay does not change - // trend < 0 -> the delay decreases, queues are being emptied - trend = LinearFitSlope(delay_hist_).value_or(trend); - } - - // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend); - - MS_DEBUG_DEV("trend:%f, send_delta_ms:%f, recv_delta_ms:%f, delta_ms:%f arrival_time_ms:%" PRIi64 ", accumulated_delay_:%f, smoothed_delay_:%f", trend, send_delta_ms, recv_delta_ms, delta_ms, arrival_time_ms, accumulated_delay_, smoothed_delay_); - Detect(trend, send_delta_ms, arrival_time_ms); - } - else { - MS_DEBUG_DEV("no calculated deltas"); + UpdateTrendline(recv_delta_ms, send_delta_ms, send_time_ms, arrival_time_ms); } - if (network_state_predictor_) { hypothesis_predicted_ = network_state_predictor_->Update( send_time_ms, arrival_time_ms, hypothesis_); @@ -212,6 +220,7 @@ void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) { if (trend >= prev_trend_) { time_over_using_ = 0; overuse_counter_ = 0; + hypothesis_ = BandwidthUsage::kBwOverusing; MS_DEBUG_DEV("hypothesis_: BandwidthUsage::kBwOverusing"); #if MS_LOG_DEV_LEVEL == 3 @@ -219,8 +228,6 @@ void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) { MS_DEBUG_DEV("arrival_time_ms - first_arrival_time_ms_:%f, smoothed_delay_:%f", kv.first, kv.second); } #endif - - hypothesis_ = BandwidthUsage::kBwOverusing; } } } else if (modified_trend < -threshold_) { @@ -231,8 +238,8 @@ void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) { } else { time_over_using_ = -1; overuse_counter_ = 0; - MS_DEBUG_DEV("---- BandwidthUsage::kBwNormal ---"); hypothesis_ = BandwidthUsage::kBwNormal; + MS_DEBUG_DEV("---- BandwidthUsage::kBwNormal ---"); } prev_trend_ = trend; UpdateThreshold(modified_trend, now_ms); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index f4c23d706d..7eeb101d02 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -10,37 +10,48 @@ #ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_TRENDLINE_ESTIMATOR_H_ #define MODULES_CONGESTION_CONTROLLER_GOOG_CC_TRENDLINE_ESTIMATOR_H_ +#include +#include + +#include +#include +#include + #include "api/network_state_predictor.h" #include "api/transport/webrtc_key_value_config.h" #include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "rtc_base/constructor_magic.h" -#include -#include -#include -#include - namespace webrtc { +struct TrendlineEstimatorSettings { + static constexpr unsigned kDefaultTrendlineWindowSize = 20; + + // Sort the packets in the window. Should be redundant, + // but then almost no cost. + bool enable_sort = false; + + // Cap the trendline slope based on the minimum delay seen + // in the beginning_packets and end_packets respectively. + bool enable_cap = false; + unsigned beginning_packets = 7; + unsigned end_packets = 7; + double cap_uncertainty = 0.0; + + // Size (in packets) of the window. + unsigned window_size = kDefaultTrendlineWindowSize; +}; + class TrendlineEstimator : public DelayIncreaseDetectorInterface { public: - TrendlineEstimator(const WebRtcKeyValueConfig* key_value_config, - NetworkStatePredictor* network_state_predictor); - // |window_size| is the number of points required to compute a trend line. - // |smoothing_coef| controls how much we smooth out the delay before fitting - // the trend line. |threshold_gain| is used to scale the trendline slope for - // comparison to the old threshold. Once the old estimator has been removed - // (or the thresholds been merged into the estimators), we can just set the - // threshold instead of setting a gain.|network_state_predictor| is used to - // bettter predict network state. - TrendlineEstimator(size_t window_size, - double smoothing_coef, - double threshold_gain, - NetworkStatePredictor* network_state_predictor); + TrendlineEstimator(NetworkStatePredictor* network_state_predictor); ~TrendlineEstimator() override; + TrendlineEstimator(const TrendlineEstimator&) = delete; + TrendlineEstimator& operator=(const TrendlineEstimator&) = delete; + // Update the estimator with a new sample. The deltas should represent deltas // between timestamp groups as defined by the InterArrival class. void Update(double recv_delta_ms, @@ -49,21 +60,33 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { int64_t arrival_time_ms, bool calculated_deltas) override; + void UpdateTrendline(double recv_delta_ms, + double send_delta_ms, + int64_t send_time_ms, + int64_t arrival_time_ms); + BandwidthUsage State() const override; - protected: - // Used in unit tests. - double modified_trend() const { return prev_trend_ * threshold_gain_; } + struct PacketTiming { + PacketTiming(double arrival_time_ms, + double smoothed_delay_ms, + double raw_delay_ms) + : arrival_time_ms(arrival_time_ms), + smoothed_delay_ms(smoothed_delay_ms), + raw_delay_ms(raw_delay_ms) {} + double arrival_time_ms; + double smoothed_delay_ms; + double raw_delay_ms; + }; private: friend class GoogCcStatePrinter; - void Detect(double trend, double ts_delta, int64_t now_ms); void UpdateThreshold(double modified_offset, int64_t now_ms); // Parameters. - const size_t window_size_; + TrendlineEstimatorSettings settings_; const double smoothing_coef_; const double threshold_gain_; // Used by the existing threshold. @@ -74,7 +97,7 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { double accumulated_delay_; double smoothed_delay_; // Linear least squares regression. - std::deque> delay_hist_; + std::deque delay_hist_; const double k_up_; const double k_down_; @@ -88,8 +111,6 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { BandwidthUsage hypothesis_; BandwidthUsage hypothesis_predicted_; NetworkStatePredictor* network_state_predictor_; - - RTC_DISALLOW_COPY_AND_ASSIGN(TrendlineEstimator); }; } // namespace webrtc From 640fa3453bca34424b083614ee1107b1a8be7ae5 Mon Sep 17 00:00:00 2001 From: Vittorio Palmisano Date: Fri, 14 Apr 2023 10:29:46 +0200 Subject: [PATCH 085/525] Fix bandwidth probation dead state (#1031) * Fix bandwidth probation dead state * Fix comment * Refactor timeout setting --- .../goog_cc/alr_detector.cc | 21 ++++++++++++++++++- .../goog_cc/alr_detector.h | 3 +++ .../goog_cc/goog_cc_network_control.cc | 2 +- .../rtc_base/experiments/alr_experiment.cc | 13 +++++++----- .../rtc_base/experiments/alr_experiment.h | 1 + 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc index 95a000d346..6af0a8c924 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc @@ -62,6 +62,11 @@ AlrDetector::AlrDetector( experiment_settings ? experiment_settings->alr_stop_budget_level_percent / 100.0 : kDefaultStopBudgetLevelRatio), + alr_timeout_( + "alr_timeout", + experiment_settings + ? experiment_settings->alr_timeout + : kDefaultAlrTimeout), alr_budget_(0, true) { ParseFieldTrial({&bandwidth_usage_ratio_, &start_budget_level_ratio_, &stop_budget_level_ratio_}, @@ -73,7 +78,7 @@ AlrDetector::~AlrDetector() {} void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { if (!last_send_time_ms_.has_value()) { last_send_time_ms_ = send_time_ms; - // Since the duration for sending the bytes is unknwon, return without + // Since the duration for sending the bytes is unknown, return without // updating alr state. return; } @@ -109,4 +114,18 @@ absl::optional AlrDetector::GetApplicationLimitedRegionStartTime() return alr_started_time_ms_; } +absl::optional AlrDetector::GetApplicationLimitedRegionStartTime( + int64_t at_time_ms) { + if (!alr_started_time_ms_ && *last_send_time_ms_) { + int64_t delta_time_ms = at_time_ms - *last_send_time_ms_; + // If ALR is stopped and we haven't sent any packets for a while, force start. + if (delta_time_ms > alr_timeout_) { + MS_WARN_TAG(bwe, "large delta_time_ms: %ld, forcing alr state change", + delta_time_ms); + alr_started_time_ms_.emplace(at_time_ms); + } + } + return alr_started_time_ms_; +} + } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h index e1fbb74525..e1cf8de92b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h @@ -43,6 +43,7 @@ class AlrDetector { // Returns time in milliseconds when the current application-limited region // started or empty result if the sender is currently not application-limited. absl::optional GetApplicationLimitedRegionStartTime() const; + absl::optional GetApplicationLimitedRegionStartTime(int64_t at_time_ms); void UpdateBudgetWithElapsedTime(int64_t delta_time_ms); void UpdateBudgetWithBytesSent(size_t bytes_sent); @@ -56,6 +57,7 @@ class AlrDetector { static constexpr double kDefaultBandwidthUsageRatio = 0.65; static constexpr double kDefaultStartBudgetLevelRatio = 0.80; static constexpr double kDefaultStopBudgetLevelRatio = 0.50; + static constexpr int kDefaultAlrTimeout = 3000; AlrDetector(const WebRtcKeyValueConfig* key_value_config, absl::optional experiment_settings); @@ -64,6 +66,7 @@ class AlrDetector { FieldTrialParameter bandwidth_usage_ratio_; FieldTrialParameter start_budget_level_ratio_; FieldTrialParameter stop_budget_level_ratio_; + FieldTrialParameter alr_timeout_; absl::optional last_send_time_ms_; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index aced2db317..df64112a41 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -195,7 +195,7 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( } bandwidth_estimation_->UpdateEstimate(msg.at_time); absl::optional start_time_ms = - alr_detector_->GetApplicationLimitedRegionStartTime(); + alr_detector_->GetApplicationLimitedRegionStartTime(msg.at_time.ms()); probe_controller_->SetAlrStartTimeMs(start_time_ms); auto probes = probe_controller_->Process(msg.at_time.ms()); diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/alr_experiment.cc b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/alr_experiment.cc index 43f36889a8..dd5b5c5957 100644 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/alr_experiment.cc +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/alr_experiment.cc @@ -26,7 +26,7 @@ const char AlrExperimentSettings::kScreenshareProbingBweExperimentName[] = "WebRTC-ProbingScreenshareBwe"; const char AlrExperimentSettings::kStrictPacingAndProbingExperimentName[] = "WebRTC-StrictPacingAndProbing"; -const char kDefaultProbingScreenshareBweSettings[] = "1.0,2875,80,40,-60,3"; +const char kDefaultProbingScreenshareBweSettings[] = "1.0,2875,80,40,-60,3,3000"; bool AlrExperimentSettings::MaxOneFieldTrialEnabled() { return AlrExperimentSettings::MaxOneFieldTrialEnabled( @@ -71,12 +71,13 @@ AlrExperimentSettings::CreateFromFieldTrial( } AlrExperimentSettings settings; - if (sscanf(group_name.c_str(), "%f,%" PRId64 ",%d,%d,%d,%d", + if (sscanf(group_name.c_str(), "%f,%" PRId64 ",%d,%d,%d,%d,%d", &settings.pacing_factor, &settings.max_paced_queue_time, &settings.alr_bandwidth_usage_percent, &settings.alr_start_budget_level_percent, &settings.alr_stop_budget_level_percent, - &settings.group_id) == 6) { + &settings.group_id, + &settings.alr_timeout) == 7) { ret.emplace(settings); MS_DEBUG_TAG(bwe, "Using ALR experiment settings: " "pacing factor: %f" @@ -84,13 +85,15 @@ AlrExperimentSettings::CreateFromFieldTrial( ", ALR bandwidth usage percent: %d" ", ALR start budget level percent: %d" ", ALR end budget level percent: %d" - ", ALR experiment group ID: %d", + ", ALR experiment group ID: %d" + ", ALR timeout: %d", settings.pacing_factor, settings.max_paced_queue_time, settings.alr_bandwidth_usage_percent, settings.alr_start_budget_level_percent, settings.alr_stop_budget_level_percent, - settings.group_id); + settings.group_id, + settings.alr_timeout); } else { MS_DEBUG_TAG(bwe, "Failed to parse ALR experiment: %s", experiment_name); } diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/alr_experiment.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/alr_experiment.h index 4d4c38337b..64ab57b85f 100644 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/alr_experiment.h +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/alr_experiment.h @@ -24,6 +24,7 @@ struct AlrExperimentSettings { int alr_bandwidth_usage_percent; int alr_start_budget_level_percent; int alr_stop_budget_level_percent; + int alr_timeout; // Will be sent to the receive side for stats slicing. // Can be 0..6, because it's sent as a 3 bits value and there's also // reserved value to indicate absence of experiment. From de8d8ce4c6ed48b0651a07157a316048425628be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Fri, 14 Apr 2023 10:33:45 +0200 Subject: [PATCH 086/525] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e02769781a..734acc910b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### NEXT * `SeqManager`: Properly remove old dropped entries ([PR #1054](https://github.com/versatica/mediasoup/pull/1054)). +* libwebrtc: Upgrade trendline estimator to improve low bandwidth conditions ([PR #1055](https://github.com/versatica/mediasoup/pull/1055) by @ggarber). +* libwebrtc: Fix bandwidth probation dead state ([PR #1031](https://github.com/versatica/mediasoup/pull/1031) by @vpalmisano). ### 3.11.21 From 05d107f0f0f94155d6204c6155b60aefe63e05cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 14 Apr 2023 11:55:50 +0200 Subject: [PATCH 087/525] Only perform RTP inactivity checks on simulcast streams (#1061) --- CHANGELOG.md | 1 + worker/include/RTC/RtpStreamRecv.hpp | 4 +++- worker/src/RTC/Producer.cpp | 5 ++++- worker/src/RTC/RtpStreamRecv.cpp | 25 +++++++++++++---------- worker/test/src/RTC/TestRtpStreamRecv.cpp | 7 ++++--- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 734acc910b..36894891ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT +* `RtpStreamRecv`: Only perform RTP inactivity check on simulcast streams ([PR #1061](https://github.com/versatica/mediasoup/pull/1061)). * `SeqManager`: Properly remove old dropped entries ([PR #1054](https://github.com/versatica/mediasoup/pull/1054)). * libwebrtc: Upgrade trendline estimator to improve low bandwidth conditions ([PR #1055](https://github.com/versatica/mediasoup/pull/1055) by @ggarber). * libwebrtc: Fix bandwidth probation dead state ([PR #1031](https://github.com/versatica/mediasoup/pull/1031) by @vpalmisano). diff --git a/worker/include/RTC/RtpStreamRecv.hpp b/worker/include/RTC/RtpStreamRecv.hpp index 4457e38205..afe7c0c83c 100644 --- a/worker/include/RTC/RtpStreamRecv.hpp +++ b/worker/include/RTC/RtpStreamRecv.hpp @@ -45,7 +45,8 @@ namespace RTC RtpStreamRecv( RTC::RtpStreamRecv::Listener* listener, RTC::RtpStream::Params& params, - unsigned int sendNackDelayMs); + unsigned int sendNackDelayMs, + bool useRtpInactivityCheck); ~RtpStreamRecv(); void FillJsonStats(json& jsonObject) override; @@ -96,6 +97,7 @@ namespace RTC private: // Passed by argument. unsigned int sendNackDelayMs{ 0u }; + bool useRtpInactivityCheck{ false }; // Others. // Packets expected at last interval. uint32_t expectedPrior{ 0u }; diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index 768c2b6943..1c0e674a8d 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -1223,8 +1223,11 @@ namespace RTC } } + // Only perform RTP inactivity check on simulcast. + auto useRtpInactivityCheck = this->type == RtpParameters::Type::SIMULCAST; + // Create a RtpStreamRecv for receiving a media stream. - auto* rtpStream = new RTC::RtpStreamRecv(this, params, SendNackDelay); + auto* rtpStream = new RTC::RtpStreamRecv(this, params, SendNackDelay, useRtpInactivityCheck); // Insert into the maps. this->mapSsrcRtpStream[ssrc] = rtpStream; diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index 240e260e69..abee7f293b 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -189,8 +189,12 @@ namespace RTC /* Instance methods. */ RtpStreamRecv::RtpStreamRecv( - RTC::RtpStreamRecv::Listener* listener, RTC::RtpStream::Params& params, unsigned int sendNackDelayMs) + RTC::RtpStreamRecv::Listener* listener, + RTC::RtpStream::Params& params, + unsigned int sendNackDelayMs, + bool useRtpInactivityCheck) : RTC::RtpStream::RtpStream(listener, params, 10), sendNackDelayMs(sendNackDelayMs), + useRtpInactivityCheck(useRtpInactivityCheck), transmissionCounter( params.spatialLayers, params.temporalLayers, this->params.useDtx ? 6000 : 2500) { @@ -201,18 +205,16 @@ namespace RTC this->nackGenerator.reset(new RTC::NackGenerator(this, this->sendNackDelayMs)); } - // Run the RTP inactivity periodic timer (use a different timeout if DTX is - // enabled). - this->inactivityCheckPeriodicTimer = new Timer(this); - this->inactive = false; + this->inactive = false; - if (!this->params.useDtx) + if (this->useRtpInactivityCheck) { - this->inactivityCheckPeriodicTimer->Start(InactivityCheckInterval); - } - else - { - this->inactivityCheckPeriodicTimer->Start(InactivityCheckIntervalWithDtx); + // Run the RTP inactivity periodic timer (use a different timeout if DTX is + // enabled). + this->inactivityCheckPeriodicTimer = new Timer(this); + + this->inactivityCheckPeriodicTimer->Start( + this->params.useDtx ? InactivityCheckIntervalWithDtx : InactivityCheckInterval); } } @@ -222,6 +224,7 @@ namespace RTC // Close the RTP inactivity check periodic timer. delete this->inactivityCheckPeriodicTimer; + this->inactivityCheckPeriodicTimer = nullptr; } void RtpStreamRecv::FillJsonStats(json& jsonObject) diff --git a/worker/test/src/RTC/TestRtpStreamRecv.cpp b/worker/test/src/RTC/TestRtpStreamRecv.cpp index 417759523f..3f8399df60 100644 --- a/worker/test/src/RTC/TestRtpStreamRecv.cpp +++ b/worker/test/src/RTC/TestRtpStreamRecv.cpp @@ -11,6 +11,7 @@ using namespace RTC; // 17: 16 bit mask + the initial sequence number. static constexpr size_t MaxRequestedPackets{ 17 }; static constexpr unsigned int SendNackDelay{ 0u }; // In ms. +static const bool UseRtpInactivityCheck{ false }; SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") { @@ -141,7 +142,7 @@ SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") SECTION("NACK one packet") { RtpStreamRecvListener listener; - RtpStreamRecv rtpStream(&listener, params, SendNackDelay); + RtpStreamRecv rtpStream(&listener, params, SendNackDelay, UseRtpInactivityCheck); packet->SetSequenceNumber(1); rtpStream.ReceivePacket(packet); @@ -170,7 +171,7 @@ SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") SECTION("wrapping sequence numbers") { RtpStreamRecvListener listener; - RtpStreamRecv rtpStream(&listener, params, SendNackDelay); + RtpStreamRecv rtpStream(&listener, params, SendNackDelay, UseRtpInactivityCheck); packet->SetSequenceNumber(0xfffe); rtpStream.ReceivePacket(packet); @@ -190,7 +191,7 @@ SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") SECTION("require key frame") { RtpStreamRecvListener listener; - RtpStreamRecv rtpStream(&listener, params, SendNackDelay); + RtpStreamRecv rtpStream(&listener, params, SendNackDelay, UseRtpInactivityCheck); packet->SetSequenceNumber(1); rtpStream.ReceivePacket(packet); From 6c9a9424352d5504f9b1f7acbd077f6be9368d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 14 Apr 2023 11:57:52 +0200 Subject: [PATCH 088/525] 3.11.22 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36894891ba..fa4af0cffd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.11.22 * `RtpStreamRecv`: Only perform RTP inactivity check on simulcast streams ([PR #1061](https://github.com/versatica/mediasoup/pull/1061)). * `SeqManager`: Properly remove old dropped entries ([PR #1054](https://github.com/versatica/mediasoup/pull/1054)). diff --git a/package-lock.json b/package-lock.json index 4e09d10124..1f14995717 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.21", + "version": "3.11.22", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.21", + "version": "3.11.22", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 16e5543a2f..25ae180fd4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.21", + "version": "3.11.22", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 361123ef9b84258c13cb22f1e69e9e59b34147a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 17 Apr 2023 18:10:02 +0200 Subject: [PATCH 089/525] mediasoup-node: Fix appData for Transport and RtpObserver parent classes (#1066) ### Before This fails at TypeScript level: ```ts let transport: mediasoupTypes.Transport<{ foo: number }>; let transport: mediasoupTypes.RtpObserver<{ foo: number }>; ``` Now it doesn't. --- node/src/ActiveSpeakerObserver.ts | 2 +- node/src/AudioLevelObserver.ts | 2 +- node/src/DirectTransport.ts | 2 +- node/src/PipeTransport.ts | 2 +- node/src/PlainTransport.ts | 2 +- node/src/RtpObserver.ts | 4 ++-- node/src/Transport.ts | 6 +++--- node/src/WebRtcTransport.ts | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index a9af22c569..cee690b240 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -43,7 +43,7 @@ type RtpObserverObserverConstructorOptions = const logger = new Logger('ActiveSpeakerObserver'); export class ActiveSpeakerObserver - extends RtpObserver + extends RtpObserver { /** * @private diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index 597e3ed882..03cd7789d5 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -65,7 +65,7 @@ type AudioLevelObserverConstructorOptions = const logger = new Logger('AudioLevelObserver'); export class AudioLevelObserver - extends RtpObserver + extends RtpObserver { /** * @private diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index f4bc0be37a..3775f02eb5 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -73,7 +73,7 @@ export type DirectTransportData = const logger = new Logger('DirectTransport'); export class DirectTransport - extends Transport + extends Transport { // DirectTransport data. readonly #data: DirectTransportData; diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index f312a79ec6..90185d46a0 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -140,7 +140,7 @@ export type PipeTransportData = const logger = new Logger('PipeTransport'); export class PipeTransport - extends Transport + extends Transport { // PipeTransport data. readonly #data: PipeTransportData; diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index 23c4e266c0..e20fe1500d 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -144,7 +144,7 @@ export type PlainTransportData = const logger = new Logger('PlainTransport'); export class PlainTransport - extends Transport + extends Transport { // PlainTransport data. readonly #data: PlainTransportData; diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 3821d728d4..0eedb19626 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -47,8 +47,8 @@ export type RtpObserverAddRemoveProducerOptions = }; export class RtpObserver - + extends EnhancedEventEmitter { // Internal data. diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 5d31e794ac..ddecd0d02b 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -137,9 +137,9 @@ type TransportData = const logger = new Logger('Transport'); export class Transport - + extends EnhancedEventEmitter { // Internal data. diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index e297a5d4a1..164af8880d 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -211,7 +211,7 @@ export type WebRtcTransportData = const logger = new Logger('WebRtcTransport'); export class WebRtcTransport - extends Transport + extends Transport { // WebRtcTransport data. readonly #data: WebRtcTransportData; From c7adc04a47ba8c2b219bb88900dfd203047b1444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 17 Apr 2023 18:11:55 +0200 Subject: [PATCH 090/525] Update NPM deps --- package-lock.json | 208 +++++++++++++++++++++++----------------------- package.json | 8 +- 2 files changed, 108 insertions(+), 108 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f14995717..170fab9928 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,9 +20,9 @@ "@types/jest": "^29.5.0", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.57.1", - "@typescript-eslint/parser": "^5.57.1", - "eslint": "^8.37.0", + "@typescript-eslint/eslint-plugin": "^5.58.0", + "@typescript-eslint/parser": "^5.58.0", + "eslint": "^8.38.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", "open-cli": "^7.2.0", @@ -30,7 +30,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.1.0", "tsc-watch": "^6.0.0", - "typescript": "^5.0.3" + "typescript": "^5.0.4" }, "engines": { "node": ">=16" @@ -690,9 +690,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", - "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", + "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1392,15 +1392,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz", - "integrity": "sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz", + "integrity": "sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.57.1", - "@typescript-eslint/type-utils": "5.57.1", - "@typescript-eslint/utils": "5.57.1", + "@typescript-eslint/scope-manager": "5.58.0", + "@typescript-eslint/type-utils": "5.58.0", + "@typescript-eslint/utils": "5.58.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1426,14 +1426,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.1.tgz", - "integrity": "sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.58.0.tgz", + "integrity": "sha512-ixaM3gRtlfrKzP8N6lRhBbjTow1t6ztfBvQNGuRM8qH1bjFFXIJ35XY+FC0RRBKn3C6cT+7VW1y8tNm7DwPHDQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.57.1", - "@typescript-eslint/types": "5.57.1", - "@typescript-eslint/typescript-estree": "5.57.1", + "@typescript-eslint/scope-manager": "5.58.0", + "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/typescript-estree": "5.58.0", "debug": "^4.3.4" }, "engines": { @@ -1453,13 +1453,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.1.tgz", - "integrity": "sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.58.0.tgz", + "integrity": "sha512-b+w8ypN5CFvrXWQb9Ow9T4/6LC2MikNf1viLkYTiTbkQl46CnR69w7lajz1icW0TBsYmlpg+mRzFJ4LEJ8X9NA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.57.1", - "@typescript-eslint/visitor-keys": "5.57.1" + "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/visitor-keys": "5.58.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1470,13 +1470,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.1.tgz", - "integrity": "sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz", + "integrity": "sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.57.1", - "@typescript-eslint/utils": "5.57.1", + "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/utils": "5.58.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1497,9 +1497,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.1.tgz", - "integrity": "sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.58.0.tgz", + "integrity": "sha512-JYV4eITHPzVQMnHZcYJXl2ZloC7thuUHrcUmxtzvItyKPvQ50kb9QXBkgNAt90OYMqwaodQh2kHutWZl1fc+1g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1510,13 +1510,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.1.tgz", - "integrity": "sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.58.0.tgz", + "integrity": "sha512-cRACvGTodA+UxnYM2uwA2KCwRL7VAzo45syNysqlMyNyjw0Z35Icc9ihPJZjIYuA5bXJYiJ2YGUB59BqlOZT1Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.57.1", - "@typescript-eslint/visitor-keys": "5.57.1", + "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/visitor-keys": "5.58.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1537,17 +1537,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.1.tgz", - "integrity": "sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.58.0.tgz", + "integrity": "sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.57.1", - "@typescript-eslint/types": "5.57.1", - "@typescript-eslint/typescript-estree": "5.57.1", + "@typescript-eslint/scope-manager": "5.58.0", + "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/typescript-estree": "5.58.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1563,12 +1563,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz", - "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.58.0.tgz", + "integrity": "sha512-/fBraTlPj0jwdyTwLyrRTxv/3lnU2H96pNTVM6z3esTWLtA5MZ9ghSMJ7Rb+TtUAdtEw9EyJzJ0EydIMKxQ9gA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/types": "5.58.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2423,15 +2423,15 @@ } }, "node_modules/eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", + "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.37.0", + "@eslint/js": "8.38.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -5808,9 +5808,9 @@ } }, "node_modules/typescript": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", - "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -6589,9 +6589,9 @@ } }, "@eslint/js": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", - "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", + "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", "dev": true }, "@humanwhocodes/config-array": { @@ -7177,15 +7177,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz", - "integrity": "sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz", + "integrity": "sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.57.1", - "@typescript-eslint/type-utils": "5.57.1", - "@typescript-eslint/utils": "5.57.1", + "@typescript-eslint/scope-manager": "5.58.0", + "@typescript-eslint/type-utils": "5.58.0", + "@typescript-eslint/utils": "5.58.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7195,53 +7195,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.1.tgz", - "integrity": "sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.58.0.tgz", + "integrity": "sha512-ixaM3gRtlfrKzP8N6lRhBbjTow1t6ztfBvQNGuRM8qH1bjFFXIJ35XY+FC0RRBKn3C6cT+7VW1y8tNm7DwPHDQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.57.1", - "@typescript-eslint/types": "5.57.1", - "@typescript-eslint/typescript-estree": "5.57.1", + "@typescript-eslint/scope-manager": "5.58.0", + "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/typescript-estree": "5.58.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.1.tgz", - "integrity": "sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.58.0.tgz", + "integrity": "sha512-b+w8ypN5CFvrXWQb9Ow9T4/6LC2MikNf1viLkYTiTbkQl46CnR69w7lajz1icW0TBsYmlpg+mRzFJ4LEJ8X9NA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.57.1", - "@typescript-eslint/visitor-keys": "5.57.1" + "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/visitor-keys": "5.58.0" } }, "@typescript-eslint/type-utils": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.1.tgz", - "integrity": "sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz", + "integrity": "sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.57.1", - "@typescript-eslint/utils": "5.57.1", + "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/utils": "5.58.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.1.tgz", - "integrity": "sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.58.0.tgz", + "integrity": "sha512-JYV4eITHPzVQMnHZcYJXl2ZloC7thuUHrcUmxtzvItyKPvQ50kb9QXBkgNAt90OYMqwaodQh2kHutWZl1fc+1g==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.1.tgz", - "integrity": "sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.58.0.tgz", + "integrity": "sha512-cRACvGTodA+UxnYM2uwA2KCwRL7VAzo45syNysqlMyNyjw0Z35Icc9ihPJZjIYuA5bXJYiJ2YGUB59BqlOZT1Q==", "dev": true, "requires": { - "@typescript-eslint/types": "5.57.1", - "@typescript-eslint/visitor-keys": "5.57.1", + "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/visitor-keys": "5.58.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7250,28 +7250,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.1.tgz", - "integrity": "sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.58.0.tgz", + "integrity": "sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.57.1", - "@typescript-eslint/types": "5.57.1", - "@typescript-eslint/typescript-estree": "5.57.1", + "@typescript-eslint/scope-manager": "5.58.0", + "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/typescript-estree": "5.58.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz", - "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==", + "version": "5.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.58.0.tgz", + "integrity": "sha512-/fBraTlPj0jwdyTwLyrRTxv/3lnU2H96pNTVM6z3esTWLtA5MZ9ghSMJ7Rb+TtUAdtEw9EyJzJ0EydIMKxQ9gA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/types": "5.58.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -7879,15 +7879,15 @@ "dev": true }, "eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", + "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.37.0", + "@eslint/js": "8.38.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -10295,9 +10295,9 @@ "dev": true }, "typescript": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", - "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index 25ae180fd4..c2af0e1231 100644 --- a/package.json +++ b/package.json @@ -95,9 +95,9 @@ "@types/jest": "^29.5.0", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.57.1", - "@typescript-eslint/parser": "^5.57.1", - "eslint": "^8.37.0", + "@typescript-eslint/eslint-plugin": "^5.58.0", + "@typescript-eslint/parser": "^5.58.0", + "eslint": "^8.38.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", "open-cli": "^7.2.0", @@ -105,6 +105,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.1.0", "tsc-watch": "^6.0.0", - "typescript": "^5.0.3" + "typescript": "^5.0.4" } } From 28e51745cfecde2b8ded2b99c0c2086a3596ee12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 17 Apr 2023 18:13:33 +0200 Subject: [PATCH 091/525] 3.11.23 --- CHANGELOG.md | 5 +++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa4af0cffd..cc81390a9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.11.23 + +* Node: Fix `appData` for `Transport` and `RtpObserver` parent classes ([PR #1066](https://github.com/versatica/mediasoup/pull/1066)). + + ### 3.11.22 * `RtpStreamRecv`: Only perform RTP inactivity check on simulcast streams ([PR #1061](https://github.com/versatica/mediasoup/pull/1061)). diff --git a/package-lock.json b/package-lock.json index 170fab9928..3463dc7609 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.22", + "version": "3.11.23", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.22", + "version": "3.11.23", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index c2af0e1231..81cfb144a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.22", + "version": "3.11.23", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 245ce8b2d72d661fa4660e7f8a5e6f5f69bce375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 18 Apr 2023 20:24:57 +0200 Subject: [PATCH 092/525] Update NPM dev deps --- package-lock.json | 164 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 84 insertions(+), 84 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3463dc7609..95f07cf150 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,8 @@ "@types/jest": "^29.5.0", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.58.0", - "@typescript-eslint/parser": "^5.58.0", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", "eslint": "^8.38.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", @@ -1392,15 +1392,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz", - "integrity": "sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.0.tgz", + "integrity": "sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/type-utils": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/type-utils": "5.59.0", + "@typescript-eslint/utils": "5.59.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1426,14 +1426,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.58.0.tgz", - "integrity": "sha512-ixaM3gRtlfrKzP8N6lRhBbjTow1t6ztfBvQNGuRM8qH1bjFFXIJ35XY+FC0RRBKn3C6cT+7VW1y8tNm7DwPHDQ==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", + "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", "debug": "^4.3.4" }, "engines": { @@ -1453,13 +1453,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.58.0.tgz", - "integrity": "sha512-b+w8ypN5CFvrXWQb9Ow9T4/6LC2MikNf1viLkYTiTbkQl46CnR69w7lajz1icW0TBsYmlpg+mRzFJ4LEJ8X9NA==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", + "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/visitor-keys": "5.58.0" + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1470,13 +1470,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz", - "integrity": "sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.0.tgz", + "integrity": "sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/utils": "5.59.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1497,9 +1497,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.58.0.tgz", - "integrity": "sha512-JYV4eITHPzVQMnHZcYJXl2ZloC7thuUHrcUmxtzvItyKPvQ50kb9QXBkgNAt90OYMqwaodQh2kHutWZl1fc+1g==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1510,13 +1510,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.58.0.tgz", - "integrity": "sha512-cRACvGTodA+UxnYM2uwA2KCwRL7VAzo45syNysqlMyNyjw0Z35Icc9ihPJZjIYuA5bXJYiJ2YGUB59BqlOZT1Q==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", + "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/visitor-keys": "5.58.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1537,17 +1537,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.58.0.tgz", - "integrity": "sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", + "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1563,12 +1563,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.58.0.tgz", - "integrity": "sha512-/fBraTlPj0jwdyTwLyrRTxv/3lnU2H96pNTVM6z3esTWLtA5MZ9ghSMJ7Rb+TtUAdtEw9EyJzJ0EydIMKxQ9gA==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/types": "5.59.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -7177,15 +7177,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz", - "integrity": "sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.0.tgz", + "integrity": "sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/type-utils": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/type-utils": "5.59.0", + "@typescript-eslint/utils": "5.59.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7195,53 +7195,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.58.0.tgz", - "integrity": "sha512-ixaM3gRtlfrKzP8N6lRhBbjTow1t6ztfBvQNGuRM8qH1bjFFXIJ35XY+FC0RRBKn3C6cT+7VW1y8tNm7DwPHDQ==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", + "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.58.0.tgz", - "integrity": "sha512-b+w8ypN5CFvrXWQb9Ow9T4/6LC2MikNf1viLkYTiTbkQl46CnR69w7lajz1icW0TBsYmlpg+mRzFJ4LEJ8X9NA==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", + "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/visitor-keys": "5.58.0" + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0" } }, "@typescript-eslint/type-utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz", - "integrity": "sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.0.tgz", + "integrity": "sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/utils": "5.59.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.58.0.tgz", - "integrity": "sha512-JYV4eITHPzVQMnHZcYJXl2ZloC7thuUHrcUmxtzvItyKPvQ50kb9QXBkgNAt90OYMqwaodQh2kHutWZl1fc+1g==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.58.0.tgz", - "integrity": "sha512-cRACvGTodA+UxnYM2uwA2KCwRL7VAzo45syNysqlMyNyjw0Z35Icc9ihPJZjIYuA5bXJYiJ2YGUB59BqlOZT1Q==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", + "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/visitor-keys": "5.58.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7250,28 +7250,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.58.0.tgz", - "integrity": "sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", + "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.58.0.tgz", - "integrity": "sha512-/fBraTlPj0jwdyTwLyrRTxv/3lnU2H96pNTVM6z3esTWLtA5MZ9ghSMJ7Rb+TtUAdtEw9EyJzJ0EydIMKxQ9gA==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/types": "5.59.0", "eslint-visitor-keys": "^3.3.0" } }, diff --git a/package.json b/package.json index 81cfb144a2..8c6ef08d86 100644 --- a/package.json +++ b/package.json @@ -95,8 +95,8 @@ "@types/jest": "^29.5.0", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.58.0", - "@typescript-eslint/parser": "^5.58.0", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", "eslint": "^8.38.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", From d146ee5b45bbf5298d746fccc23091b79d5a53d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 19 Apr 2023 00:50:19 +0200 Subject: [PATCH 093/525] RtpRetransmissionBuffer.cpp: fix dev debug --- worker/src/RTC/RtpRetransmissionBuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/RtpRetransmissionBuffer.cpp b/worker/src/RTC/RtpRetransmissionBuffer.cpp index 2ddbc2a028..78e57d0c77 100644 --- a/worker/src/RTC/RtpRetransmissionBuffer.cpp +++ b/worker/src/RTC/RtpRetransmissionBuffer.cpp @@ -489,7 +489,7 @@ namespace RTC if (numItemsRemoved) { - MS_DEBUG_DEV("removed 1 blank slot from the front"); + MS_DEBUG_DEV("removed %zu blank slots from the front", numItemsRemoved); } } From df26c9edca655652b0605f3064f0437892e33612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Thu, 20 Apr 2023 10:09:48 +0200 Subject: [PATCH 094/525] SeqManager: performance, invert std::distance range (#1068) * SeqManager: performance, invert std::distance range Fixes #1067. There are way more dropped elements in the range [begin(), input] than [input, end()] and std::distance complexity is linear. * SeqManager: performance, explicitly insert the dropped input at the end Which is more performant as std::set does not need to calculate its position. * Update CHANGELOG --- CHANGELOG.md | 5 +++++ worker/src/RTC/SeqManager.cpp | 15 ++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc81390a9e..3df51b5451 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.11.24 + +* `SeqManager`: Fix performance regression ([PR #1068](https://github.com/versatica/mediasoup/pull/1068), thanks to @vpalmisano for properly reporting). + + ### 3.11.23 * Node: Fix `appData` for `Transport` and `RtpObserver` parent classes ([PR #1066](https://github.com/versatica/mediasoup/pull/1066)). diff --git a/worker/src/RTC/SeqManager.cpp b/worker/src/RTC/SeqManager.cpp index 27ca6efba1..35ebc2db27 100644 --- a/worker/src/RTC/SeqManager.cpp +++ b/worker/src/RTC/SeqManager.cpp @@ -59,7 +59,10 @@ namespace RTC if (SeqManager::IsSeqHigherThan(input, this->maxInput)) { this->maxInput = input; - this->dropped.insert(input); + // Insert input in the last position. + // Explicitly indicate insert() to add the input at the end, which is + // more performant. + this->dropped.insert(this->dropped.end(), input); ClearDropped(); } @@ -104,15 +107,13 @@ namespace RTC // There are dropped inputs, calculate 'base' for this input. else { + auto droppedCount = this->dropped.size(); + // Get the first dropped input which is higher than or equal 'input'. auto it = this->dropped.lower_bound(input); - // There are dropped inputs lower than 'input'. - if (it != this->dropped.begin()) - { - auto count = std::distance(this->dropped.begin(), it); - base = (this->base - count) & MaxValue; - } + droppedCount -= std::distance(it, this->dropped.end()); + base = (this->base - droppedCount) & MaxValue; } done: From c999912764e50de2f1fe78136c32ac850355bb02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Thu, 20 Apr 2023 10:12:01 +0200 Subject: [PATCH 095/525] 3.11.24 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 95f07cf150..dc89b588b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.23", + "version": "3.11.24", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.23", + "version": "3.11.24", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 8c6ef08d86..cfff0927be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.23", + "version": "3.11.24", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 02f768b58b7776ebf7d20b0e45b0a47207fdac5f Mon Sep 17 00:00:00 2001 From: qqpmsc2006 Date: Fri, 5 May 2023 20:25:05 +0800 Subject: [PATCH 096/525] Fix AlrDetector crash issue in debug mode (#1072) --- .../modules/congestion_controller/goog_cc/alr_detector.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc index 6af0a8c924..46b4a0addc 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc @@ -116,7 +116,7 @@ absl::optional AlrDetector::GetApplicationLimitedRegionStartTime() absl::optional AlrDetector::GetApplicationLimitedRegionStartTime( int64_t at_time_ms) { - if (!alr_started_time_ms_ && *last_send_time_ms_) { + if (!alr_started_time_ms_ && last_send_time_ms_.has_value()) { int64_t delta_time_ms = at_time_ms - *last_send_time_ms_; // If ALR is stopped and we haven't sent any packets for a while, force start. if (delta_time_ms > alr_timeout_) { From c045b11c3e636b7171e2192b510f89ffba561df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 12 May 2023 13:53:19 +0200 Subject: [PATCH 097/525] Update NPM deps and fix C++ log --- package-lock.json | 297 +++++++++--------- package.json | 10 +- .../goog_cc/alr_detector.cc | 2 +- 3 files changed, 156 insertions(+), 153 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc89b588b7..54f6183322 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,19 +17,19 @@ }, "devDependencies": { "@types/debug": "^4.1.7", - "@types/jest": "^29.5.0", + "@types/jest": "^29.5.1", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.0", - "@typescript-eslint/parser": "^5.59.0", - "eslint": "^8.38.0", + "@typescript-eslint/eslint-plugin": "^5.59.5", + "@typescript-eslint/parser": "^5.59.5", + "eslint": "^8.40.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.0", - "tsc-watch": "^6.0.0", + "tsc-watch": "^6.0.4", "typescript": "^5.0.4" }, "engines": { @@ -667,14 +667,14 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -690,9 +690,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", - "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", + "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1313,9 +1313,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", + "version": "29.5.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", + "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1392,15 +1392,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.0.tgz", - "integrity": "sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", + "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/type-utils": "5.59.0", - "@typescript-eslint/utils": "5.59.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/type-utils": "5.59.5", + "@typescript-eslint/utils": "5.59.5", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1426,14 +1426,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", - "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", + "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", "debug": "^4.3.4" }, "engines": { @@ -1453,13 +1453,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", - "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", + "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0" + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1470,13 +1470,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.0.tgz", - "integrity": "sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", + "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.0", - "@typescript-eslint/utils": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/utils": "5.59.5", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1497,9 +1497,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", + "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1510,13 +1510,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", - "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", + "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1537,17 +1537,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", - "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", + "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1563,12 +1563,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", + "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/types": "5.59.5", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2423,15 +2423,15 @@ } }, "node_modules/eslint": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", - "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", + "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.38.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.40.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2441,9 +2441,9 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2517,9 +2517,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2529,9 +2529,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -2539,6 +2539,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/estraverse": { @@ -2551,14 +2554,14 @@ } }, "node_modules/espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -5733,9 +5736,9 @@ } }, "node_modules/tsc-watch": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.0.tgz", - "integrity": "sha512-zgpju+/z5z29/kK5V28Nz16CMkX2voFOUxkTlCim/R25hxzbyUqu2NfTnmJBQfESBSPbEQUGqDdB9A8opAcB4A==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.4.tgz", + "integrity": "sha512-cHvbvhjO86w2aGlaHgSCeQRl+Aqw6X6XN4sQMPZKF88GoP30O+oTuh5lRIJr5pgFWrRpF1AgXnJJ2DoFEIPHyg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", @@ -6572,14 +6575,14 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -6589,9 +6592,9 @@ } }, "@eslint/js": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", - "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", + "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", "dev": true }, "@humanwhocodes/config-array": { @@ -7098,9 +7101,9 @@ } }, "@types/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", + "version": "29.5.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", + "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", "dev": true, "requires": { "expect": "^29.0.0", @@ -7177,15 +7180,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.0.tgz", - "integrity": "sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", + "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/type-utils": "5.59.0", - "@typescript-eslint/utils": "5.59.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/type-utils": "5.59.5", + "@typescript-eslint/utils": "5.59.5", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7195,53 +7198,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", - "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", + "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", - "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", + "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0" + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5" } }, "@typescript-eslint/type-utils": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.0.tgz", - "integrity": "sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", + "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.59.0", - "@typescript-eslint/utils": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/utils": "5.59.5", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", + "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", - "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", + "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7250,28 +7253,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", - "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", + "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", + "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/types": "5.59.5", "eslint-visitor-keys": "^3.3.0" } }, @@ -7879,15 +7882,15 @@ "dev": true }, "eslint": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", - "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", + "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.38.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.40.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7897,9 +7900,9 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -7927,9 +7930,9 @@ }, "dependencies": { "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -7964,20 +7967,20 @@ } }, "eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true }, "espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "requires": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "eslint-visitor-keys": "^3.4.1" } }, "esprima": { @@ -10247,9 +10250,9 @@ } }, "tsc-watch": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.0.tgz", - "integrity": "sha512-zgpju+/z5z29/kK5V28Nz16CMkX2voFOUxkTlCim/R25hxzbyUqu2NfTnmJBQfESBSPbEQUGqDdB9A8opAcB4A==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.4.tgz", + "integrity": "sha512-cHvbvhjO86w2aGlaHgSCeQRl+Aqw6X6XN4sQMPZKF88GoP30O+oTuh5lRIJr5pgFWrRpF1AgXnJJ2DoFEIPHyg==", "dev": true, "requires": { "cross-spawn": "^7.0.3", diff --git a/package.json b/package.json index cfff0927be..6753d7b97a 100644 --- a/package.json +++ b/package.json @@ -92,19 +92,19 @@ }, "devDependencies": { "@types/debug": "^4.1.7", - "@types/jest": "^29.5.0", + "@types/jest": "^29.5.1", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.0", - "@typescript-eslint/parser": "^5.59.0", - "eslint": "^8.38.0", + "@typescript-eslint/eslint-plugin": "^5.59.5", + "@typescript-eslint/parser": "^5.59.5", + "eslint": "^8.40.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.0", - "tsc-watch": "^6.0.0", + "tsc-watch": "^6.0.4", "typescript": "^5.0.4" } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc index 46b4a0addc..eb03fae118 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc @@ -120,7 +120,7 @@ absl::optional AlrDetector::GetApplicationLimitedRegionStartTime( int64_t delta_time_ms = at_time_ms - *last_send_time_ms_; // If ALR is stopped and we haven't sent any packets for a while, force start. if (delta_time_ms > alr_timeout_) { - MS_WARN_TAG(bwe, "large delta_time_ms: %ld, forcing alr state change", + MS_WARN_TAG(bwe, "large delta_time_ms: %" PRIi64 ", forcing alr state change", delta_time_ms); alr_started_time_ms_.emplace(at_time_ms); } From b425fe027dcaaad7241927ec92057e4eab449091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 16 May 2023 17:41:45 +0200 Subject: [PATCH 098/525] Update NPM deps --- package-lock.json | 164 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 84 insertions(+), 84 deletions(-) diff --git a/package-lock.json b/package-lock.json index 54f6183322..bb01de5ca3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,8 @@ "@types/jest": "^29.5.1", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.5", - "@typescript-eslint/parser": "^5.59.5", + "@typescript-eslint/eslint-plugin": "^5.59.6", + "@typescript-eslint/parser": "^5.59.6", "eslint": "^8.40.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", @@ -1392,15 +1392,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", - "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", + "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.5", - "@typescript-eslint/type-utils": "5.59.5", - "@typescript-eslint/utils": "5.59.5", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/type-utils": "5.59.6", + "@typescript-eslint/utils": "5.59.6", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1426,14 +1426,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", - "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", + "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.5", - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", "debug": "^4.3.4" }, "engines": { @@ -1453,13 +1453,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", - "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", + "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/visitor-keys": "5.59.5" + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1470,13 +1470,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", - "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", + "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.5", - "@typescript-eslint/utils": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/utils": "5.59.6", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1497,9 +1497,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", - "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", + "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1510,13 +1510,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", - "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", + "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/visitor-keys": "5.59.5", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1537,17 +1537,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", - "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", + "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.5", - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1563,12 +1563,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", - "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", + "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/types": "5.59.6", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -7180,15 +7180,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", - "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", + "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.5", - "@typescript-eslint/type-utils": "5.59.5", - "@typescript-eslint/utils": "5.59.5", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/type-utils": "5.59.6", + "@typescript-eslint/utils": "5.59.6", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7198,53 +7198,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", - "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", + "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.5", - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", - "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", + "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/visitor-keys": "5.59.5" + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6" } }, "@typescript-eslint/type-utils": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", - "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", + "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.59.5", - "@typescript-eslint/utils": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/utils": "5.59.6", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", - "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", + "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", - "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", + "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/visitor-keys": "5.59.5", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7253,28 +7253,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", - "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", + "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.5", - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", - "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", + "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/types": "5.59.6", "eslint-visitor-keys": "^3.3.0" } }, diff --git a/package.json b/package.json index 6753d7b97a..5d7fae3814 100644 --- a/package.json +++ b/package.json @@ -95,8 +95,8 @@ "@types/jest": "^29.5.1", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.5", - "@typescript-eslint/parser": "^5.59.5", + "@typescript-eslint/eslint-plugin": "^5.59.6", + "@typescript-eslint/parser": "^5.59.6", "eslint": "^8.40.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", From 07827b4c8d03bdc9d3dc59af9606218ac9175abd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 17 May 2023 19:20:22 +0200 Subject: [PATCH 099/525] [mediasoup-worker] Require C++17, Meson >= 1.1.0 and update subprojects (#1081) --- CHANGELOG.md | 5 +++++ worker/Makefile | 2 +- worker/meson.build | 4 ++-- worker/subprojects/abseil-cpp.wrap | 16 ++++++++-------- worker/subprojects/libuv.wrap | 9 +++++---- worker/subprojects/openssl.wrap | 17 +++++++++-------- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3df51b5451..784723c743 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* `Worker`: Require C++17, Meson >= 1.1.0 and update subprojects ([PR #1081](https://github.com/versatica/mediasoup/pull/1081)). + + ### 3.11.24 * `SeqManager`: Fix performance regression ([PR #1068](https://github.com/versatica/mediasoup/pull/1068), thanks to @vpalmisano for properly reporting). diff --git a/worker/Makefile b/worker/Makefile index 3e8fc4eac7..8dcd424453 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -20,7 +20,7 @@ PIP_DIR = $(MEDIASOUP_OUT_DIR)/pip INSTALL_DIR ?= $(MEDIASOUP_OUT_DIR)/$(MEDIASOUP_BUILDTYPE) BUILD_DIR ?= $(INSTALL_DIR)/build MESON ?= $(PIP_DIR)/bin/meson -MESON_VERSION ?= 0.61.5 +MESON_VERSION ?= 1.1.0 # `MESON_ARGS` can be used to provide extra configuration parameters to Meson, # such as adding defines or changing optimization options. For instance, use # `MESON_ARGS="-Dms_log_trace=true -Dms_log_file_line=true" npm i` to compile diff --git a/worker/meson.build b/worker/meson.build index 4be31c0c0b..ba2ed3f321 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -3,10 +3,10 @@ project( ['c', 'cpp'], default_options : [ 'warning_level=1', - 'cpp_std=c++11', + 'cpp_std=c++17', 'default_library=static', ], - meson_version: '>= 0.58', + meson_version: '>= 1.1.0', ) cpp_args = [ diff --git a/worker/subprojects/abseil-cpp.wrap b/worker/subprojects/abseil-cpp.wrap index 72928cb6ac..29ad8c2ee2 100644 --- a/worker/subprojects/abseil-cpp.wrap +++ b/worker/subprojects/abseil-cpp.wrap @@ -1,11 +1,12 @@ [wrap-file] -directory = abseil-cpp-20211102.0 -source_url = https://github.com/abseil/abseil-cpp/archive/20211102.0.tar.gz -source_filename = abseil-cpp-20211102.0.tar.gz -source_hash = dcf71b9cba8dc0ca9940c4b316a0c796be8fab42b070bb6b7cab62b48f0e66c4 -patch_filename = abseil-cpp_20211102.0-2_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20211102.0-2/get_patch -patch_hash = 9463930367b0db984435350c7d7614e400faa8811a7e9a2def5a63ff39fdb325 +directory = abseil-cpp-20220623.0 +source_url = https://github.com/abseil/abseil-cpp/archive/20220623.0.tar.gz +source_filename = abseil-cpp-20220623.0.tar.gz +source_hash = 4208129b49006089ba1d6710845a45e31c59b0ab6bff9e5788a87f55c5abd602 +patch_filename = abseil-cpp_20220623.0-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20220623.0-2/get_patch +patch_hash = d19cb16610d9310658a815ebcd87a9e2966aafbd57964341c0d1a3a3778c03b6 +wrapdb_version = 20220623.0-2 [provide] absl_base = absl_base_dep @@ -20,4 +21,3 @@ absl_strings = absl_strings_dep absl_synchronization = absl_synchronization_dep absl_time = absl_time_dep absl_types = absl_types_dep - diff --git a/worker/subprojects/libuv.wrap b/worker/subprojects/libuv.wrap index 6bd828d8b0..b8a7529d50 100644 --- a/worker/subprojects/libuv.wrap +++ b/worker/subprojects/libuv.wrap @@ -3,10 +3,11 @@ directory = libuv-v1.44.2 source_url = https://dist.libuv.org/dist/v1.44.2/libuv-v1.44.2.tar.gz source_filename = libuv-v1.44.2.tar.gz source_hash = ccfcdc968c55673c6526d8270a9c8655a806ea92468afcbcabc2b16040f03cb4 -patch_filename = libuv_1.44.2-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/libuv_1.44.2-1/get_patch -patch_hash = c77f6104cffd53f697c3030fccbfd5cc684b59772e8f24529b01908ee27bd751 -wrapdb_version = 1.44.2-1 +patch_filename = libuv_1.44.2-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/libuv_1.44.2-2/get_patch +patch_hash = 12a0850e1c925811f54bb022339d3105afaed8bc006b197351006c9c841f06ce +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libuv_1.44.2-2/libuv-v1.44.2.tar.gz +wrapdb_version = 1.44.2-2 [provide] libuv = libuv_dep diff --git a/worker/subprojects/openssl.wrap b/worker/subprojects/openssl.wrap index 2f16b50451..7d15b54cfc 100644 --- a/worker/subprojects/openssl.wrap +++ b/worker/subprojects/openssl.wrap @@ -1,12 +1,13 @@ [wrap-file] -directory = openssl-3.0.7 -source_url = https://www.openssl.org/source/openssl-3.0.7.tar.gz -source_filename = openssl-3.0.72.tar.gz -source_hash = 83049d042a260e696f62406ac5c08bf706fd84383f945cf21bd61e9ed95c396e -patch_filename = openssl_3.0.7-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.7-1/get_patch -patch_hash = 8f04d911dc22d1dddc6a192ab27d6d8275976a252bd9c73e09f95f1f927e42b5 -wrapdb_version = 3.0.7-1 +directory = openssl-3.0.8 +source_url = https://www.openssl.org/source/openssl-3.0.8.tar.gz +source_filename = openssl-3.0.8.tar.gz +source_hash = 6c13d2bf38fdf31eac3ce2a347073673f5d63263398f1f69d0df4a41253e4b3e +patch_filename = openssl_3.0.8-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.8-1/get_patch +patch_hash = 12d9c884174a91ccd1aa9230e9567c019f8a582ce46c98736f99a5200b4f2514 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openssl_3.0.8-1/openssl-3.0.8.tar.gz +wrapdb_version = 3.0.8-1 [provide] libcrypto = libcrypto_dep From 078ad641b083e9080987ec8653a5bf074033de94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 17 May 2023 21:26:20 +0200 Subject: [PATCH 100/525] 3.11.25 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 784723c743..e55034911f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.11.25 * `Worker`: Require C++17, Meson >= 1.1.0 and update subprojects ([PR #1081](https://github.com/versatica/mediasoup/pull/1081)). diff --git a/package-lock.json b/package-lock.json index bb01de5ca3..5d24aac43b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.24", + "version": "3.11.25", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.24", + "version": "3.11.25", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 5d7fae3814..15c6c03196 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.24", + "version": "3.11.25", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 75c11eee93f007f1149af0057d91082d93eadb4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 18 May 2023 12:34:19 +0200 Subject: [PATCH 101/525] worker: Fix NACK timer and avoid negative RTT (#1082) - Stop NACK timer when NACK list is empty as explained in https://github.com/versatica/mediasoup/pull/1076#issuecomment-1537148706. - Avoid RTT becoming negative in `RtpStreamSend` and `RtpStreamRecv`. If so, assign it with 0.0f. - And if 0.0f, use `DefaultRtt` (100 ms) in `NackGenerator`. - Remove useless `RtpStream::hasRtt` and check `RtpStream::rtt > 0.0f` instead. - Add some brackets in condition blocks. --- CHANGELOG.md | 5 ++++ worker/include/RTC/RtpStream.hpp | 3 +-- worker/src/RTC/NackGenerator.cpp | 40 +++++++++++++++++++++++++++++--- worker/src/RTC/RtpStream.cpp | 2 +- worker/src/RTC/RtpStreamRecv.cpp | 5 ++-- worker/src/RTC/RtpStreamSend.cpp | 7 +++--- 6 files changed, 51 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e55034911f..3239d06a55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* `Worker`: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). + + ### 3.11.25 * `Worker`: Require C++17, Meson >= 1.1.0 and update subprojects ([PR #1081](https://github.com/versatica/mediasoup/pull/1081)). diff --git a/worker/include/RTC/RtpStream.hpp b/worker/include/RTC/RtpStream.hpp index 9a0ca8daa6..e404013a56 100644 --- a/worker/include/RTC/RtpStream.hpp +++ b/worker/include/RTC/RtpStream.hpp @@ -214,8 +214,7 @@ namespace RTC uint64_t lastSenderReportNtpMs{ 0u }; // RTP timestamp in last Sender Report. uint32_t lastSenderReportTs{ 0u }; - float rtt{ 0 }; - bool hasRtt{ false }; + float rtt{ 0.0f }; // Instance of RtxStream. RTC::RtxStream* rtxStream{ nullptr }; diff --git a/worker/src/RTC/NackGenerator.cpp b/worker/src/RTC/NackGenerator.cpp index 48fe2e8512..289d6dd3df 100644 --- a/worker/src/RTC/NackGenerator.cpp +++ b/worker/src/RTC/NackGenerator.cpp @@ -51,14 +51,18 @@ namespace RTC this->lastSeq = seq; if (isKeyFrame) + { this->keyFrameList.insert(seq); + } return false; } // Obviously never nacked, so ignore. if (seq == this->lastSeq) + { return false; + } // May be an out of order packet, or already handled retransmitted packet, // or a retransmitted packet. @@ -80,9 +84,13 @@ namespace RTC this->nackList.erase(it); if (retries != 0) + { return true; + } else + { return false; + } } // Out of order packet or already handled NACKed packet. @@ -101,14 +109,18 @@ namespace RTC // newer than the latest seq seen. if (isKeyFrame) + { this->keyFrameList.insert(seq); + } // Remove old keyframes. { auto it = this->keyFrameList.lower_bound(seq - MaxPacketAge); if (it != this->keyFrameList.begin()) + { this->keyFrameList.erase(this->keyFrameList.begin(), it); + } } if (isRecovered) @@ -119,7 +131,9 @@ namespace RTC auto it = this->recoveredList.lower_bound(seq - MaxPacketAge); if (it != this->recoveredList.begin()) + { this->recoveredList.erase(this->recoveredList.begin(), it); + } // Do not let a packet pass if it's newer than last seen seq and came via // RTX. @@ -134,12 +148,16 @@ namespace RTC std::vector nackBatch = GetNackBatch(NackFilter::SEQ); if (!nackBatch.empty()) + { this->listener->OnNackGeneratorNackRequired(nackBatch); + } // This is important. Otherwise the running timer (filter:TIME) would be // interrupted and NACKs would never been sent more than once for each seq. if (!this->timer->IsActive()) + { MayRunTimer(); + } return false; } @@ -187,7 +205,9 @@ namespace RTC // Do not send NACK for packets that are already recovered by RTX. if (this->recoveredList.find(seq) != this->recoveredList.end()) + { continue; + } this->nackList.emplace(std::make_pair( seq, @@ -277,7 +297,10 @@ namespace RTC continue; } - if (filter == NackFilter::TIME && (nackInfo.sentAtMs == 0 || nowMs - nackInfo.sentAtMs >= this->rtt)) + if ( + filter == NackFilter::TIME && + (nackInfo.sentAtMs == 0 || + nowMs - nackInfo.sentAtMs >= (this->rtt > 0u ? this->rtt : DefaultRtt))) { nackBatch.emplace_back(seq); nackInfo.retries++; @@ -313,9 +336,13 @@ namespace RTC seqsStream << nackBatch.back(); if (filter == NackFilter::SEQ) + { MS_DEBUG_DEV("[filter:SEQ, asking seqs:%s]", seqsStream.str().c_str()); + } else + { MS_DEBUG_DEV("[filter:TIME, asking seqs:%s]", seqsStream.str().c_str()); + } } #endif @@ -329,15 +356,20 @@ namespace RTC this->nackList.clear(); this->keyFrameList.clear(); this->recoveredList.clear(); - this->started = false; this->lastSeq = 0u; } inline void NackGenerator::MayRunTimer() const { - if (!this->nackList.empty()) + if (this->nackList.empty()) + { + this->timer->Stop(); + } + else + { this->timer->Start(TimerInterval); + } } inline void NackGenerator::OnTimer(Timer* /*timer*/) @@ -347,7 +379,9 @@ namespace RTC std::vector nackBatch = GetNackBatch(NackFilter::TIME); if (!nackBatch.empty()) + { this->listener->OnNackGeneratorNackRequired(nackBatch); + } MayRunTimer(); } diff --git a/worker/src/RTC/RtpStream.cpp b/worker/src/RTC/RtpStream.cpp index 85b6850b81..8503025f31 100644 --- a/worker/src/RTC/RtpStream.cpp +++ b/worker/src/RTC/RtpStream.cpp @@ -76,7 +76,7 @@ namespace RTC if (this->rtxStream) jsonObject["rtxPacketsDiscarded"] = this->rtxStream->GetPacketsDiscarded(); - if (this->hasRtt) + if (this->rtt > 0.0f) jsonObject["roundTripTime"] = this->rtt; } diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index abee7f293b..0fe1de02cb 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -608,9 +608,10 @@ namespace RTC this->rtt = static_cast(rtt >> 16) * 1000; this->rtt += (static_cast(rtt & 0x0000FFFF) / 65536) * 1000; - if (this->rtt > 0.0f) + // Avoid negative RTT value since it doesn't make sense. + if (this->rtt <= 0.0f) { - this->hasRtt = true; + this->rtt = 0.0f; } // Tell it to the NackGenerator. diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index b8949a37ff..ebc8780d58 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -223,9 +223,10 @@ namespace RTC this->rtt = static_cast(rtt >> 16) * 1000; this->rtt += (static_cast(rtt & 0x0000FFFF) / 65536) * 1000; - if (this->rtt > 0.0f) + // Avoid negative RTT value since it doesn't make sense. + if (this->rtt <= 0.0f) { - this->hasRtt = true; + this->rtt = 0.0f; } this->packetsLost = report->GetTotalLost(); @@ -399,7 +400,7 @@ namespace RTC // Look for each requested packet. const uint64_t nowMs = DepLibUV::GetTimeMs(); - const uint16_t rtt = (this->rtt != 0u ? this->rtt : DefaultRtt); + const uint16_t rtt = (this->rtt > 0.0f ? this->rtt : DefaultRtt); uint16_t currentSeq = seq; bool requested{ true }; size_t containerIdx{ 0 }; From a16066c67f8a44011227fb3e15ff79bff313ba74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 18 May 2023 12:36:48 +0200 Subject: [PATCH 102/525] 3.11.26 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3239d06a55..0eb2f33350 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.11.26 * `Worker`: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). diff --git a/package-lock.json b/package-lock.json index 5d24aac43b..bf84748354 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.25", + "version": "3.11.26", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.25", + "version": "3.11.26", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 15c6c03196..80c7e7c81a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.25", + "version": "3.11.26", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From c977028c050d0cc22f4564d4fbe9ff0b9912c81d Mon Sep 17 00:00:00 2001 From: aankur Date: Tue, 23 May 2023 15:13:49 +0530 Subject: [PATCH 103/525] Fix: Compilation error of Implicitly deleted defaulted constructor (#1086) --- .../deps/libwebrtc/libwebrtc/api/transport/network_types.cc | 3 +-- worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc index d0a0c4a05f..88b67b3a47 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc @@ -13,8 +13,7 @@ #include namespace webrtc { -// TODO(srte): Revert to using default after removing union member. -StreamsConfig::StreamsConfig() {} +StreamsConfig::StreamsConfig() = default; StreamsConfig::StreamsConfig(const StreamsConfig&) = default; StreamsConfig::~StreamsConfig() = default; diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h index 20ab6aaba7..0604b6d383 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h @@ -34,9 +34,7 @@ struct StreamsConfig { Timestamp at_time = Timestamp::PlusInfinity(); absl::optional requests_alr_probing; absl::optional pacing_factor; - union { - absl::optional min_total_allocated_bitrate = absl::nullopt; - }; + absl::optional min_total_allocated_bitrate = absl::nullopt; absl::optional max_padding_rate; absl::optional max_total_allocated_bitrate; }; From 6d0a4e14a862bd7690960a33113ef68539d13181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 26 May 2023 12:17:06 +0200 Subject: [PATCH 104/525] Automate and publish prebuilt mediasoup-worker binaries (#1087) --- .github/workflows/mediasoup-node.yaml | 11 +- .../workflows/mediasoup-worker-prebuild.yaml | 57 ++ .github/workflows/mediasoup-worker.yaml | 3 + .gitignore | 3 +- CHANGELOG.md | 6 +- doc/Building.md | 10 +- node/.eslintrc.js | 13 +- npm-scripts.js | 628 +++++++++---- package-lock.json | 832 +++++++++++++++--- package.json | 16 +- 10 files changed, 1277 insertions(+), 302 deletions(-) create mode 100644 .github/workflows/mediasoup-worker-prebuild.yaml diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index a925d6dc69..1baa7301f0 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -12,18 +12,21 @@ jobs: ci: strategy: matrix: - # Different Node versions on Ubuntu, the latest Node on other platforms. ci: - - os: ubuntu-22.04 - node: 16 - - os: ubuntu-22.04 + - os: ubuntu-20.04 node: 18 + - os: ubuntu-22.04 + node: 20 - os: macos-12 node: 18 - os: windows-2022 node: 18 + runs-on: ${{ matrix.ci.os }} + env: + MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: "true" + steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml new file mode 100644 index 0000000000..19ee70c161 --- /dev/null +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -0,0 +1,57 @@ +name: mediasoup-worker-prebuild + +on: + push: + # Only trigger for production releases. + tags: + - "*.*.*" + + # Only trigger when other workflows succeeded. + workflow_run: + workflows: [mediasoup-worker, mediasoup-node, mediasoup-rust] + types: + - completed + +jobs: + ci: + strategy: + fail-fast: false + matrix: + build: + - os: ubuntu-22.04 + cc: gcc + cxx: g++ + - os: macos-12 + cc: clang + cxx: clang++ + - os: windows-2022 + cc: cl + cxx: cl + node: + - 18 + + runs-on: ${{ matrix.build.os }} + + env: + CC: ${{ matrix.build.cc }} + CXX: ${{ matrix.build.cxx }} + MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: "true" + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Node.js + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node }} + + # We need to install some NPM production deps for npm-scripts.js to work. + - run: npm ci --ignore-scripts --omit=dev + - run: npm run worker:build + # Publish prebuild binaries on tag. + - run: npm run worker:prebuild + - name: Upload mediasoup-worker prebuilt binary + uses: softprops/action-gh-release@v1 + with: + files: worker/prebuild/mediasoup-worker-*.tgz diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 20474fe075..f0b0dc6fb9 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -44,6 +44,7 @@ jobs: env: CC: ${{ matrix.build.cc }} CXX: ${{ matrix.build.cxx }} + MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: "true" steps: - name: Checkout @@ -54,6 +55,8 @@ jobs: with: node-version: ${{ matrix.node }} + # We need to install some NPM production deps for npm-scripts.js to work. + - run: npm ci --ignore-scripts --omit=dev - run: npm run install-clang-tools # TODO: Maybe fix this one day. if: runner.os != 'Windows' diff --git a/.gitignore b/.gitignore index 7f8ebf4acb..366e4c3de8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ ## Meson. +/worker/out /worker/subprojects/* !/worker/subprojects/*.wrap !/worker/subprojects/.clang-tidy @@ -14,8 +15,8 @@ /target ## Worker. -/worker/out /worker/scripts/node_modules +/worker/prebuild # Vistual Studio generated Stuff. /worker/**/Debug /worker/**/Release diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eb2f33350..f5964971e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,13 @@ # Changelog +### NEXT + +* Automate and publish prebuilt `mediasoup-worker` binaries ([PR #1087](https://github.com/versatica/mediasoup/pull/1087), thanks to @barlock for his work in ([PR #1083](https://github.com/versatica/mediasoup/pull/1083)). + ### 3.11.26 -* `Worker`: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). +* `Worker`: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to @o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). ### 3.11.25 diff --git a/doc/Building.md b/doc/Building.md index 93e103b3d9..ca18ebf5ad 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -18,6 +18,10 @@ Compiles mediasoup TypeScript code (`lib` folder) JavaScript, places it into the Builds the `mediasoup-worker` binary. It invokes `make`below. +### `npm run worker:prebuild` + +Creates a prebuilt of `mediasoup-worker` in the `worker/prebuild` folder. + ### `npm run lint` Runs both `npm run lint:node` and `npm run lint:worker`. @@ -60,7 +64,7 @@ Installs clang tools needed for local development. ## Rust -The only special feature in Rust case is special environment variable `KEEP_BUILD_ARTIFACTS`, that when set to `1` will allow incremental recompilation of changed C++ sources during hacking on mediasoup. +The only special feature in Rust case is special environment variable `"KEEP_BUILD_ARTIFACTS", that when set to `1` will allow incremental recompilation of changed C++ sources during hacking on mediasoup. It is not necessary for normal usage of mediasoup as a dependency. ## Makefile @@ -132,7 +136,7 @@ MEDIASOUP_WORKER_BIN="/home/xxx/src/foo/mediasoup-worker" node myapp.js Builds the `libmediasoup-worker` static library at `worker/out/Release/`. -`MEDIASOUP_MAX_CORES` and `MEDIASOUP_BUILDTYPE` environment variables from above still apply for static library build. +"MEDIASOUP_MAX_CORES"` and "MEDIASOUP_BUILDTYPE" environment variables from above still apply for static library build. ### `make xcode` @@ -160,7 +164,7 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy/) and performs C++ code * [PyYAML](https://pyyaml.org/) is required. - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. -`MEDIASOUP_TIDY_CHECKS` environment variable with a comma separated list of checks overrides the checks defined in `.clang-tidy` file. +"MEDIASOUP_TIDY_CHECKS" environment variable with a comma separated list of checks overrides the checks defined in `.clang-tidy` file. ### `make fuzzer` diff --git a/node/.eslintrc.js b/node/.eslintrc.js index ca8e7cefc4..61a42372e6 100644 --- a/node/.eslintrc.js +++ b/node/.eslintrc.js @@ -13,13 +13,13 @@ const eslintConfig = settings : {}, parserOptions : { - ecmaVersion : 2018, + ecmaVersion : 2022, sourceType : 'module', ecmaFeatures : { impliedStrict : true }, - lib : [ 'es2018' ], + lib : [ 'es2022' ], project : 'node/tsconfig.json' }, globals : @@ -78,7 +78,7 @@ const eslintConfig = 'max-len' : [ 2, 100, { tabWidth : 2, - comments : 84, + comments : 88, ignoreUrls : true, ignoreStrings : true, ignoreTemplateLiterals : true, @@ -166,7 +166,12 @@ const eslintConfig = 'prefer-rest-params' : 2, 'prefer-spread' : 2, 'prefer-template' : 2, - 'quotes' : [ 2, 'single', { avoidEscape: true } ], + 'quotes' : [ 2, 'single', + { + avoidEscape : true, + allowTemplateLiterals : true + } + ], 'semi' : [ 2, 'always' ], 'semi-spacing' : 2, 'space-before-blocks' : 2, diff --git a/npm-scripts.js b/npm-scripts.js index 2e8a8ab4b5..dfd048930b 100644 --- a/npm-scripts.js +++ b/npm-scripts.js @@ -1,177 +1,269 @@ -/* eslint-disable no-console */ - const process = require('process'); const os = require('os'); const fs = require('fs'); const { execSync, spawnSync } = require('child_process'); -const { version } = require('./package.json'); +const fetch = require('node-fetch'); +const tar = require('tar'); + +const PKG = JSON.parse(fs.readFileSync('./package.json').toString()); +const IS_FREEBSD = os.platform() === 'freebsd'; +const IS_WINDOWS = os.platform() === 'win32'; +const MAYOR_VERSION = PKG.version.split('.')[0]; +const MAKE = process.env.MAKE || (IS_FREEBSD ? 'gmake' : 'make'); +const WORKER_RELEASE_DIR = 'worker/out/Release'; +const WORKER_RELEASE_BIN = IS_WINDOWS ? 'mediasoup-worker.exe' : 'mediasoup-worker'; +const WORKER_RELEASE_BIN_PATH = `${WORKER_RELEASE_DIR}/${WORKER_RELEASE_BIN}`; +const WORKER_PREBUILD_DIR = 'worker/prebuild'; +const WORKER_PREBUILD_TAR = `mediasoup-worker-${PKG.version}-${os.platform()}-${os.arch()}.tgz`; +const WORKER_PREBUILD_TAR_PATH = `${WORKER_PREBUILD_DIR}/${WORKER_PREBUILD_TAR}`; +const GH_OWNER = 'versatica'; +const GH_REPO = 'mediasoup'; -const isFreeBSD = os.platform() === 'freebsd'; -const isWindows = os.platform() === 'win32'; const task = process.argv.slice(2).join(' '); -// mediasoup mayor version. -const MAYOR_VERSION = version.split('.')[0]; - -// make command to use. -const MAKE = process.env.MAKE || (isFreeBSD ? 'gmake' : 'make'); +run(); -console.log(`npm-scripts.js [INFO] running task "${task}"`); - -switch (task) +async function run() { - // As per NPM documentation (https://docs.npmjs.com/cli/v9/using-npm/scripts) - // `prepare` script: - // - // - Runs BEFORE the package is packed, i.e. during `npm publish` and `npm pack`. - // - Runs on local `npm install` without any arguments. - // - NOTE: If a package being installed through git contains a `prepare` script, - // its dependencies and devDependencies will be installed, and the `prepare` - // script will be run, before the package is packaged and installed. - // - // So here we compile TypeScript and flatbuffers to JavaScript. - case 'prepare': + switch (task) { - buildTypescript(/* force */ false); + // As per NPM documentation (https://docs.npmjs.com/cli/v9/using-npm/scripts) + // `prepare` script: + // + // - Runs BEFORE the package is packed, i.e. during `npm publish` and + // `npm pack`. + // - Runs on local `npm install` without any arguments. + // - NOTE: If a package being installed through git contains a `prepare` script, + // its dependencies and devDependencies will be installed, and the `prepare` + // script will be run, before the package is packaged and installed. + // + // So here we compile TypeScript and flatbuffers to JavaScript. + case 'prepare': + { + buildTypescript(/* force */ false); - // TODO: Compile flatbuffers. + // TODO: Compile flatbuffers. - break; - } + break; + } - case 'postinstall': - { - if (!process.env.MEDIASOUP_WORKER_BIN) + case 'postinstall': { - buildWorker(); + // If the user/app provides us with a custom mediasoup-worker binary then + // don't do anything. + if (process.env.MEDIASOUP_WORKER_BIN) + { + logInfo('MEDIASOUP_WORKER_BIN environment variable given, skipping'); + + break; + } + // If MEDIASOUP_LOCAL_DEV is given, or if MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD + // env is given, or if mediasoup package is being installed via git+ssh + // (instead of via npm), and if MEDIASOUP_FORCE_PREBUILT_WORKER_DOWNLOAD env is + // not set, then skip mediasoup-worker prebuilt download. + else if ( + ( + process.env.MEDIASOUP_LOCAL_DEV || + process.env.MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD || + process.env.npm_package_resolved?.startsWith('git+ssh://') + ) && + !process.env.MEDIASOUP_FORCE_WORKER_PREBUILT_DOWNLOAD + ) + { + logInfo('skipping mediasoup-worker prebuilt download, building it locally'); - if (!process.env.MEDIASOUP_LOCAL_DEV) + buildWorker(); + cleanWorkerArtifacts(); + } + // Attempt to download a prebuilt binary. Fallback to building locally. + else if (!(await downloadPrebuiltWorker())) { - cleanWorker(); + logInfo(`couldn't fetch any mediasoup-worker prebuilt binary, building it locally`); + + buildWorker(); + cleanWorkerArtifacts(); } + + break; } - break; - } + case 'typescript:build': + { + installNodeDeps(); + buildTypescript(/* force */ true); + replaceVersion(); - case 'typescript:build': - { - installNodeDeps(); - buildTypescript(/* force */ true); - replaceVersion(); + break; + } - break; - } + case 'typescript:watch': + { + // NOTE: Load dep here since it's a devDependency. + const { TscWatchClient } = require('tsc-watch/client'); - case 'typescript:watch': - { - deleteNodeLib(); + const watch = new TscWatchClient(); - const { TscWatchClient } = require('tsc-watch/client'); - const watch = new TscWatchClient(); + deleteNodeLib(); - watch.on('success', replaceVersion); - watch.start('--project', 'node', '--pretty'); + watch.on('success', replaceVersion); + watch.start('--project', 'node', '--pretty'); - break; - } + break; + } - case 'worker:build': - { - buildWorker(); + case 'worker:build': + { + buildWorker(); - break; - } + break; + } - case 'lint:node': - { - lintNode(); + case 'worker:prebuild': + { + await prebuildWorker(); - break; - } + break; + } - case 'lint:worker': - { - lintWorker(); + case 'lint:node': + { + lintNode(); - break; - } + break; + } - case 'format:worker': - { - executeCmd(`${MAKE} format -C worker`); + case 'lint:worker': + { + lintWorker(); - break; - } + break; + } - case 'test:node': - { - buildTypescript(/* force */ false); - replaceVersion(); - testNode(); + case 'format:worker': + { + executeCmd(`${MAKE} format -C worker`); - break; - } + break; + } - case 'test:worker': - { - testWorker(); + case 'test:node': + { + buildTypescript(/* force */ false); + replaceVersion(); + testNode(); - break; - } + break; + } - case 'coverage:node': - { - buildTypescript(/* force */ false); - replaceVersion(); - executeCmd('jest --coverage'); - executeCmd('open-cli coverage/lcov-report/index.html'); + case 'test:worker': + { + testWorker(); - break; - } + break; + } - case 'install-deps:node': - { - installNodeDeps(); + case 'coverage:node': + { + buildTypescript(/* force */ false); + replaceVersion(); + executeCmd('jest --coverage'); + executeCmd('open-cli coverage/lcov-report/index.html'); - break; - } + break; + } - case 'install-clang-tools': - { - executeCmd('npm ci --prefix worker/scripts'); + case 'install-deps:node': + { + installNodeDeps(); - break; - } + break; + } - case 'release:check': - { - checkRelease(); + case 'install-clang-tools': + { + executeCmd('npm ci --prefix worker/scripts'); - break; - } + break; + } - case 'release': - { - checkRelease(); - executeCmd(`git commit -am '${version}'`); - executeCmd(`git tag -a ${version} -m '${version}'`); - executeCmd(`git push origin v${MAYOR_VERSION}`); - executeCmd(`git push origin '${version}'`); - executeCmd('npm publish'); - - break; - } + case 'release:check': + { + checkRelease(); - default: - { - throw new TypeError(`unknown task "${task}"`); + break; + } + + case 'release': + { + let octokit; + let versionChanges; + + try + { + octokit = getOctokit(); + versionChanges = getVersionChanges(); + } + catch (error) + { + logError(error.message); + exitWithError(); + } + + checkRelease(); + + executeCmd(`git commit -am '${PKG.version}'`); + executeCmd(`git tag -a ${PKG.version} -m '${PKG.version}'`); + executeCmd(`git push origin v${MAYOR_VERSION}`); + executeCmd(`git push origin '${PKG.version}'`); + + logInfo('creating release in GitHub…'); + + await octokit.repos.createRelease( + { + owner : GH_OWNER, + repo : GH_REPO, + name : PKG.version, + body : versionChanges, + // eslint-disable-next-line camelcase + tag_name : PKG.version, + draft : false + }); + + // GitHub mediasoup-worker-prebuild CI action doesn't create mediasoup-worker + // prebuilt binary for macOS ARM. If this is a macOS ARM machine, do it here + // and upload it to the release. + if (os.platform() === 'darwin' && os.arch() === 'arm64') + { + await uploadMacArmPrebuiltWorker(); + } + + executeCmd('npm publish'); + + break; + } + + case 'release:upload-mac-arm-prebuilt-worker': + { + checkRelease(); + + await prebuildWorker(); + await uploadMacArmPrebuiltWorker(); + + break; + } + + default: + { + logError('unknown task'); + + exitWithError(); + } } } function replaceVersion() { - console.log('npm-scripts.js [INFO] replaceVersion()'); + logInfo('replaceVersion()'); const files = [ @@ -183,7 +275,7 @@ function replaceVersion() for (const file of files) { const text = fs.readFileSync(file, { encoding: 'utf8' }); - const result = text.replace(/__MEDIASOUP_VERSION__/g, version); + const result = text.replace(/__MEDIASOUP_VERSION__/g, PKG.version); fs.writeFileSync(file, result, { encoding: 'utf8' }); } @@ -196,9 +288,9 @@ function deleteNodeLib() return; } - console.log('npm-scripts.js [INFO] deleteNodeLib()'); + logInfo('deleteNodeLib()'); - if (!isWindows) + if (!IS_WINDOWS) { executeCmd('rm -rf node/lib'); } @@ -216,18 +308,17 @@ function buildTypescript(force = false) return; } - console.log('npm-scripts.js [INFO] buildTypescript()'); + logInfo('buildTypescript()'); deleteNodeLib(); - executeCmd('tsc --project node'); } function buildWorker() { - console.log('npm-scripts.js [INFO] buildWorker()'); + logInfo('buildWorker()'); - if (isWindows) + if (IS_WINDOWS) { if (!fs.existsSync('worker/out/msys/bin/make.exe')) { @@ -236,18 +327,18 @@ function buildWorker() const msysPath = `${process.cwd()}\\worker\\out\\msys\\bin`; - if (!process.env['PATH'].includes(msysPath)) + if (!process.env.PATH.includes(msysPath)) { - process.env['PATH'] = `${msysPath};${process.env['PATH']}`; + process.env.PATH = `${msysPath};${process.env.PATH}`; } } executeCmd(`${MAKE} -C worker`); } -function cleanWorker() +function cleanWorkerArtifacts() { - console.log('npm-scripts.js [INFO] cleanWorker()'); + logInfo('cleanWorkerArtifacts()'); // Clean build artifacts except `mediasoup-worker`. executeCmd(`${MAKE} clean-build -C worker`); @@ -256,7 +347,7 @@ function cleanWorker() // Clean PIP/Meson/Ninja. executeCmd(`${MAKE} clean-pip -C worker`); - if (isWindows) + if (IS_WINDOWS) { executeCmd('rd /s /q worker\\out\\msys'); } @@ -264,21 +355,21 @@ function cleanWorker() function lintNode() { - console.log('npm-scripts.js [INFO] lintNode()'); + logInfo('lintNode()'); executeCmd('eslint -c node/.eslintrc.js --max-warnings 0 node/src node/.eslintrc.js npm-scripts.js worker/scripts/gulpfile.js'); } function lintWorker() { - console.log('npm-scripts.js [INFO] lintWorker()'); + logInfo('lintWorker()'); executeCmd(`${MAKE} lint -C worker`); } function testNode() { - console.log('npm-scripts.js [INFO] testNode()'); + logInfo('testNode()'); if (!process.env.TEST_FILE) { @@ -292,14 +383,14 @@ function testNode() function testWorker() { - console.log('npm-scripts.js [INFO] testWorker()'); + logInfo('testWorker()'); executeCmd(`${MAKE} test -C worker`); } function installNodeDeps() { - console.log('npm-scripts.js [INFO] installNodeDeps()'); + logInfo('installNodeDeps()'); // Install/update Node deps. executeCmd('npm ci --ignore-scripts'); @@ -309,7 +400,7 @@ function installNodeDeps() function checkRelease() { - console.log('npm-scripts.js [INFO] checkRelease()'); + logInfo('checkRelease()'); installNodeDeps(); buildTypescript(/* force */ true); @@ -321,47 +412,264 @@ function checkRelease() testWorker(); } -function executeCmd(command, exitOnError = true) +function installMsysMake() { - console.log(`npm-scripts.js [INFO] executeCmd(): ${command}`); + logInfo('installMsysMake()'); - try + let res = spawnSync('where', [ 'python3.exe' ]); + + if (res.status !== 0) { - execSync(command, { stdio: [ 'ignore', process.stdout, process.stderr ] }); + res = spawnSync('where', [ 'python.exe' ]); + + if (res.status !== 0) + { + logError('`installMsysMake() | cannot find Python executable'); + exitWithError(); + } } - catch (error) + + executeCmd(`${String(res.stdout).trim()} worker\\scripts\\getmake.py`); +} + +function ensureDir(dir) +{ + logInfo(`ensureDir() [dir:${dir}]`); + + if (!fs.existsSync(dir)) { - if (exitOnError) + fs.mkdirSync(dir, { recursive: true }); + } +} + +async function prebuildWorker() +{ + logInfo('prebuildWorker()'); + + ensureDir(WORKER_PREBUILD_DIR); + + return new Promise((resolve, reject) => + { + // Generate a gzip file which just contains mediasoup-worker binary without + // any folder. + tar.create( + { + cwd : WORKER_RELEASE_DIR, + gzip : true + }, + [ WORKER_RELEASE_BIN ]) + .pipe(fs.createWriteStream(WORKER_PREBUILD_TAR_PATH)) + .on('finish', resolve) + .on('error', reject); + }); +} + +// Returns a Promise resolving to true if a mediasoup-worker prebuilt binary +// was downloaded and uncompressed, false otherwise. +async function downloadPrebuiltWorker() +{ + const releaseBase = + process.env.MEDIASOUP_WORKER_PREBUILT_DOWNLOAD_BASE_URL || + `${PKG.repository.url.replace(/\.git$/, '')}/releases/download`; + + const tarUrl = `${releaseBase}/${PKG.version}/${WORKER_PREBUILD_TAR}`; + + logInfo(`downloadPrebuiltWorker() [tarUrl:${tarUrl}]`); + + ensureDir(WORKER_PREBUILD_DIR); + + let res; + + try + { + res = await fetch(tarUrl); + + if (res.status === 404) { - console.error(`npm-scripts.js [ERROR] executeCmd() failed, exiting: ${error}`); + logInfo( + 'downloadPrebuiltWorker() | no available mediasoup-worker prebuilt binary for current architecture' + ); - process.exit(1); + return false; } - else + else if (!res.ok) { - console.log(`npm-scripts.js [INFO] executeCmd() failed, ignoring: ${error}`); + logError( + `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${res.status} ${res.statusText}` + ); + + return false; } } + catch (error) + { + logError( + `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${error}` + ); + + return false; + } + + ensureDir(WORKER_RELEASE_DIR); + + return new Promise((resolve) => + { + // Extract mediasoup-worker in the official mediasoup-worker path. + res.body + .pipe(tar.extract( + { + newer : false, + cwd : WORKER_RELEASE_DIR + })) + .on('finish', () => + { + logInfo('downloadPrebuiltWorker() | got mediasoup-worker prebuilt binary'); + + try + { + // Give execution permission to the binary. + fs.chmodSync(WORKER_RELEASE_BIN_PATH, 0o775); + + resolve(true); + } + catch (error) + { + logError( + `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${error}` + ); + + resolve(false); + } + }) + .on('error', (error) => + { + logError( + `downloadPrebuiltWorker() | failed to uncompress downloaded mediasoup-worker prebuilt binary: ${error}` + ); + + resolve(false); + }); + }); } -function installMsysMake() +async function uploadMacArmPrebuiltWorker() { - console.log('npm-scripts.js [INFO] installMsysMake()'); + if (os.platform() !== 'darwin' || os.arch() !== 'arm64') + { + logWarn('uploadMacArmPrebuiltWorker() | invalid platform or architecture'); - let res = spawnSync('where', [ 'python3.exe' ]); + return; + } - if (res.status !== 0) + const octokit = getOctokit(); + + logInfo('uploadMacArmPrebuiltWorker() | getting release info…'); + + const release = await octokit.rest.repos.getReleaseByTag( + { + owner : GH_OWNER, + repo : GH_REPO, + tag : PKG.version + }); + + logInfo('uploadMacArmPrebuiltWorker() | uploading release asset…'); + + await octokit.rest.repos.uploadReleaseAsset( + { + owner : GH_OWNER, + repo : GH_REPO, + // eslint-disable-next-line camelcase + release_id : release.data.id, + name : WORKER_PREBUILD_TAR, + data : fs.readFileSync(WORKER_PREBUILD_TAR_PATH) + }); +} + +function getOctokit() +{ + if (!process.env.GITHUB_TOKEN) { - res = spawnSync('where', [ 'python.exe' ]); + throw new Error('missing GITHUB_TOKEN environment variable'); + } - if (res.status !== 0) + // NOTE: Load dep here since it's a devDependency. + const { Octokit } = require('@octokit/rest'); + + const octokit = new Octokit( + { + auth : process.env.GITHUB_TOKEN + }); + + return octokit; +} + +function getVersionChanges() +{ + logInfo('getVersionChanges()'); + + // NOTE: Load dep here since it's a devDependency. + const marked = require('marked'); + + const changelog = fs.readFileSync('./CHANGELOG.md').toString(); + const entries = marked.lexer(changelog); + + for (let idx = 0; idx < entries.length; ++idx) + { + const entry = entries[idx]; + + if (entry.type === 'heading' && entry.text === PKG.version) { - // eslint-disable-next-line no-console - console.error('`npm-scripts.js [ERROR] installMsysMake() cannot find Python executable'); + const changes = entries[idx + 1].raw; - process.exit(1); + return changes; } } - executeCmd(`${String(res.stdout).trim()} worker\\scripts\\getmake.py`); + // This should not happen (unless author forgot to update CHANGELOG). + throw new Error(`no entry found in CHANGELOG.md for version '${PKG.version}'`); +} + +function executeCmd(command, exitOnError = true) +{ + logInfo(`executeCmd(): ${command}`); + + try + { + execSync(command, { stdio: [ 'ignore', process.stdout, process.stderr ] }); + } + catch (error) + { + if (exitOnError) + { + logError(`executeCmd() failed, exiting: ${error}`); + exitWithError(); + } + else + { + logInfo(`executeCmd() failed, ignoring: ${error}`); + } + } +} + +function logInfo(message) +{ + // eslint-disable-next-line no-console + console.log(`npm-scripts.js \x1b[36m[INFO] [${task}]\x1b\[0m`, message); +} + +function logWarn(message) +{ + // eslint-disable-next-line no-console + console.warn(`npm-scripts.js \x1b[33m[WARN] [${task}]\x1b\[0m`, message); +} + +function logError(message) +{ + // eslint-disable-next-line no-console + console.error(`npm-scripts.js \x1b[31m[ERROR] [${task}]\x1b\[0m`, message); +} + +function exitWithError() +{ + process.exit(1); } diff --git a/package-lock.json b/package-lock.json index bf84748354..26e7e6dee6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,19 +12,23 @@ "dependencies": { "debug": "^4.3.4", "h264-profile-level-id": "^1.0.1", + "node-fetch": "^2.6.11", "supports-color": "^9.3.1", + "tar": "^6.1.15", "uuid": "^9.0.0" }, "devDependencies": { - "@types/debug": "^4.1.7", + "@octokit/rest": "^19.0.11", + "@types/debug": "^4.1.8", "@types/jest": "^29.5.1", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.6", - "@typescript-eslint/parser": "^5.59.6", - "eslint": "^8.40.0", + "@typescript-eslint/eslint-plugin": "^5.59.7", + "@typescript-eslint/parser": "^5.59.7", + "eslint": "^8.41.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", + "marked": "^5.0.2", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -690,9 +694,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", - "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1199,6 +1203,172 @@ "node": ">= 8" } }, + "node_modules/@octokit/auth-token": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", + "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", + "dev": true, + "dependencies": { + "@octokit/types": "^9.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/core": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", + "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^3.0.0", + "@octokit/graphql": "^5.0.0", + "@octokit/request": "^6.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^9.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/endpoint": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", + "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", + "dev": true, + "dependencies": { + "@octokit/types": "^9.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/graphql": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", + "dev": true, + "dependencies": { + "@octokit/request": "^6.0.0", + "@octokit/types": "^9.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", + "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", + "dev": true, + "dependencies": { + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "@octokit/core": ">=4" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "dev": true, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.1.2.tgz", + "integrity": "sha512-R0oJ7j6f/AdqPLtB9qRXLO+wjI9pctUn8Ka8UGfGaFCcCv3Otx14CshQ89K4E88pmyYZS8p0rNTiprML/81jig==", + "dev": true, + "dependencies": { + "@octokit/types": "^9.2.3", + "deprecation": "^2.3.1" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", + "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^7.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^9.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/request-error": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", + "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "dev": true, + "dependencies": { + "@octokit/types": "^9.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/rest": { + "version": "19.0.11", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", + "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", + "dev": true, + "dependencies": { + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", + "dev": true + }, + "node_modules/@octokit/types": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", + "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^17.2.0" + } + }, "node_modules/@sinclair/typebox": { "version": "0.25.23", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.23.tgz", @@ -1271,9 +1441,9 @@ } }, "node_modules/@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", + "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", "dev": true, "dependencies": { "@types/ms": "*" @@ -1392,15 +1562,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", - "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", + "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.6", - "@typescript-eslint/type-utils": "5.59.6", - "@typescript-eslint/utils": "5.59.6", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/type-utils": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1426,14 +1596,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", - "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", + "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.6", - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "debug": "^4.3.4" }, "engines": { @@ -1453,13 +1623,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", - "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", + "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/visitor-keys": "5.59.6" + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1470,13 +1640,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", - "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.7.tgz", + "integrity": "sha512-ozuz/GILuYG7osdY5O5yg0QxXUAEoI4Go3Do5xeu+ERH9PorHBPSdvD3Tjp2NN2bNLh1NJQSsQu2TPu/Ly+HaQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.6", - "@typescript-eslint/utils": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1497,9 +1667,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", - "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", + "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1510,13 +1680,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", - "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", + "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/visitor-keys": "5.59.6", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1537,17 +1707,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", - "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", + "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.6", - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1563,12 +1733,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", - "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", + "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/types": "5.59.7", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1801,6 +1971,12 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true + }, "node_modules/big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", @@ -2036,6 +2212,14 @@ "node": ">=10" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/ci-info": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", @@ -2320,6 +2504,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -2423,15 +2613,15 @@ } }, "node_modules/eslint": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", - "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.40.0", + "@eslint/js": "8.41.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2451,13 +2641,12 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -2852,6 +3041,28 @@ "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", "dev": true }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3008,6 +3219,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/h264-profile-level-id": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.0.1.tgz", @@ -3309,6 +3526,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4017,12 +4243,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4225,6 +4445,18 @@ "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", "dev": true }, + "node_modules/marked": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.2.tgz", + "integrity": "sha512-TXksm9GwqXCRNbFUZmMtqNLvy3K2cQHuWmyBDLOrY1e6i9UvZpOTJXoz7fBjYkJkaUFzV9hBFxMuZSyQt8R6KQ==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/meow": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", @@ -4335,6 +4567,48 @@ "node": ">= 6" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4358,6 +4632,25 @@ "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", "dev": true }, + "node_modules/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -5550,6 +5843,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -5680,6 +5989,11 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/trim-newlines": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", @@ -5838,6 +6152,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + }, "node_modules/untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", @@ -5935,6 +6255,20 @@ "makeerror": "1.0.12" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6057,8 +6391,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "17.7.1", @@ -6592,9 +6925,9 @@ } }, "@eslint/js": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", - "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", "dev": true }, "@humanwhocodes/config-array": { @@ -6987,6 +7320,137 @@ "fastq": "^1.6.0" } }, + "@octokit/auth-token": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", + "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", + "dev": true, + "requires": { + "@octokit/types": "^9.0.0" + } + }, + "@octokit/core": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", + "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", + "dev": true, + "requires": { + "@octokit/auth-token": "^3.0.0", + "@octokit/graphql": "^5.0.0", + "@octokit/request": "^6.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^9.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", + "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", + "dev": true, + "requires": { + "@octokit/types": "^9.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", + "dev": true, + "requires": { + "@octokit/request": "^6.0.0", + "@octokit/types": "^9.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", + "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==", + "dev": true + }, + "@octokit/plugin-paginate-rest": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", + "dev": true, + "requires": { + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" + } + }, + "@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "dev": true, + "requires": {} + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.1.2.tgz", + "integrity": "sha512-R0oJ7j6f/AdqPLtB9qRXLO+wjI9pctUn8Ka8UGfGaFCcCv3Otx14CshQ89K4E88pmyYZS8p0rNTiprML/81jig==", + "dev": true, + "requires": { + "@octokit/types": "^9.2.3", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", + "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", + "dev": true, + "requires": { + "@octokit/endpoint": "^7.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^9.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", + "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "dev": true, + "requires": { + "@octokit/types": "^9.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "19.0.11", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", + "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", + "dev": true, + "requires": { + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" + } + }, + "@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", + "dev": true + }, + "@octokit/types": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", + "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", + "dev": true, + "requires": { + "@octokit/openapi-types": "^17.2.0" + } + }, "@sinclair/typebox": { "version": "0.25.23", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.23.tgz", @@ -7059,9 +7523,9 @@ } }, "@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", + "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", "dev": true, "requires": { "@types/ms": "*" @@ -7180,15 +7644,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", - "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", + "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.6", - "@typescript-eslint/type-utils": "5.59.6", - "@typescript-eslint/utils": "5.59.6", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/type-utils": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7198,53 +7662,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", - "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", + "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.6", - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", - "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", + "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/visitor-keys": "5.59.6" + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7" } }, "@typescript-eslint/type-utils": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", - "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.7.tgz", + "integrity": "sha512-ozuz/GILuYG7osdY5O5yg0QxXUAEoI4Go3Do5xeu+ERH9PorHBPSdvD3Tjp2NN2bNLh1NJQSsQu2TPu/Ly+HaQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.59.6", - "@typescript-eslint/utils": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", - "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", + "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", - "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", + "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/visitor-keys": "5.59.6", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7253,28 +7717,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", - "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", + "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.6", - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", - "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", + "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/types": "5.59.7", "eslint-visitor-keys": "^3.3.0" } }, @@ -7439,6 +7903,12 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true + }, "big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", @@ -7595,6 +8065,11 @@ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "ci-info": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", @@ -7806,6 +8281,12 @@ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -7882,15 +8363,15 @@ "dev": true }, "eslint": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", - "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.40.0", + "@eslint/js": "8.41.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7910,13 +8391,12 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -8207,6 +8687,24 @@ "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", "dev": true }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -8314,6 +8812,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "h264-profile-level-id": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.0.1.tgz", @@ -8513,6 +9017,12 @@ "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -9053,12 +9563,6 @@ } } }, - "js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9212,6 +9716,12 @@ "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", "dev": true }, + "marked": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.2.tgz", + "integrity": "sha512-TXksm9GwqXCRNbFUZmMtqNLvy3K2cQHuWmyBDLOrY1e6i9UvZpOTJXoz7fBjYkJkaUFzV9hBFxMuZSyQt8R6KQ==", + "dev": true + }, "meow": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", @@ -9294,6 +9804,35 @@ "kind-of": "^6.0.3" } }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -9317,6 +9856,14 @@ "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", "dev": true }, + "node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -10135,6 +10682,19 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, "temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -10227,6 +10787,11 @@ "ieee754": "^1.2.1" } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "trim-newlines": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", @@ -10312,6 +10877,12 @@ "crypto-random-string": "^4.0.0" } }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + }, "untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", @@ -10386,6 +10957,20 @@ "makeerror": "1.0.12" } }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -10477,8 +11062,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { "version": "17.7.1", diff --git a/package.json b/package.json index 80c7e7c81a..1fba778411 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "typescript:build": "node npm-scripts.js typescript:build", "typescript:watch": "node npm-scripts.js typescript:watch", "worker:build": "node npm-scripts.js worker:build", + "worker:prebuild": "node npm-scripts.js worker:prebuild", "lint": "npm run lint:node && npm run lint:worker", "lint:node": "node npm-scripts.js lint:node", "lint:worker": "node npm-scripts.js lint:worker", @@ -64,7 +65,8 @@ "install-deps:node": "node npm-scripts.js install-deps:node", "install-clang-tools": "node npm-scripts.js install-clang-tools", "release:check": "node npm-scripts.js release:check", - "release": "node npm-scripts.js release" + "release": "node npm-scripts.js release", + "release:upload-mac-arm-prebuilt-worker": "node npm-scripts.js release:upload-mac-arm-prebuilt-worker" }, "jest": { "verbose": true, @@ -87,19 +89,23 @@ "dependencies": { "debug": "^4.3.4", "h264-profile-level-id": "^1.0.1", + "node-fetch": "^2.6.11", "supports-color": "^9.3.1", + "tar": "^6.1.15", "uuid": "^9.0.0" }, "devDependencies": { - "@types/debug": "^4.1.7", + "@octokit/rest": "^19.0.11", + "@types/debug": "^4.1.8", "@types/jest": "^29.5.1", "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.6", - "@typescript-eslint/parser": "^5.59.6", - "eslint": "^8.40.0", + "@typescript-eslint/eslint-plugin": "^5.59.7", + "@typescript-eslint/parser": "^5.59.7", + "eslint": "^8.41.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", + "marked": "^5.0.2", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From cf668882e695685025e210d0791aab99a38e37c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 26 May 2023 12:19:22 +0200 Subject: [PATCH 105/525] 3.12.0 --- CHANGELOG.md | 3 ++- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5964971e2..26199c6cfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ # Changelog -### NEXT +### 3.12.0 * Automate and publish prebuilt `mediasoup-worker` binaries ([PR #1087](https://github.com/versatica/mediasoup/pull/1087), thanks to @barlock for his work in ([PR #1083](https://github.com/versatica/mediasoup/pull/1083)). + ### 3.11.26 * `Worker`: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to @o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). diff --git a/package-lock.json b/package-lock.json index 26e7e6dee6..309cce6f0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.11.26", + "version": "3.12.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.11.26", + "version": "3.12.0", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 1fba778411..d68c2a9a58 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.11.26", + "version": "3.12.0", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From a30d27d8420a91c08ed94654d5566cd304074a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 26 May 2023 14:44:27 +0200 Subject: [PATCH 106/525] mediasoup-worker prebuild: Fallback to local building if fetched binary doesn't run on current host (#1090) --- CHANGELOG.md | 5 +++++ npm-scripts.js | 49 ++++++++++++++++++++++++++++++++++++--------- worker/src/lib.cpp | 12 +++++++---- worker/src/main.cpp | 13 +++--------- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26199c6cfe..b554313a43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +* mediasoup-worker prebuild: Fallback to local building if fetched binary doesn't run on current host ([PR #1090](https://github.com/versatica/mediasoup/pull/1090)). + + ### 3.12.0 * Automate and publish prebuilt `mediasoup-worker` binaries ([PR #1087](https://github.com/versatica/mediasoup/pull/1087), thanks to @barlock for his work in ([PR #1083](https://github.com/versatica/mediasoup/pull/1083)). diff --git a/npm-scripts.js b/npm-scripts.js index dfd048930b..14559faa1f 100644 --- a/npm-scripts.js +++ b/npm-scripts.js @@ -216,7 +216,7 @@ async function run() executeCmd(`git push origin v${MAYOR_VERSION}`); executeCmd(`git push origin '${PKG.version}'`); - logInfo('creating release in GitHub…'); + logInfo('creating release in GitHub'); await octokit.repos.createRelease( { @@ -529,16 +529,47 @@ async function downloadPrebuiltWorker() { // Give execution permission to the binary. fs.chmodSync(WORKER_RELEASE_BIN_PATH, 0o775); - - resolve(true); } catch (error) { - logError( - `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${error}` - ); + logWarn(`downloadPrebuiltWorker() | failed to give execution permissions to the mediasoup-worker prebuilt binary: ${error}`); + } + + // Let's confirm that the fetched mediasoup-worker prebuit binary does + // run in current host. This is to prevent weird issues related to + // different versions of libc in the system and so on. + // So run mediasoup-worker without the required MEDIASOUP_VERSION env and + // expect exit code 41 (see main.cpp). + + logInfo( + 'downloadPrebuiltWorker() | checking fetched mediasoup-worker prebuilt binary in current host' + ); - resolve(false); + try + { + execSync(`${WORKER_RELEASE_BIN_PATH}`, { stdio: [ 'ignore', 'ignore', 'ignore' ] }); + } + catch (error) + { + if (error.status === 41) + { + resolve(true); + } + else + { + logError( + `downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary fails to run in this host [status:${error.status}]` + ); + + try + { + fs.unlinkSync(WORKER_RELEASE_BIN_PATH); + } + catch (error2) + {} + + resolve(false); + } } }) .on('error', (error) => @@ -563,7 +594,7 @@ async function uploadMacArmPrebuiltWorker() const octokit = getOctokit(); - logInfo('uploadMacArmPrebuiltWorker() | getting release info…'); + logInfo('uploadMacArmPrebuiltWorker() | getting release info'); const release = await octokit.rest.repos.getReleaseByTag( { @@ -572,7 +603,7 @@ async function uploadMacArmPrebuiltWorker() tag : PKG.version }); - logInfo('uploadMacArmPrebuiltWorker() | uploading release asset…'); + logInfo('uploadMacArmPrebuiltWorker() | uploading release asset'); await octokit.rest.repos.uploadReleaseAsset( { diff --git a/worker/src/lib.cpp b/worker/src/lib.cpp index 86246cf270..705e1b7981 100644 --- a/worker/src/lib.cpp +++ b/worker/src/lib.cpp @@ -75,7 +75,8 @@ extern "C" int mediasoup_worker_run( DepLibUV::RunLoop(); DepLibUV::ClassDestroy(); - return 1; + // 40 is a custom exit code to notify "unknown error" to the Node library. + return 40; } try @@ -99,7 +100,8 @@ extern "C" int mediasoup_worker_run( DepLibUV::RunLoop(); DepLibUV::ClassDestroy(); - return 1; + // 40 is a custom exit code to notify "unknown error" to the Node library. + return 40; } // Initialize the Logger. @@ -130,7 +132,8 @@ extern "C" int mediasoup_worker_run( DepLibUV::RunLoop(); DepLibUV::ClassDestroy(); - return 1; + // 40 is a custom exit code to notify "unknown error" to the Node library. + return 40; } MS_DEBUG_TAG(info, "starting mediasoup-worker process [version:%s]", version); @@ -193,7 +196,8 @@ extern "C" int mediasoup_worker_run( { MS_ERROR_STD("failure exit: %s", error.what()); - return 1; + // 40 is a custom exit code to notify "unknown error" to the Node library. + return 40; } } diff --git a/worker/src/main.cpp b/worker/src/main.cpp index fcf4f47872..212b14ec26 100644 --- a/worker/src/main.cpp +++ b/worker/src/main.cpp @@ -18,7 +18,8 @@ int main(int argc, char* argv[]) { MS_ERROR_STD("you don't seem to be my real father!"); - std::_Exit(EXIT_FAILURE); + // 41 is a custom exit code to notify about "missing MEDIASOUP_VERSION" env. + std::_Exit(41); } const std::string version = std::getenv("MEDIASOUP_VERSION"); @@ -40,13 +41,5 @@ int main(int argc, char* argv[]) nullptr, nullptr); - switch (statusCode) - { - case 0: - std::_Exit(EXIT_SUCCESS); - case 1: - std::_Exit(EXIT_FAILURE); - case 42: - std::_Exit(42); - } + std::_Exit(statusCode); } From c0c4daec7dee0c6ee6a825c25ca031d05d375024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 26 May 2023 14:45:47 +0200 Subject: [PATCH 107/525] 3.12.1 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b554313a43..3d1ad2437e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.12.1 * mediasoup-worker prebuild: Fallback to local building if fetched binary doesn't run on current host ([PR #1090](https://github.com/versatica/mediasoup/pull/1090)). diff --git a/package-lock.json b/package-lock.json index 309cce6f0e..dc353dded0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.0", + "version": "3.12.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.0", + "version": "3.12.1", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index d68c2a9a58..04026948fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.0", + "version": "3.12.1", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 35d1a589c55c98a6753c7641e87b4808cda564c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 26 May 2023 17:49:20 +0200 Subject: [PATCH 108/525] npm-scripts.js: minor improvement --- npm-scripts.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/npm-scripts.js b/npm-scripts.js index 14559faa1f..1328272848 100644 --- a/npm-scripts.js +++ b/npm-scripts.js @@ -547,7 +547,14 @@ async function downloadPrebuiltWorker() try { - execSync(`${WORKER_RELEASE_BIN_PATH}`, { stdio: [ 'ignore', 'ignore', 'ignore' ] }); + execSync( + `${WORKER_RELEASE_BIN_PATH}`, + { + stdio : [ 'ignore', 'ignore', 'ignore' ], + // Ensure no env is passed to avoid accidents. + env : {} + } + ); } catch (error) { From 0bed828bf34de319d994debd07ebc160b30a121b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 May 2023 12:37:11 +0200 Subject: [PATCH 109/525] CI: Use ubuntu-20.04 to build mediasoup-worker prebuilt on Linux (#1092) Fixes #1089 --- .github/workflows/mediasoup-worker-prebuild.yaml | 6 +++++- CHANGELOG.md | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 19ee70c161..e5cac618d3 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -18,7 +18,11 @@ jobs: fail-fast: false matrix: build: - - os: ubuntu-22.04 + # For Linux let's use an old version of Ubuntu (20.04) that builds the + # mediasoup-worker binary using an old version of GLib, so it will work + # on Linux hosts running more modern GLib versions. + # See https://github.com/versatica/mediasoup/issues/1089. + - os: ubuntu-20.04 cc: gcc cxx: g++ - os: macos-12 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d1ad2437e..077e1dece3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +* CI: Use `ubuntu-20.04` to build mediasoup-worker prebuilt on Linux ([PR #1092](https://github.com/versatica/mediasoup/pull/1092)). + + ### 3.12.1 * mediasoup-worker prebuild: Fallback to local building if fetched binary doesn't run on current host ([PR #1090](https://github.com/versatica/mediasoup/pull/1090)). From ad298bf9cd939f73c70ddf8852fcefe3c3c448a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 May 2023 12:39:30 +0200 Subject: [PATCH 110/525] 3.12.2 --- CHANGELOG.md | 2 +- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 077e1dece3..1ae189d082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.12.2 * CI: Use `ubuntu-20.04` to build mediasoup-worker prebuilt on Linux ([PR #1092](https://github.com/versatica/mediasoup/pull/1092)). diff --git a/package-lock.json b/package-lock.json index dc353dded0..149e11c7bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.1", + "version": "3.12.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.1", + "version": "3.12.2", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -28,7 +28,7 @@ "eslint": "^8.41.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", - "marked": "^5.0.2", + "marked": "^5.0.3", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -4446,9 +4446,9 @@ "dev": true }, "node_modules/marked": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.2.tgz", - "integrity": "sha512-TXksm9GwqXCRNbFUZmMtqNLvy3K2cQHuWmyBDLOrY1e6i9UvZpOTJXoz7fBjYkJkaUFzV9hBFxMuZSyQt8R6KQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.3.tgz", + "integrity": "sha512-KUONa43Uk74uUNWMxh6lfaNYmSAsRMiDAaX8QBCCRVXzEufR0zX6T33vrGbvTnQLL02ungDM3KSzZtO+chJaHg==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -9717,9 +9717,9 @@ "dev": true }, "marked": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.2.tgz", - "integrity": "sha512-TXksm9GwqXCRNbFUZmMtqNLvy3K2cQHuWmyBDLOrY1e6i9UvZpOTJXoz7fBjYkJkaUFzV9hBFxMuZSyQt8R6KQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.3.tgz", + "integrity": "sha512-KUONa43Uk74uUNWMxh6lfaNYmSAsRMiDAaX8QBCCRVXzEufR0zX6T33vrGbvTnQLL02ungDM3KSzZtO+chJaHg==", "dev": true }, "meow": { diff --git a/package.json b/package.json index 04026948fb..6c61c1a8b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.1", + "version": "3.12.2", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -105,7 +105,7 @@ "eslint": "^8.41.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", - "marked": "^5.0.2", + "marked": "^5.0.3", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From 5ccd4d0a711925446181b3784b954b95e45a6023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 May 2023 13:48:16 +0200 Subject: [PATCH 111/525] Migrate npm-scripts.js to npm-scripts.mjs (ES Module) (#1093) --- .../workflows/mediasoup-worker-prebuild.yaml | 2 +- .github/workflows/mediasoup-worker.yaml | 2 +- CHANGELOG.md | 5 + npm-scripts.js => npm-scripts.mjs | 42 ++-- package-lock.json | 192 +++++++++++++++--- package.json | 40 ++-- 6 files changed, 212 insertions(+), 71 deletions(-) rename npm-scripts.js => npm-scripts.mjs (93%) diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index e5cac618d3..e825424b80 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -50,7 +50,7 @@ jobs: with: node-version: ${{ matrix.node }} - # We need to install some NPM production deps for npm-scripts.js to work. + # We need to install some NPM production deps for npm-scripts.mjs to work. - run: npm ci --ignore-scripts --omit=dev - run: npm run worker:build # Publish prebuild binaries on tag. diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index f0b0dc6fb9..5e1ad512c8 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -55,7 +55,7 @@ jobs: with: node-version: ${{ matrix.node }} - # We need to install some NPM production deps for npm-scripts.js to work. + # We need to install some NPM production deps for npm-scripts.mjs to work. - run: npm ci --ignore-scripts --omit=dev - run: npm run install-clang-tools # TODO: Maybe fix this one day. diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ae189d082..73623bdbc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://github.com/versatica/mediasoup/pull/1093)). + + ### 3.12.2 * CI: Use `ubuntu-20.04` to build mediasoup-worker prebuilt on Linux ([PR #1092](https://github.com/versatica/mediasoup/pull/1092)). diff --git a/npm-scripts.js b/npm-scripts.mjs similarity index 93% rename from npm-scripts.js rename to npm-scripts.mjs index 1328272848..20a6e450dc 100644 --- a/npm-scripts.js +++ b/npm-scripts.mjs @@ -1,9 +1,9 @@ -const process = require('process'); -const os = require('os'); -const fs = require('fs'); -const { execSync, spawnSync } = require('child_process'); -const fetch = require('node-fetch'); -const tar = require('tar'); +import process from 'process'; +import os from 'os'; +import fs from 'fs'; +import { execSync, spawnSync } from 'child_process'; +import fetch from 'node-fetch'; +import tar from 'tar'; const PKG = JSON.parse(fs.readFileSync('./package.json').toString()); const IS_FREEBSD = os.platform() === 'freebsd'; @@ -98,8 +98,8 @@ async function run() case 'typescript:watch': { - // NOTE: Load dep here since it's a devDependency. - const { TscWatchClient } = require('tsc-watch/client'); + // NOTE: Load dep on demand since it's a devDependency. + const { TscWatchClient } = await import('tsc-watch/client.js'); const watch = new TscWatchClient(); @@ -200,8 +200,8 @@ async function run() try { - octokit = getOctokit(); - versionChanges = getVersionChanges(); + octokit = await getOctokit(); + versionChanges = await getVersionChanges(); } catch (error) { @@ -357,7 +357,7 @@ function lintNode() { logInfo('lintNode()'); - executeCmd('eslint -c node/.eslintrc.js --max-warnings 0 node/src node/.eslintrc.js npm-scripts.js worker/scripts/gulpfile.js'); + executeCmd('eslint -c node/.eslintrc.js --max-warnings 0 node/src node/.eslintrc.js npm-scripts.mjs worker/scripts/gulpfile.js'); } function lintWorker() @@ -599,7 +599,7 @@ async function uploadMacArmPrebuiltWorker() return; } - const octokit = getOctokit(); + const octokit = await getOctokit(); logInfo('uploadMacArmPrebuiltWorker() | getting release info'); @@ -623,15 +623,15 @@ async function uploadMacArmPrebuiltWorker() }); } -function getOctokit() +async function getOctokit() { if (!process.env.GITHUB_TOKEN) { throw new Error('missing GITHUB_TOKEN environment variable'); } - // NOTE: Load dep here since it's a devDependency. - const { Octokit } = require('@octokit/rest'); + // NOTE: Load dep on demand since it's a devDependency. + const { Octokit } = await import('@octokit/rest'); const octokit = new Octokit( { @@ -641,12 +641,12 @@ function getOctokit() return octokit; } -function getVersionChanges() +async function getVersionChanges() { logInfo('getVersionChanges()'); - // NOTE: Load dep here since it's a devDependency. - const marked = require('marked'); + // NOTE: Load dep on demand since it's a devDependency. + const marked = await import('marked'); const changelog = fs.readFileSync('./CHANGELOG.md').toString(); const entries = marked.lexer(changelog); @@ -692,19 +692,19 @@ function executeCmd(command, exitOnError = true) function logInfo(message) { // eslint-disable-next-line no-console - console.log(`npm-scripts.js \x1b[36m[INFO] [${task}]\x1b\[0m`, message); + console.log(`npm-scripts \x1b[36m[INFO] [${task}]\x1b\[0m`, message); } function logWarn(message) { // eslint-disable-next-line no-console - console.warn(`npm-scripts.js \x1b[33m[WARN] [${task}]\x1b\[0m`, message); + console.warn(`npm-scripts \x1b[33m[WARN] [${task}]\x1b\[0m`, message); } function logError(message) { // eslint-disable-next-line no-console - console.error(`npm-scripts.js \x1b[31m[ERROR] [${task}]\x1b\[0m`, message); + console.error(`npm-scripts \x1b[31m[ERROR] [${task}]\x1b\[0m`, message); } function exitWithError() diff --git a/package-lock.json b/package-lock.json index 149e11c7bc..d9da74cc3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "dependencies": { "debug": "^4.3.4", "h264-profile-level-id": "^1.0.1", - "node-fetch": "^2.6.11", + "node-fetch": "^3.3.1", "supports-color": "^9.3.1", "tar": "^6.1.15", "uuid": "^9.0.0" @@ -21,7 +21,7 @@ "@octokit/rest": "^19.0.11", "@types/debug": "^4.1.8", "@types/jest": "^29.5.1", - "@types/node": "^18.15.11", + "@types/node": "^20.2.5", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.59.7", "@typescript-eslint/parser": "^5.59.7", @@ -1339,6 +1339,26 @@ "node": ">= 14" } }, + "node_modules/@octokit/request/node_modules/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/@octokit/rest": { "version": "19.0.11", "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", @@ -1511,9 +1531,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.15.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", - "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", + "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -2375,6 +2395,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2959,6 +2987,28 @@ "bser": "2.1.1" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -3035,6 +3085,17 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/from": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", @@ -4632,23 +4693,39 @@ "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", "dependencies": { - "whatwg-url": "^5.0.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, "node_modules/node-int64": { @@ -5992,7 +6069,8 @@ "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true }, "node_modules/trim-newlines": { "version": "4.0.2", @@ -6255,15 +6333,25 @@ "makeerror": "1.0.12" } }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -7411,6 +7499,17 @@ "is-plain-object": "^5.0.0", "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + } } }, "@octokit/request-error": { @@ -7593,9 +7692,9 @@ "dev": true }, "@types/node": { - "version": "18.15.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", - "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", + "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", "dev": true }, "@types/normalize-package-data": { @@ -8197,6 +8296,11 @@ } } }, + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -8626,6 +8730,15 @@ "bser": "2.1.1" } }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -8681,6 +8794,14 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, "from": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", @@ -9856,12 +9977,19 @@ "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", "dev": true }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, "node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", "requires": { - "whatwg-url": "^5.0.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" } }, "node-int64": { @@ -10790,7 +10918,8 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true }, "trim-newlines": { "version": "4.0.2", @@ -10957,15 +11086,22 @@ "makeerror": "1.0.12" } }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" diff --git a/package.json b/package.json index 6c61c1a8b4..5ee1628b88 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "worker/Makefile", "worker/meson.build", "worker/meson_options.txt", - "npm-scripts.js" + "npm-scripts.mjs" ], "keywords": [ "webrtc", @@ -48,25 +48,25 @@ "node": ">=16" }, "scripts": { - "prepare": "node npm-scripts.js prepare", - "postinstall": "node npm-scripts.js postinstall", - "typescript:build": "node npm-scripts.js typescript:build", - "typescript:watch": "node npm-scripts.js typescript:watch", - "worker:build": "node npm-scripts.js worker:build", - "worker:prebuild": "node npm-scripts.js worker:prebuild", + "prepare": "node npm-scripts.mjs prepare", + "postinstall": "node npm-scripts.mjs postinstall", + "typescript:build": "node npm-scripts.mjs typescript:build", + "typescript:watch": "node npm-scripts.mjs typescript:watch", + "worker:build": "node npm-scripts.mjs worker:build", + "worker:prebuild": "node npm-scripts.mjs worker:prebuild", "lint": "npm run lint:node && npm run lint:worker", - "lint:node": "node npm-scripts.js lint:node", - "lint:worker": "node npm-scripts.js lint:worker", - "format:worker": "node npm-scripts.js format:worker", + "lint:node": "node npm-scripts.mjs lint:node", + "lint:worker": "node npm-scripts.mjs lint:worker", + "format:worker": "node npm-scripts.mjs format:worker", "test": "npm run test:node && npm run test:worker", - "test:node": "node npm-scripts.js test:node", - "test:worker": "node npm-scripts.js test:worker", - "coverage:node": "node npm-scripts.js coverage:node", - "install-deps:node": "node npm-scripts.js install-deps:node", - "install-clang-tools": "node npm-scripts.js install-clang-tools", - "release:check": "node npm-scripts.js release:check", - "release": "node npm-scripts.js release", - "release:upload-mac-arm-prebuilt-worker": "node npm-scripts.js release:upload-mac-arm-prebuilt-worker" + "test:node": "node npm-scripts.mjs test:node", + "test:worker": "node npm-scripts.mjs test:worker", + "coverage:node": "node npm-scripts.mjs coverage:node", + "install-deps:node": "node npm-scripts.mjs install-deps:node", + "install-clang-tools": "node npm-scripts.mjs install-clang-tools", + "release:check": "node npm-scripts.mjs release:check", + "release": "node npm-scripts.mjs release", + "release:upload-mac-arm-prebuilt-worker": "node npm-scripts.mjs release:upload-mac-arm-prebuilt-worker" }, "jest": { "verbose": true, @@ -89,7 +89,7 @@ "dependencies": { "debug": "^4.3.4", "h264-profile-level-id": "^1.0.1", - "node-fetch": "^2.6.11", + "node-fetch": "^3.3.1", "supports-color": "^9.3.1", "tar": "^6.1.15", "uuid": "^9.0.0" @@ -98,7 +98,7 @@ "@octokit/rest": "^19.0.11", "@types/debug": "^4.1.8", "@types/jest": "^29.5.1", - "@types/node": "^18.15.11", + "@types/node": "^20.2.5", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.59.7", "@typescript-eslint/parser": "^5.59.7", From ccf6c43c4a393e3577c3d44f65bcb2d52d628dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 May 2023 13:50:29 +0200 Subject: [PATCH 112/525] 3.12.3 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73623bdbc6..e29c6758e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.12.3 Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://github.com/versatica/mediasoup/pull/1093)). diff --git a/package-lock.json b/package-lock.json index d9da74cc3b..a1acc22cbe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.2", + "version": "3.12.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.2", + "version": "3.12.3", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 5ee1628b88..613c2ffb51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.2", + "version": "3.12.3", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 313d1f86a49cac9cdda137434e8d84c0889eaee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 May 2023 14:07:34 +0200 Subject: [PATCH 113/525] npm-scripts 'postinstall': do NOT clear worker artifacts if MEDIASOUP_LOCAL_DEV is set --- npm-scripts.mjs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 20a6e450dc..bc3b532314 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -73,7 +73,11 @@ async function run() logInfo('skipping mediasoup-worker prebuilt download, building it locally'); buildWorker(); - cleanWorkerArtifacts(); + + if (!process.env.MEDIASOUP_LOCAL_DEV) + { + cleanWorkerArtifacts(); + } } // Attempt to download a prebuilt binary. Fallback to building locally. else if (!(await downloadPrebuiltWorker())) From 652f90f25816d368cd5f3aa2e8b6218350001a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 May 2023 14:11:40 +0200 Subject: [PATCH 114/525] Also migrate worker/scripts/gulpfile.js to ES module --- npm-scripts.mjs | 2 +- worker/Makefile | 4 ++-- worker/scripts/{gulpfile.js => gulpfile.mjs} | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename worker/scripts/{gulpfile.js => gulpfile.mjs} (85%) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index bc3b532314..2d99f5b6e6 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -361,7 +361,7 @@ function lintNode() { logInfo('lintNode()'); - executeCmd('eslint -c node/.eslintrc.js --max-warnings 0 node/src node/.eslintrc.js npm-scripts.mjs worker/scripts/gulpfile.js'); + executeCmd('eslint -c node/.eslintrc.js --max-warnings 0 node/src node/.eslintrc.js npm-scripts.mjs worker/scripts/gulpfile.mjs'); } function lintWorker() diff --git a/worker/Makefile b/worker/Makefile index 8dcd424453..ed969cce4c 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -208,10 +208,10 @@ xcode: setup $(MESON) setup --buildtype debug --backend xcode $(MEDIASOUP_OUT_DIR)/xcode lint: - $(GULP) --gulpfile ./scripts/gulpfile.js lint:worker + $(GULP) --gulpfile ./scripts/gulpfile.mjs lint:worker format: - $(GULP) --gulpfile ./scripts/gulpfile.js format:worker + $(GULP) --gulpfile ./scripts/gulpfile.mjs format:worker test: setup $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test diff --git a/worker/scripts/gulpfile.js b/worker/scripts/gulpfile.mjs similarity index 85% rename from worker/scripts/gulpfile.js rename to worker/scripts/gulpfile.mjs index 9859a1530d..b4c3e9650d 100644 --- a/worker/scripts/gulpfile.js +++ b/worker/scripts/gulpfile.mjs @@ -1,5 +1,5 @@ -const gulp = require('gulp'); -const clangFormat = require('gulp-clang-format'); +import gulp from 'gulp'; +import clangFormat from 'gulp-clang-format'; const workerFiles = [ From 525ac76717292741b89db145a4128e9595d1f587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 6 Jun 2023 10:47:50 +0200 Subject: [PATCH 115/525] Update NPM deps --- package-lock.json | 254 +++++++++++++++++++++++----------------------- package.json | 12 +-- 2 files changed, 133 insertions(+), 133 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1acc22cbe..2912e2dfea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,21 +20,21 @@ "devDependencies": { "@octokit/rest": "^19.0.11", "@types/debug": "^4.1.8", - "@types/jest": "^29.5.1", + "@types/jest": "^29.5.2", "@types/node": "^20.2.5", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.7", - "@typescript-eslint/parser": "^5.59.7", - "eslint": "^8.41.0", + "@typescript-eslint/eslint-plugin": "^5.59.9", + "@typescript-eslint/parser": "^5.59.9", + "eslint": "^8.42.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", - "marked": "^5.0.3", + "marked": "^5.0.4", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.0", "tsc-watch": "^6.0.4", - "typescript": "^5.0.4" + "typescript": "^5.1.3" }, "engines": { "node": ">=16" @@ -694,18 +694,18 @@ } }, "node_modules/@eslint/js": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", + "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -1503,9 +1503,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", - "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", + "version": "29.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", + "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1582,15 +1582,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", - "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", + "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/type-utils": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@typescript-eslint/scope-manager": "5.59.9", + "@typescript-eslint/type-utils": "5.59.9", + "@typescript-eslint/utils": "5.59.9", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1616,14 +1616,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", - "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", + "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/scope-manager": "5.59.9", + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/typescript-estree": "5.59.9", "debug": "^4.3.4" }, "engines": { @@ -1643,13 +1643,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", - "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", + "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7" + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/visitor-keys": "5.59.9" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1660,13 +1660,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.7.tgz", - "integrity": "sha512-ozuz/GILuYG7osdY5O5yg0QxXUAEoI4Go3Do5xeu+ERH9PorHBPSdvD3Tjp2NN2bNLh1NJQSsQu2TPu/Ly+HaQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", + "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/utils": "5.59.9", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1687,9 +1687,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", - "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", + "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1700,13 +1700,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", - "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", + "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7", + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/visitor-keys": "5.59.9", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1727,17 +1727,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", - "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", + "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/scope-manager": "5.59.9", + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/typescript-estree": "5.59.9", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1753,12 +1753,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", - "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", + "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/types": "5.59.9", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2641,16 +2641,16 @@ } }, "node_modules/eslint": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", + "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.41.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint/js": "8.42.0", + "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", @@ -4507,9 +4507,9 @@ "dev": true }, "node_modules/marked": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.3.tgz", - "integrity": "sha512-KUONa43Uk74uUNWMxh6lfaNYmSAsRMiDAaX8QBCCRVXzEufR0zX6T33vrGbvTnQLL02ungDM3KSzZtO+chJaHg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.4.tgz", + "integrity": "sha512-r0W8/DK56fAkV0qfUCO9cEt/VlFWUzoJOqEigvijmsVkTuPOHckh7ZutNJepRO1AxHhK96/9txonHg4bWd/aLA==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -6203,16 +6203,16 @@ } }, "node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", + "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=12.20" + "node": ">=14.17" } }, "node_modules/unique-string": { @@ -7013,15 +7013,15 @@ } }, "@eslint/js": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", + "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", "dev": true }, "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -7664,9 +7664,9 @@ } }, "@types/jest": { - "version": "29.5.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", - "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", + "version": "29.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", + "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", "dev": true, "requires": { "expect": "^29.0.0", @@ -7743,15 +7743,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", - "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", + "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/type-utils": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@typescript-eslint/scope-manager": "5.59.9", + "@typescript-eslint/type-utils": "5.59.9", + "@typescript-eslint/utils": "5.59.9", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7761,53 +7761,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", - "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", + "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/scope-manager": "5.59.9", + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/typescript-estree": "5.59.9", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", - "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", + "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7" + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/visitor-keys": "5.59.9" } }, "@typescript-eslint/type-utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.7.tgz", - "integrity": "sha512-ozuz/GILuYG7osdY5O5yg0QxXUAEoI4Go3Do5xeu+ERH9PorHBPSdvD3Tjp2NN2bNLh1NJQSsQu2TPu/Ly+HaQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", + "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/utils": "5.59.9", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", - "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", + "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", - "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", + "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7", + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/visitor-keys": "5.59.9", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7816,28 +7816,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", - "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", + "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/scope-manager": "5.59.9", + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/typescript-estree": "5.59.9", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", - "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", + "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/types": "5.59.9", "eslint-visitor-keys": "^3.3.0" } }, @@ -8467,16 +8467,16 @@ "dev": true }, "eslint": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", + "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.41.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint/js": "8.42.0", + "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", @@ -9838,9 +9838,9 @@ "dev": true }, "marked": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.3.tgz", - "integrity": "sha512-KUONa43Uk74uUNWMxh6lfaNYmSAsRMiDAaX8QBCCRVXzEufR0zX6T33vrGbvTnQLL02ungDM3KSzZtO+chJaHg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.4.tgz", + "integrity": "sha512-r0W8/DK56fAkV0qfUCO9cEt/VlFWUzoJOqEigvijmsVkTuPOHckh7ZutNJepRO1AxHhK96/9txonHg4bWd/aLA==", "dev": true }, "meow": { @@ -10992,9 +10992,9 @@ "dev": true }, "typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", + "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index 613c2ffb51..eae1e89ed7 100644 --- a/package.json +++ b/package.json @@ -97,20 +97,20 @@ "devDependencies": { "@octokit/rest": "^19.0.11", "@types/debug": "^4.1.8", - "@types/jest": "^29.5.1", + "@types/jest": "^29.5.2", "@types/node": "^20.2.5", "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.7", - "@typescript-eslint/parser": "^5.59.7", - "eslint": "^8.41.0", + "@typescript-eslint/eslint-plugin": "^5.59.9", + "@typescript-eslint/parser": "^5.59.9", + "eslint": "^8.42.0", "eslint-plugin-jest": "^27.2.1", "jest": "^29.5.0", - "marked": "^5.0.3", + "marked": "^5.0.4", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.0", "tsc-watch": "^6.0.4", - "typescript": "^5.0.4" + "typescript": "^5.1.3" } } From dd3533f0241e16c6dd6448e5d09c131732de3e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 16 Jun 2023 10:54:43 +0200 Subject: [PATCH 116/525] Downgrade types/node to version 18 because Node 20 is not yet stable --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2912e2dfea..0bda7e7fdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@octokit/rest": "^19.0.11", "@types/debug": "^4.1.8", "@types/jest": "^29.5.2", - "@types/node": "^20.2.5", + "@types/node": "^18.16.18", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", @@ -1531,9 +1531,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", + "version": "18.16.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.18.tgz", + "integrity": "sha512-/aNaQZD0+iSBAGnvvN2Cx92HqE5sZCPZtx2TsK+4nvV23fFe09jVDvpArXr2j9DnYlzuU9WuoykDDc6wqvpNcw==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -7692,9 +7692,9 @@ "dev": true }, "@types/node": { - "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", + "version": "18.16.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.18.tgz", + "integrity": "sha512-/aNaQZD0+iSBAGnvvN2Cx92HqE5sZCPZtx2TsK+4nvV23fFe09jVDvpArXr2j9DnYlzuU9WuoykDDc6wqvpNcw==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index eae1e89ed7..880bb90931 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "@octokit/rest": "^19.0.11", "@types/debug": "^4.1.8", "@types/jest": "^29.5.2", - "@types/node": "^20.2.5", + "@types/node": "^18.16.18", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", From fe62c16722157deb89db71df318886c162580855 Mon Sep 17 00:00:00 2001 From: woodfe Date: Fri, 23 Jun 2023 16:27:39 +0800 Subject: [PATCH 117/525] fix downloaded prebuilt binary check on Windows (#1105) --- npm-scripts.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 2d99f5b6e6..caefbb3eb8 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -4,6 +4,7 @@ import fs from 'fs'; import { execSync, spawnSync } from 'child_process'; import fetch from 'node-fetch'; import tar from 'tar'; +import path from 'path'; const PKG = JSON.parse(fs.readFileSync('./package.json').toString()); const IS_FREEBSD = os.platform() === 'freebsd'; @@ -551,8 +552,9 @@ async function downloadPrebuiltWorker() try { + const resolvedBinPath = path.resolve(WORKER_RELEASE_BIN_PATH); execSync( - `${WORKER_RELEASE_BIN_PATH}`, + resolvedBinPath, { stdio : [ 'ignore', 'ignore', 'ignore' ], // Ensure no env is passed to avoid accidents. From f882b998493d78cb08b591eeb651cafb1725b1af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 23 Jun 2023 10:38:28 +0200 Subject: [PATCH 118/525] 3.12.4 --- CHANGELOG.md | 5 + npm-scripts.mjs | 3 +- package-lock.json | 257 +++++++++++++++++++++++----------------------- package.json | 16 +-- 4 files changed, 144 insertions(+), 137 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e29c6758e9..12abb6ece8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.12.4 + +* Fix downloaded prebuilt binary check on Windows ([PR #1105](https://github.com/versatica/mediasoup/pull/1105) by @woodfe). + + ### 3.12.3 Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://github.com/versatica/mediasoup/pull/1093)). diff --git a/npm-scripts.mjs b/npm-scripts.mjs index caefbb3eb8..2a8d4ea7a2 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -1,10 +1,10 @@ import process from 'process'; import os from 'os'; import fs from 'fs'; +import path from 'path'; import { execSync, spawnSync } from 'child_process'; import fetch from 'node-fetch'; import tar from 'tar'; -import path from 'path'; const PKG = JSON.parse(fs.readFileSync('./package.json').toString()); const IS_FREEBSD = os.platform() === 'freebsd'; @@ -553,6 +553,7 @@ async function downloadPrebuiltWorker() try { const resolvedBinPath = path.resolve(WORKER_RELEASE_BIN_PATH); + execSync( resolvedBinPath, { diff --git a/package-lock.json b/package-lock.json index 0bda7e7fdd..6a0a6ad7a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.3", + "version": "3.12.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.3", + "version": "3.12.4", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -18,17 +18,17 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@octokit/rest": "^19.0.11", + "@octokit/rest": "^19.0.13", "@types/debug": "^4.1.8", "@types/jest": "^29.5.2", "@types/node": "^18.16.18", - "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.9", - "@typescript-eslint/parser": "^5.59.9", - "eslint": "^8.42.0", - "eslint-plugin-jest": "^27.2.1", + "@types/uuid": "^9.0.2", + "@typescript-eslint/eslint-plugin": "^5.60.0", + "@typescript-eslint/parser": "^5.60.0", + "eslint": "^8.43.0", + "eslint-plugin-jest": "^27.2.2", "jest": "^29.5.0", - "marked": "^5.0.4", + "marked": "^5.1.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -694,9 +694,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", - "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", + "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1360,9 +1360,9 @@ } }, "node_modules/@octokit/rest": { - "version": "19.0.11", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", - "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", + "version": "19.0.13", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", + "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", "dev": true, "dependencies": { "@octokit/core": "^4.2.1", @@ -1561,9 +1561,9 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", "dev": true }, "node_modules/@types/yargs": { @@ -1582,15 +1582,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", - "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz", + "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/type-utils": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.0", + "@typescript-eslint/type-utils": "5.60.0", + "@typescript-eslint/utils": "5.60.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1616,14 +1616,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", - "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz", + "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.0", + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/typescript-estree": "5.60.0", "debug": "^4.3.4" }, "engines": { @@ -1643,13 +1643,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", - "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz", + "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9" + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/visitor-keys": "5.60.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1660,13 +1660,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", - "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz", + "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/utils": "5.60.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1687,9 +1687,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", - "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz", + "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1700,13 +1700,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", - "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz", + "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9", + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/visitor-keys": "5.60.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1727,17 +1727,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", - "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz", + "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.0", + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/typescript-estree": "5.60.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1753,12 +1753,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", - "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz", + "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/types": "5.60.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2641,15 +2641,15 @@ } }, "node_modules/eslint": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", - "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", + "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.42.0", + "@eslint/js": "8.43.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2697,9 +2697,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz", - "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==", + "version": "27.2.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz", + "integrity": "sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -2709,7 +2709,8 @@ }, "peerDependencies": { "@typescript-eslint/eslint-plugin": "^5.0.0", - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0", + "jest": "*" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -4507,9 +4508,9 @@ "dev": true }, "node_modules/marked": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.4.tgz", - "integrity": "sha512-r0W8/DK56fAkV0qfUCO9cEt/VlFWUzoJOqEigvijmsVkTuPOHckh7ZutNJepRO1AxHhK96/9txonHg4bWd/aLA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.0.tgz", + "integrity": "sha512-z3/nBe7aTI8JDszlYLk7dDVNpngjw0o1ZJtrA9kIfkkHcIF+xH7mO23aISl4WxP83elU+MFROgahqdpd05lMEQ==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -7013,9 +7014,9 @@ } }, "@eslint/js": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", - "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", + "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", "dev": true }, "@humanwhocodes/config-array": { @@ -7524,9 +7525,9 @@ } }, "@octokit/rest": { - "version": "19.0.11", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", - "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", + "version": "19.0.13", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", + "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", "dev": true, "requires": { "@octokit/core": "^4.2.1", @@ -7722,9 +7723,9 @@ "dev": true }, "@types/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", "dev": true }, "@types/yargs": { @@ -7743,15 +7744,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", - "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz", + "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/type-utils": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.0", + "@typescript-eslint/type-utils": "5.60.0", + "@typescript-eslint/utils": "5.60.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -7761,53 +7762,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", - "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz", + "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.0", + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/typescript-estree": "5.60.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", - "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz", + "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9" + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/visitor-keys": "5.60.0" } }, "@typescript-eslint/type-utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", - "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz", + "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/utils": "5.60.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", - "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz", + "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", - "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz", + "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9", + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/visitor-keys": "5.60.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7816,28 +7817,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", - "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz", + "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.0", + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/typescript-estree": "5.60.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", - "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz", + "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/types": "5.60.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -8467,15 +8468,15 @@ "dev": true }, "eslint": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", - "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", + "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.42.0", + "@eslint/js": "8.43.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -8532,9 +8533,9 @@ } }, "eslint-plugin-jest": { - "version": "27.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz", - "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==", + "version": "27.2.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz", + "integrity": "sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" @@ -9838,9 +9839,9 @@ "dev": true }, "marked": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.0.4.tgz", - "integrity": "sha512-r0W8/DK56fAkV0qfUCO9cEt/VlFWUzoJOqEigvijmsVkTuPOHckh7ZutNJepRO1AxHhK96/9txonHg4bWd/aLA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.0.tgz", + "integrity": "sha512-z3/nBe7aTI8JDszlYLk7dDVNpngjw0o1ZJtrA9kIfkkHcIF+xH7mO23aISl4WxP83elU+MFROgahqdpd05lMEQ==", "dev": true }, "meow": { diff --git a/package.json b/package.json index 880bb90931..cecdfbaa78 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.3", + "version": "3.12.4", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -95,17 +95,17 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@octokit/rest": "^19.0.11", + "@octokit/rest": "^19.0.13", "@types/debug": "^4.1.8", "@types/jest": "^29.5.2", "@types/node": "^18.16.18", - "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.9", - "@typescript-eslint/parser": "^5.59.9", - "eslint": "^8.42.0", - "eslint-plugin-jest": "^27.2.1", + "@types/uuid": "^9.0.2", + "@typescript-eslint/eslint-plugin": "^5.60.0", + "@typescript-eslint/parser": "^5.60.0", + "eslint": "^8.43.0", + "eslint-plugin-jest": "^27.2.2", "jest": "^29.5.0", - "marked": "^5.0.4", + "marked": "^5.1.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From 369a0157fa953a712f95bf12b56f999f9bd435cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 26 Jun 2023 12:12:23 +0200 Subject: [PATCH 119/525] Remove tsc-watch and use tsc --watch built-in feature (#1106) --- node/src/tests/test-AudioLevelObserver.ts | 1 + node/src/tests/test-mediasoup.ts | 4 +- node/tsconfig.json | 8 +- npm-scripts.mjs | 9 +- package-lock.json | 220 ---------------------- package.json | 1 - 6 files changed, 11 insertions(+), 232 deletions(-) diff --git a/node/src/tests/test-AudioLevelObserver.ts b/node/src/tests/test-AudioLevelObserver.ts index cc8155e3a5..e82be0c7dd 100644 --- a/node/src/tests/test-AudioLevelObserver.ts +++ b/node/src/tests/test-AudioLevelObserver.ts @@ -1,4 +1,5 @@ import * as mediasoup from '../'; + const { createWorker } = mediasoup; let worker: mediasoup.types.Worker; diff --git a/node/src/tests/test-mediasoup.ts b/node/src/tests/test-mediasoup.ts index 706341748e..ea080b7bb6 100644 --- a/node/src/tests/test-mediasoup.ts +++ b/node/src/tests/test-mediasoup.ts @@ -19,7 +19,7 @@ test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabili const rtpCapabilities2 = getSupportedRtpCapabilities(); expect(rtpCapabilities2).not.toEqual(rtpCapabilities); -}, 500); +}); test('parseScalabilityMode() works', () => { @@ -52,4 +52,4 @@ test('parseScalabilityMode() works', () => expect(parseScalabilityMode('L4T7_KEY_SHIFT')) .toEqual({ spatialLayers: 4, temporalLayers: 7, ksvc: true }); -}, 500); +}); diff --git a/node/tsconfig.json b/node/tsconfig.json index 9196896ea0..bcdc2139c1 100644 --- a/node/tsconfig.json +++ b/node/tsconfig.json @@ -11,5 +11,11 @@ "declaration": true, "declarationMap": true }, - "include": [ "src" ] + "include": [ "src" ], + "watchOptions": { + "watchFile": "useFsEvents", + "watchDirectory": "useFsEvents", + "fallbackPolling": "dynamicPriority", + "synchronousWatchDirectory": true + } } diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 2a8d4ea7a2..d0d0d678c6 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -103,15 +103,8 @@ async function run() case 'typescript:watch': { - // NOTE: Load dep on demand since it's a devDependency. - const { TscWatchClient } = await import('tsc-watch/client.js'); - - const watch = new TscWatchClient(); - deleteNodeLib(); - - watch.on('success', replaceVersion); - watch.start('--project', 'node', '--pretty'); + executeCmd('tsc --project node --watch'); break; } diff --git a/package-lock.json b/package-lock.json index 6a0a6ad7a4..6bd7603847 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,6 @@ "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.0", - "tsc-watch": "^6.0.4", "typescript": "^5.1.3" }, "engines": { @@ -2580,12 +2579,6 @@ "node": ">=6.0.0" } }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, "node_modules/electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -2861,21 +2854,6 @@ "node": ">=0.10.0" } }, - "node_modules/event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -3097,12 +3075,6 @@ "node": ">=12.20.0" } }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", - "dev": true - }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -4501,12 +4473,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", - "dev": true - }, "node_modules/marked": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.0.tgz", @@ -4688,12 +4654,6 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, - "node_modules/node-cleanup": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", - "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", - "dev": true - }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -4978,15 +4938,6 @@ "node": ">=8" } }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dev": true, - "dependencies": { - "through": "~2.3" - } - }, "node_modules/peek-readable": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", @@ -5154,21 +5105,6 @@ "node": ">= 6" } }, - "node_modules/ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "dev": true, - "dependencies": { - "event-stream": "=3.3.4" - }, - "bin": { - "ps-tree": "bin/ps-tree.js" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -5722,18 +5658,6 @@ "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, - "node_modules/split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -5761,15 +5685,6 @@ "node": ">=8" } }, - "node_modules/stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5779,15 +5694,6 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -6008,12 +5914,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, "node_modules/titleize": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", @@ -6128,27 +6028,6 @@ } } }, - "node_modules/tsc-watch": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.4.tgz", - "integrity": "sha512-cHvbvhjO86w2aGlaHgSCeQRl+Aqw6X6XN4sQMPZKF88GoP30O+oTuh5lRIJr5pgFWrRpF1AgXnJJ2DoFEIPHyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "node-cleanup": "^2.1.2", - "ps-tree": "^1.2.0", - "string-argv": "^0.3.1" - }, - "bin": { - "tsc-watch": "dist/lib/tsc-watch.js" - }, - "engines": { - "node": ">=12.12.0" - }, - "peerDependencies": { - "typescript": "*" - } - }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -8422,12 +8301,6 @@ "esutils": "^2.0.2" } }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, "electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -8620,21 +8493,6 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -8803,12 +8661,6 @@ "fetch-blob": "^3.1.2" } }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", - "dev": true - }, "fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -9832,12 +9684,6 @@ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", - "dev": true - }, "marked": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.0.tgz", @@ -9972,12 +9818,6 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, - "node-cleanup": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", - "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", - "dev": true - }, "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -10170,15 +10010,6 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dev": true, - "requires": { - "through": "~2.3" - } - }, "peek-readable": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", @@ -10301,15 +10132,6 @@ "sisteransi": "^1.0.5" } }, - "ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "dev": true, - "requires": { - "event-stream": "=3.3.4" - } - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -10671,15 +10493,6 @@ "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "dev": true, - "requires": { - "through": "2" - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -10703,15 +10516,6 @@ } } }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -10721,12 +10525,6 @@ "safe-buffer": "~5.2.0" } }, - "string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true - }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -10873,12 +10671,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, "titleize": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", @@ -10944,18 +10736,6 @@ "yargs-parser": "^21.0.1" } }, - "tsc-watch": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.4.tgz", - "integrity": "sha512-cHvbvhjO86w2aGlaHgSCeQRl+Aqw6X6XN4sQMPZKF88GoP30O+oTuh5lRIJr5pgFWrRpF1AgXnJJ2DoFEIPHyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "node-cleanup": "^2.1.2", - "ps-tree": "^1.2.0", - "string-argv": "^0.3.1" - } - }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", diff --git a/package.json b/package.json index cecdfbaa78..380e583769 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,6 @@ "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.0", - "tsc-watch": "^6.0.4", "typescript": "^5.1.3" } } From 217ce025ed74860766c1e5bb0ccf3446502d4b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 26 Jun 2023 12:20:39 +0200 Subject: [PATCH 120/525] npm-scripts: improve replaceVersion() --- npm-scripts.mjs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index d0d0d678c6..52f995a738 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -263,19 +263,24 @@ function replaceVersion() { logInfo('replaceVersion()'); - const files = - [ - 'node/lib/index.js', - 'node/lib/index.d.ts', - 'node/lib/Worker.js' - ]; + const files = fs.readdirSync('node/lib', + { + withFileTypes : true, + recursive : true + }); for (const file of files) { - const text = fs.readFileSync(file, { encoding: 'utf8' }); + if (!file.isFile()) + { + continue; + } + + const filePath = path.join('node/lib', file.name); + const text = fs.readFileSync(filePath, { encoding: 'utf8' }); const result = text.replace(/__MEDIASOUP_VERSION__/g, PKG.version); - fs.writeFileSync(file, result, { encoding: 'utf8' }); + fs.writeFileSync(filePath, result, { encoding: 'utf8' }); } } From 760f203dfe19aabe2e46684d8c7814e3cee6dd30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 7 Jul 2023 12:01:56 +0200 Subject: [PATCH 121/525] Node: make types.ts only export types rather than the entire class/code (#1109) Same as in https://github.com/versatica/mediasoup-client/issues/273 --- node/src/types.ts | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/node/src/types.ts b/node/src/types.ts index fe72cb95fb..51b20a6a02 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -1,23 +1,24 @@ -export * from './Worker'; -export * from './WebRtcServer'; -export * from './Router'; -export * from './Transport'; -export * from './WebRtcTransport'; -export * from './PlainTransport'; -export * from './PipeTransport'; -export * from './DirectTransport'; -export * from './Producer'; -export * from './Consumer'; -export * from './DataProducer'; -export * from './DataConsumer'; -export * from './RtpObserver'; -export * from './ActiveSpeakerObserver'; -export * from './AudioLevelObserver'; -export * from './RtpParameters'; -export * from './SctpParameters'; -export * from './SrtpParameters'; +export type * from './Worker'; +export type * from './WebRtcServer'; +export type * from './Router'; +export type * from './Transport'; +export type * from './WebRtcTransport'; +export type * from './PlainTransport'; +export type * from './PipeTransport'; +export type * from './DirectTransport'; +export type * from './Producer'; +export type * from './Consumer'; +export type * from './DataProducer'; +export type * from './DataConsumer'; +export type * from './RtpObserver'; +export type * from './ActiveSpeakerObserver'; +export type * from './AudioLevelObserver'; +export type * from './RtpParameters'; +export type * from './SctpParameters'; +export type * from './SrtpParameters'; +// We cannot export only the type of error classes because those are useless. export * from './errors'; -export { ScalabilityMode } from './scalabilityModes'; +export type { ScalabilityMode } from './scalabilityModes'; export type AppData = { From f6c7a179f01b31978e95dead761546062ebcf72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 10 Jul 2023 10:34:22 +0200 Subject: [PATCH 122/525] DataConsumer: Fix, send 'bufferedamountlow' notification (#1113) Removed by error in previous commit ed15a863a5ed095f58a16d972c8e25bf24f17933 --- worker/src/RTC/DataConsumer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/worker/src/RTC/DataConsumer.cpp b/worker/src/RTC/DataConsumer.cpp index 9add8cab3b..f96fd64ad7 100644 --- a/worker/src/RTC/DataConsumer.cpp +++ b/worker/src/RTC/DataConsumer.cpp @@ -212,6 +212,8 @@ namespace RTC data.append(std::to_string(this->bufferedAmount)); data.append("}"); + + this->shared->channelNotifier->Emit(this->id, "bufferedamountlow", data); } // Force the trigger of 'bufferedamountlow' once there is less or same // buffered data than the given threshold. From 9940300518a931bc00a1411551b8d6dfbfbb2ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 10 Jul 2023 10:39:52 +0200 Subject: [PATCH 123/525] 3.12.5 --- CHANGELOG.md | 5 + package-lock.json | 1680 ++++++++++++++++++++++----------------------- package.json | 18 +- 3 files changed, 847 insertions(+), 856 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12abb6ece8..c4e6f622ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.12.5 + +* `DataConsumer`: Fix removed 'bufferedamountlow' notification ([PR #1113](https://github.com/versatica/mediasoup/pull/1113)). + + ### 3.12.4 * Fix downloaded prebuilt binary check on Windows ([PR #1105](https://github.com/versatica/mediasoup/pull/1105) by @woodfe). diff --git a/package-lock.json b/package-lock.json index 6bd7603847..5bbf13f976 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "mediasoup", - "version": "3.12.4", + "version": "3.12.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.4", + "version": "3.12.5", "hasInstallScript": true, "license": "ISC", "dependencies": { "debug": "^4.3.4", "h264-profile-level-id": "^1.0.1", "node-fetch": "^3.3.1", - "supports-color": "^9.3.1", + "supports-color": "^9.4.0", "tar": "^6.1.15", "uuid": "^9.0.0" }, @@ -23,17 +23,17 @@ "@types/jest": "^29.5.2", "@types/node": "^18.16.18", "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^5.60.0", - "@typescript-eslint/parser": "^5.60.0", - "eslint": "^8.43.0", + "@typescript-eslint/eslint-plugin": "^5.61.0", + "@typescript-eslint/parser": "^5.61.0", + "eslint": "^8.44.0", "eslint-plugin-jest": "^27.2.2", - "jest": "^29.5.0", - "marked": "^5.1.0", + "jest": "^29.6.1", + "marked": "^5.1.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", - "ts-jest": "^29.1.0", - "typescript": "^5.1.3" + "ts-jest": "^29.1.1", + "typescript": "^5.1.6" }, "engines": { "node": ">=16" @@ -43,6 +43,15 @@ "url": "https://opencollective.com/mediasoup" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -243,9 +252,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -465,12 +474,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -567,12 +576,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -670,14 +679,14 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -693,9 +702,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", - "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -843,16 +852,16 @@ } }, "node_modules/@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", + "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0" }, "engines": { @@ -860,16 +869,16 @@ } }, "node_modules/@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", + "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/reporters": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", @@ -877,20 +886,20 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", + "jest-config": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-resolve-dependencies": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", + "jest-watcher": "^29.6.1", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -907,37 +916,37 @@ } }, "node_modules/@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", + "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0" + "jest-mock": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", "dev": true, "dependencies": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "expect": "^29.6.1", + "jest-snapshot": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", + "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3" @@ -947,49 +956,49 @@ } }, "node_modules/@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", + "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", + "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/types": "^29.6.1", + "jest-mock": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", + "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -1001,9 +1010,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -1022,24 +1031,24 @@ } }, "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", + "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", + "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, @@ -1048,13 +1057,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", + "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/types": "^29.6.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1063,14 +1072,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", + "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", "dev": true, "dependencies": { - "@jest/test-result": "^29.5.0", + "@jest/test-result": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "slash": "^3.0.0" }, "engines": { @@ -1078,22 +1087,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", + "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1104,12 +1113,12 @@ } }, "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", + "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1158,9 +1167,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "3.1.0", @@ -1389,27 +1398,27 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.25.23", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.23.tgz", - "integrity": "sha512-VEB8ygeP42CFLWyAJhN5OklpxUliqdNEUcXb4xZ/CINqtYGTjL5ukluKdKzQ0iWdUxyQ7B0539PAUhHKrCNWSQ==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@tokenizer/token": { @@ -1542,9 +1551,9 @@ "dev": true }, "node_modules/@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "dev": true }, "node_modules/@types/semver": { @@ -1581,17 +1590,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz", - "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.61.0.tgz", + "integrity": "sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/type-utils": "5.60.0", - "@typescript-eslint/utils": "5.60.0", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/type-utils": "5.61.0", + "@typescript-eslint/utils": "5.61.0", "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", @@ -1615,14 +1624,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz", - "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.61.0.tgz", + "integrity": "sha512-yGr4Sgyh8uO6fSi9hw3jAFXNBHbCtKKFMdX2IkT3ZqpKmtAq3lHS4ixB/COFuAIJpwl9/AqF7j72ZDWYKmIfvg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/typescript-estree": "5.61.0", "debug": "^4.3.4" }, "engines": { @@ -1642,13 +1651,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz", - "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.61.0.tgz", + "integrity": "sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0" + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/visitor-keys": "5.61.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1659,13 +1668,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz", - "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.61.0.tgz", + "integrity": "sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.60.0", - "@typescript-eslint/utils": "5.60.0", + "@typescript-eslint/typescript-estree": "5.61.0", + "@typescript-eslint/utils": "5.61.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1686,9 +1695,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz", - "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.61.0.tgz", + "integrity": "sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1699,13 +1708,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz", - "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.61.0.tgz", + "integrity": "sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0", + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/visitor-keys": "5.61.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1726,17 +1735,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz", - "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.61.0.tgz", + "integrity": "sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/typescript-estree": "5.61.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1752,12 +1761,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz", - "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.61.0.tgz", + "integrity": "sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/types": "5.61.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1769,9 +1778,9 @@ } }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1894,12 +1903,12 @@ } }, "node_modules/babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", + "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", "dev": true, "dependencies": { - "@jest/transform": "^29.5.0", + "@jest/transform": "^29.6.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.5.0", @@ -2249,9 +2258,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, "node_modules/cliui": { @@ -2279,9 +2288,9 @@ } }, "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, "node_modules/color-convert": { @@ -2634,15 +2643,15 @@ } }, "node_modules/eslint": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", - "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz", + "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.43.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2654,7 +2663,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "espree": "^9.6.0", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2674,7 +2683,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -2765,12 +2774,12 @@ } }, "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz", + "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" }, @@ -2887,16 +2896,17 @@ } }, "node_modules/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.5.0", + "@jest/expect-utils": "^29.6.1", + "@types/node": "*", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2909,9 +2919,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -3247,12 +3257,6 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -3711,15 +3715,15 @@ } }, "node_modules/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", + "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", "dev": true, "dependencies": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.6.1", + "@jest/types": "^29.6.1", "import-local": "^3.0.2", - "jest-cli": "^29.5.0" + "jest-cli": "^29.6.1" }, "bin": { "jest": "bin/jest.js" @@ -3750,28 +3754,28 @@ } }, "node_modules/jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", + "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-each": "^29.6.1", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -3781,21 +3785,21 @@ } }, "node_modules/jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", + "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", "dev": true, "dependencies": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-config": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -3815,31 +3819,31 @@ } }, "node_modules/jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", + "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", + "@jest/test-sequencer": "^29.6.1", + "@jest/types": "^29.6.1", + "babel-jest": "^29.6.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", + "jest-circus": "^29.6.1", + "jest-environment-node": "^29.6.1", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3860,15 +3864,15 @@ } }, "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", + "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3887,33 +3891,33 @@ } }, "node_modules/jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", + "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "jest-util": "^29.6.1", + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", + "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3929,20 +3933,20 @@ } }, "node_modules/jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", + "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3954,46 +3958,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", + "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", + "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", + "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -4002,14 +4006,14 @@ } }, "node_modules/jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", + "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-util": "^29.5.0" + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4042,17 +4046,17 @@ } }, "node_modules/jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", + "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -4062,43 +4066,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", + "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" + "jest-snapshot": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", + "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/environment": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-environment-node": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-leak-detector": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-resolve": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-util": "^29.6.1", + "jest-watcher": "^29.6.1", + "jest-worker": "^29.6.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -4107,31 +4111,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", + "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/globals": "^29.6.1", + "@jest/source-map": "^29.6.0", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -4140,46 +4144,44 @@ } }, "node_modules/jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", + "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", + "@jest/expect-utils": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.5.0", + "expect": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" + "pretty-format": "^29.6.1", + "semver": "^7.5.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", + "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -4191,17 +4193,17 @@ } }, "node_modules/jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", + "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4220,18 +4222,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", + "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "string-length": "^4.0.1" }, "engines": { @@ -4239,13 +4241,13 @@ } }, "node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", + "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4474,9 +4476,9 @@ } }, "node_modules/marked": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.0.tgz", - "integrity": "sha512-z3/nBe7aTI8JDszlYLk7dDVNpngjw0o1ZJtrA9kIfkkHcIF+xH7mO23aISl4WxP83elU+MFROgahqdpd05lMEQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.1.tgz", + "integrity": "sha512-bTmmGdEINWmOMDjnPWDxGPQ4qkDLeYorpYbEtFOXzOruTwUE671q4Guiuchn4N8h/v6NGd7916kXsm3Iz4iUSg==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -4811,17 +4813,17 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -5067,12 +5069,12 @@ } }, "node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -5121,9 +5123,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.1.tgz", - "integrity": "sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", + "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", "dev": true, "funding": [ { @@ -5398,12 +5400,12 @@ } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -5445,9 +5447,9 @@ } }, "node_modules/resolve.exports": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.1.tgz", - "integrity": "sha512-OEJWVeimw8mgQuj3HfkNl4KqRevH7lzeQNaWRPfx0PPse7Jk6ozcsG4FKVgtzDsC1KUF+YlTHh17NcgHOPykLw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, "engines": { "node": ">=10" @@ -5551,9 +5553,9 @@ } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -5805,9 +5807,9 @@ } }, "node_modules/supports-color": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.3.1.tgz", - "integrity": "sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "engines": { "node": ">=12" }, @@ -5986,9 +5988,9 @@ } }, "node_modules/ts-jest": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", - "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -5997,7 +5999,7 @@ "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", + "semver": "^7.5.3", "yargs-parser": "^21.0.1" }, "bin": { @@ -6083,9 +6085,9 @@ } }, "node_modules/typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -6252,15 +6254,6 @@ "node": ">= 8" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -6362,9 +6355,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { "cliui": "^8.0.1", @@ -6402,6 +6395,12 @@ } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, "@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -6559,9 +6558,9 @@ } }, "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true }, "@babel/helper-simple-access": { @@ -6726,12 +6725,12 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -6798,12 +6797,12 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.22.5" } }, "@babel/template": { @@ -6876,14 +6875,14 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -6893,9 +6892,9 @@ } }, "@eslint/js": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", - "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", "dev": true }, "@humanwhocodes/config-array": { @@ -7005,30 +7004,30 @@ "dev": true }, "@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", + "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", + "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", "dev": true, "requires": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/reporters": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", @@ -7036,93 +7035,93 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", + "jest-config": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-resolve-dependencies": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", + "jest-watcher": "^29.6.1", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", + "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", "dev": true, "requires": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0" + "jest-mock": "^29.6.1" } }, "@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", "dev": true, "requires": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "expect": "^29.6.1", + "jest-snapshot": "^29.6.1" } }, "@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", + "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", "dev": true, "requires": { "jest-get-type": "^29.4.3" } }, "@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", + "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" } }, "@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", + "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/types": "^29.6.1", + "jest-mock": "^29.6.1" } }, "@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", + "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -7134,9 +7133,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -7144,66 +7143,66 @@ } }, "@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", + "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", "dev": true, "requires": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" } }, "@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", + "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } }, "@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", + "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", "dev": true, "requires": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/types": "^29.6.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", + "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", "dev": true, "requires": { - "@jest/test-result": "^29.5.0", + "@jest/test-result": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", + "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -7211,12 +7210,12 @@ } }, "@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", + "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", "dev": true, "requires": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -7253,9 +7252,9 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, "requires": { "@jridgewell/resolve-uri": "3.1.0", @@ -7431,27 +7430,27 @@ } }, "@sinclair/typebox": { - "version": "0.25.23", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.23.tgz", - "integrity": "sha512-VEB8ygeP42CFLWyAJhN5OklpxUliqdNEUcXb4xZ/CINqtYGTjL5ukluKdKzQ0iWdUxyQ7B0539PAUhHKrCNWSQ==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "requires": { - "@sinonjs/commons": "^2.0.0" + "@sinonjs/commons": "^3.0.0" } }, "@tokenizer/token": { @@ -7584,9 +7583,9 @@ "dev": true }, "@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "dev": true }, "@types/semver": { @@ -7623,17 +7622,17 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz", - "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.61.0.tgz", + "integrity": "sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/type-utils": "5.60.0", - "@typescript-eslint/utils": "5.60.0", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/type-utils": "5.61.0", + "@typescript-eslint/utils": "5.61.0", "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", @@ -7641,53 +7640,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz", - "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.61.0.tgz", + "integrity": "sha512-yGr4Sgyh8uO6fSi9hw3jAFXNBHbCtKKFMdX2IkT3ZqpKmtAq3lHS4ixB/COFuAIJpwl9/AqF7j72ZDWYKmIfvg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/typescript-estree": "5.61.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz", - "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.61.0.tgz", + "integrity": "sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0" + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/visitor-keys": "5.61.0" } }, "@typescript-eslint/type-utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz", - "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.61.0.tgz", + "integrity": "sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.60.0", - "@typescript-eslint/utils": "5.60.0", + "@typescript-eslint/typescript-estree": "5.61.0", + "@typescript-eslint/utils": "5.61.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz", - "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.61.0.tgz", + "integrity": "sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz", - "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.61.0.tgz", + "integrity": "sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0", + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/visitor-keys": "5.61.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7696,35 +7695,35 @@ } }, "@typescript-eslint/utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz", - "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.61.0.tgz", + "integrity": "sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/typescript-estree": "5.61.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz", - "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.61.0.tgz", + "integrity": "sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/types": "5.61.0", "eslint-visitor-keys": "^3.3.0" } }, "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true }, "acorn-jsx": { @@ -7807,12 +7806,12 @@ "dev": true }, "babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", + "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", "dev": true, "requires": { - "@jest/transform": "^29.5.0", + "@jest/transform": "^29.6.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.5.0", @@ -8056,9 +8055,9 @@ "dev": true }, "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, "cliui": { @@ -8079,9 +8078,9 @@ "dev": true }, "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, "color-convert": { @@ -8341,15 +8340,15 @@ "dev": true }, "eslint": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", - "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz", + "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.43.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -8361,7 +8360,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "espree": "^9.6.0", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -8381,7 +8380,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -8431,12 +8430,12 @@ "dev": true }, "espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz", + "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==", "dev": true, "requires": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } @@ -8517,16 +8516,17 @@ "dev": true }, "expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", "dev": true, "requires": { - "@jest/expect-utils": "^29.5.0", + "@jest/expect-utils": "^29.6.1", + "@types/node": "*", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1" } }, "fast-deep-equal": { @@ -8536,9 +8536,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -8780,12 +8780,6 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, "graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -9103,15 +9097,15 @@ } }, "jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", + "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", "dev": true, "requires": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.6.1", + "@jest/types": "^29.6.1", "import-local": "^3.0.2", - "jest-cli": "^29.5.0" + "jest-cli": "^29.6.1" } }, "jest-changed-files": { @@ -9125,93 +9119,93 @@ } }, "jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", + "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-each": "^29.6.1", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", + "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", "dev": true, "requires": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-config": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "prompts": "^2.0.1", "yargs": "^17.3.1" } }, "jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", + "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", + "@jest/test-sequencer": "^29.6.1", + "@jest/types": "^29.6.1", + "babel-jest": "^29.6.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", + "jest-circus": "^29.6.1", + "jest-environment-node": "^29.6.1", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" } }, "jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", + "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", "dev": true, "requires": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" } }, "jest-docblock": { @@ -9224,30 +9218,30 @@ } }, "jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", + "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "jest-util": "^29.6.1", + "pretty-format": "^29.6.1" } }, "jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", + "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" } }, "jest-get-type": { @@ -9257,12 +9251,12 @@ "dev": true }, "jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", + "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", @@ -9270,60 +9264,60 @@ "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", + "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", "dev": true, "requires": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" } }, "jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", + "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" } }, "jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", + "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", + "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-util": "^29.5.0" + "jest-util": "^29.6.1" } }, "jest-pnp-resolver": { @@ -9340,129 +9334,127 @@ "dev": true }, "jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", + "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", + "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", "dev": true, "requires": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" + "jest-snapshot": "^29.6.1" } }, "jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", + "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", "dev": true, "requires": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/environment": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-environment-node": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-leak-detector": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-resolve": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-util": "^29.6.1", + "jest-watcher": "^29.6.1", + "jest-worker": "^29.6.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", + "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/globals": "^29.6.1", + "@jest/source-map": "^29.6.0", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", + "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", + "@jest/expect-utils": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.5.0", + "expect": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" + "pretty-format": "^29.6.1", + "semver": "^7.5.3" } }, "jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", + "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -9471,17 +9463,17 @@ } }, "jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", + "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "dependencies": { "camelcase": { @@ -9493,29 +9485,29 @@ } }, "jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", + "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", "dev": true, "requires": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", + "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -9685,9 +9677,9 @@ "dev": true }, "marked": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.0.tgz", - "integrity": "sha512-z3/nBe7aTI8JDszlYLk7dDVNpngjw0o1ZJtrA9kIfkkHcIF+xH7mO23aISl4WxP83elU+MFROgahqdpd05lMEQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.1.tgz", + "integrity": "sha512-bTmmGdEINWmOMDjnPWDxGPQ4qkDLeYorpYbEtFOXzOruTwUE671q4Guiuchn4N8h/v6NGd7916kXsm3Iz4iUSg==", "dev": true }, "meow": { @@ -9922,17 +9914,17 @@ } }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" } }, "p-limit": { @@ -10104,12 +10096,12 @@ "dev": true }, "pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "requires": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -10145,9 +10137,9 @@ "dev": true }, "pure-rand": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.1.tgz", - "integrity": "sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", + "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", "dev": true }, "queue-microtask": { @@ -10314,12 +10306,12 @@ "dev": true }, "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, "requires": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -10348,9 +10340,9 @@ "dev": true }, "resolve.exports": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.1.tgz", - "integrity": "sha512-OEJWVeimw8mgQuj3HfkNl4KqRevH7lzeQNaWRPfx0PPse7Jk6ozcsG4FKVgtzDsC1KUF+YlTHh17NcgHOPykLw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true }, "reusify": { @@ -10404,9 +10396,9 @@ } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -10599,9 +10591,9 @@ } }, "supports-color": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.3.1.tgz", - "integrity": "sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==" + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==" }, "supports-preserve-symlinks-flag": { "version": "1.0.0", @@ -10721,9 +10713,9 @@ "dev": true }, "ts-jest": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", - "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", "dev": true, "requires": { "bs-logger": "0.x", @@ -10732,7 +10724,7 @@ "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", + "semver": "^7.5.3", "yargs-parser": "^21.0.1" } }, @@ -10773,9 +10765,9 @@ "dev": true }, "typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", "dev": true }, "unique-string": { @@ -10897,12 +10889,6 @@ "isexe": "^2.0.0" } }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -10982,9 +10968,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { "cliui": "^8.0.1", diff --git a/package.json b/package.json index 380e583769..f1c916f985 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.4", + "version": "3.12.5", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -90,7 +90,7 @@ "debug": "^4.3.4", "h264-profile-level-id": "^1.0.1", "node-fetch": "^3.3.1", - "supports-color": "^9.3.1", + "supports-color": "^9.4.0", "tar": "^6.1.15", "uuid": "^9.0.0" }, @@ -100,16 +100,16 @@ "@types/jest": "^29.5.2", "@types/node": "^18.16.18", "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^5.60.0", - "@typescript-eslint/parser": "^5.60.0", - "eslint": "^8.43.0", + "@typescript-eslint/eslint-plugin": "^5.61.0", + "@typescript-eslint/parser": "^5.61.0", + "eslint": "^8.44.0", "eslint-plugin-jest": "^27.2.2", - "jest": "^29.5.0", - "marked": "^5.1.0", + "jest": "^29.6.1", + "marked": "^5.1.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", - "ts-jest": "^29.1.0", - "typescript": "^5.1.3" + "ts-jest": "^29.1.1", + "typescript": "^5.1.6" } } From 644e2a447a44548040f0bd1eb1d908212955c268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 10 Jul 2023 17:29:15 +0200 Subject: [PATCH 124/525] worker: Add Transport::Destroying() protected method (#1114) --- CHANGELOG.md | 5 +++++ worker/include/RTC/Transport.hpp | 1 + worker/src/RTC/DirectTransport.cpp | 4 ++++ worker/src/RTC/PipeTransport.cpp | 4 ++++ worker/src/RTC/PlainTransport.cpp | 4 ++++ worker/src/RTC/Transport.cpp | 10 +++++++--- worker/src/RTC/WebRtcTransport.cpp | 5 +++++ 7 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4e6f622ad..99b8eadfca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +* `Worker`: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). + + ### 3.12.5 * `DataConsumer`: Fix removed 'bufferedamountlow' notification ([PR #1113](https://github.com/versatica/mediasoup/pull/1113)). diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index 87e5e81909..1ce6812cf0 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -144,6 +144,7 @@ namespace RTC protected: // Must be called from the subclass. + void Destroying(); void Connected(); void Disconnected(); void DataReceived(size_t len) diff --git a/worker/src/RTC/DirectTransport.cpp b/worker/src/RTC/DirectTransport.cpp index fe28591730..903881170b 100644 --- a/worker/src/RTC/DirectTransport.cpp +++ b/worker/src/RTC/DirectTransport.cpp @@ -28,6 +28,10 @@ namespace RTC { MS_TRACE(); + // Tell the Transport parent class that we are about to destroy + // the class instance. + Destroying(); + this->shared->channelMessageRegistrator->UnregisterHandler(this->id); } diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index 39bc2a0ead..d46624a649 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -117,6 +117,10 @@ namespace RTC { MS_TRACE(); + // Tell the Transport parent class that we are about to destroy + // the class instance. + Destroying(); + this->shared->channelMessageRegistrator->UnregisterHandler(this->id); delete this->udpSocket; diff --git a/worker/src/RTC/PlainTransport.cpp b/worker/src/RTC/PlainTransport.cpp index a90ecdd8dc..6a461dc78d 100644 --- a/worker/src/RTC/PlainTransport.cpp +++ b/worker/src/RTC/PlainTransport.cpp @@ -206,6 +206,10 @@ namespace RTC { MS_TRACE(); + // Tell the Transport parent class that we are about to destroy + // the class instance. + Destroying(); + this->shared->channelMessageRegistrator->UnregisterHandler(this->id); delete this->udpSocket; diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 65e0b57c73..3bf589286b 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -182,9 +182,6 @@ namespace RTC { MS_TRACE(); - // Set the destroying flag. - this->destroying = true; - // The destructor must delete and clear everything silently. // Delete all Producers. @@ -1594,6 +1591,13 @@ namespace RTC } } + void Transport::Destroying() + { + MS_TRACE(); + + this->destroying = true; + } + void Transport::Connected() { MS_TRACE(); diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 4ec9065d50..000b389dbb 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -300,6 +300,11 @@ namespace RTC { MS_TRACE(); + // We need to tell the Transport parent class that we are about to destroy + // the class instance. This is because child's destructor runs before + // parent's destructor. See comment in Transport::OnSctpAssociationSendData(). + Destroying(); + this->shared->channelMessageRegistrator->UnregisterHandler(this->id); // Must delete the DTLS transport first since it will generate a DTLS alert From 9257b2135c25b223d342b29f74c3d4caf5aec747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 11 Jul 2023 13:40:08 +0200 Subject: [PATCH 125/525] Remove unused C includes --- worker/src/lib.cpp | 6 ++++-- worker/src/main.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/worker/src/lib.cpp b/worker/src/lib.cpp index 705e1b7981..f1ba68a62b 100644 --- a/worker/src/lib.cpp +++ b/worker/src/lib.cpp @@ -20,8 +20,6 @@ #include #include #include // sigaction() -#include // std::_Exit(), std::genenv() -#include // std::cerr, std::endl #include void IgnoreSignals(); @@ -225,7 +223,9 @@ void IgnoreSignals() err = sigfillset(&act.sa_mask); if (err != 0) + { MS_THROW_ERROR("sigfillset() failed: %s", std::strerror(errno)); + } for (auto& kv : ignoredSignals) { @@ -235,7 +235,9 @@ void IgnoreSignals() err = sigaction(sigId, &act, nullptr); if (err != 0) + { MS_THROW_ERROR("sigaction() failed for signal %s: %s", sigName.c_str(), std::strerror(errno)); + } } #endif } diff --git a/worker/src/main.cpp b/worker/src/main.cpp index 212b14ec26..b7aefc0198 100644 --- a/worker/src/main.cpp +++ b/worker/src/main.cpp @@ -3,7 +3,7 @@ #include "MediaSoupErrors.hpp" #include "lib.hpp" -#include // std::_Exit(), std::genenv() +#include // std::_Exit() #include static constexpr int ConsumerChannelFd{ 3 }; From 99b8d93b5a4c01f783d3060c7c8040248ab3e8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 11 Jul 2023 13:44:17 +0200 Subject: [PATCH 126/525] make format --- worker/src/lib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/lib.cpp b/worker/src/lib.cpp index f1ba68a62b..3bc232f511 100644 --- a/worker/src/lib.cpp +++ b/worker/src/lib.cpp @@ -19,7 +19,7 @@ #include #include #include -#include // sigaction() +#include // sigaction() #include void IgnoreSignals(); From 9c7225abc92a8c69df7a90146c29ed38302cc63d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 11 Jul 2023 16:34:21 +0200 Subject: [PATCH 127/525] cosmetic --- npm-scripts.mjs | 5 +++-- package.json | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 52f995a738..0522a1f930 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -204,11 +204,11 @@ async function run() catch (error) { logError(error.message); + exitWithError(); } checkRelease(); - executeCmd(`git commit -am '${PKG.version}'`); executeCmd(`git tag -a ${PKG.version} -m '${PKG.version}'`); executeCmd(`git push origin v${MAYOR_VERSION}`); @@ -243,7 +243,6 @@ async function run() case 'release:upload-mac-arm-prebuilt-worker': { checkRelease(); - await prebuildWorker(); await uploadMacArmPrebuiltWorker(); @@ -428,6 +427,7 @@ function installMsysMake() if (res.status !== 0) { logError('`installMsysMake() | cannot find Python executable'); + exitWithError(); } } @@ -685,6 +685,7 @@ function executeCmd(command, exitOnError = true) if (exitOnError) { logError(`executeCmd() failed, exiting: ${error}`); + exitWithError(); } else diff --git a/package.json b/package.json index f1c916f985..cdbbd4328a 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "José Luis Millán (https://github.com/jmillan)", "Nazar Mokynskyi (https://github.com/nazar-pc)" ], - "homepage": "https://mediasoup.org", "license": "ISC", + "homepage": "https://mediasoup.org", "repository": { "type": "git", "url": "https://github.com/versatica/mediasoup.git" @@ -38,15 +38,15 @@ "worker/meson_options.txt", "npm-scripts.mjs" ], + "engines": { + "node": ">=16" + }, "keywords": [ "webrtc", "ortc", "sfu", "nodejs" ], - "engines": { - "node": ">=16" - }, "scripts": { "prepare": "node npm-scripts.mjs prepare", "postinstall": "node npm-scripts.mjs postinstall", From dfbd6184b320e68af3d3b5ee58a0482959b98e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 12 Jul 2023 10:32:15 +0200 Subject: [PATCH 128/525] Add comment about jitter in ms --- worker/include/RTC/RtpStreamRecv.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/worker/include/RTC/RtpStreamRecv.hpp b/worker/include/RTC/RtpStreamRecv.hpp index afe7c0c83c..eec7a51a72 100644 --- a/worker/include/RTC/RtpStreamRecv.hpp +++ b/worker/include/RTC/RtpStreamRecv.hpp @@ -114,6 +114,7 @@ namespace RTC uint64_t lastSrReceived{ 0u }; // Relative transit time for prev packet. int32_t transit{ 0u }; + // Jitter in ms. uint32_t jitter{ 0u }; uint8_t firSeqNumber{ 0u }; uint32_t reportedPacketLost{ 0u }; From 5d31b5354929b99784b9d496e8198f6b54b4f558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 12 Jul 2023 15:49:09 +0200 Subject: [PATCH 129/525] Fix jitter calculation in RtpStreamRecv (#1117) --- CHANGELOG.md | 1 + worker/include/RTC/RTCP/ReceiverReport.hpp | 4 ++-- worker/include/RTC/RtpStreamRecv.hpp | 5 +++-- worker/src/RTC/RtpStreamRecv.cpp | 11 +++++------ 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99b8eadfca..f18e9bf990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Next * `Worker`: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). +* `RtpStreamRecv`: Fix jitter calculation ([PR #1117](https://github.com/versatica/mediasoup/pull/1117), thanks to @penguinol). ### 3.12.5 diff --git a/worker/include/RTC/RTCP/ReceiverReport.hpp b/worker/include/RTC/RTCP/ReceiverReport.hpp index 26f10394ff..44fbb2e02e 100644 --- a/worker/include/RTC/RTCP/ReceiverReport.hpp +++ b/worker/include/RTC/RTCP/ReceiverReport.hpp @@ -102,9 +102,9 @@ namespace RTC { return uint32_t{ ntohl(this->header->jitter) }; } - void SetJitter(uint32_t jitter) + void SetJitter(float jitter) { - this->header->jitter = uint32_t{ htonl(jitter) }; + this->header->jitter = uint32_t{ htonl(static_cast(jitter)) }; } uint32_t GetLastSenderReport() const { diff --git a/worker/include/RTC/RtpStreamRecv.hpp b/worker/include/RTC/RtpStreamRecv.hpp index eec7a51a72..193625155f 100644 --- a/worker/include/RTC/RtpStreamRecv.hpp +++ b/worker/include/RTC/RtpStreamRecv.hpp @@ -114,8 +114,9 @@ namespace RTC uint64_t lastSrReceived{ 0u }; // Relative transit time for prev packet. int32_t transit{ 0u }; - // Jitter in ms. - uint32_t jitter{ 0u }; + // Jitter in RTP timestamp units. As per spec it's kept as floating value + // although it's exposed as integer in the stats. + float jitter{ 0 }; uint8_t firSeqNumber{ 0u }; uint32_t reportedPacketLost{ 0u }; std::unique_ptr nackGenerator; diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index 0fe1de02cb..b4b8fc2c0f 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -236,7 +236,7 @@ namespace RTC RTC::RtpStream::FillJsonStats(jsonObject); jsonObject["type"] = "inbound-rtp"; - jsonObject["jitter"] = this->jitter; + jsonObject["jitter"] = static_cast(this->jitter); jsonObject["packetCount"] = this->transmissionCounter.GetPacketCount(); jsonObject["byteCount"] = this->transmissionCounter.GetBytes(); jsonObject["bitrate"] = this->transmissionCounter.GetBitrate(nowMs); @@ -692,15 +692,14 @@ namespace RTC { MS_TRACE(); - if (this->params.clockRate == 0u) + if (GetClockRate() == 0u) { return; } // NOTE: Based on https://github.com/versatica/mediasoup/issues/1018. - auto transit = static_cast( - DepLibUV::GetTimeMs() - (static_cast(rtpTimestamp) * 1000 / this->params.clockRate)); - int d = transit - this->transit; + auto transit = static_cast((DepLibUV::GetTimeMs() * GetClockRate() / 1000) - rtpTimestamp); + int d = transit - this->transit; // First transit calculation, save and return. if (this->transit == 0) @@ -717,7 +716,7 @@ namespace RTC d = -d; } - this->jitter += (1. / 16.) * (static_cast(d) - this->jitter); + this->jitter += (1. / 16.) * (static_cast(d) - this->jitter); } void RtpStreamRecv::UpdateScore() From a9a34ca8948eb19cf25aa6cd0374581bd786b362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 13 Jul 2023 17:11:01 +0200 Subject: [PATCH 130/525] Revert PR #1109 "Node: make types.ts only export types rather than the entire class/code" Such a change requires typescript >= 5 in the apps that import mediasoup. We'll do this again once we can assume that all users use typescript >= 5. --- node/src/types.ts | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/node/src/types.ts b/node/src/types.ts index 51b20a6a02..7de0c0e72f 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -1,22 +1,21 @@ -export type * from './Worker'; -export type * from './WebRtcServer'; -export type * from './Router'; -export type * from './Transport'; -export type * from './WebRtcTransport'; -export type * from './PlainTransport'; -export type * from './PipeTransport'; -export type * from './DirectTransport'; -export type * from './Producer'; -export type * from './Consumer'; -export type * from './DataProducer'; -export type * from './DataConsumer'; -export type * from './RtpObserver'; -export type * from './ActiveSpeakerObserver'; -export type * from './AudioLevelObserver'; -export type * from './RtpParameters'; -export type * from './SctpParameters'; -export type * from './SrtpParameters'; -// We cannot export only the type of error classes because those are useless. +export * from './Worker'; +export * from './WebRtcServer'; +export * from './Router'; +export * from './Transport'; +export * from './WebRtcTransport'; +export * from './PlainTransport'; +export * from './PipeTransport'; +export * from './DirectTransport'; +export * from './Producer'; +export * from './Consumer'; +export * from './DataProducer'; +export * from './DataConsumer'; +export * from './RtpObserver'; +export * from './ActiveSpeakerObserver'; +export * from './AudioLevelObserver'; +export * from './RtpParameters'; +export * from './SctpParameters'; +export * from './SrtpParameters'; export * from './errors'; export type { ScalabilityMode } from './scalabilityModes'; From af5a515ecd6b6d26cba0cf53df820d107eebf250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 13 Jul 2023 17:15:28 +0200 Subject: [PATCH 131/525] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f18e9bf990..4d217c39db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * `Worker`: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). * `RtpStreamRecv`: Fix jitter calculation ([PR #1117](https://github.com/versatica/mediasoup/pull/1117), thanks to @penguinol). +* Revert "Node: make types.ts only export types rather than the entire class/code" ([PR #1109](https://github.com/versatica/mediasoup/pull/1109)) because it requires `typescript` >= 5 in the apps that import mediasoup and we don't want to be that strict yet. ### 3.12.5 From 15cdc143bf89a0a788b3e6210f1b7bb3d6fb3053 Mon Sep 17 00:00:00 2001 From: satoren Date: Fri, 14 Jul 2023 00:17:07 +0900 Subject: [PATCH 132/525] add test with ASAN (#1118) --- doc/Building.md | 5 +++++ worker/Makefile | 6 ++++++ worker/meson.build | 49 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/doc/Building.md b/doc/Building.md index ca18ebf5ad..a591bbfc9f 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -154,6 +154,11 @@ Rewrites mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/ Builds and runs the `mediasoup-worker-test` binary at `worker/out/Release/` (or at `worker/out/Debug/` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"), which uses [Catch2](https://github.com/catchorg/Catch2) to run test units located at `worker/test/` folder. + +### 'make test-asan' + +Run test with Address Sanitizer. + ### `make tidy` Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy/) and performs C++ code checks following `worker/.clang-tidy` rules. diff --git a/worker/Makefile b/worker/Makefile index ed969cce4c..af74457eb5 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -81,6 +81,7 @@ endif lint \ format \ test \ + test-asan \ tidy \ fuzzer \ fuzzer-run-all \ @@ -225,6 +226,11 @@ else $(BUILD_DIR)/mediasoup-worker-test --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS) endif +test-asan: setup + $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test-asan + $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-test-asan + ASAN_OPTIONS=detect_leaks=1 $(BUILD_DIR)/mediasoup-worker-test-asan --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS) + tidy: $(PYTHON) ./scripts/clang-tidy.py \ -clang-tidy-binary=./scripts/node_modules/.bin/clang-tidy \ diff --git a/worker/meson.build b/worker/meson.build index ba2ed3f321..9aaff0da55 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -280,15 +280,7 @@ executable( cpp_args: cpp_args + ['-DMS_EXECUTABLE'], ) -mediasoup_worker_test = executable( - 'mediasoup-worker-test', - build_by_default: false, - install: true, - install_tag: 'mediasoup-worker-test', - dependencies: dependencies + [ - catch2_proj.get_variable('catch2_dep'), - ], - sources: common_sources + [ +test_sources = [ 'test/src/tests.cpp', 'test/src/PayloadChannel/TestPayloadChannelNotification.cpp', 'test/src/PayloadChannel/TestPayloadChannelRequest.cpp', @@ -333,7 +325,17 @@ mediasoup_worker_test = executable( 'test/src/Utils/TestJson.cpp', 'test/src/Utils/TestString.cpp', 'test/src/Utils/TestTime.cpp', +] + +mediasoup_worker_test = executable( + 'mediasoup-worker-test', + build_by_default: false, + install: true, + install_tag: 'mediasoup-worker-test', + dependencies: dependencies + [ + catch2_proj.get_variable('catch2_dep'), ], + sources: common_sources + test_sources, include_directories: include_directories( 'include', 'test/include', @@ -350,6 +352,35 @@ test( workdir: meson.project_source_root(), ) +mediasoup_worker_test_asan = executable( + 'mediasoup-worker-test-asan', + build_by_default: false, + install: true, + install_tag: 'mediasoup-worker-test-asan', + dependencies: dependencies + [ + catch2_proj.get_variable('catch2_dep'), + ], + sources: common_sources + test_sources, + include_directories: include_directories( + 'include', + 'test/include', + ), + cpp_args: cpp_args + [ + '-DMS_LOG_STD', + '-DMS_TEST', + '-fsanitize=address', + ], + link_args: [ + '-fsanitize=address', + ], +) + +test( + 'mediasoup-worker-test-asan', + mediasoup_worker_test_asan, + workdir: meson.project_source_root(), +) + executable( 'mediasoup-worker-fuzzer', build_by_default: false, From fd3313dc65914e086586d370ff4ec59981c4acba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 13 Jul 2023 17:23:02 +0200 Subject: [PATCH 133/525] 3.12.6 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d217c39db..7b894d1403 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.12.6 * `Worker`: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). * `RtpStreamRecv`: Fix jitter calculation ([PR #1117](https://github.com/versatica/mediasoup/pull/1117), thanks to @penguinol). diff --git a/package-lock.json b/package-lock.json index 5bbf13f976..ea8c5f995e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.5", + "version": "3.12.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.5", + "version": "3.12.6", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index cdbbd4328a..bc7232a472 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.5", + "version": "3.12.6", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 1e3a57cb9cf418371a85a2bd661433f7bf77415e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 17 Jul 2023 13:19:48 +0200 Subject: [PATCH 134/525] Use v3 in CI steps --- .github/workflows/mediasoup-worker-prebuild.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index e825424b80..5e5f588fc4 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -43,10 +43,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node }} From 2f6bfcab697be781bbac74d70a716d9a89971e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 19 Jul 2023 16:25:29 +0200 Subject: [PATCH 135/525] Fix lack of "consumerlayerschange" event when all streams in the producer die (#1122) --- CHANGELOG.md | 4 ++++ worker/include/RTC/Consumer.hpp | 9 +++++---- worker/include/RTC/PipeConsumer.hpp | 10 +++++----- worker/include/RTC/Producer.hpp | 9 ++++++--- worker/include/RTC/Router.hpp | 11 +++++++---- worker/include/RTC/RtpStreamRecv.hpp | 4 ++++ worker/include/RTC/SimpleConsumer.hpp | 16 +++++++++------- worker/include/RTC/SimulcastConsumer.hpp | 24 +++++++++++++----------- worker/include/RTC/SvcConsumer.hpp | 16 +++++++++------- worker/include/RTC/Transport.hpp | 18 ++++++++++++------ worker/src/RTC/PipeConsumer.cpp | 8 ++++---- worker/src/RTC/Producer.cpp | 11 +++++++---- worker/src/RTC/Router.cpp | 9 ++++++--- worker/src/RTC/SimpleConsumer.cpp | 8 ++++---- worker/src/RTC/SimulcastConsumer.cpp | 24 +++++++++++++++--------- worker/src/RTC/SvcConsumer.cpp | 8 ++++---- worker/src/RTC/Transport.cpp | 6 +++--- 17 files changed, 117 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b894d1403..a4d92b3d20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Next + +* `SimulcastConsumer`: Fix lack of "consumerlayerschange" event when all streams in the producer die ([PR #1122](https://github.com/versatica/mediasoup/pull/1122)). + ### 3.12.6 diff --git a/worker/include/RTC/Consumer.hpp b/worker/include/RTC/Consumer.hpp index 016a5ed085..20961ad340 100644 --- a/worker/include/RTC/Consumer.hpp +++ b/worker/include/RTC/Consumer.hpp @@ -14,6 +14,7 @@ #include "RTC/RtpHeaderExtensionIds.hpp" #include "RTC/RtpPacket.hpp" #include "RTC/RtpStream.hpp" +#include "RTC/RtpStreamRecv.hpp" #include "RTC/RtpStreamSend.hpp" #include "RTC/Shared.hpp" #include @@ -129,12 +130,12 @@ namespace RTC } void ProducerPaused(); void ProducerResumed(); - virtual void ProducerRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) = 0; - virtual void ProducerNewRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) = 0; + virtual void ProducerRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) = 0; + virtual void ProducerNewRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) = 0; void ProducerRtpStreamScores(const std::vector* scores); virtual void ProducerRtpStreamScore( - RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) = 0; - virtual void ProducerRtcpSenderReport(RTC::RtpStream* rtpStream, bool first) = 0; + RTC::RtpStreamRecv* rtpStream, uint8_t score, uint8_t previousScore) = 0; + virtual void ProducerRtcpSenderReport(RTC::RtpStreamRecv* rtpStream, bool first) = 0; void ProducerClosed(); void SetExternallyManagedBitrate() { diff --git a/worker/include/RTC/PipeConsumer.hpp b/worker/include/RTC/PipeConsumer.hpp index 3de9030ee4..924a3015f6 100644 --- a/worker/include/RTC/PipeConsumer.hpp +++ b/worker/include/RTC/PipeConsumer.hpp @@ -2,7 +2,6 @@ #define MS_RTC_PIPE_CONSUMER_HPP #include "RTC/Consumer.hpp" -#include "RTC/RtpStreamSend.hpp" #include "RTC/SeqManager.hpp" #include "RTC/Shared.hpp" @@ -23,10 +22,11 @@ namespace RTC void FillJson(json& jsonObject) const override; void FillJsonStats(json& jsonArray) const override; void FillJsonScore(json& jsonObject) const override; - void ProducerRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; - void ProducerNewRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; - void ProducerRtpStreamScore(RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) override; - void ProducerRtcpSenderReport(RTC::RtpStream* rtpStream, bool first) override; + void ProducerRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; + void ProducerNewRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; + void ProducerRtpStreamScore( + RTC::RtpStreamRecv* rtpStream, uint8_t score, uint8_t previousScore) override; + void ProducerRtcpSenderReport(RTC::RtpStreamRecv* rtpStream, bool first) override; uint8_t GetBitratePriority() const override; uint32_t IncreaseLayer(uint32_t bitrate, bool considerLoss) override; void ApplyLayers() override; diff --git a/worker/include/RTC/Producer.hpp b/worker/include/RTC/Producer.hpp index 9fb4306586..46ceeceb9a 100644 --- a/worker/include/RTC/Producer.hpp +++ b/worker/include/RTC/Producer.hpp @@ -40,11 +40,14 @@ namespace RTC virtual void OnProducerPaused(RTC::Producer* producer) = 0; virtual void OnProducerResumed(RTC::Producer* producer) = 0; virtual void OnProducerNewRtpStream( - RTC::Producer* producer, RTC::RtpStream* rtpStream, uint32_t mappedSsrc) = 0; + RTC::Producer* producer, RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) = 0; virtual void OnProducerRtpStreamScore( - RTC::Producer* producer, RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) = 0; + RTC::Producer* producer, + RTC::RtpStreamRecv* rtpStream, + uint8_t score, + uint8_t previousScore) = 0; virtual void OnProducerRtcpSenderReport( - RTC::Producer* producer, RTC::RtpStream* rtpStream, bool first) = 0; + RTC::Producer* producer, RTC::RtpStreamRecv* rtpStream, bool first) = 0; virtual void OnProducerRtpPacketReceived(RTC::Producer* producer, RTC::RtpPacket* packet) = 0; virtual void OnProducerSendRtcpPacket(RTC::Producer* producer, RTC::RTCP::Packet* packet) = 0; virtual void OnProducerNeedWorstRemoteFractionLost( diff --git a/worker/include/RTC/Router.hpp b/worker/include/RTC/Router.hpp index 6aa38d072c..4ab7a8e6b2 100644 --- a/worker/include/RTC/Router.hpp +++ b/worker/include/RTC/Router.hpp @@ -11,7 +11,7 @@ #include "RTC/Producer.hpp" #include "RTC/RtpObserver.hpp" #include "RTC/RtpPacket.hpp" -#include "RTC/RtpStream.hpp" +#include "RTC/RtpStreamRecv.hpp" #include "RTC/Shared.hpp" #include "RTC/Transport.hpp" #include "RTC/WebRtcServer.hpp" @@ -65,16 +65,19 @@ namespace RTC void OnTransportProducerNewRtpStream( RTC::Transport* transport, RTC::Producer* producer, - RTC::RtpStream* rtpStream, + RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; void OnTransportProducerRtpStreamScore( RTC::Transport* transport, RTC::Producer* producer, - RTC::RtpStream* rtpStream, + RTC::RtpStreamRecv* rtpStream, uint8_t score, uint8_t previousScore) override; void OnTransportProducerRtcpSenderReport( - RTC::Transport* transport, RTC::Producer* producer, RTC::RtpStream* rtpStream, bool first) override; + RTC::Transport* transport, + RTC::Producer* producer, + RTC::RtpStreamRecv* rtpStream, + bool first) override; void OnTransportProducerRtpPacketReceived( RTC::Transport* transport, RTC::Producer* producer, RTC::RtpPacket* packet) override; void OnTransportNeedWorstRemoteFractionLost( diff --git a/worker/include/RTC/RtpStreamRecv.hpp b/worker/include/RTC/RtpStreamRecv.hpp index 193625155f..e4ad525ecb 100644 --- a/worker/include/RTC/RtpStreamRecv.hpp +++ b/worker/include/RTC/RtpStreamRecv.hpp @@ -76,6 +76,10 @@ namespace RTC { return this->transmissionCounter.GetLayerBitrate(nowMs, spatialLayer, temporalLayer); } + bool HasRtpInactivityCheckEnabled() const + { + return this->useRtpInactivityCheck; + } private: void CalculateJitter(uint32_t rtpTimestamp); diff --git a/worker/include/RTC/SimpleConsumer.hpp b/worker/include/RTC/SimpleConsumer.hpp index 7932d13e2f..4822677969 100644 --- a/worker/include/RTC/SimpleConsumer.hpp +++ b/worker/include/RTC/SimpleConsumer.hpp @@ -2,7 +2,6 @@ #define MS_RTC_SIMPLE_CONSUMER_HPP #include "RTC/Consumer.hpp" -#include "RTC/RtpStreamSend.hpp" #include "RTC/SeqManager.hpp" #include "RTC/Shared.hpp" @@ -29,14 +28,17 @@ namespace RTC return ( RTC::Consumer::IsActive() && this->producerRtpStream && - (this->producerRtpStream->GetScore() > 0u || this->producerRtpStream->HasDtx()) + // If there is no RTP inactivity check do not consider the stream + // inactive despite it has score 0. + (this->producerRtpStream->GetScore() > 0u || !this->producerRtpStream->HasRtpInactivityCheckEnabled()) ); // clang-format on } - void ProducerRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; - void ProducerNewRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; - void ProducerRtpStreamScore(RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) override; - void ProducerRtcpSenderReport(RTC::RtpStream* rtpStream, bool first) override; + void ProducerRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; + void ProducerNewRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; + void ProducerRtpStreamScore( + RTC::RtpStreamRecv* rtpStream, uint8_t score, uint8_t previousScore) override; + void ProducerRtcpSenderReport(RTC::RtpStreamRecv* rtpStream, bool first) override; uint8_t GetBitratePriority() const override; uint32_t IncreaseLayer(uint32_t bitrate, bool considerLoss) override; void ApplyLayers() override; @@ -78,7 +80,7 @@ namespace RTC RTC::RtpStreamSend* rtpStream{ nullptr }; // Others. std::vector rtpStreams; - RTC::RtpStream* producerRtpStream{ nullptr }; + RTC::RtpStreamRecv* producerRtpStream{ nullptr }; bool keyFrameSupported{ false }; bool syncRequired{ false }; RTC::SeqManager rtpSeqManager; diff --git a/worker/include/RTC/SimulcastConsumer.hpp b/worker/include/RTC/SimulcastConsumer.hpp index c08dd83af2..d9fbd33983 100644 --- a/worker/include/RTC/SimulcastConsumer.hpp +++ b/worker/include/RTC/SimulcastConsumer.hpp @@ -3,7 +3,6 @@ #include "RTC/Codecs/PayloadDescriptorHandler.hpp" #include "RTC/Consumer.hpp" -#include "RTC/RtpStreamSend.hpp" #include "RTC/SeqManager.hpp" #include "RTC/Shared.hpp" @@ -41,18 +40,21 @@ namespace RTC std::any_of( this->producerRtpStreams.begin(), this->producerRtpStreams.end(), - [](const RTC::RtpStream* rtpStream) + [](const RTC::RtpStreamRecv* rtpStream) { - return (rtpStream != nullptr && (rtpStream->GetScore() > 0u || rtpStream->HasDtx())); + // If there is no RTP inactivity check do not consider the stream + // inactive despite it has score 0. + return (rtpStream != nullptr && (rtpStream->GetScore() > 0u || !rtpStream->HasRtpInactivityCheckEnabled())); } ) ); // clang-format on } - void ProducerRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; - void ProducerNewRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; - void ProducerRtpStreamScore(RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) override; - void ProducerRtcpSenderReport(RTC::RtpStream* rtpStream, bool first) override; + void ProducerRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; + void ProducerNewRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; + void ProducerRtpStreamScore( + RTC::RtpStreamRecv* rtpStream, uint8_t score, uint8_t previousScore) override; + void ProducerRtcpSenderReport(RTC::RtpStreamRecv* rtpStream, bool first) override; uint8_t GetBitratePriority() const override; uint32_t IncreaseLayer(uint32_t bitrate, bool considerLoss) override; void ApplyLayers() override; @@ -90,9 +92,9 @@ namespace RTC bool CanSwitchToSpatialLayer(int16_t spatialLayer) const; void EmitScore() const; void EmitLayersChange() const; - RTC::RtpStream* GetProducerCurrentRtpStream() const; - RTC::RtpStream* GetProducerTargetRtpStream() const; - RTC::RtpStream* GetProducerTsReferenceRtpStream() const; + RTC::RtpStreamRecv* GetProducerCurrentRtpStream() const; + RTC::RtpStreamRecv* GetProducerTargetRtpStream() const; + RTC::RtpStreamRecv* GetProducerTsReferenceRtpStream() const; /* Pure virtual methods inherited from RtpStreamSend::Listener. */ public: @@ -105,7 +107,7 @@ namespace RTC // Others. absl::flat_hash_map mapMappedSsrcSpatialLayer; std::vector rtpStreams; - std::vector producerRtpStreams; // Indexed by spatial layer. + std::vector producerRtpStreams; // Indexed by spatial layer. bool syncRequired{ false }; int16_t spatialLayerToSync{ -1 }; bool lastSentPacketHasMarker{ false }; diff --git a/worker/include/RTC/SvcConsumer.hpp b/worker/include/RTC/SvcConsumer.hpp index 949a86ef65..3e85536cf9 100644 --- a/worker/include/RTC/SvcConsumer.hpp +++ b/worker/include/RTC/SvcConsumer.hpp @@ -3,7 +3,6 @@ #include "RTC/Codecs/PayloadDescriptorHandler.hpp" #include "RTC/Consumer.hpp" -#include "RTC/RtpStreamSend.hpp" #include "RTC/SeqManager.hpp" #include "RTC/Shared.hpp" #include @@ -40,14 +39,17 @@ namespace RTC return ( RTC::Consumer::IsActive() && this->producerRtpStream && - (this->producerRtpStream->GetScore() > 0u || this->producerRtpStream->HasDtx()) + // If there is no RTP inactivity check do not consider the stream + // inactive despite it has score 0. + (this->producerRtpStream->GetScore() > 0u || !this->producerRtpStream->HasRtpInactivityCheckEnabled()) ); // clang-format on } - void ProducerRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; - void ProducerNewRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; - void ProducerRtpStreamScore(RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) override; - void ProducerRtcpSenderReport(RTC::RtpStream* rtpStream, bool first) override; + void ProducerRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; + void ProducerNewRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; + void ProducerRtpStreamScore( + RTC::RtpStreamRecv* rtpStream, uint8_t score, uint8_t previousScore) override; + void ProducerRtcpSenderReport(RTC::RtpStreamRecv* rtpStream, bool first) override; uint8_t GetBitratePriority() const override; uint32_t IncreaseLayer(uint32_t bitrate, bool considerLoss) override; void ApplyLayers() override; @@ -93,7 +95,7 @@ namespace RTC RTC::RtpStreamSend* rtpStream{ nullptr }; // Others. std::vector rtpStreams; - RTC::RtpStream* producerRtpStream{ nullptr }; + RTC::RtpStreamRecv* producerRtpStream{ nullptr }; bool syncRequired{ false }; RTC::SeqManager rtpSeqManager; int16_t preferredSpatialLayer{ -1 }; diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index 1ce6812cf0..08450ae58a 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -69,16 +69,19 @@ namespace RTC virtual void OnTransportProducerNewRtpStream( RTC::Transport* transport, RTC::Producer* producer, - RTC::RtpStream* rtpStream, + RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) = 0; virtual void OnTransportProducerRtpStreamScore( RTC::Transport* transport, RTC::Producer* producer, - RTC::RtpStream* rtpStream, + RTC::RtpStreamRecv* rtpStream, uint8_t score, uint8_t previousScore) = 0; virtual void OnTransportProducerRtcpSenderReport( - RTC::Transport* transport, RTC::Producer* producer, RTC::RtpStream* rtpStream, bool first) = 0; + RTC::Transport* transport, + RTC::Producer* producer, + RTC::RtpStreamRecv* rtpStream, + bool first) = 0; virtual void OnTransportProducerRtpPacketReceived( RTC::Transport* transport, RTC::Producer* producer, RTC::RtpPacket* packet) = 0; virtual void OnTransportNeedWorstRemoteFractionLost( @@ -204,11 +207,14 @@ namespace RTC void OnProducerPaused(RTC::Producer* producer) override; void OnProducerResumed(RTC::Producer* producer) override; void OnProducerNewRtpStream( - RTC::Producer* producer, RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; + RTC::Producer* producer, RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; void OnProducerRtpStreamScore( - RTC::Producer* producer, RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) override; + RTC::Producer* producer, + RTC::RtpStreamRecv* rtpStream, + uint8_t score, + uint8_t previousScore) override; void OnProducerRtcpSenderReport( - RTC::Producer* producer, RTC::RtpStream* rtpStream, bool first) override; + RTC::Producer* producer, RTC::RtpStreamRecv* rtpStream, bool first) override; void OnProducerRtpPacketReceived(RTC::Producer* producer, RTC::RtpPacket* packet) override; void OnProducerSendRtcpPacket(RTC::Producer* producer, RTC::RTCP::Packet* packet) override; void OnProducerNeedWorstRemoteFractionLost( diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index f4f1d767ef..9078dc83ea 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -137,14 +137,14 @@ namespace RTC } } - void PipeConsumer::ProducerRtpStream(RTC::RtpStream* /*rtpStream*/, uint32_t /*mappedSsrc*/) + void PipeConsumer::ProducerRtpStream(RTC::RtpStreamRecv* /*rtpStream*/, uint32_t /*mappedSsrc*/) { MS_TRACE(); // Do nothing. } - void PipeConsumer::ProducerNewRtpStream(RTC::RtpStream* /*rtpStream*/, uint32_t /*mappedSsrc*/) + void PipeConsumer::ProducerNewRtpStream(RTC::RtpStreamRecv* /*rtpStream*/, uint32_t /*mappedSsrc*/) { MS_TRACE(); @@ -152,14 +152,14 @@ namespace RTC } void PipeConsumer::ProducerRtpStreamScore( - RTC::RtpStream* /*rtpStream*/, uint8_t /*score*/, uint8_t /*previousScore*/) + RTC::RtpStreamRecv* /*rtpStream*/, uint8_t /*score*/, uint8_t /*previousScore*/) { MS_TRACE(); // Do nothing. } - void PipeConsumer::ProducerRtcpSenderReport(RTC::RtpStream* /*rtpStream*/, bool /*first*/) + void PipeConsumer::ProducerRtcpSenderReport(RTC::RtpStreamRecv* /*rtpStream*/, bool /*first*/) { MS_TRACE(); diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index 1c0e674a8d..c4d542d4e9 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -1223,8 +1223,10 @@ namespace RTC } } - // Only perform RTP inactivity check on simulcast. - auto useRtpInactivityCheck = this->type == RtpParameters::Type::SIMULCAST; + // Only perform RTP inactivity check on simulcast and only if there are + // more than 1 stream. + auto useRtpInactivityCheck = + this->type == RtpParameters::Type::SIMULCAST && this->rtpMapping.encodings.size() > 1; // Create a RtpStreamRecv for receiving a media stream. auto* rtpStream = new RTC::RtpStreamRecv(this, params, SendNackDelay, useRtpInactivityCheck); @@ -1255,7 +1257,7 @@ namespace RTC auto mappedSsrc = this->mapRtpStreamMappedSsrc.at(rtpStream); // Notify the listener. - this->listener->OnProducerNewRtpStream(this, static_cast(rtpStream), mappedSsrc); + this->listener->OnProducerNewRtpStream(this, rtpStream, mappedSsrc); } inline void Producer::PreProcessRtpPacket(RTC::RtpPacket* packet) @@ -1637,7 +1639,8 @@ namespace RTC this->rtpStreamScores[rtpStream->GetEncodingIdx()] = score; // Notify the listener. - this->listener->OnProducerRtpStreamScore(this, rtpStream, score, previousScore); + this->listener->OnProducerRtpStreamScore( + this, static_cast(rtpStream), score, previousScore); // Emit the score event. EmitScore(); diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index b56dc1c345..61b46a6dd8 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -659,7 +659,10 @@ namespace RTC } inline void Router::OnTransportProducerNewRtpStream( - RTC::Transport* /*transport*/, RTC::Producer* producer, RTC::RtpStream* rtpStream, uint32_t mappedSsrc) + RTC::Transport* /*transport*/, + RTC::Producer* producer, + RTC::RtpStreamRecv* rtpStream, + uint32_t mappedSsrc) { MS_TRACE(); @@ -674,7 +677,7 @@ namespace RTC inline void Router::OnTransportProducerRtpStreamScore( RTC::Transport* /*transport*/, RTC::Producer* producer, - RTC::RtpStream* rtpStream, + RTC::RtpStreamRecv* rtpStream, uint8_t score, uint8_t previousScore) { @@ -689,7 +692,7 @@ namespace RTC } inline void Router::OnTransportProducerRtcpSenderReport( - RTC::Transport* /*transport*/, RTC::Producer* producer, RTC::RtpStream* rtpStream, bool first) + RTC::Transport* /*transport*/, RTC::Producer* producer, RTC::RtpStreamRecv* rtpStream, bool first) { MS_TRACE(); diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index 01da96fb0e..44463793c0 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -147,14 +147,14 @@ namespace RTC } } - void SimpleConsumer::ProducerRtpStream(RTC::RtpStream* rtpStream, uint32_t /*mappedSsrc*/) + void SimpleConsumer::ProducerRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t /*mappedSsrc*/) { MS_TRACE(); this->producerRtpStream = rtpStream; } - void SimpleConsumer::ProducerNewRtpStream(RTC::RtpStream* rtpStream, uint32_t /*mappedSsrc*/) + void SimpleConsumer::ProducerNewRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t /*mappedSsrc*/) { MS_TRACE(); @@ -165,7 +165,7 @@ namespace RTC } void SimpleConsumer::ProducerRtpStreamScore( - RTC::RtpStream* /*rtpStream*/, uint8_t /*score*/, uint8_t /*previousScore*/) + RTC::RtpStreamRecv* /*rtpStream*/, uint8_t /*score*/, uint8_t /*previousScore*/) { MS_TRACE(); @@ -173,7 +173,7 @@ namespace RTC EmitScore(); } - void SimpleConsumer::ProducerRtcpSenderReport(RTC::RtpStream* /*rtpStream*/, bool /*first*/) + void SimpleConsumer::ProducerRtcpSenderReport(RTC::RtpStreamRecv* /*rtpStream*/, bool /*first*/) { MS_TRACE(); diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index 44076dca1f..a26f6bb2b9 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -1,3 +1,4 @@ + #define MS_CLASS "RTC::SimulcastConsumer" // #define MS_LOG_DEV_LEVEL 3 @@ -302,7 +303,7 @@ namespace RTC } } - void SimulcastConsumer::ProducerRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) + void SimulcastConsumer::ProducerRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) { MS_TRACE(); @@ -315,7 +316,7 @@ namespace RTC this->producerRtpStreams[spatialLayer] = rtpStream; } - void SimulcastConsumer::ProducerNewRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) + void SimulcastConsumer::ProducerNewRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) { MS_TRACE(); @@ -335,7 +336,7 @@ namespace RTC } void SimulcastConsumer::ProducerRtpStreamScore( - RTC::RtpStream* /*rtpStream*/, uint8_t score, uint8_t previousScore) + RTC::RtpStreamRecv* /*rtpStream*/, uint8_t score, uint8_t previousScore) { MS_TRACE(); @@ -344,9 +345,14 @@ namespace RTC if (RTC::Consumer::IsActive()) { + // All Producer streams are dead. + if (!IsActive()) + { + UpdateTargetLayers(-1, -1); + } // Just check target layers if the stream has died or reborned. // clang-format off - if ( + else if ( !this->externallyManagedBitrate || (score == 0u || previousScore == 0u) ) @@ -357,7 +363,7 @@ namespace RTC } } - void SimulcastConsumer::ProducerRtcpSenderReport(RTC::RtpStream* rtpStream, bool first) + void SimulcastConsumer::ProducerRtcpSenderReport(RTC::RtpStreamRecv* rtpStream, bool first) { MS_TRACE(); @@ -1533,7 +1539,7 @@ namespace RTC this->shared->channelNotifier->Emit(this->id, "layerschange", data); } - inline RTC::RtpStream* SimulcastConsumer::GetProducerCurrentRtpStream() const + inline RTC::RtpStreamRecv* SimulcastConsumer::GetProducerCurrentRtpStream() const { MS_TRACE(); @@ -1544,7 +1550,7 @@ namespace RTC return this->producerRtpStreams.at(this->currentSpatialLayer); } - inline RTC::RtpStream* SimulcastConsumer::GetProducerTargetRtpStream() const + inline RTC::RtpStreamRecv* SimulcastConsumer::GetProducerTargetRtpStream() const { MS_TRACE(); @@ -1555,7 +1561,7 @@ namespace RTC return this->producerRtpStreams.at(this->targetSpatialLayer); } - inline RTC::RtpStream* SimulcastConsumer::GetProducerTsReferenceRtpStream() const + inline RTC::RtpStreamRecv* SimulcastConsumer::GetProducerTsReferenceRtpStream() const { MS_TRACE(); @@ -1567,7 +1573,7 @@ namespace RTC } inline void SimulcastConsumer::OnRtpStreamScore( - RTC::RtpStream* /*rtpStream*/, uint8_t /*score*/, uint8_t /*previousScore*/) + RTC::RtpStream* /*rtpStream*/, uint8_t score, uint8_t /*previousScore*/) { MS_TRACE(); diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index d2b6af9566..aadf4f8b63 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -279,14 +279,14 @@ namespace RTC } } - void SvcConsumer::ProducerRtpStream(RTC::RtpStream* rtpStream, uint32_t /*mappedSsrc*/) + void SvcConsumer::ProducerRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t /*mappedSsrc*/) { MS_TRACE(); this->producerRtpStream = rtpStream; } - void SvcConsumer::ProducerNewRtpStream(RTC::RtpStream* rtpStream, uint32_t /*mappedSsrc*/) + void SvcConsumer::ProducerNewRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t /*mappedSsrc*/) { MS_TRACE(); @@ -300,7 +300,7 @@ namespace RTC } void SvcConsumer::ProducerRtpStreamScore( - RTC::RtpStream* /*rtpStream*/, uint8_t score, uint8_t previousScore) + RTC::RtpStreamRecv* /*rtpStream*/, uint8_t score, uint8_t previousScore) { MS_TRACE(); @@ -322,7 +322,7 @@ namespace RTC } } - void SvcConsumer::ProducerRtcpSenderReport(RTC::RtpStream* /*rtpStream*/, bool /*first*/) + void SvcConsumer::ProducerRtcpSenderReport(RTC::RtpStreamRecv* /*rtpStream*/, bool /*first*/) { MS_TRACE(); diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 3bf589286b..a99915b71c 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -2621,7 +2621,7 @@ namespace RTC } inline void Transport::OnProducerNewRtpStream( - RTC::Producer* producer, RTC::RtpStream* rtpStream, uint32_t mappedSsrc) + RTC::Producer* producer, RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) { MS_TRACE(); @@ -2629,7 +2629,7 @@ namespace RTC } inline void Transport::OnProducerRtpStreamScore( - RTC::Producer* producer, RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) + RTC::Producer* producer, RTC::RtpStreamRecv* rtpStream, uint8_t score, uint8_t previousScore) { MS_TRACE(); @@ -2637,7 +2637,7 @@ namespace RTC } inline void Transport::OnProducerRtcpSenderReport( - RTC::Producer* producer, RTC::RtpStream* rtpStream, bool first) + RTC::Producer* producer, RTC::RtpStreamRecv* rtpStream, bool first) { MS_TRACE(); From f3167c015119b1b14be86ce06b5abce26b17e96a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 19 Jul 2023 16:30:33 +0200 Subject: [PATCH 136/525] Update deps --- package-lock.json | 1126 +++++++++++++++++++++++++++++---------------- package.json | 14 +- 2 files changed, 748 insertions(+), 392 deletions(-) diff --git a/package-lock.json b/package-lock.json index ea8c5f995e..4cf2601171 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,15 +18,15 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@octokit/rest": "^19.0.13", + "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", - "@types/jest": "^29.5.2", - "@types/node": "^18.16.18", + "@types/jest": "^29.5.3", + "@types/node": "^20.4.2", "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^5.61.0", - "@typescript-eslint/parser": "^5.61.0", - "eslint": "^8.44.0", - "eslint-plugin-jest": "^27.2.2", + "@typescript-eslint/eslint-plugin": "^6.1.0", + "@typescript-eslint/parser": "^6.1.0", + "eslint": "^8.45.0", + "eslint-plugin-jest": "^27.2.3", "jest": "^29.6.1", "marked": "^5.1.1", "open-cli": "^7.2.0", @@ -655,9 +655,9 @@ "dev": true }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", - "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" @@ -670,9 +670,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -1212,189 +1212,160 @@ } }, "node_modules/@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", "dev": true, - "dependencies": { - "@octokit/types": "^9.0.0" - }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/core": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", - "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", + "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", "dev": true, "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.0.0", + "@octokit/request": "^8.0.2", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/endpoint": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", - "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", + "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", "dev": true, "dependencies": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^11.0.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/graphql": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", + "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", "dev": true, "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", + "@octokit/request": "^8.0.1", + "@octokit/types": "^11.0.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/openapi-types": { - "version": "17.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", - "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", - "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-8.0.0.tgz", + "integrity": "sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==", "dev": true, "dependencies": { - "@octokit/tsconfig": "^1.0.2", - "@octokit/types": "^9.2.3" + "@octokit/types": "^11.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=4" + "@octokit/core": ">=5" } }, "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", + "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", "dev": true, + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@octokit/core": ">=3" + "@octokit/core": ">=5" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.1.2.tgz", - "integrity": "sha512-R0oJ7j6f/AdqPLtB9qRXLO+wjI9pctUn8Ka8UGfGaFCcCv3Otx14CshQ89K4E88pmyYZS8p0rNTiprML/81jig==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-9.0.0.tgz", + "integrity": "sha512-KquMF/VB1IkKNiVnzJKspY5mFgGyLd7HzdJfVEGTJFzqu9BRFNWt+nwTCMuUiWc72gLQhRWYubTwOkQj+w/1PA==", "dev": true, "dependencies": { - "@octokit/types": "^9.2.3", - "deprecation": "^2.3.1" + "@octokit/types": "^11.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=3" + "@octokit/core": ">=5" } }, "node_modules/@octokit/request": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", - "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", + "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", "dev": true, "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.1.0", "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", + "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", "dev": true, "dependencies": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^11.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request/node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">= 18" } }, "node_modules/@octokit/rest": { - "version": "19.0.13", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", - "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.1.tgz", + "integrity": "sha512-wROV21RwHQIMNb2Dgd4+pY+dVy1Dwmp85pBrgr6YRRDYRBu9Gb+D73f4Bl2EukZSj5hInq2Tui9o7gAQpc2k2Q==", "dev": true, "dependencies": { - "@octokit/core": "^4.2.1", - "@octokit/plugin-paginate-rest": "^6.1.2", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.1.2" + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^8.0.0", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-rest-endpoint-methods": "^9.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, - "node_modules/@octokit/tsconfig": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", - "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", - "dev": true - }, "node_modules/@octokit/types": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", - "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", + "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^17.2.0" + "@octokit/openapi-types": "^18.0.0" } }, "node_modules/@sinclair/typebox": { @@ -1511,9 +1482,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", - "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", + "version": "29.5.3", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", + "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1521,9 +1492,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "node_modules/@types/minimist": { @@ -1539,9 +1510,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.16.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.18.tgz", - "integrity": "sha512-/aNaQZD0+iSBAGnvvN2Cx92HqE5sZCPZtx2TsK+4nvV23fFe09jVDvpArXr2j9DnYlzuU9WuoykDDc6wqvpNcw==", + "version": "20.4.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz", + "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1557,9 +1528,9 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, "node_modules/@types/stack-utils": { @@ -1590,32 +1561,91 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.61.0.tgz", - "integrity": "sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.1.0.tgz", + "integrity": "sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.61.0", - "@typescript-eslint/type-utils": "5.61.0", - "@typescript-eslint/utils": "5.61.0", + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/type-utils": "6.1.0", + "@typescript-eslint/utils": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", "debug": "^4.3.4", "graphemer": "^1.4.0", - "ignore": "^5.2.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", + "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", + "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", + "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependenciesMeta": { "typescript": { @@ -1623,26 +1653,69 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", + "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.61.0.tgz", - "integrity": "sha512-yGr4Sgyh8uO6fSi9hw3jAFXNBHbCtKKFMdX2IkT3ZqpKmtAq3lHS4ixB/COFuAIJpwl9/AqF7j72ZDWYKmIfvg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.1.0.tgz", + "integrity": "sha512-hIzCPvX4vDs4qL07SYzyomamcs2/tQYXg5DtdAfj35AyJ5PIUqhsLf4YrEIFzZcND7R2E8tpQIZKayxg8/6Wbw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.61.0", - "@typescript-eslint/types": "5.61.0", - "@typescript-eslint/typescript-estree": "5.61.0", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1650,14 +1723,88 @@ } } }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", + "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", + "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", + "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", + "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.61.0.tgz", - "integrity": "sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.61.0", - "@typescript-eslint/visitor-keys": "5.61.0" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1668,25 +1815,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.61.0.tgz", - "integrity": "sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.1.0.tgz", + "integrity": "sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.61.0", - "@typescript-eslint/utils": "5.61.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/utils": "6.1.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1694,10 +1841,109 @@ } } }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", + "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", + "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", + "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", + "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/types": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.61.0.tgz", - "integrity": "sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1708,13 +1954,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.61.0.tgz", - "integrity": "sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.61.0", - "@typescript-eslint/visitor-keys": "5.61.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1735,17 +1981,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.61.0.tgz", - "integrity": "sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.61.0", - "@typescript-eslint/types": "5.61.0", - "@typescript-eslint/typescript-estree": "5.61.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1761,12 +2007,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.61.0.tgz", - "integrity": "sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2643,9 +2889,9 @@ } }, "node_modules/eslint": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz", - "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==", + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", + "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -2673,7 +2919,6 @@ "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", @@ -2685,7 +2930,6 @@ "natural-compare": "^1.4.0", "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { @@ -2699,9 +2943,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz", - "integrity": "sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw==", + "version": "27.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", + "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -2710,7 +2954,7 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", "eslint": "^7.0.0 || ^8.0.0", "jest": "*" }, @@ -3361,9 +3605,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "engines": { "node": ">= 4" @@ -5969,12 +6213,6 @@ "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, "node_modules/trim-newlines": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", @@ -5987,6 +6225,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-jest": { "version": "29.1.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", @@ -6223,22 +6473,6 @@ "node": ">= 8" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6860,18 +7094,18 @@ "dev": true }, "@eslint-community/eslint-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", - "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "requires": { "eslint-visitor-keys": "^3.3.0" } }, "@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", "dev": true }, "@eslint/eslintrc": { @@ -7288,145 +7522,122 @@ } }, "@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", - "dev": true, - "requires": { - "@octokit/types": "^9.0.0" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true }, "@octokit/core": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", - "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", + "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", "dev": true, "requires": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.0.0", + "@octokit/request": "^8.0.2", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" } }, "@octokit/endpoint": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", - "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", + "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", "dev": true, "requires": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^11.0.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/graphql": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", + "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", "dev": true, "requires": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", + "@octokit/request": "^8.0.1", + "@octokit/types": "^11.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/openapi-types": { - "version": "17.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", - "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", "dev": true }, "@octokit/plugin-paginate-rest": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", - "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-8.0.0.tgz", + "integrity": "sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==", "dev": true, "requires": { - "@octokit/tsconfig": "^1.0.2", - "@octokit/types": "^9.2.3" + "@octokit/types": "^11.0.0" } }, "@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", + "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", "dev": true, "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.1.2.tgz", - "integrity": "sha512-R0oJ7j6f/AdqPLtB9qRXLO+wjI9pctUn8Ka8UGfGaFCcCv3Otx14CshQ89K4E88pmyYZS8p0rNTiprML/81jig==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-9.0.0.tgz", + "integrity": "sha512-KquMF/VB1IkKNiVnzJKspY5mFgGyLd7HzdJfVEGTJFzqu9BRFNWt+nwTCMuUiWc72gLQhRWYubTwOkQj+w/1PA==", "dev": true, "requires": { - "@octokit/types": "^9.2.3", - "deprecation": "^2.3.1" + "@octokit/types": "^11.0.0" } }, "@octokit/request": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", - "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", + "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", "dev": true, "requires": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.1.0", "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - } } }, "@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", + "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", "dev": true, "requires": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^11.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" } }, "@octokit/rest": { - "version": "19.0.13", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", - "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.1.tgz", + "integrity": "sha512-wROV21RwHQIMNb2Dgd4+pY+dVy1Dwmp85pBrgr6YRRDYRBu9Gb+D73f4Bl2EukZSj5hInq2Tui9o7gAQpc2k2Q==", "dev": true, "requires": { - "@octokit/core": "^4.2.1", - "@octokit/plugin-paginate-rest": "^6.1.2", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.1.2" + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^8.0.0", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-rest-endpoint-methods": "^9.0.0" } }, - "@octokit/tsconfig": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", - "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", - "dev": true - }, "@octokit/types": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", - "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", + "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", "dev": true, "requires": { - "@octokit/openapi-types": "^17.2.0" + "@octokit/openapi-types": "^18.0.0" } }, "@sinclair/typebox": { @@ -7543,9 +7754,9 @@ } }, "@types/jest": { - "version": "29.5.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", - "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", + "version": "29.5.3", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", + "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", "dev": true, "requires": { "expect": "^29.0.0", @@ -7553,9 +7764,9 @@ } }, "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "@types/minimist": { @@ -7571,9 +7782,9 @@ "dev": true }, "@types/node": { - "version": "18.16.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.18.tgz", - "integrity": "sha512-/aNaQZD0+iSBAGnvvN2Cx92HqE5sZCPZtx2TsK+4nvV23fFe09jVDvpArXr2j9DnYlzuU9WuoykDDc6wqvpNcw==", + "version": "20.4.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz", + "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==", "dev": true }, "@types/normalize-package-data": { @@ -7589,9 +7800,9 @@ "dev": true }, "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, "@types/stack-utils": { @@ -7622,71 +7833,233 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.61.0.tgz", - "integrity": "sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.1.0.tgz", + "integrity": "sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw==", "dev": true, "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.61.0", - "@typescript-eslint/type-utils": "5.61.0", - "@typescript-eslint/utils": "5.61.0", + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/type-utils": "6.1.0", + "@typescript-eslint/utils": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", "debug": "^4.3.4", "graphemer": "^1.4.0", - "ignore": "^5.2.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", + "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0" + } + }, + "@typescript-eslint/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", + "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", + "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", + "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "eslint-visitor-keys": "^3.4.1" + } + } } }, "@typescript-eslint/parser": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.61.0.tgz", - "integrity": "sha512-yGr4Sgyh8uO6fSi9hw3jAFXNBHbCtKKFMdX2IkT3ZqpKmtAq3lHS4ixB/COFuAIJpwl9/AqF7j72ZDWYKmIfvg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.1.0.tgz", + "integrity": "sha512-hIzCPvX4vDs4qL07SYzyomamcs2/tQYXg5DtdAfj35AyJ5PIUqhsLf4YrEIFzZcND7R2E8tpQIZKayxg8/6Wbw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.61.0", - "@typescript-eslint/types": "5.61.0", - "@typescript-eslint/typescript-estree": "5.61.0", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", "debug": "^4.3.4" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", + "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0" + } + }, + "@typescript-eslint/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", + "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", + "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", + "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "eslint-visitor-keys": "^3.4.1" + } + } } }, "@typescript-eslint/scope-manager": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.61.0.tgz", - "integrity": "sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "requires": { - "@typescript-eslint/types": "5.61.0", - "@typescript-eslint/visitor-keys": "5.61.0" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" } }, "@typescript-eslint/type-utils": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.61.0.tgz", - "integrity": "sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.1.0.tgz", + "integrity": "sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.61.0", - "@typescript-eslint/utils": "5.61.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/utils": "6.1.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", + "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0" + } + }, + "@typescript-eslint/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", + "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", + "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", + "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "eslint-visitor-keys": "^3.4.1" + } + } } }, "@typescript-eslint/types": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.61.0.tgz", - "integrity": "sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.61.0.tgz", - "integrity": "sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.61.0", - "@typescript-eslint/visitor-keys": "5.61.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7695,28 +8068,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.61.0.tgz", - "integrity": "sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.61.0", - "@typescript-eslint/types": "5.61.0", - "@typescript-eslint/typescript-estree": "5.61.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.61.0.tgz", - "integrity": "sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -8340,9 +8713,9 @@ "dev": true }, "eslint": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz", - "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==", + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", + "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", @@ -8370,7 +8743,6 @@ "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", @@ -8382,7 +8754,6 @@ "natural-compare": "^1.4.0", "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "dependencies": { @@ -8405,9 +8776,9 @@ } }, "eslint-plugin-jest": { - "version": "27.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz", - "integrity": "sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw==", + "version": "27.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", + "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" @@ -8851,9 +9222,9 @@ "dev": true }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, "import-fresh": { @@ -10700,18 +11071,19 @@ "ieee754": "^1.2.1" } }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, "trim-newlines": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", "dev": true }, + "ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "requires": {} + }, "ts-jest": { "version": "29.1.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", @@ -10864,22 +11236,6 @@ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index bc7232a472..d1080ed5b7 100644 --- a/package.json +++ b/package.json @@ -95,15 +95,15 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@octokit/rest": "^19.0.13", + "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", - "@types/jest": "^29.5.2", - "@types/node": "^18.16.18", + "@types/jest": "^29.5.3", + "@types/node": "^20.4.2", "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^5.61.0", - "@typescript-eslint/parser": "^5.61.0", - "eslint": "^8.44.0", - "eslint-plugin-jest": "^27.2.2", + "@typescript-eslint/eslint-plugin": "^6.1.0", + "@typescript-eslint/parser": "^6.1.0", + "eslint": "^8.45.0", + "eslint-plugin-jest": "^27.2.3", "jest": "^29.6.1", "marked": "^5.1.1", "open-cli": "^7.2.0", From 3751deb05f118930d8af7981976ef52774253924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 19 Jul 2023 16:31:52 +0200 Subject: [PATCH 137/525] 3.12.7 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4d92b3d20..ce0f5cf240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### Next +### 3.12.7 * `SimulcastConsumer`: Fix lack of "consumerlayerschange" event when all streams in the producer die ([PR #1122](https://github.com/versatica/mediasoup/pull/1122)). diff --git a/package-lock.json b/package-lock.json index 4cf2601171..af6a3b8af5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.6", + "version": "3.12.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.6", + "version": "3.12.7", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index d1080ed5b7..4cb468fc8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.6", + "version": "3.12.7", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From dbc377cdd05ae8afe6bb496a222f54f145081464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 19 Jul 2023 17:22:10 +0200 Subject: [PATCH 138/525] Fix CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce0f5cf240..f66b72f744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### 3.12.7 -* `SimulcastConsumer`: Fix lack of "consumerlayerschange" event when all streams in the producer die ([PR #1122](https://github.com/versatica/mediasoup/pull/1122)). +* `SimulcastConsumer`: Fix lack of "layerschange" event when all streams in the producer die ([PR #1122](https://github.com/versatica/mediasoup/pull/1122)). ### 3.12.6 From 1621b373788c6ab5d7acfa999879e1a3e92f767b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 20 Jul 2023 13:03:22 +0200 Subject: [PATCH 139/525] Export workerBin absolute path (#1123) --- CHANGELOG.md | 5 +++++ doc/Building.md | 2 +- node/src/Worker.ts | 2 +- node/src/index.ts | 7 ++++++- node/src/tests/test-Worker.ts | 11 +++++++++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f66b72f744..2c64b0d01c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +### Next + +* Export `workerBin` absolute path ([PR #1123](https://github.com/versatica/mediasoup/pull/1123)). + + ### 3.12.7 * `SimulcastConsumer`: Fix lack of "layerschange" event when all streams in the producer die ([PR #1122](https://github.com/versatica/mediasoup/pull/1122)). diff --git a/doc/Building.md b/doc/Building.md index a591bbfc9f..218faa8850 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -126,7 +126,7 @@ In order to instruct the mediasoup Node.js module to use the `Debug` mediasoup-w MEDIASOUP_BUILDTYPE=Debug node myapp.js ``` -If the "MEDIASOUP_WORKER_BIN" environment variable is set, mediasoup will use the it as mediasoup-worker binary and **won't** compile the binary: +If the "MEDIASOUP_WORKER_BIN" environment variable is set (it must be an absolute file path), mediasoup will use the it as mediasoup-worker binary and **won't** compile the binary: ```bash MEDIASOUP_WORKER_BIN="/home/xxx/src/foo/mediasoup-worker" node myapp.js diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 3c6ce2d61d..860bef53c1 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -195,7 +195,7 @@ export type WorkerObserverEvents = // If env MEDIASOUP_WORKER_BIN is given, use it as worker binary. // Otherwise if env MEDIASOUP_BUILDTYPE is 'Debug' use the Debug binary. // Otherwise use the Release binary. -const workerBin = process.env.MEDIASOUP_WORKER_BIN +export const workerBin = process.env.MEDIASOUP_WORKER_BIN ? process.env.MEDIASOUP_WORKER_BIN : process.env.MEDIASOUP_BUILDTYPE === 'Debug' ? path.join(__dirname, '..', '..', 'worker', 'out', 'Debug', 'mediasoup-worker') diff --git a/node/src/index.ts b/node/src/index.ts index c98d349e7b..06f30f7008 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -1,6 +1,6 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; -import { Worker, WorkerSettings } from './Worker'; +import { workerBin, Worker, WorkerSettings } from './Worker'; import * as utils from './utils'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; import { RtpCapabilities } from './RtpParameters'; @@ -36,6 +36,11 @@ const observer = new EnhancedEventEmitter(); */ export { observer }; +/** + * Full path of the mediasoup-worker binary. + */ +export { workerBin }; + /** * Create a Worker. */ diff --git a/node/src/tests/test-Worker.ts b/node/src/tests/test-Worker.ts index 15ab5ace52..365e7fac05 100644 --- a/node/src/tests/test-Worker.ts +++ b/node/src/tests/test-Worker.ts @@ -11,6 +11,17 @@ let worker: mediasoup.types.Worker; beforeEach(() => worker && !worker.closed && worker.close()); afterEach(() => worker && !worker.closed && worker.close()); +test('Worker.workerBin matches mediasoup-worker absolute path', async () => +{ + const workerBin = process.env.MEDIASOUP_WORKER_BIN + ? process.env.MEDIASOUP_WORKER_BIN + : process.env.MEDIASOUP_BUILDTYPE === 'Debug' + ? path.join(__dirname, '..', '..', '..', 'worker', 'out', 'Debug', 'mediasoup-worker') + : path.join(__dirname, '..', '..', '..', 'worker', 'out', 'Release', 'mediasoup-worker'); + + expect(mediasoup.workerBin).toBe(workerBin); +}); + test('createWorker() succeeds', async () => { const onObserverNewWorker = jest.fn(); From dc4f8f306d31148a1054f5ecbe14e98ede779e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 20 Jul 2023 13:05:51 +0200 Subject: [PATCH 140/525] 3.12.8 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c64b0d01c..0e9d623b8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### Next +### 3.12.8 * Export `workerBin` absolute path ([PR #1123](https://github.com/versatica/mediasoup/pull/1123)). diff --git a/package-lock.json b/package-lock.json index af6a3b8af5..ac282bdf6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.7", + "version": "3.12.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.7", + "version": "3.12.8", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 4cb468fc8c..b283ca6056 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.7", + "version": "3.12.8", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 222ebd2c5d19b36a956aadea02d480f7264a2235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 28 Jul 2023 14:03:06 +0200 Subject: [PATCH 141/525] Avoid ASAN "new-delete-type-mismatch" harmless but noisy warning (#1129) --- worker/src/Channel/ChannelSocket.cpp | 7 +- worker/src/DepLibUV.cpp | 6 +- .../PayloadChannel/PayloadChannelSocket.cpp | 7 +- worker/src/RTC/PortManager.cpp | 64 ++++++++++++++++--- worker/src/handles/SignalsHandler.cpp | 6 +- worker/src/handles/TcpConnectionHandler.cpp | 15 +++-- worker/src/handles/TcpServerHandler.cpp | 10 +-- worker/src/handles/Timer.cpp | 6 +- worker/src/handles/UdpSocketHandler.cpp | 10 +-- worker/src/handles/UnixStreamSocket.cpp | 19 ++++-- 10 files changed, 105 insertions(+), 45 deletions(-) diff --git a/worker/src/Channel/ChannelSocket.cpp b/worker/src/Channel/ChannelSocket.cpp index 22bc0a4b69..473b8927f2 100644 --- a/worker/src/Channel/ChannelSocket.cpp +++ b/worker/src/Channel/ChannelSocket.cpp @@ -24,9 +24,9 @@ namespace Channel } } - inline static void onClose(uv_handle_t* handle) + inline static void onCloseAsync(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); } /* Instance methods. */ @@ -100,7 +100,8 @@ namespace Channel if (this->uvReadHandle) { - uv_close(reinterpret_cast(this->uvReadHandle), static_cast(onClose)); + uv_close( + reinterpret_cast(this->uvReadHandle), static_cast(onCloseAsync)); } if (this->consumerSocket) diff --git a/worker/src/DepLibUV.cpp b/worker/src/DepLibUV.cpp index aaa697baa5..dfe5f9b6fb 100644 --- a/worker/src/DepLibUV.cpp +++ b/worker/src/DepLibUV.cpp @@ -11,9 +11,9 @@ thread_local uv_loop_t* DepLibUV::loop{ nullptr }; /* Static methods for UV callbacks. */ -inline static void onClose(uv_handle_t* handle) +inline static void onCloseLoop(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); } inline static void onWalk(uv_handle_t* handle, void* /*arg*/) @@ -27,7 +27,7 @@ inline static void onWalk(uv_handle_t* handle, void* /*arg*/) uv_has_ref(handle)); if (!uv_is_closing(handle)) - uv_close(handle, onClose); + uv_close(handle, onCloseLoop); } /* Static methods. */ diff --git a/worker/src/PayloadChannel/PayloadChannelSocket.cpp b/worker/src/PayloadChannel/PayloadChannelSocket.cpp index 52ba754f06..6f407a09de 100644 --- a/worker/src/PayloadChannel/PayloadChannelSocket.cpp +++ b/worker/src/PayloadChannel/PayloadChannelSocket.cpp @@ -25,9 +25,9 @@ namespace PayloadChannel } } - inline static void onClose(uv_handle_t* handle) + inline static void onCloseAsync(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); } /* Instance methods. */ @@ -102,7 +102,8 @@ namespace PayloadChannel if (this->uvReadHandle) { - uv_close(reinterpret_cast(this->uvReadHandle), static_cast(onClose)); + uv_close( + reinterpret_cast(this->uvReadHandle), static_cast(onCloseAsync)); } if (this->consumerSocket) diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index 5269fced06..368bbee096 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -12,9 +12,16 @@ /* Static methods for UV callbacks. */ -static inline void onClose(uv_handle_t* handle) +// NOTE: We have different onCloseXxx() callbacks to avoid an ASAN warning by +// ensuring that we call `delete xxx` with same type as `new xxx` before. +static inline void onCloseUdp(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); +} + +static inline void onCloseTcp(uv_handle_t* handle) +{ + delete reinterpret_cast(handle); } inline static void onFakeConnection(uv_stream_t* /*handle*/, int /*status*/) @@ -161,30 +168,44 @@ namespace RTC switch (transport) { case Transport::UDP: + { uvHandle = reinterpret_cast(new uv_udp_t()); err = uv_udp_init_ex( DepLibUV::GetLoop(), reinterpret_cast(uvHandle), UV_UDP_RECVMMSG); + break; + } case Transport::TCP: + { uvHandle = reinterpret_cast(new uv_tcp_t()); err = uv_tcp_init(DepLibUV::GetLoop(), reinterpret_cast(uvHandle)); + break; + } } if (err != 0) { - delete uvHandle; - switch (transport) { case Transport::UDP: + { + delete reinterpret_cast(uvHandle); + MS_THROW_ERROR("uv_udp_init_ex() failed: %s", uv_strerror(err)); + break; + } case Transport::TCP: + { + delete reinterpret_cast(uvHandle); + MS_THROW_ERROR("uv_tcp_init() failed: %s", uv_strerror(err)); + break; + } } } @@ -259,7 +280,22 @@ namespace RTC break; // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onClose)); + switch (transport) + { + case Transport::UDP: + { + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseUdp)); + + break; + }; + + case Transport::TCP: + { + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); + + break; + } + } switch (err) { @@ -400,17 +436,25 @@ namespace RTC if (err != 0) { - delete uvHandle; - switch (transport) { case Transport::UDP: + { + delete reinterpret_cast(uvHandle); + MS_THROW_ERROR("uv_udp_init_ex() failed: %s", uv_strerror(err)); + break; + } case Transport::TCP: + { + delete reinterpret_cast(uvHandle); + MS_THROW_ERROR("uv_tcp_init() failed: %s", uv_strerror(err)); + break; + } } } @@ -426,7 +470,7 @@ namespace RTC if (err != 0) { // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseUdp)); MS_THROW_ERROR( "uv_udp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 "]: %s", @@ -449,7 +493,7 @@ namespace RTC if (err != 0) { // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); MS_THROW_ERROR( "uv_tcp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 "]: %s", @@ -469,7 +513,7 @@ namespace RTC if (err != 0) { // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); MS_THROW_ERROR( "uv_listen() failed [transport:%s, ip:'%s', port:%" PRIu16 "]: %s", diff --git a/worker/src/handles/SignalsHandler.cpp b/worker/src/handles/SignalsHandler.cpp index f23240bd5b..9d6ca8900e 100644 --- a/worker/src/handles/SignalsHandler.cpp +++ b/worker/src/handles/SignalsHandler.cpp @@ -13,9 +13,9 @@ inline static void onSignal(uv_signal_t* handle, int signum) static_cast(handle->data)->OnUvSignal(signum); } -inline static void onClose(uv_handle_t* handle) +inline static void onCloseSignal(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); } /* Instance methods. */ @@ -44,7 +44,7 @@ void SignalsHandler::Close() for (auto* uvHandle : this->uvHandles) { - uv_close(reinterpret_cast(uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseSignal)); } } diff --git a/worker/src/handles/TcpConnectionHandler.cpp b/worker/src/handles/TcpConnectionHandler.cpp index 5e3fa110ed..253dc99c26 100644 --- a/worker/src/handles/TcpConnectionHandler.cpp +++ b/worker/src/handles/TcpConnectionHandler.cpp @@ -40,9 +40,16 @@ inline static void onWrite(uv_write_t* req, int status) delete writeData; } -inline static void onClose(uv_handle_t* handle) +// NOTE: We have different onCloseXxx() callbacks to avoid an ASAN warning by +// ensuring that we call `delete xxx` with same type as `new xxx` before. +inline static void onCloseTcp(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); +} + +inline static void onCloseShutdown(uv_handle_t* handle) +{ + delete reinterpret_cast(handle); } inline static void onShutdown(uv_shutdown_t* req, int /*status*/) @@ -52,7 +59,7 @@ inline static void onShutdown(uv_shutdown_t* req, int /*status*/) delete req; // Now do close the handle. - uv_close(reinterpret_cast(handle), static_cast(onClose)); + uv_close(reinterpret_cast(handle), static_cast(onCloseShutdown)); } /* Instance methods. */ @@ -114,7 +121,7 @@ void TcpConnectionHandler::Close() // Otherwise directly close the socket. else { - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTcp)); } } diff --git a/worker/src/handles/TcpServerHandler.cpp b/worker/src/handles/TcpServerHandler.cpp index f6513603f0..7b04ad1abc 100644 --- a/worker/src/handles/TcpServerHandler.cpp +++ b/worker/src/handles/TcpServerHandler.cpp @@ -20,9 +20,9 @@ inline static void onConnection(uv_stream_t* handle, int status) server->OnUvConnection(status); } -inline static void onClose(uv_handle_t* handle) +inline static void onCloseTcp(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); } /* Instance methods. */ @@ -43,7 +43,7 @@ TcpServerHandler::TcpServerHandler(uv_tcp_t* uvHandle) : uvHandle(uvHandle) if (err != 0) { - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTcp)); MS_THROW_ERROR("uv_listen() failed: %s", uv_strerror(err)); } @@ -51,7 +51,7 @@ TcpServerHandler::TcpServerHandler(uv_tcp_t* uvHandle) : uvHandle(uvHandle) // Set local address. if (!SetLocalAddress()) { - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTcp)); MS_THROW_ERROR("error setting local IP and port"); } @@ -84,7 +84,7 @@ void TcpServerHandler::Close() delete connection; } - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTcp)); } void TcpServerHandler::Dump() const diff --git a/worker/src/handles/Timer.cpp b/worker/src/handles/Timer.cpp index ce6bad6264..efc9133d33 100644 --- a/worker/src/handles/Timer.cpp +++ b/worker/src/handles/Timer.cpp @@ -13,9 +13,9 @@ inline static void onTimer(uv_timer_t* handle) static_cast(handle->data)->OnUvTimer(); } -inline static void onClose(uv_handle_t* handle) +inline static void onCloseTimer(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); } /* Instance methods. */ @@ -59,7 +59,7 @@ void Timer::Close() this->closed = true; - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTimer)); } void Timer::Start(uint64_t timeout, uint64_t repeat) diff --git a/worker/src/handles/UdpSocketHandler.cpp b/worker/src/handles/UdpSocketHandler.cpp index 6cb7ef3702..5bf4ba7cdf 100644 --- a/worker/src/handles/UdpSocketHandler.cpp +++ b/worker/src/handles/UdpSocketHandler.cpp @@ -45,9 +45,9 @@ inline static void onSend(uv_udp_send_t* req, int status) delete sendData; } -inline static void onClose(uv_handle_t* handle) +inline static void onCloseUdp(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); } /* Instance methods. */ @@ -66,7 +66,7 @@ UdpSocketHandler::UdpSocketHandler(uv_udp_t* uvHandle) : uvHandle(uvHandle) if (err != 0) { - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseUdp)); MS_THROW_ERROR("uv_udp_recv_start() failed: %s", uv_strerror(err)); } @@ -74,7 +74,7 @@ UdpSocketHandler::UdpSocketHandler(uv_udp_t* uvHandle) : uvHandle(uvHandle) // Set local address. if (!SetLocalAddress()) { - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseUdp)); MS_THROW_ERROR("error setting local IP and port"); } @@ -106,7 +106,7 @@ void UdpSocketHandler::Close() if (err != 0) MS_ABORT("uv_udp_recv_stop() failed: %s", uv_strerror(err)); - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseUdp)); } void UdpSocketHandler::Dump() const diff --git a/worker/src/handles/UnixStreamSocket.cpp b/worker/src/handles/UnixStreamSocket.cpp index 8f4f5b5aca..8d8037d3ea 100644 --- a/worker/src/handles/UnixStreamSocket.cpp +++ b/worker/src/handles/UnixStreamSocket.cpp @@ -44,9 +44,16 @@ inline static void onWrite(uv_write_t* req, int status) delete writeData; } -inline static void onClose(uv_handle_t* handle) +// NOTE: We have different onCloseXxx() callbacks to avoid an ASAN warning by +// ensuring that we call `delete xxx` with same type as `new xxx` before. +inline static void onClosePipe(uv_handle_t* handle) { - delete handle; + delete reinterpret_cast(handle); +} + +inline static void onCloseShutdown(uv_handle_t* handle) +{ + delete reinterpret_cast(handle); } inline static void onShutdown(uv_shutdown_t* req, int /*status*/) @@ -56,7 +63,7 @@ inline static void onShutdown(uv_shutdown_t* req, int /*status*/) delete req; // Now do close the handle. - uv_close(reinterpret_cast(handle), static_cast(onClose)); + uv_close(reinterpret_cast(handle), static_cast(onCloseShutdown)); } /* Instance methods. */ @@ -85,7 +92,7 @@ UnixStreamSocket::UnixStreamSocket(int fd, size_t bufferSize, UnixStreamSocket:: if (err != 0) { - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onClosePipe)); MS_THROW_ERROR_STD("uv_pipe_open() failed: %s", uv_strerror(err)); } @@ -100,7 +107,7 @@ UnixStreamSocket::UnixStreamSocket(int fd, size_t bufferSize, UnixStreamSocket:: if (err != 0) { - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onClosePipe)); MS_THROW_ERROR_STD("uv_read_start() failed: %s", uv_strerror(err)); } @@ -157,7 +164,7 @@ void UnixStreamSocket::Close() // Otherwise directly close the socket. else { - uv_close(reinterpret_cast(this->uvHandle), static_cast(onClose)); + uv_close(reinterpret_cast(this->uvHandle), static_cast(onClosePipe)); } } From 0b628632bd18f60a30a9742fc0b37eb58c8efd68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 3 Aug 2023 11:48:42 +0200 Subject: [PATCH 142/525] Remove space --- node/src/tests/test-Consumer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/tests/test-Consumer.ts b/node/src/tests/test-Consumer.ts index 156eb76535..2749fa3486 100644 --- a/node/src/tests/test-Consumer.ts +++ b/node/src/tests/test-Consumer.ts @@ -529,7 +529,7 @@ test('transport.consume() with enableRtx succeeds', async () => audioConsumer2.close(); }, 2000); -test('transport.consume() can be created with user provided mid', async () => +test('transport.consume() can be created with user provided mid', async () => { const audioConsumer1 = await transport2.consume( { From 54698cf55d78f1a42c3b07facc3d1650a8f15a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 8 Aug 2023 17:10:48 +0200 Subject: [PATCH 143/525] Update deps --- package-lock.json | 1544 ++++++++++++++++++++++----------------------- package.json | 14 +- 2 files changed, 768 insertions(+), 790 deletions(-) diff --git a/package-lock.json b/package-lock.json index ac282bdf6e..3ea8a3cec2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "dependencies": { "debug": "^4.3.4", "h264-profile-level-id": "^1.0.1", - "node-fetch": "^3.3.1", + "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.1.15", "uuid": "^9.0.0" @@ -21,14 +21,14 @@ "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", "@types/jest": "^29.5.3", - "@types/node": "^20.4.2", + "@types/node": "^20.4.8", "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^6.1.0", - "@typescript-eslint/parser": "^6.1.0", - "eslint": "^8.45.0", + "@typescript-eslint/eslint-plugin": "^6.3.0", + "@typescript-eslint/parser": "^6.3.0", + "eslint": "^8.46.0", "eslint-plugin-jest": "^27.2.3", - "jest": "^29.6.1", - "marked": "^5.1.1", + "jest": "^29.6.2", + "marked": "^7.0.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -670,18 +670,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz", + "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -702,9 +702,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "version": "8.46.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz", + "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -852,16 +852,16 @@ } }, "node_modules/@jest/console": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", - "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", + "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", "slash": "^3.0.0" }, "engines": { @@ -869,15 +869,15 @@ } }, "node_modules/@jest/core": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", - "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", + "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", "dev": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/reporters": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/console": "^29.6.2", + "@jest/reporters": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", @@ -886,20 +886,20 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", + "jest-config": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-resolve-dependencies": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "jest-watcher": "^29.6.1", + "jest-resolve": "^29.6.2", + "jest-resolve-dependencies": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "jest-watcher": "^29.6.2", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -916,37 +916,37 @@ } }, "node_modules/@jest/environment": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", - "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz", + "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.6.1", + "@jest/fake-timers": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.6.1" + "jest-mock": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", "dev": true, "dependencies": { - "expect": "^29.6.1", - "jest-snapshot": "^29.6.1" + "expect": "^29.6.2", + "jest-snapshot": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", - "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", + "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3" @@ -956,47 +956,47 @@ } }, "node_modules/@jest/fake-timers": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", - "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz", + "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", - "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", + "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", "@jest/types": "^29.6.1", - "jest-mock": "^29.6.1" + "jest-mock": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", - "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", + "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/console": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", @@ -1010,9 +1010,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -1057,12 +1057,12 @@ } }, "node_modules/@jest/test-result": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", - "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", + "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", "dev": true, "dependencies": { - "@jest/console": "^29.6.1", + "@jest/console": "^29.6.2", "@jest/types": "^29.6.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" @@ -1072,14 +1072,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", - "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", + "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.1", + "@jest/test-result": "^29.6.2", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.2", "slash": "^3.0.0" }, "engines": { @@ -1087,9 +1087,9 @@ } }, "node_modules/@jest/transform": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", - "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz", + "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -1100,9 +1100,9 @@ "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.2", "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", + "jest-util": "^29.6.2", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1510,9 +1510,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.4.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz", - "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==", + "version": "20.4.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz", + "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1521,12 +1521,6 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, "node_modules/@types/semver": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", @@ -1561,16 +1555,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.1.0.tgz", - "integrity": "sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz", + "integrity": "sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.1.0", - "@typescript-eslint/type-utils": "6.1.0", - "@typescript-eslint/utils": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/scope-manager": "6.3.0", + "@typescript-eslint/type-utils": "6.3.0", + "@typescript-eslint/utils": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1597,13 +1591,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", - "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", + "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0" + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1614,9 +1608,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", - "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", + "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1627,13 +1621,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", - "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", + "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1654,17 +1648,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", - "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz", + "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.1.0", - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/scope-manager": "6.3.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/typescript-estree": "6.3.0", "semver": "^7.5.4" }, "engines": { @@ -1679,12 +1673,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", - "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", + "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/types": "6.3.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1696,15 +1690,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.1.0.tgz", - "integrity": "sha512-hIzCPvX4vDs4qL07SYzyomamcs2/tQYXg5DtdAfj35AyJ5PIUqhsLf4YrEIFzZcND7R2E8tpQIZKayxg8/6Wbw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.3.0.tgz", + "integrity": "sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.1.0", - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/typescript-estree": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/scope-manager": "6.3.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/typescript-estree": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4" }, "engines": { @@ -1724,13 +1718,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", - "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", + "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0" + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1741,9 +1735,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", - "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", + "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1754,13 +1748,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", - "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", + "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1781,12 +1775,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", - "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", + "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/types": "6.3.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1815,13 +1809,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.1.0.tgz", - "integrity": "sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.3.0.tgz", + "integrity": "sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.1.0", - "@typescript-eslint/utils": "6.1.0", + "@typescript-eslint/typescript-estree": "6.3.0", + "@typescript-eslint/utils": "6.3.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1842,13 +1836,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", - "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", + "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0" + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1859,9 +1853,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", - "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", + "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1872,13 +1866,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", - "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", + "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1899,17 +1893,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", - "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz", + "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.1.0", - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/scope-manager": "6.3.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/typescript-estree": "6.3.0", "semver": "^7.5.4" }, "engines": { @@ -1924,12 +1918,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", - "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", + "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/types": "6.3.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2149,12 +2143,12 @@ } }, "node_modules/babel-jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", - "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz", + "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==", "dev": true, "dependencies": { - "@jest/transform": "^29.6.1", + "@jest/transform": "^29.6.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.5.0", @@ -2720,10 +2714,18 @@ } }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deep-is": { "version": "0.1.4", @@ -2889,27 +2891,27 @@ } }, "node_modules/eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.46.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz", + "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.1", + "@eslint/js": "^8.46.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.2", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2981,9 +2983,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", + "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2993,9 +2995,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -3018,9 +3020,9 @@ } }, "node_modules/espree": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz", - "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { "acorn": "^8.9.0", @@ -3140,17 +3142,17 @@ } }, "node_modules/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.6.1", + "@jest/expect-utils": "^29.6.2", "@types/node": "*", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1" + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3698,9 +3700,9 @@ "dev": true }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -3897,17 +3899,17 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-report/node_modules/has-flag": { @@ -3946,9 +3948,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -3959,15 +3961,15 @@ } }, "node_modules/jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", - "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", + "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", "dev": true, "dependencies": { - "@jest/core": "^29.6.1", + "@jest/core": "^29.6.2", "@jest/types": "^29.6.1", "import-local": "^3.0.2", - "jest-cli": "^29.6.1" + "jest-cli": "^29.6.2" }, "bin": { "jest": "bin/jest.js" @@ -3998,28 +4000,28 @@ } }, "node_modules/jest-circus": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", - "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", + "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/test-result": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", + "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.1", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-each": "^29.6.2", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", "p-limit": "^3.1.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -4029,21 +4031,21 @@ } }, "node_modules/jest-cli": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", - "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", + "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", "dev": true, "dependencies": { - "@jest/core": "^29.6.1", - "@jest/test-result": "^29.6.1", + "@jest/core": "^29.6.2", + "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-config": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -4063,31 +4065,31 @@ } }, "node_modules/jest-config": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", - "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", + "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.1", + "@jest/test-sequencer": "^29.6.2", "@jest/types": "^29.6.1", - "babel-jest": "^29.6.1", + "babel-jest": "^29.6.2", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.1", - "jest-environment-node": "^29.6.1", + "jest-circus": "^29.6.2", + "jest-environment-node": "^29.6.2", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-resolve": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -4108,15 +4110,15 @@ } }, "node_modules/jest-diff": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", - "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz", + "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==", "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4135,33 +4137,33 @@ } }, "node_modules/jest-each": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", - "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", + "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.6.1", - "pretty-format": "^29.6.1" + "jest-util": "^29.6.2", + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", - "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz", + "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4177,9 +4179,9 @@ } }, "node_modules/jest-haste-map": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", - "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz", + "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", @@ -4189,8 +4191,8 @@ "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -4202,37 +4204,37 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", - "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", + "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", - "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz", + "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.6.1", + "jest-diff": "^29.6.2", "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", - "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", + "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", @@ -4241,7 +4243,7 @@ "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -4250,14 +4252,14 @@ } }, "node_modules/jest-mock": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", - "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz", + "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", "@types/node": "*", - "jest-util": "^29.6.1" + "jest-util": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4290,17 +4292,17 @@ } }, "node_modules/jest-resolve": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", - "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", + "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -4310,43 +4312,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", - "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", + "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.1" + "jest-snapshot": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", - "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", + "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", "dev": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/environment": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/console": "^29.6.2", + "@jest/environment": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-leak-detector": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-resolve": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-util": "^29.6.1", - "jest-watcher": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-environment-node": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-leak-detector": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-resolve": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-util": "^29.6.2", + "jest-watcher": "^29.6.2", + "jest-worker": "^29.6.2", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -4355,17 +4357,17 @@ } }, "node_modules/jest-runtime": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", - "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", + "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/globals": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", + "@jest/globals": "^29.6.2", "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", @@ -4373,13 +4375,13 @@ "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-resolve": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -4388,9 +4390,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", - "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", + "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -4398,21 +4400,20 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/expect-utils": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", - "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.1", + "expect": "^29.6.2", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.1", + "jest-diff": "^29.6.2", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "semver": "^7.5.3" }, "engines": { @@ -4420,9 +4421,9 @@ } }, "node_modules/jest-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", - "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz", + "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", @@ -4437,9 +4438,9 @@ } }, "node_modules/jest-validate": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", - "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz", + "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", @@ -4447,7 +4448,7 @@ "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4466,18 +4467,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", - "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", + "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.1", + "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.1", + "jest-util": "^29.6.2", "string-length": "^4.0.1" }, "engines": { @@ -4485,13 +4486,13 @@ } }, "node_modules/jest-worker": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", - "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz", + "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.6.1", + "jest-util": "^29.6.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4669,29 +4670,20 @@ } }, "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "dependencies": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4720,15 +4712,15 @@ } }, "node_modules/marked": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.1.tgz", - "integrity": "sha512-bTmmGdEINWmOMDjnPWDxGPQ4qkDLeYorpYbEtFOXzOruTwUE671q4Guiuchn4N8h/v6NGd7916kXsm3Iz4iUSg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.1.tgz", + "integrity": "sha512-m8Aze620Ts62yaciz2DghZGUkUfdgvSNRicS2/XtQkStMNoce3NWjOD2b/jWF32+XXK6udM6pRhv2dKNlneAFA==", "dev": true, "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 18" + "node": ">= 16" } }, "node_modules/meow": { @@ -4919,9 +4911,9 @@ } }, "node_modules/node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -5313,9 +5305,9 @@ } }, "node_modules/pretty-format": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", - "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz", + "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==", "dev": true, "dependencies": { "@jest/schemas": "^29.6.0", @@ -5644,12 +5636,12 @@ } }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -7103,15 +7095,15 @@ } }, "@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", "dev": true }, "@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz", + "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -7126,9 +7118,9 @@ } }, "@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "version": "8.46.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz", + "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==", "dev": true }, "@humanwhocodes/config-array": { @@ -7238,29 +7230,29 @@ "dev": true }, "@jest/console": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", - "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", + "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", "dev": true, "requires": { "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", - "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", + "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", "dev": true, "requires": { - "@jest/console": "^29.6.1", - "@jest/reporters": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/console": "^29.6.2", + "@jest/reporters": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", @@ -7269,91 +7261,91 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", + "jest-config": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-resolve-dependencies": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "jest-watcher": "^29.6.1", + "jest-resolve": "^29.6.2", + "jest-resolve-dependencies": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "jest-watcher": "^29.6.2", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", - "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz", + "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==", "dev": true, "requires": { - "@jest/fake-timers": "^29.6.1", + "@jest/fake-timers": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.6.1" + "jest-mock": "^29.6.2" } }, "@jest/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", "dev": true, "requires": { - "expect": "^29.6.1", - "jest-snapshot": "^29.6.1" + "expect": "^29.6.2", + "jest-snapshot": "^29.6.2" } }, "@jest/expect-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", - "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", + "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", "dev": true, "requires": { "jest-get-type": "^29.4.3" } }, "@jest/fake-timers": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", - "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz", + "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==", "dev": true, "requires": { "@jest/types": "^29.6.1", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" } }, "@jest/globals": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", - "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", + "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", "dev": true, "requires": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", "@jest/types": "^29.6.1", - "jest-mock": "^29.6.1" + "jest-mock": "^29.6.2" } }, "@jest/reporters": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", - "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", + "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/console": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", @@ -7367,9 +7359,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -7397,33 +7389,33 @@ } }, "@jest/test-result": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", - "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", + "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", "dev": true, "requires": { - "@jest/console": "^29.6.1", + "@jest/console": "^29.6.2", "@jest/types": "^29.6.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", - "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", + "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", "dev": true, "requires": { - "@jest/test-result": "^29.6.1", + "@jest/test-result": "^29.6.2", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.2", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", - "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz", + "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -7434,9 +7426,9 @@ "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.2", "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", + "jest-util": "^29.6.2", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -7782,9 +7774,9 @@ "dev": true }, "@types/node": { - "version": "20.4.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz", - "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==", + "version": "20.4.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz", + "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==", "dev": true }, "@types/normalize-package-data": { @@ -7793,12 +7785,6 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, - "@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, "@types/semver": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", @@ -7833,16 +7819,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.1.0.tgz", - "integrity": "sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz", + "integrity": "sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.1.0", - "@typescript-eslint/type-utils": "6.1.0", - "@typescript-eslint/utils": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/scope-manager": "6.3.0", + "@typescript-eslint/type-utils": "6.3.0", + "@typescript-eslint/utils": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7853,29 +7839,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", - "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", + "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0" + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0" } }, "@typescript-eslint/types": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", - "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", + "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", - "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", + "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7884,69 +7870,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", - "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz", + "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.1.0", - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/scope-manager": "6.3.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/typescript-estree": "6.3.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", - "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", + "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/types": "6.3.0", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.1.0.tgz", - "integrity": "sha512-hIzCPvX4vDs4qL07SYzyomamcs2/tQYXg5DtdAfj35AyJ5PIUqhsLf4YrEIFzZcND7R2E8tpQIZKayxg8/6Wbw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.3.0.tgz", + "integrity": "sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.1.0", - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/typescript-estree": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/scope-manager": "6.3.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/typescript-estree": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", - "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", + "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0" + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0" } }, "@typescript-eslint/types": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", - "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", + "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", - "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", + "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7955,12 +7941,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", - "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", + "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/types": "6.3.0", "eslint-visitor-keys": "^3.4.1" } } @@ -7977,41 +7963,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.1.0.tgz", - "integrity": "sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.3.0.tgz", + "integrity": "sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.1.0", - "@typescript-eslint/utils": "6.1.0", + "@typescript-eslint/typescript-estree": "6.3.0", + "@typescript-eslint/utils": "6.3.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", - "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", + "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0" + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0" } }, "@typescript-eslint/types": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", - "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", + "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", - "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", + "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/visitor-keys": "6.1.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/visitor-keys": "6.3.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8020,27 +8006,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", - "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz", + "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.1.0", - "@typescript-eslint/types": "6.1.0", - "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/scope-manager": "6.3.0", + "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/typescript-estree": "6.3.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", - "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", + "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/types": "6.3.0", "eslint-visitor-keys": "^3.4.1" } } @@ -8179,12 +8165,12 @@ "dev": true }, "babel-jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", - "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz", + "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==", "dev": true, "requires": { - "@jest/transform": "^29.6.1", + "@jest/transform": "^29.6.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.5.0", @@ -8592,10 +8578,11 @@ } }, "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "requires": {} }, "deep-is": { "version": "0.1.4", @@ -8713,27 +8700,27 @@ "dev": true }, "eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.46.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz", + "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.1", + "@eslint/js": "^8.46.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.2", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -8758,9 +8745,9 @@ }, "dependencies": { "eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -8795,15 +8782,15 @@ } }, "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", + "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", "dev": true }, "espree": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz", - "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "requires": { "acorn": "^8.9.0", @@ -8887,17 +8874,17 @@ "dev": true }, "expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", "dev": true, "requires": { - "@jest/expect-utils": "^29.6.1", + "@jest/expect-utils": "^29.6.2", "@types/node": "*", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1" + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2" } }, "fast-deep-equal": { @@ -9288,9 +9275,9 @@ "dev": true }, "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "dev": true, "requires": { "has": "^1.0.3" @@ -9419,13 +9406,13 @@ } }, "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "requires": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "dependencies": { @@ -9458,9 +9445,9 @@ } }, "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -9468,15 +9455,15 @@ } }, "jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", - "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", + "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", "dev": true, "requires": { - "@jest/core": "^29.6.1", + "@jest/core": "^29.6.2", "@jest/types": "^29.6.1", "import-local": "^3.0.2", - "jest-cli": "^29.6.1" + "jest-cli": "^29.6.2" } }, "jest-changed-files": { @@ -9490,93 +9477,93 @@ } }, "jest-circus": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", - "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", + "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", "dev": true, "requires": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/test-result": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", + "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.1", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-each": "^29.6.2", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", "p-limit": "^3.1.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", - "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", + "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", "dev": true, "requires": { - "@jest/core": "^29.6.1", - "@jest/test-result": "^29.6.1", + "@jest/core": "^29.6.2", + "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-config": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", "prompts": "^2.0.1", "yargs": "^17.3.1" } }, "jest-config": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", - "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", + "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.1", + "@jest/test-sequencer": "^29.6.2", "@jest/types": "^29.6.1", - "babel-jest": "^29.6.1", + "babel-jest": "^29.6.2", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.1", - "jest-environment-node": "^29.6.1", + "jest-circus": "^29.6.2", + "jest-environment-node": "^29.6.2", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-resolve": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" } }, "jest-diff": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", - "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz", + "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==", "dev": true, "requires": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" } }, "jest-docblock": { @@ -9589,30 +9576,30 @@ } }, "jest-each": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", - "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", + "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", "dev": true, "requires": { "@jest/types": "^29.6.1", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.6.1", - "pretty-format": "^29.6.1" + "jest-util": "^29.6.2", + "pretty-format": "^29.6.2" } }, "jest-environment-node": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", - "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz", + "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==", "dev": true, "requires": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" } }, "jest-get-type": { @@ -9622,9 +9609,9 @@ "dev": true }, "jest-haste-map": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", - "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz", + "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==", "dev": true, "requires": { "@jest/types": "^29.6.1", @@ -9635,38 +9622,38 @@ "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "jest-leak-detector": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", - "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", + "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", "dev": true, "requires": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" } }, "jest-matcher-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", - "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz", + "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.6.1", + "jest-diff": "^29.6.2", "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" } }, "jest-message-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", - "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", + "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", @@ -9675,20 +9662,20 @@ "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", - "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz", + "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==", "dev": true, "requires": { "@jest/types": "^29.6.1", "@types/node": "*", - "jest-util": "^29.6.1" + "jest-util": "^29.6.2" } }, "jest-pnp-resolver": { @@ -9705,73 +9692,73 @@ "dev": true }, "jest-resolve": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", - "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", + "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", - "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", + "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", "dev": true, "requires": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.1" + "jest-snapshot": "^29.6.2" } }, "jest-runner": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", - "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", + "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", "dev": true, "requires": { - "@jest/console": "^29.6.1", - "@jest/environment": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/console": "^29.6.2", + "@jest/environment": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-leak-detector": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-resolve": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-util": "^29.6.1", - "jest-watcher": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-environment-node": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-leak-detector": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-resolve": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-util": "^29.6.2", + "jest-watcher": "^29.6.2", + "jest-worker": "^29.6.2", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", - "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", + "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", "dev": true, "requires": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/globals": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", + "@jest/globals": "^29.6.2", "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", @@ -9779,21 +9766,21 @@ "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-resolve": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", - "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", + "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -9801,28 +9788,27 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/expect-utils": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", - "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.1", + "expect": "^29.6.2", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.1", + "jest-diff": "^29.6.2", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "semver": "^7.5.3" } }, "jest-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", - "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz", + "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==", "dev": true, "requires": { "@jest/types": "^29.6.1", @@ -9834,9 +9820,9 @@ } }, "jest-validate": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", - "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz", + "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==", "dev": true, "requires": { "@jest/types": "^29.6.1", @@ -9844,7 +9830,7 @@ "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" }, "dependencies": { "camelcase": { @@ -9856,29 +9842,29 @@ } }, "jest-watcher": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", - "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", + "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", "dev": true, "requires": { - "@jest/test-result": "^29.6.1", + "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.1", + "jest-util": "^29.6.2", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", - "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz", + "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.6.1", + "jest-util": "^29.6.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -10010,20 +9996,12 @@ } }, "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "semver": "^7.5.3" } }, "make-error": { @@ -10048,9 +10026,9 @@ "dev": true }, "marked": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.1.tgz", - "integrity": "sha512-bTmmGdEINWmOMDjnPWDxGPQ4qkDLeYorpYbEtFOXzOruTwUE671q4Guiuchn4N8h/v6NGd7916kXsm3Iz4iUSg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.1.tgz", + "integrity": "sha512-m8Aze620Ts62yaciz2DghZGUkUfdgvSNRicS2/XtQkStMNoce3NWjOD2b/jWF32+XXK6udM6pRhv2dKNlneAFA==", "dev": true }, "meow": { @@ -10187,9 +10165,9 @@ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" }, "node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "requires": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -10467,9 +10445,9 @@ "dev": true }, "pretty-format": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", - "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz", + "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==", "dev": true, "requires": { "@jest/schemas": "^29.6.0", @@ -10677,12 +10655,12 @@ "dev": true }, "resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "dev": true, "requires": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } diff --git a/package.json b/package.json index b283ca6056..9bd154058d 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "dependencies": { "debug": "^4.3.4", "h264-profile-level-id": "^1.0.1", - "node-fetch": "^3.3.1", + "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.1.15", "uuid": "^9.0.0" @@ -98,14 +98,14 @@ "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", "@types/jest": "^29.5.3", - "@types/node": "^20.4.2", + "@types/node": "^20.4.8", "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^6.1.0", - "@typescript-eslint/parser": "^6.1.0", - "eslint": "^8.45.0", + "@typescript-eslint/eslint-plugin": "^6.3.0", + "@typescript-eslint/parser": "^6.3.0", + "eslint": "^8.46.0", "eslint-plugin-jest": "^27.2.3", - "jest": "^29.6.1", - "marked": "^5.1.1", + "jest": "^29.6.2", + "marked": "^7.0.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From df1f224ee97ae83cfeb26c326b01fb5cfdacf576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s-Combarro?= Date: Wed, 9 Aug 2023 03:11:18 +0200 Subject: [PATCH 144/525] Emit Router's observer 'newtransport' event before WebRtcServer's observer 'webrtctransporthandled' (#1138) --- node/src/Router.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/node/src/Router.ts b/node/src/Router.ts index 21466d4c23..dd4c685b7d 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -106,7 +106,7 @@ type PipeTransportPair = }; export type RouterEvents = -{ +{ workerclose: []; // Private events. '@close': []; @@ -465,14 +465,14 @@ export class Router this.#dataProducers.delete(dataProducer.id) )); + // Emit observer event. + this.#observer.safeEmit('newtransport', transport); + if (webRtcServer) { webRtcServer.handleWebRtcTransport(transport); } - // Emit observer event. - this.#observer.safeEmit('newtransport', transport); - return transport; } @@ -1080,7 +1080,7 @@ export class Router { throw new TypeError('if given, appData must be an object'); } - + const reqData = { rtpObserverId : uuidv4(), @@ -1103,7 +1103,7 @@ export class Router this.#producers.get(producerId) ) }); - + this.#rtpObservers.set(activeSpeakerObserver.id, activeSpeakerObserver); activeSpeakerObserver.on('@close', () => { From 6697804fea5e7cf5edf834c21eee4163cbb4d097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 9 Aug 2023 20:23:22 +0200 Subject: [PATCH 145/525] Fix RTCP SDES (#1139) --- CHANGELOG.md | 5 + worker/Dockerfile | 2 +- worker/include/RTC/RTCP/Sdes.hpp | 3 + worker/src/RTC/RTCP/Sdes.cpp | 98 ++++++- worker/test/src/RTC/RTCP/TestSdes.cpp | 399 +++++++++++++++++++++++--- worker/test/src/tests.cpp | 4 + 6 files changed, 458 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e9d623b8e..a4d97878b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +### Next + +* Fix RTCP SDES ([PR #1139](https://github.com/versatica/mediasoup/pull/1139)). + + ### 3.12.8 * Export `workerBin` absolute path ([PR #1123](https://github.com/versatica/mediasoup/pull/1123)). diff --git a/worker/Dockerfile b/worker/Dockerfile index 574be2d7b2..06075a7e75 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -12,7 +12,7 @@ RUN \ clang # Install node 16. -RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - +RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - RUN apt-get install -y nodejs # Make CC and CXX point to clang/clang++ installed above. diff --git a/worker/include/RTC/RTCP/Sdes.hpp b/worker/include/RTC/RTCP/Sdes.hpp index eb7750f980..24bf977c77 100644 --- a/worker/include/RTC/RTCP/Sdes.hpp +++ b/worker/include/RTC/RTCP/Sdes.hpp @@ -121,6 +121,9 @@ namespace RTC size += item->GetSize(); } + // Add the mandatory null octet. + ++size; + // Consider pading to 32 bits (4 bytes) boundary. // http://stackoverflow.com/questions/11642210/computing-padding-required-for-n-byte-alignment return (size + 3) & ~3; diff --git a/worker/src/RTC/RTCP/Sdes.cpp b/worker/src/RTC/RTCP/Sdes.cpp index 91244c7589..222aa1f13d 100644 --- a/worker/src/RTC/RTCP/Sdes.cpp +++ b/worker/src/RTC/RTCP/Sdes.cpp @@ -36,17 +36,21 @@ namespace RTC // Get the header. auto* header = const_cast(reinterpret_cast(data)); + // If item type is 0, there is no need for length field (unless padding + // is needed). + if (len > 0 && header->type == SdesItem::Type::END) + { + return nullptr; + } + // data size must be >= header + length value. - if (len < HeaderSize || len < (1u * 2) + header->length) + if (len < HeaderSize || len < HeaderSize + header->length) { MS_WARN_TAG(rtcp, "not enough space for SDES item, discarded"); return nullptr; } - if (header->type == SdesItem::Type::END) - return nullptr; - return new SdesItem(header); } @@ -57,7 +61,9 @@ namespace RTC auto it = SdesItem::type2String.find(type); if (it == SdesItem::type2String.end()) + { return Unknown; + } return it->second; } @@ -123,19 +129,77 @@ namespace RTC std::unique_ptr chunk(new SdesChunk(ssrc)); - size_t offset = 4u /* ssrc */; + size_t offset{ 4u }; /* ssrc */ + size_t chunkLength{ 4u }; while (len > offset) { - SdesItem* item = SdesItem::Parse(data + offset, len - offset); + auto* item = SdesItem::Parse(data + offset, len - offset); if (!item) + { break; + } chunk->AddItem(item); + chunkLength += item->GetSize(); offset += item->GetSize(); } + // Once all items have been parsed, there must be 1, 2, 3 or 4 null octets + // (this is mandatory). The first one (AKA item type 0) means "end of + // items", and the others maybe needed for padding the chunk to 4 bytes. + + // First ensure that there is at least one null octet. + if (offset == len || (offset < len && Utils::Byte::Get1Byte(data, offset) != 0u)) + { + MS_WARN_TAG(rtcp, "invalid SDES chunk (missing mandatory null octet), discarded"); + + return nullptr; + } + + // So we have the mandatory null octet. + ++chunkLength; + ++offset; + + // Then check that there are 0, 1, 2 or 3 (no more) null octets that pad + // the chunk to 4 bytes. + uint16_t neededAdditionalNullOctets = + Utils::Byte::PadTo4Bytes(static_cast(chunkLength)) - + static_cast(chunkLength); + uint16_t foundAdditionalNullOctets{ 0u }; + + for (uint16_t i{ 0u }; len > offset && i < neededAdditionalNullOctets; ++i) + { + if (Utils::Byte::Get1Byte(data, offset) != 0u) + { + MS_WARN_TAG( + rtcp, + "invalid SDES chunk (missing additional null octets [needed:%" PRIu16 ", found:%" PRIu16 + "]), discarded", + neededAdditionalNullOctets, + foundAdditionalNullOctets); + + return nullptr; + } + + ++foundAdditionalNullOctets; + ++chunkLength; + ++offset; + } + + if (foundAdditionalNullOctets != neededAdditionalNullOctets) + { + MS_WARN_TAG( + rtcp, + "invalid SDES chunk (missing additional null octets [needed:%" PRIu16 ", found:%" PRIu16 + "]), discarded", + neededAdditionalNullOctets, + foundAdditionalNullOctets); + + return nullptr; + } + return chunk.release(); } @@ -155,10 +219,15 @@ namespace RTC offset += item->Serialize(buffer + offset); } + // Add the mandatory null octet. + buffer[offset] = 0; + + ++offset; + // 32 bits padding. const size_t padding = (-offset) & 3; - for (size_t i{ 0 }; i < padding; ++i) + for (size_t i{ 0u }; i < padding; ++i) { buffer[offset + i] = 0; } @@ -195,9 +264,9 @@ namespace RTC size_t offset = Packet::CommonHeaderSize; uint8_t count = header->count; - while ((count-- != 0u) && (len > offset)) + while (count-- && (len > offset)) { - SdesChunk* chunk = SdesChunk::Parse(data + offset, len - offset); + auto* chunk = SdesChunk::Parse(data + offset, len - offset); if (chunk != nullptr) { @@ -206,10 +275,17 @@ namespace RTC } else { - return packet.release(); + break; } } + if (packet->GetCount() != header->count) + { + MS_WARN_TAG(rtcp, "RTCP count value doesn't match found number of chunks, discarded"); + + return nullptr; + } + return packet.release(); } @@ -223,7 +299,7 @@ namespace RTC size_t length = 0; uint8_t* header = { nullptr }; - for (size_t i = 0; i < this->GetCount(); i++) + for (size_t i{ 0u }; i < this->GetCount(); ++i) { // Create a new SDES packet header for each 31 chunks. if (i % MaxChunksPerPacket == 0) diff --git a/worker/test/src/RTC/RTCP/TestSdes.cpp b/worker/test/src/RTC/RTCP/TestSdes.cpp index 46bf9ae77c..eb64766391 100644 --- a/worker/test/src/RTC/RTCP/TestSdes.cpp +++ b/worker/test/src/RTC/RTCP/TestSdes.cpp @@ -11,68 +11,378 @@ namespace TestSdes // RTCP Sdes Packet. // clang-format off - uint8_t buffer[] = + uint8_t buffer1[] = { 0x81, 0xca, 0x00, 0x06, // Type: 202 (SDES), Count: 1, Length: 6 0x9f, 0x65, 0xe7, 0x42, // SSRC: 0x9f65e742 + // Chunk 1 0x01, 0x10, 0x74, 0x37, // Item Type: 1 (CNAME), Length: 16, Value: t7mkYnCm46OcINy/ 0x6d, 0x6b, 0x59, 0x6e, 0x43, 0x6d, 0x34, 0x36, 0x4f, 0x63, 0x49, 0x4e, - 0x79, 0x2f, 0x00, 0x00 + 0x79, 0x2f, 0x00, 0x00 // 2 null octets }; // clang-format on - uint8_t* chunkBuffer = buffer + Packet::CommonHeaderSize; + // First chunk (chunk 1). + uint32_t ssrc1{ 0x9f65e742 }; + // First item (item 1). + SdesItem::Type item1Type{ SdesItem::Type::CNAME }; + std::string item1Value{ "t7mkYnCm46OcINy/" }; + size_t item1Length{ 16u }; - // SDES values. - uint32_t ssrc{ 0x9f65e742 }; - SdesItem::Type type{ SdesItem::Type::CNAME }; - std::string value{ "t7mkYnCm46OcINy/" }; - size_t length = 16; - - void verify(SdesChunk* chunk) + // clang-format off + uint8_t buffer2[] = { - REQUIRE(chunk->GetSsrc() == ssrc); + 0xa2, 0xca, 0x00, 0x0d, // Padding, Type: 202 (SDES), Count: 2, Length: 13 + // Chunk 2 + 0x00, 0x00, 0x04, 0xd2, // SSRC: 1234 + 0x01, 0x06, 0x71, 0x77, // Item Type: 1 (CNAME), Length: 6, Text: "qwerty" + 0x65, 0x72, 0x74, 0x79, + 0x06, 0x06, 0x69, 0xc3, // Item Type: 6 (TOOL), Length: 6, Text: "iñaki" + 0xb1, 0x61, 0x6b, 0x69, + 0x00, 0x00, 0x00, 0x00, // 4 null octets + // Chunk 3 + 0x00, 0x00, 0x16, 0x2e, // SSRC: 5678 + 0x05, 0x11, 0x73, 0x6f, // Item Type: 5 (LOC), Length: 17, Text: "somewhere œæ€" + 0x6d, 0x65, 0x77, 0x68, + 0x65, 0x72, 0x65, 0x20, + 0xc5, 0x93, 0xc3, 0xa6, + 0xe2, 0x82, 0xac, 0x00, // 1 null octet + 0x00, 0x00, 0x00, 0x00 // Pading (4 bytes) + }; + // clang-format on - SdesItem* item = *(chunk->Begin()); + // First chunk (chunk 2). + uint32_t ssrc2{ 1234 }; + // First item (item 2). + SdesItem::Type item2Type{ SdesItem::Type::CNAME }; + std::string item2Value{ "qwerty" }; + size_t item2Length{ 6u }; + // First item (item 3). + SdesItem::Type item3Type{ SdesItem::Type::TOOL }; + std::string item3Value{ "iñaki" }; + size_t item3Length{ 6u }; + + // Second chunk (chunk 3). + uint32_t ssrc3{ 5678 }; + // First item (item 4). + SdesItem::Type item4Type{ SdesItem::Type::LOC }; + std::string item4Value{ "somewhere œæ€" }; + size_t item4Length{ 17u }; - REQUIRE(item->GetType() == type); - REQUIRE(item->GetLength() == length); - REQUIRE(std::string(item->GetValue(), length) == value); - } + // clang-format off + uint8_t buffer3[] = + { + 0x81, 0xca, 0x00, 0x03, // Type: 202 (SDES), Count: 1, Length: 3 + // Chunk + 0x11, 0x22, 0x33, 0x44, // SSRC: 0x11223344 + 0x05, 0x02, 0x61, 0x62, // Item Type: 5 (LOC), Length: 2, Text: "ab" + 0x00, 0x00, 0x00, 0x00 // 4 null octets + }; + // clang-format on + + // First chunk (chunk 4). + uint32_t ssrc4{ 0x11223344 }; + // First item (item 5). + SdesItem::Type item5Type{ SdesItem::Type::LOC }; + std::string item5Value{ "ab" }; + size_t item5Length{ 2u }; } // namespace TestSdes using namespace TestSdes; SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") { - SECTION("parse packet") + SECTION("parse packet 1") { - SdesPacket* packet = SdesPacket::Parse(buffer, sizeof(buffer)); - SdesChunk* chunk = *(packet->Begin()); - - auto* header = reinterpret_cast(buffer); + SdesPacket* packet = SdesPacket::Parse(buffer1, sizeof(buffer1)); + auto* header = reinterpret_cast(buffer1); + REQUIRE(packet); REQUIRE(ntohs(header->length) == 6); - REQUIRE(chunk); + REQUIRE(packet->GetSize() == 28); + REQUIRE(packet->GetCount() == 1); + + size_t chunkIdx{ 0u }; + + for (auto it = packet->Begin(); it != packet->End(); ++it, ++chunkIdx) + { + auto* chunk = *it; + + switch (chunkIdx) + { + /* First chunk (chunk 1). */ + case 0: + { + // Chunk size must be 24 bytes (including 4 null octets). + REQUIRE(chunk->GetSize() == 24); + REQUIRE(chunk->GetSsrc() == ssrc1); + + size_t itemIdx{ 0u }; + + for (auto it2 = chunk->Begin(); it2 != chunk->End(); ++it2, ++itemIdx) + { + auto* item = *it2; + + switch (itemIdx) + { + /* First item (item 1). */ + case 0: + { + REQUIRE(item->GetType() == item1Type); + REQUIRE(item->GetLength() == item1Length); + REQUIRE(std::string(item->GetValue(), item1Length) == item1Value); + + break; + } + } + } + + // There is 1 item. + REQUIRE(itemIdx == 1); + + break; + } + } + } - verify(chunk); + // There is 1 chunk. + REQUIRE(chunkIdx == 1); SECTION("serialize SdesChunk instance") { - uint8_t serialized[sizeof(buffer) - Packet::CommonHeaderSize] = { 0 }; + auto it = packet->Begin(); + auto* chunk1 = *it; + uint8_t* chunk1Buffer = buffer1 + Packet::CommonHeaderSize; - chunk->Serialize(serialized); + // NOTE: Length of first chunk (including null octets) is 24. + uint8_t serialized1[24] = { 0 }; - SECTION("compare serialized SdesChunk with original buffer") + chunk1->Serialize(serialized1); + + REQUIRE(std::memcmp(chunk1Buffer, serialized1, 24) == 0); + } + + delete packet; + } + + SECTION("parse packet 2") + { + SdesPacket* packet = SdesPacket::Parse(buffer2, sizeof(buffer2)); + auto* header = reinterpret_cast(buffer2); + + REQUIRE(packet); + REQUIRE(ntohs(header->length) == 13); + // Despite total buffer size is 56 bytes, our GetSize() method doesn't not + // consider RTCP padding (4 bytes in this case). + REQUIRE(packet->GetSize() == 52); + REQUIRE(packet->GetCount() == 2); + + size_t chunkIdx{ 0u }; + + for (auto it = packet->Begin(); it != packet->End(); ++it, ++chunkIdx) + { + auto* chunk = *it; + + switch (chunkIdx) { - REQUIRE(std::memcmp(chunkBuffer, serialized, sizeof(buffer) - Packet::CommonHeaderSize) == 0); + /* First chunk (chunk 2). */ + case 0: + { + // Chunk size must be 24 bytes (including 4 null octets). + REQUIRE(chunk->GetSize() == 24); + REQUIRE(chunk->GetSsrc() == ssrc2); + + size_t itemIdx{ 0u }; + + for (auto it2 = chunk->Begin(); it2 != chunk->End(); ++it2, ++itemIdx) + { + auto* item = *it2; + + switch (itemIdx) + { + /* First item (item 2). */ + case 0: + { + REQUIRE(item->GetType() == item2Type); + REQUIRE(item->GetLength() == item2Length); + REQUIRE(std::string(item->GetValue(), item2Length) == item2Value); + + break; + } + + /* Second item (item 3). */ + case 1: + { + REQUIRE(item->GetType() == item3Type); + REQUIRE(item->GetLength() == item3Length); + REQUIRE(std::string(item->GetValue(), item3Length) == item3Value); + + break; + } + } + } + + // There are 2 items. + REQUIRE(itemIdx == 2); + + break; + } + + /* Second chunk (chunk 3). */ + case 1: + { + // Chunk size must be 24 bytes (including 1 null octet). + REQUIRE(chunk->GetSize() == 24); + REQUIRE(chunk->GetSsrc() == ssrc3); + + size_t itemIdx{ 0u }; + + for (auto it2 = chunk->Begin(); it2 != chunk->End(); ++it2, ++itemIdx) + { + auto* item = *it2; + + switch (itemIdx) + { + /* First item (item 4). */ + case 0: + { + REQUIRE(item->GetType() == item4Type); + REQUIRE(item->GetLength() == item4Length); + REQUIRE(std::string(item->GetValue(), item4Length) == item4Value); + + break; + } + } + } + + // There is 1 item. + REQUIRE(itemIdx == 1); + + break; + } } } + + // There are 2 chunks. + REQUIRE(chunkIdx == 2); + + SECTION("serialize SdesChunk instances") + { + auto it = packet->Begin(); + auto* chunk1 = *it; + uint8_t* chunk1Buffer = buffer2 + Packet::CommonHeaderSize; + + // NOTE: Length of first chunk (including null octets) is 24. + uint8_t serialized1[24] = { 0 }; + + chunk1->Serialize(serialized1); + + REQUIRE(std::memcmp(chunk1Buffer, serialized1, 24) == 0); + + auto* chunk2 = *(++it); + uint8_t* chunk2Buffer = buffer2 + Packet::CommonHeaderSize + 24; + + // NOTE: Length of second chunk (including null octets) is 24. + uint8_t serialized2[24] = { 0 }; + + chunk2->Serialize(serialized2); + + REQUIRE(std::memcmp(chunk2Buffer, serialized2, 24) == 0); + } + + delete packet; + } + + SECTION("parse packet 3") + { + SdesPacket* packet = SdesPacket::Parse(buffer3, sizeof(buffer3)); + auto* header = reinterpret_cast(buffer3); + + REQUIRE(packet); + REQUIRE(ntohs(header->length) == 3); + REQUIRE(packet->GetSize() == 16); + REQUIRE(packet->GetCount() == 1); + + size_t chunkIdx{ 0u }; + + for (auto it = packet->Begin(); it != packet->End(); ++it, ++chunkIdx) + { + auto* chunk = *it; + + switch (chunkIdx) + { + /* First chunk (chunk 4). */ + case 0: + { + REQUIRE(chunk->GetSize() == 12); + REQUIRE(chunk->GetSsrc() == ssrc4); + + size_t itemIdx{ 0u }; + + for (auto it2 = chunk->Begin(); it2 != chunk->End(); ++it2, ++itemIdx) + { + auto* item = *it2; + + switch (itemIdx) + { + /* First item (item 5). */ + case 0: + { + REQUIRE(item->GetType() == item5Type); + REQUIRE(item->GetLength() == item5Length); + REQUIRE(std::string(item->GetValue(), item5Length) == item5Value); + + break; + } + } + } + + // There is 1 item. + REQUIRE(itemIdx == 1); + + break; + } + } + } + + // There is 1 chunk. + REQUIRE(chunkIdx == 1); + + SECTION("serialize SdesChunk instance") + { + auto it = packet->Begin(); + auto* chunk1 = *it; + uint8_t* chunk1Buffer = buffer3 + Packet::CommonHeaderSize; + + // NOTE: Length of first chunk (including null octets) is 12. + uint8_t serialized1[12] = { 0 }; + + chunk1->Serialize(serialized1); + + REQUIRE(std::memcmp(chunk1Buffer, serialized1, 12) == 0); + } + delete packet; } + SECTION("parsing a packet with missing null octects fails") + { + // clang-format off + uint8_t buffer[] = + { + 0x81, 0xca, 0x00, 0x02, // Type: 202 (SDES), Count: 1, Length: 2 + // Chunk + 0x11, 0x22, 0x33, 0x44, // SSRC: 0x11223344 + 0x08, 0x02, 0x61, 0x62 // Item Type: 8 (PRIV), Length: 2, Text: "ab" + }; + + SdesPacket* packet = SdesPacket::Parse(buffer, sizeof(buffer)); + + REQUIRE(!packet); + } + SECTION("create SDES packet with more than 31 chunks") { const size_t count = 33; @@ -82,23 +392,24 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") for (auto i = 1; i <= count; i++) { // Create chunk and add to packet. - SdesChunk* chunk = new SdesChunk(i /*ssrc*/); + SdesChunk* chunk1 = new SdesChunk(i /*ssrc*/); - auto* item = new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, value.size(), value.c_str()); + auto* item1 = + new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str()); - chunk->AddItem(item); + chunk1->AddItem(item1); - packet.AddChunk(chunk); + packet.AddChunk(chunk1); } REQUIRE(packet.GetCount() == count); - uint8_t buffer[1500] = { 0 }; + uint8_t buffer1[1500] = { 0 }; // Serialization must contain 2 RR packets since report count exceeds 31. - packet.Serialize(buffer); + packet.Serialize(buffer1); - auto* packet2 = static_cast(Packet::Parse(buffer, sizeof(buffer))); + auto* packet2 = static_cast(Packet::Parse(buffer1, sizeof(buffer1))); REQUIRE(packet2 != nullptr); REQUIRE(packet2->GetCount() == 31); @@ -114,8 +425,8 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") auto* item = *(chunk->Begin()); REQUIRE(item->GetType() == SdesItem::Type::CNAME); - REQUIRE(item->GetSize() == 2 + value.size()); - REQUIRE(std::string(item->GetValue()) == value); + REQUIRE(item->GetSize() == 2 + item1Value.size()); + REQUIRE(std::string(item->GetValue()) == item1Value); } SdesPacket* packet3 = static_cast(packet2->GetNext()); @@ -134,8 +445,8 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") auto* item = *(chunk->Begin()); REQUIRE(item->GetType() == SdesItem::Type::CNAME); - REQUIRE(item->GetSize() == 2 + value.size()); - REQUIRE(std::string(item->GetValue()) == value); + REQUIRE(item->GetSize() == 2 + item1Value.size()); + REQUIRE(std::string(item->GetValue()) == item1Value); } delete packet2; @@ -144,13 +455,19 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") SECTION("create SdesChunk") { - auto* item = new SdesItem(type, length, value.c_str()); + auto* item = new SdesItem(item1Type, item1Length, item1Value.c_str()); // Create sdes chunk. - SdesChunk chunk(ssrc); + SdesChunk chunk(ssrc1); chunk.AddItem(item); - verify(&chunk); + REQUIRE(chunk.GetSsrc() == ssrc1); + + SdesItem* item1 = *(chunk.Begin()); + + REQUIRE(item1->GetType() == item1Type); + REQUIRE(item1->GetLength() == item1Length); + REQUIRE(std::string(item1->GetValue(), item1Length) == item1Value); } } diff --git a/worker/test/src/tests.cpp b/worker/test/src/tests.cpp index e7b960fc54..6584789af6 100644 --- a/worker/test/src/tests.cpp +++ b/worker/test/src/tests.cpp @@ -40,6 +40,10 @@ int main(int argc, char* argv[]) { Settings::configuration.logTags.rtp = true; } + if (std::getenv("MS_TEST_LOG_TAG_RTCP")) + { + Settings::configuration.logTags.rtcp = true; + } // Initialize static stuff. DepLibUV::ClassInit(); From c0a6988fd594b05ec17535265a37cb7d5b93884f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 9 Aug 2023 20:40:25 +0200 Subject: [PATCH 146/525] 3.12.9 --- CHANGELOG.md | 2 +- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4d97878b7..999e41bfac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### Next +### 3.12.9 * Fix RTCP SDES ([PR #1139](https://github.com/versatica/mediasoup/pull/1139)). diff --git a/package-lock.json b/package-lock.json index 3ea8a3cec2..d30b8f27d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.8", + "version": "3.12.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.8", + "version": "3.12.9", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -21,7 +21,7 @@ "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", "@types/jest": "^29.5.3", - "@types/node": "^20.4.8", + "@types/node": "^20.4.9", "@types/uuid": "^9.0.2", "@typescript-eslint/eslint-plugin": "^6.3.0", "@typescript-eslint/parser": "^6.3.0", @@ -1510,9 +1510,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.4.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz", - "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==", + "version": "20.4.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz", + "integrity": "sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -7774,9 +7774,9 @@ "dev": true }, "@types/node": { - "version": "20.4.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz", - "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==", + "version": "20.4.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz", + "integrity": "sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 9bd154058d..4e2a621dae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.8", + "version": "3.12.9", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -98,7 +98,7 @@ "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", "@types/jest": "^29.5.3", - "@types/node": "^20.4.8", + "@types/node": "^20.4.9", "@types/uuid": "^9.0.2", "@typescript-eslint/eslint-plugin": "^6.3.0", "@typescript-eslint/parser": "^6.3.0", From a34ca02f9ae6856e5f550382a08d6460e6157154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 11 Aug 2023 11:25:29 +0200 Subject: [PATCH 147/525] test-WebRtcServer.ts: add tests --- node/src/tests/test-WebRtcServer.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/node/src/tests/test-WebRtcServer.ts b/node/src/tests/test-WebRtcServer.ts index ff28ebe26b..072608590f 100644 --- a/node/src/tests/test-WebRtcServer.ts +++ b/node/src/tests/test-WebRtcServer.ts @@ -556,6 +556,10 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer expect(onObserverWebRtcTransportUnhandled).toHaveBeenCalledTimes(1); expect(onObserverWebRtcTransportUnhandled).toHaveBeenCalledWith(transport); expect(transport.closed).toBe(true); + expect(transport.iceState).toBe('closed'); + expect(transport.iceSelectedTuple).toBe(undefined); + expect(transport.dtlsState).toBe('closed'); + expect(transport.sctpState).toBe(undefined); expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); expect(router.transportsForTesting.size).toBe(0); From 60f57d114628d69c6610a8fa4baf36495dd82b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s-Combarro?= Date: Fri, 11 Aug 2023 11:28:10 +0200 Subject: [PATCH 148/525] Renamed WebRtcTransport `webRtcServerClosed()` to `listenServerClosed()` (#1141) --- node/src/WebRtcTransport.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 164af8880d..422f15f208 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -374,11 +374,11 @@ export class WebRtcTransport } /** - * Called when closing the associated WebRtcServer. + * Called when closing the associated listenServer (WebRtcServer). * * @private */ - webRtcServerClosed(): void + listenServerClosed(): void { if (this.closed) { From be98f0f3d9b3eaab12632d23d4f1cc9b95e0f8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 11 Aug 2023 11:32:22 +0200 Subject: [PATCH 149/525] 3.12.10 --- CHANGELOG.md | 6 ++++++ package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 999e41bfac..45caa1881c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog + +### 3.12.10 + +* Node: Rename `WebRtcTransport.webRtcServerClosed()` to `listenServerClosed()` ([PR #1141](https://github.com/versatica/mediasoup/pull/1141) by @piranna). + + ### 3.12.9 * Fix RTCP SDES ([PR #1139](https://github.com/versatica/mediasoup/pull/1139)). diff --git a/package-lock.json b/package-lock.json index d30b8f27d2..61c81fb08d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.9", + "version": "3.12.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.9", + "version": "3.12.10", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -28,7 +28,7 @@ "eslint": "^8.46.0", "eslint-plugin-jest": "^27.2.3", "jest": "^29.6.2", - "marked": "^7.0.1", + "marked": "^7.0.2", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -4712,9 +4712,9 @@ } }, "node_modules/marked": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.1.tgz", - "integrity": "sha512-m8Aze620Ts62yaciz2DghZGUkUfdgvSNRicS2/XtQkStMNoce3NWjOD2b/jWF32+XXK6udM6pRhv2dKNlneAFA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.2.tgz", + "integrity": "sha512-ADEBjnCHOrsLoV7JPvUNWtELZ0b4SeIALhrfxuA9uhS3hw2PCezROoFduIqMOjeagBPto732+YC5tZHBMQRdqg==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -10026,9 +10026,9 @@ "dev": true }, "marked": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.1.tgz", - "integrity": "sha512-m8Aze620Ts62yaciz2DghZGUkUfdgvSNRicS2/XtQkStMNoce3NWjOD2b/jWF32+XXK6udM6pRhv2dKNlneAFA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.2.tgz", + "integrity": "sha512-ADEBjnCHOrsLoV7JPvUNWtELZ0b4SeIALhrfxuA9uhS3hw2PCezROoFduIqMOjeagBPto732+YC5tZHBMQRdqg==", "dev": true }, "meow": { diff --git a/package.json b/package.json index 4e2a621dae..b840ffa585 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.9", + "version": "3.12.10", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -105,7 +105,7 @@ "eslint": "^8.46.0", "eslint-plugin-jest": "^27.2.3", "jest": "^29.6.2", - "marked": "^7.0.1", + "marked": "^7.0.2", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From e8a18a1605fd6007f9306e14d436a67f4e8e5f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 18 Aug 2023 14:21:00 +0200 Subject: [PATCH 150/525] cosmetic --- worker/include/RTC/RTCP/FeedbackPsRpsi.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/worker/include/RTC/RTCP/FeedbackPsRpsi.hpp b/worker/include/RTC/RTCP/FeedbackPsRpsi.hpp index 123aa692f5..a3a531e5ea 100644 --- a/worker/include/RTC/RTCP/FeedbackPsRpsi.hpp +++ b/worker/include/RTC/RTCP/FeedbackPsRpsi.hpp @@ -10,9 +10,8 @@ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | PB | - |0| Payload Type| - | Native RPSI bit string | + | PB |0| Payload Type| Native RPSI bit string | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | defined per codec ... | Padding (0) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ From 9b28af7f4a11f47983381bee5972d522705d3197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 28 Aug 2023 16:49:02 +0200 Subject: [PATCH 151/525] Google Transport Feedback: read Reference Time field as 24bits signed as per spec (#1145) Fixes #1144 --- CHANGELOG.md | 5 ++ .../include/RTC/RTCP/FeedbackRtpTransport.hpp | 6 +- worker/include/Utils.hpp | 20 ++++++ worker/meson.build | 1 + worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 4 +- .../src/RTC/RTCP/TestFeedbackRtpTransport.cpp | 16 ++--- worker/test/src/Utils/TestBits.cpp | 2 - worker/test/src/Utils/TestByte.cpp | 61 +++++++++++++++++++ worker/test/src/Utils/TestIP.cpp | 1 + 9 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 worker/test/src/Utils/TestByte.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 45caa1881c..c414b6e968 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +* Google Transport Feedback: Read Reference Time field as 24bits signed as per spec ([PR #1145](https://github.com/versatica/mediasoup/pull/1145)). + + ### 3.12.10 * Node: Rename `WebRtcTransport.webRtcServerClosed()` to `listenServerClosed()` ([PR #1141](https://github.com/versatica/mediasoup/pull/1141) by @piranna). diff --git a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp index 2d1cb7f67c..2c333e966c 100644 --- a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp +++ b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp @@ -242,7 +242,8 @@ namespace RTC { return this->referenceTime; } - void SetReferenceTime(uint64_t referenceTime) // We only use this for testing purpose. + // NOTE: We only use this for testing purpose. + void SetReferenceTime(int64_t referenceTime) { this->referenceTime = (referenceTime % TimeWrapPeriod) / BaseTimeTick; } @@ -315,7 +316,8 @@ namespace RTC private: uint16_t baseSequenceNumber{ 0u }; - uint32_t referenceTime{ 0 }; + // 24 bits signed integer. + int32_t referenceTime{ 0 }; // Just for locally generated packets. uint16_t latestSequenceNumber{ 0u }; // Just for locally generated packets. diff --git a/worker/include/Utils.hpp b/worker/include/Utils.hpp index d41ecb6551..96ee42a13a 100644 --- a/worker/include/Utils.hpp +++ b/worker/include/Utils.hpp @@ -119,6 +119,19 @@ namespace Utils return uint32_t{ data[i + 2] } | uint32_t{ data[i + 1] } << 8 | uint32_t{ data[i] } << 16; } + static int32_t Get3BytesSigned(const uint8_t* data, size_t i) + { + auto byte2 = data[i]; // The most significant byte. + auto byte1 = data[i + 1]; + auto byte0 = data[i + 2]; // The less significant byte. + + // Check bit 7 (sign). + uint8_t extension = byte2 & 0b10000000 ? 0b11111111 : 0b00000000; + + return int32_t{ byte0 } | (int32_t{ byte1 } << 8) | (int32_t{ byte2 } << 16) | + (int32_t{ extension } << 24); + } + static uint32_t Get4Bytes(const uint8_t* data, size_t i) { return uint32_t{ data[i + 3] } | uint32_t{ data[i + 2] } << 8 | @@ -148,6 +161,13 @@ namespace Utils data[i] = static_cast(value >> 16); } + static void Set3BytesSigned(uint8_t* data, size_t i, int32_t value) + { + data[i + 2] = static_cast(value); + data[i + 1] = static_cast(value >> 8); + data[i] = static_cast(value >> 16); + } + static void Set4Bytes(uint8_t* data, size_t i, uint32_t value) { data[i + 3] = static_cast(value); diff --git a/worker/meson.build b/worker/meson.build index 9aaff0da55..45c5528f41 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -321,6 +321,7 @@ test_sources = [ 'test/src/RTC/RTCP/TestPacket.cpp', 'test/src/RTC/RTCP/TestXr.cpp', 'test/src/Utils/TestBits.cpp', + 'test/src/Utils/TestByte.cpp', 'test/src/Utils/TestIP.cpp', 'test/src/Utils/TestJson.cpp', 'test/src/Utils/TestString.cpp', diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index 31ba9350cb..0e41548ada 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -79,7 +79,7 @@ namespace RTC this->baseSequenceNumber = Utils::Byte::Get2Bytes(data, 0); this->packetStatusCount = Utils::Byte::Get2Bytes(data, 2); - this->referenceTime = Utils::Byte::Get3Bytes(data, 4); + this->referenceTime = Utils::Byte::Get3BytesSigned(data, 4); this->feedbackPacketCount = Utils::Byte::Get1Byte(data, 7); this->size = len; @@ -238,7 +238,7 @@ namespace RTC offset += 2; // Reference time. - Utils::Byte::Set3Bytes(buffer, offset, static_cast(this->referenceTime)); + Utils::Byte::Set3BytesSigned(buffer, offset, this->referenceTime); offset += 3; // Feedback packet count. diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp index 9cc7b65f59..547e40373e 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp @@ -513,11 +513,11 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(packet->GetSize() == sizeof(data)); REQUIRE(packet->GetBaseSequenceNumber() == 39); REQUIRE(packet->GetPacketStatusCount() == 0); - REQUIRE(packet->GetReferenceTime() == 16777214); // 0xFFFFFE (unsigned 24 bits) + REQUIRE(packet->GetReferenceTime() == -2); // 0xFFFFFE = -2 (signed 24 bits) REQUIRE( packet->GetReferenceTimestamp() == FeedbackRtpTransportPacket::TimeWrapPeriod + - static_cast(16777214) * FeedbackRtpTransportPacket::BaseTimeTick); + static_cast(-2) * FeedbackRtpTransportPacket::BaseTimeTick); REQUIRE(packet->GetFeedbackPacketCount() == 1); SECTION("serialize packet") @@ -552,11 +552,11 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(packet->GetSize() == sizeof(data)); REQUIRE(packet->GetBaseSequenceNumber() == 1); REQUIRE(packet->GetPacketStatusCount() == 2); - REQUIRE(packet->GetReferenceTime() == 12408746); + REQUIRE(packet->GetReferenceTime() == -4368470); REQUIRE( packet->GetReferenceTimestamp() == FeedbackRtpTransportPacket::TimeWrapPeriod + - static_cast(12408746) * FeedbackRtpTransportPacket::BaseTimeTick); + static_cast(-4368470) * FeedbackRtpTransportPacket::BaseTimeTick); REQUIRE(packet->GetFeedbackPacketCount() == 0); @@ -576,8 +576,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" { using FeedbackPacketsMeta = struct { - uint32_t baseTimeRaw; - uint64_t baseTimeMs; + int32_t baseTimeRaw; + int64_t baseTimeMs; uint16_t baseSequence; size_t packetStatusCount; std::vector deltas; @@ -624,8 +624,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x10 } }, - { .baseTimeRaw = 12408746, - .baseTimeMs = 1867901568, + { .baseTimeRaw = -4368470, + .baseTimeMs = 794159744, .baseSequence = 1, .packetStatusCount = 2, .deltas = std::vector{ 35, 17 }, diff --git a/worker/test/src/Utils/TestBits.cpp b/worker/test/src/Utils/TestBits.cpp index e2c95c0450..c8217d6825 100644 --- a/worker/test/src/Utils/TestBits.cpp +++ b/worker/test/src/Utils/TestBits.cpp @@ -2,8 +2,6 @@ #include "Utils.hpp" #include -using namespace Utils; - SCENARIO("Utils::Bits::CountSetBits()") { uint16_t mask; diff --git a/worker/test/src/Utils/TestByte.cpp b/worker/test/src/Utils/TestByte.cpp new file mode 100644 index 0000000000..d25d2647c5 --- /dev/null +++ b/worker/test/src/Utils/TestByte.cpp @@ -0,0 +1,61 @@ +#include "common.hpp" +#include "Utils.hpp" +#include + +SCENARIO("Utils::Byte") +{ + // NOTE: The setup and teardown are implicit in how Catch2 works, meaning that + // this buffer is initialized before each SECTION below. + // Docs: https://github.com/catchorg/Catch2/blob/devel/docs/tutorial.md#test-cases-and-sections + + // clang-format off + uint8_t buffer[] = + { + 0b00000000, 0b00000001, 0b00000010, 0b00000011, + 0b10000000, 0b01000000, 0b00100000, 0b00010000, + 0b01111111, 0b11111111, 0b11111111, 0b00000000, + 0b11111111, 0b11111111, 0b11111111, 0b00000000, + 0b10000000, 0b00000000, 0b00000000, 0b00000000 + }; + // clang-format on + + SECTION("Utils::Byte::Get3Bytes()") + { + // Bytes 4,5 and 6 in the array are number 8405024. + REQUIRE(Utils::Byte::Get3Bytes(buffer, 4) == 8405024); + } + + SECTION("Utils::Byte::Set3Bytes()") + { + Utils::Byte::Set3Bytes(buffer, 4, 5666777); + REQUIRE(Utils::Byte::Get3Bytes(buffer, 4) == 5666777); + } + + SECTION("Utils::Byte::Get3BytesSigned()") + { + // Bytes 8, 9 and 10 in the array are number 8388607 since first bit is 0 and + // all other bits are 1, so it must be maximum positive 24 bits signed integer, + // which is Math.pow(2, 23) - 1 = 8388607. + REQUIRE(Utils::Byte::Get3BytesSigned(buffer, 8) == 8388607); + + // Bytes 12, 13 and 14 in the array are number -1. + REQUIRE(Utils::Byte::Get3BytesSigned(buffer, 12) == -1); + + // Bytes 16, 17 and 18 in the array are number -8388608 since first bit is 1 + // and all other bits are 0, so it must be minimum negative 24 bits signed + // integer, which is -1 * Math.pow(2, 23) = -8388608. + REQUIRE(Utils::Byte::Get3BytesSigned(buffer, 16) == -8388608); + } + + SECTION("Utils::Byte::Set3BytesSigned()") + { + Utils::Byte::Set3BytesSigned(buffer, 0, 8388607); + REQUIRE(Utils::Byte::Get3BytesSigned(buffer, 0) == 8388607); + + Utils::Byte::Set3BytesSigned(buffer, 0, -1); + REQUIRE(Utils::Byte::Get3BytesSigned(buffer, 0) == -1); + + Utils::Byte::Set3BytesSigned(buffer, 0, -8388608); + REQUIRE(Utils::Byte::Get3BytesSigned(buffer, 0) == -8388608); + } +} diff --git a/worker/test/src/Utils/TestIP.cpp b/worker/test/src/Utils/TestIP.cpp index b97424dafa..201c83caa3 100644 --- a/worker/test/src/Utils/TestIP.cpp +++ b/worker/test/src/Utils/TestIP.cpp @@ -10,6 +10,7 @@ #include // sockaddr_in, sockaddr_in6 #include // struct sockaddr, struct sockaddr_storage, AF_INET, AF_INET6 #endif + using namespace Utils; SCENARIO("Utils::IP::GetFamily()") From 79dadec8d2b7fccc03d46242ef778aad72a84588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 28 Aug 2023 16:53:04 +0200 Subject: [PATCH 152/525] Update Node deps --- package-lock.json | 1785 +++++++++++++++++++++++---------------------- package.json | 16 +- 2 files changed, 909 insertions(+), 892 deletions(-) diff --git a/package-lock.json b/package-lock.json index 61c81fb08d..804e5f81fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,20 +20,20 @@ "devDependencies": { "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", - "@types/jest": "^29.5.3", - "@types/node": "^20.4.9", + "@types/jest": "^29.5.4", + "@types/node": "^20.5.7", "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^6.3.0", - "@typescript-eslint/parser": "^6.3.0", - "eslint": "^8.46.0", + "@typescript-eslint/eslint-plugin": "^6.4.1", + "@typescript-eslint/parser": "^6.4.1", + "eslint": "^8.48.0", "eslint-plugin-jest": "^27.2.3", - "jest": "^29.6.2", - "marked": "^7.0.2", + "jest": "^29.6.4", + "marked": "^7.0.5", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", - "typescript": "^5.1.6" + "typescript": "^5.2.2" }, "engines": { "node": ">=16" @@ -679,9 +679,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz", - "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -702,9 +702,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.46.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz", - "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -852,16 +852,16 @@ } }, "node_modules/@jest/console": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", - "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.4.tgz", + "integrity": "sha512-wNK6gC0Ha9QeEPSkeJedQuTQqxZYnDPuDcDhVuVatRvMkL4D0VTvFVZj+Yuh6caG2aOfzkUZ36KtCmLNtR02hw==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", "slash": "^3.0.0" }, "engines": { @@ -869,37 +869,37 @@ } }, "node_modules/@jest/core": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", - "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.4.tgz", + "integrity": "sha512-U/vq5ccNTSVgYH7mHnodHmCffGWHJnz/E1BEWlLuK5pM4FZmGfBn/nrJGLjUsSmyx3otCeqc1T31F4y08AMDLg==", "dev": true, "dependencies": { - "@jest/console": "^29.6.2", - "@jest/reporters": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/reporters": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.2", - "jest-haste-map": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-resolve-dependencies": "^29.6.2", - "jest-runner": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", - "jest-watcher": "^29.6.2", + "jest-changed-files": "^29.6.3", + "jest-config": "^29.6.4", + "jest-haste-map": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-resolve-dependencies": "^29.6.4", + "jest-runner": "^29.6.4", + "jest-runtime": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", + "jest-watcher": "^29.6.4", "micromatch": "^4.0.4", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -916,88 +916,88 @@ } }, "node_modules/@jest/environment": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz", - "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.4.tgz", + "integrity": "sha512-sQ0SULEjA1XUTHmkBRl7A1dyITM9yb1yb3ZNKPX3KlTd6IG7mWUe3e2yfExtC2Zz1Q+mMckOLHmL/qLiuQJrBQ==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/fake-timers": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.2" + "jest-mock": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", - "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.4.tgz", + "integrity": "sha512-Warhsa7d23+3X5bLbrbYvaehcgX5TLYhI03JKoedTiI8uJU4IhqYBWF7OSSgUyz4IgLpUYPkK0AehA5/fRclAA==", "dev": true, "dependencies": { - "expect": "^29.6.2", - "jest-snapshot": "^29.6.2" + "expect": "^29.6.4", + "jest-snapshot": "^29.6.4" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", - "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.4.tgz", + "integrity": "sha512-FEhkJhqtvBwgSpiTrocquJCdXPsyvNKcl/n7A3u7X4pVoF4bswm11c9d4AV+kfq2Gpv/mM8x7E7DsRvH+djkrg==", "dev": true, "dependencies": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz", - "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.4.tgz", + "integrity": "sha512-6UkCwzoBK60edXIIWb0/KWkuj7R7Qq91vVInOe3De6DSpaEiqjKcJw4F7XUet24Wupahj9J6PlR09JqJ5ySDHw==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.2", - "jest-mock": "^29.6.2", - "jest-util": "^29.6.2" + "jest-message-util": "^29.6.3", + "jest-mock": "^29.6.3", + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", - "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.4.tgz", + "integrity": "sha512-wVIn5bdtjlChhXAzVXavcY/3PEjf4VqM174BM3eGL5kMxLiZD5CLnbmkEyA1Dwh9q8XjP6E8RwjBsY/iCWrWsA==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.2", - "@jest/expect": "^29.6.2", - "@jest/types": "^29.6.1", - "jest-mock": "^29.6.2" + "@jest/environment": "^29.6.4", + "@jest/expect": "^29.6.4", + "@jest/types": "^29.6.3", + "jest-mock": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", - "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.4.tgz", + "integrity": "sha512-sxUjWxm7QdchdrD3NfWKrL8FBsortZeibSJv4XLjESOOjSUOkjQcb0ZHJwfhEGIvBvTluTzfG2yZWZhkrXJu8g==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", @@ -1006,13 +1006,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", - "jest-worker": "^29.6.2", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", + "jest-worker": "^29.6.4", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -1030,10 +1030,26 @@ } } }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@jest/schemas": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", - "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { "@sinclair/typebox": "^0.27.8" @@ -1043,9 +1059,9 @@ } }, "node_modules/@jest/source-map": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", - "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", @@ -1057,13 +1073,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", - "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.4.tgz", + "integrity": "sha512-uQ1C0AUEN90/dsyEirgMLlouROgSY+Wc/JanVVk0OiUKa5UFh7sJpMEM3aoUBAz2BRNvUJ8j3d294WFuRxSyOQ==", "dev": true, "dependencies": { - "@jest/console": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1072,14 +1088,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", - "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.4.tgz", + "integrity": "sha512-E84M6LbpcRq3fT4ckfKs9ryVanwkaIB0Ws9bw3/yP4seRLg/VaCZ/LgW0MCq5wwk4/iP/qnilD41aj2fsw2RMg==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.2", + "@jest/test-result": "^29.6.4", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", + "jest-haste-map": "^29.6.4", "slash": "^3.0.0" }, "engines": { @@ -1087,22 +1103,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz", - "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.4.tgz", + "integrity": "sha512-8thgRSiXUqtr/pPGY/OsyHuMjGyhVnWrFAwoxmIemlBuiMyU1WFs0tXoNxzcr4A4uErs/ABre76SGmrr5ab/AA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.2", + "jest-haste-map": "^29.6.4", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.6.3", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1113,12 +1129,12 @@ } }, "node_modules/@jest/types": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", - "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1399,9 +1415,9 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -1431,12 +1447,12 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", "dev": true, "dependencies": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "node_modules/@types/debug": { @@ -1482,9 +1498,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.3", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", - "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", + "version": "29.5.4", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.4.tgz", + "integrity": "sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1510,9 +1526,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.4.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz", - "integrity": "sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==", + "version": "20.5.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", + "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1555,21 +1571,20 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz", - "integrity": "sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz", + "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.3.0", - "@typescript-eslint/type-utils": "6.3.0", - "@typescript-eslint/utils": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/scope-manager": "6.4.1", + "@typescript-eslint/type-utils": "6.4.1", + "@typescript-eslint/utils": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", "natural-compare": "^1.4.0", - "natural-compare-lite": "^1.4.0", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -1591,13 +1606,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", - "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", + "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0" + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1608,9 +1623,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", - "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", + "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1621,13 +1636,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", - "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", + "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1648,17 +1663,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz", - "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", + "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.3.0", - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/typescript-estree": "6.3.0", + "@typescript-eslint/scope-manager": "6.4.1", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/typescript-estree": "6.4.1", "semver": "^7.5.4" }, "engines": { @@ -1673,12 +1688,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", - "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", + "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1690,15 +1705,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.3.0.tgz", - "integrity": "sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz", + "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.3.0", - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/typescript-estree": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/scope-manager": "6.4.1", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/typescript-estree": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4" }, "engines": { @@ -1718,13 +1733,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", - "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", + "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0" + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1735,9 +1750,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", - "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", + "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1748,13 +1763,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", - "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", + "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1775,12 +1790,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", - "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", + "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1809,13 +1824,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.3.0.tgz", - "integrity": "sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz", + "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.3.0", - "@typescript-eslint/utils": "6.3.0", + "@typescript-eslint/typescript-estree": "6.4.1", + "@typescript-eslint/utils": "6.4.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1836,13 +1851,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", - "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", + "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0" + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1853,9 +1868,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", - "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", + "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1866,13 +1881,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", - "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", + "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1893,17 +1908,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz", - "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", + "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.3.0", - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/typescript-estree": "6.3.0", + "@typescript-eslint/scope-manager": "6.4.1", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/typescript-estree": "6.4.1", "semver": "^7.5.4" }, "engines": { @@ -1918,12 +1933,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", - "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", + "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2143,15 +2158,15 @@ } }, "node_modules/babel-jest": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz", - "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz", + "integrity": "sha512-meLj23UlSLddj6PC+YTOFRgDAtjnZom8w/ACsrx0gtPtv5cJZk0A5Unk5bV4wixD7XaPCN1fQvpww8czkZURmw==", "dev": true, "dependencies": { - "@jest/transform": "^29.6.2", + "@jest/transform": "^29.6.4", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -2180,9 +2195,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -2218,12 +2233,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -2804,9 +2819,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2891,15 +2906,15 @@ } }, "node_modules/eslint": { - "version": "8.46.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz", - "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.1", - "@eslint/js": "^8.46.0", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.48.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2910,7 +2925,7 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.2", + "eslint-visitor-keys": "^3.4.3", "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", @@ -2983,9 +2998,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", - "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3142,17 +3157,16 @@ } }, "node_modules/expect": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", - "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.4.tgz", + "integrity": "sha512-F2W2UyQ8XYyftHT57dtfg8Ue3X5qLgm2sSug0ivvLRH/VKNRL/pDxg/TH7zVzbQB0tu80clNFy6LU7OS/VSEKA==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.6.2", - "@types/node": "*", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2" + "@jest/expect-utils": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3360,9 +3374,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -3463,9 +3477,9 @@ } }, "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3961,15 +3975,15 @@ } }, "node_modules/jest": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", - "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.4.tgz", + "integrity": "sha512-tEFhVQFF/bzoYV1YuGyzLPZ6vlPrdfvDmmAxudA1dLEuiztqg2Rkx20vkKY32xiDROcD2KXlgZ7Cu8RPeEHRKw==", "dev": true, "dependencies": { - "@jest/core": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/core": "^29.6.4", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.6.2" + "jest-cli": "^29.6.4" }, "bin": { "jest": "bin/jest.js" @@ -3987,12 +4001,13 @@ } }, "node_modules/jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.6.3.tgz", + "integrity": "sha512-G5wDnElqLa4/c66ma5PG9eRjE342lIbF6SUnTJi26C3J28Fv2TVY2rOyKB9YGbSA5ogwevgmxc4j4aVjrEK6Yg==", "dev": true, "dependencies": { "execa": "^5.0.0", + "jest-util": "^29.6.3", "p-limit": "^3.1.0" }, "engines": { @@ -4000,28 +4015,28 @@ } }, "node_modules/jest-circus": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", - "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.4.tgz", + "integrity": "sha512-YXNrRyntVUgDfZbjXWBMPslX1mQ8MrSG0oM/Y06j9EYubODIyHWP8hMUbjbZ19M3M+zamqEur7O80HODwACoJw==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.2", - "@jest/expect": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/expect": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.2", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", + "jest-each": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-runtime": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", "p-limit": "^3.1.0", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -4031,21 +4046,21 @@ } }, "node_modules/jest-cli": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", - "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.4.tgz", + "integrity": "sha512-+uMCQ7oizMmh8ZwRfZzKIEszFY9ksjjEQnTEMTaL7fYiL3Kw4XhqT9bYh+A4DQKUb67hZn2KbtEnDuHvcgK4pQ==", "dev": true, "dependencies": { - "@jest/core": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/core": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", + "jest-config": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -4065,31 +4080,31 @@ } }, "node_modules/jest-config": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", - "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.4.tgz", + "integrity": "sha512-JWohr3i9m2cVpBumQFv2akMEnFEPVOh+9L2xIBJhJ0zOaci2ZXuKJj0tgMKQCBZAKA09H049IR4HVS/43Qb19A==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.2", - "@jest/types": "^29.6.1", - "babel-jest": "^29.6.2", + "@jest/test-sequencer": "^29.6.4", + "@jest/types": "^29.6.3", + "babel-jest": "^29.6.4", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.2", - "jest-environment-node": "^29.6.2", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-runner": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", + "jest-circus": "^29.6.4", + "jest-environment-node": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-runner": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -4110,24 +4125,24 @@ } }, "node_modules/jest-diff": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz", - "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.4.tgz", + "integrity": "sha512-9F48UxR9e4XOEZvoUXEHSWY4qC4zERJaOfrbBg9JpbJOO43R1vN76REt/aMGZoY6GD5g84nnJiBIVlscegefpw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.6.3.tgz", + "integrity": "sha512-2+H+GOTQBEm2+qFSQ7Ma+BvyV+waiIFxmZF5LdpBsAEjWX8QYjSCa4FrkIYtbfXUJJJnFCYrOtt6TZ+IAiTjBQ==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" @@ -4137,62 +4152,62 @@ } }, "node_modules/jest-each": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", - "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.3.tgz", + "integrity": "sha512-KoXfJ42k8cqbkfshW7sSHcdfnv5agDdHCPA87ZBdmHP+zJstTJc0ttQaJ/x7zK6noAL76hOuTIJ6ZkQRS5dcyg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.6.2", - "pretty-format": "^29.6.2" + "jest-get-type": "^29.6.3", + "jest-util": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz", - "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.4.tgz", + "integrity": "sha512-i7SbpH2dEIFGNmxGCpSc2w9cA4qVD+wfvg2ZnfQ7XVrKL0NA5uDVBIiGH8SR4F0dKEv/0qI5r+aDomDf04DpEQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.2", - "@jest/fake-timers": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/fake-timers": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.2", - "jest-util": "^29.6.2" + "jest-mock": "^29.6.3", + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz", - "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.4.tgz", + "integrity": "sha512-12Ad+VNTDHxKf7k+M65sviyynRoZYuL1/GTuhEVb8RYsNSNln71nANRb/faSyWvx0j+gHcivChXHIoMJrGYjog==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.2", - "jest-worker": "^29.6.2", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.6.3", + "jest-worker": "^29.6.4", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -4204,46 +4219,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", - "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.3.tgz", + "integrity": "sha512-0kfbESIHXYdhAdpLsW7xdwmYhLf1BRu4AA118/OxFm0Ho1b2RcTmO4oF6aAMaxpxdxnJ3zve2rgwzNBD4Zbm7Q==", "dev": true, "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz", - "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.4.tgz", + "integrity": "sha512-KSzwyzGvK4HcfnserYqJHYi7sZVqdREJ9DMPAKVbS98JsIAvumihaNUbjrWw0St7p9IY7A9UskCW5MYlGmBQFQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.6.2", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" + "jest-diff": "^29.6.4", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", - "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.3.tgz", + "integrity": "sha512-FtzaEEHzjDpQp51HX4UMkPZjy46ati4T5pEMyM6Ik48ztu4T9LQplZ6OsimHx7EuM9dfEh5HJa6D3trEftu3dA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -4252,14 +4267,14 @@ } }, "node_modules/jest-mock": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz", - "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.3.tgz", + "integrity": "sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.6.2" + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4283,26 +4298,26 @@ } }, "node_modules/jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", - "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.4.tgz", + "integrity": "sha512-fPRq+0vcxsuGlG0O3gyoqGTAxasagOxEuyoxHeyxaZbc9QNek0AmJWSkhjlMG+mTsj+8knc/mWb3fXlRNVih7Q==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", + "jest-haste-map": "^29.6.4", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -4312,43 +4327,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", - "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.4.tgz", + "integrity": "sha512-7+6eAmr1ZBF3vOAJVsfLj1QdqeXG+WYhidfLHBRZqGN24MFRIiKG20ItpLw2qRAsW/D2ZUUmCNf6irUr/v6KHA==", "dev": true, "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.2" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.6.4" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", - "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.4.tgz", + "integrity": "sha512-SDaLrMmtVlQYDuG0iSPYLycG8P9jLI+fRm8AF/xPKhYDB2g6xDWjXBrR5M8gEWsK6KVFlebpZ4QsrxdyIX1Jaw==", "dev": true, "dependencies": { - "@jest/console": "^29.6.2", - "@jest/environment": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/environment": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.2", - "jest-haste-map": "^29.6.2", - "jest-leak-detector": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-resolve": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-util": "^29.6.2", - "jest-watcher": "^29.6.2", - "jest-worker": "^29.6.2", + "jest-docblock": "^29.6.3", + "jest-environment-node": "^29.6.4", + "jest-haste-map": "^29.6.4", + "jest-leak-detector": "^29.6.3", + "jest-message-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-runtime": "^29.6.4", + "jest-util": "^29.6.3", + "jest-watcher": "^29.6.4", + "jest-worker": "^29.6.4", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -4357,31 +4372,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", - "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.6.2", - "@jest/fake-timers": "^29.6.2", - "@jest/globals": "^29.6.2", - "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.4.tgz", + "integrity": "sha512-s/QxMBLvmwLdchKEjcLfwzP7h+jsHvNEtxGP5P+Fl1FMaJX2jMiIqe4rJw4tFprzCwuSvVUo9bn0uj4gNRXsbA==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.6.4", + "@jest/fake-timers": "^29.6.4", + "@jest/globals": "^29.6.4", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-mock": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", + "jest-haste-map": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-mock": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -4390,9 +4405,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", - "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.4.tgz", + "integrity": "sha512-VC1N8ED7+4uboUKGIDsbvNAZb6LakgIPgAF4RSpF13dN6YaMokfRqO+BaqK4zIh6X3JffgwbzuGqDEjHm/MrvA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -4400,20 +4415,20 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/expect-utils": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.2", + "expect": "^29.6.4", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.2", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", + "jest-diff": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "semver": "^7.5.3" }, "engines": { @@ -4421,12 +4436,12 @@ } }, "node_modules/jest-util": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz", - "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz", + "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -4438,17 +4453,17 @@ } }, "node_modules/jest-validate": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz", - "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.3.tgz", + "integrity": "sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.6.2" + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4467,18 +4482,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", - "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.4.tgz", + "integrity": "sha512-oqUWvx6+On04ShsT00Ir9T4/FvBeEh2M9PTubgITPxDa739p4hoQweWPRGyYeaojgT0xTpZKF0Y/rSY1UgMxvQ==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.2", + "jest-util": "^29.6.3", "string-length": "^4.0.1" }, "engines": { @@ -4486,13 +4501,13 @@ } }, "node_modules/jest-worker": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz", - "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.4.tgz", + "integrity": "sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.6.2", + "jest-util": "^29.6.3", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4712,9 +4727,9 @@ } }, "node_modules/marked": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.2.tgz", - "integrity": "sha512-ADEBjnCHOrsLoV7JPvUNWtELZ0b4SeIALhrfxuA9uhS3hw2PCezROoFduIqMOjeagBPto732+YC5tZHBMQRdqg==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.5.tgz", + "integrity": "sha512-lwNAFTfXgqpt/XvK17a/8wY9/q6fcSPZT1aP6QW0u74VwaJF/Z9KbRcX23sWE4tODM+AolJNcUtErTkgOeFP/Q==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -4886,12 +4901,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -5305,12 +5314,12 @@ } }, "node_modules/pretty-format": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz", - "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.3.tgz", + "integrity": "sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -6327,9 +6336,9 @@ } }, "node_modules/typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -7101,9 +7110,9 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz", - "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -7118,9 +7127,9 @@ } }, "@eslint/js": { - "version": "8.46.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz", - "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", "dev": true }, "@humanwhocodes/config-array": { @@ -7230,123 +7239,123 @@ "dev": true }, "@jest/console": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", - "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.4.tgz", + "integrity": "sha512-wNK6gC0Ha9QeEPSkeJedQuTQqxZYnDPuDcDhVuVatRvMkL4D0VTvFVZj+Yuh6caG2aOfzkUZ36KtCmLNtR02hw==", "dev": true, "requires": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", - "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.4.tgz", + "integrity": "sha512-U/vq5ccNTSVgYH7mHnodHmCffGWHJnz/E1BEWlLuK5pM4FZmGfBn/nrJGLjUsSmyx3otCeqc1T31F4y08AMDLg==", "dev": true, "requires": { - "@jest/console": "^29.6.2", - "@jest/reporters": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/reporters": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.2", - "jest-haste-map": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-resolve-dependencies": "^29.6.2", - "jest-runner": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", - "jest-watcher": "^29.6.2", + "jest-changed-files": "^29.6.3", + "jest-config": "^29.6.4", + "jest-haste-map": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-resolve-dependencies": "^29.6.4", + "jest-runner": "^29.6.4", + "jest-runtime": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", + "jest-watcher": "^29.6.4", "micromatch": "^4.0.4", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz", - "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.4.tgz", + "integrity": "sha512-sQ0SULEjA1XUTHmkBRl7A1dyITM9yb1yb3ZNKPX3KlTd6IG7mWUe3e2yfExtC2Zz1Q+mMckOLHmL/qLiuQJrBQ==", "dev": true, "requires": { - "@jest/fake-timers": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/fake-timers": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.2" + "jest-mock": "^29.6.3" } }, "@jest/expect": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", - "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.4.tgz", + "integrity": "sha512-Warhsa7d23+3X5bLbrbYvaehcgX5TLYhI03JKoedTiI8uJU4IhqYBWF7OSSgUyz4IgLpUYPkK0AehA5/fRclAA==", "dev": true, "requires": { - "expect": "^29.6.2", - "jest-snapshot": "^29.6.2" + "expect": "^29.6.4", + "jest-snapshot": "^29.6.4" } }, "@jest/expect-utils": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", - "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.4.tgz", + "integrity": "sha512-FEhkJhqtvBwgSpiTrocquJCdXPsyvNKcl/n7A3u7X4pVoF4bswm11c9d4AV+kfq2Gpv/mM8x7E7DsRvH+djkrg==", "dev": true, "requires": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" } }, "@jest/fake-timers": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz", - "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.4.tgz", + "integrity": "sha512-6UkCwzoBK60edXIIWb0/KWkuj7R7Qq91vVInOe3De6DSpaEiqjKcJw4F7XUet24Wupahj9J6PlR09JqJ5ySDHw==", "dev": true, "requires": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.2", - "jest-mock": "^29.6.2", - "jest-util": "^29.6.2" + "jest-message-util": "^29.6.3", + "jest-mock": "^29.6.3", + "jest-util": "^29.6.3" } }, "@jest/globals": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", - "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.4.tgz", + "integrity": "sha512-wVIn5bdtjlChhXAzVXavcY/3PEjf4VqM174BM3eGL5kMxLiZD5CLnbmkEyA1Dwh9q8XjP6E8RwjBsY/iCWrWsA==", "dev": true, "requires": { - "@jest/environment": "^29.6.2", - "@jest/expect": "^29.6.2", - "@jest/types": "^29.6.1", - "jest-mock": "^29.6.2" + "@jest/environment": "^29.6.4", + "@jest/expect": "^29.6.4", + "@jest/types": "^29.6.3", + "jest-mock": "^29.6.3" } }, "@jest/reporters": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", - "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.4.tgz", + "integrity": "sha512-sxUjWxm7QdchdrD3NfWKrL8FBsortZeibSJv4XLjESOOjSUOkjQcb0ZHJwfhEGIvBvTluTzfG2yZWZhkrXJu8g==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", @@ -7355,32 +7364,47 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", - "jest-worker": "^29.6.2", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", + "jest-worker": "^29.6.4", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + } + } } }, "@jest/schemas": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", - "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "requires": { "@sinclair/typebox": "^0.27.8" } }, "@jest/source-map": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", - "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.18", @@ -7389,46 +7413,46 @@ } }, "@jest/test-result": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", - "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.4.tgz", + "integrity": "sha512-uQ1C0AUEN90/dsyEirgMLlouROgSY+Wc/JanVVk0OiUKa5UFh7sJpMEM3aoUBAz2BRNvUJ8j3d294WFuRxSyOQ==", "dev": true, "requires": { - "@jest/console": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", - "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.4.tgz", + "integrity": "sha512-E84M6LbpcRq3fT4ckfKs9ryVanwkaIB0Ws9bw3/yP4seRLg/VaCZ/LgW0MCq5wwk4/iP/qnilD41aj2fsw2RMg==", "dev": true, "requires": { - "@jest/test-result": "^29.6.2", + "@jest/test-result": "^29.6.4", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", + "jest-haste-map": "^29.6.4", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz", - "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.4.tgz", + "integrity": "sha512-8thgRSiXUqtr/pPGY/OsyHuMjGyhVnWrFAwoxmIemlBuiMyU1WFs0tXoNxzcr4A4uErs/ABre76SGmrr5ab/AA==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.2", + "jest-haste-map": "^29.6.4", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.6.3", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -7436,12 +7460,12 @@ } }, "@jest/types": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", - "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "requires": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -7663,9 +7687,9 @@ "dev": true }, "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", "dev": true, "requires": { "@babel/parser": "^7.20.7", @@ -7695,12 +7719,12 @@ } }, "@types/babel__traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", "dev": true, "requires": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "@types/debug": { @@ -7746,9 +7770,9 @@ } }, "@types/jest": { - "version": "29.5.3", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", - "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", + "version": "29.5.4", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.4.tgz", + "integrity": "sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==", "dev": true, "requires": { "expect": "^29.0.0", @@ -7774,9 +7798,9 @@ "dev": true }, "@types/node": { - "version": "20.4.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz", - "integrity": "sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==", + "version": "20.5.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", + "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==", "dev": true }, "@types/normalize-package-data": { @@ -7819,49 +7843,48 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz", - "integrity": "sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz", + "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.3.0", - "@typescript-eslint/type-utils": "6.3.0", - "@typescript-eslint/utils": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/scope-manager": "6.4.1", + "@typescript-eslint/type-utils": "6.4.1", + "@typescript-eslint/utils": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", "natural-compare": "^1.4.0", - "natural-compare-lite": "^1.4.0", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", - "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", + "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0" + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1" } }, "@typescript-eslint/types": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", - "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", + "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", - "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", + "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7870,69 +7893,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz", - "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", + "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.3.0", - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/typescript-estree": "6.3.0", + "@typescript-eslint/scope-manager": "6.4.1", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/typescript-estree": "6.4.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", - "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", + "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.3.0.tgz", - "integrity": "sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz", + "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.3.0", - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/typescript-estree": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/scope-manager": "6.4.1", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/typescript-estree": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", - "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", + "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0" + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1" } }, "@typescript-eslint/types": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", - "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", + "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", - "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", + "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7941,12 +7964,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", - "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", + "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" } } @@ -7963,41 +7986,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.3.0.tgz", - "integrity": "sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz", + "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.3.0", - "@typescript-eslint/utils": "6.3.0", + "@typescript-eslint/typescript-estree": "6.4.1", + "@typescript-eslint/utils": "6.4.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz", - "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", + "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0" + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1" } }, "@typescript-eslint/types": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz", - "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", + "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz", - "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", + "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/visitor-keys": "6.3.0", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/visitor-keys": "6.4.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8006,27 +8029,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz", - "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", + "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.3.0", - "@typescript-eslint/types": "6.3.0", - "@typescript-eslint/typescript-estree": "6.3.0", + "@typescript-eslint/scope-manager": "6.4.1", + "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/typescript-estree": "6.4.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz", - "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", + "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.3.0", + "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" } } @@ -8165,15 +8188,15 @@ "dev": true }, "babel-jest": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz", - "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz", + "integrity": "sha512-meLj23UlSLddj6PC+YTOFRgDAtjnZom8w/ACsrx0gtPtv5cJZk0A5Unk5bV4wixD7XaPCN1fQvpww8czkZURmw==", "dev": true, "requires": { - "@jest/transform": "^29.6.2", + "@jest/transform": "^29.6.4", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -8193,9 +8216,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -8225,12 +8248,12 @@ } }, "babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^29.5.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -8637,9 +8660,9 @@ "dev": true }, "diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, "dir-glob": { @@ -8700,15 +8723,15 @@ "dev": true }, "eslint": { - "version": "8.46.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz", - "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.1", - "@eslint/js": "^8.46.0", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.48.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -8719,7 +8742,7 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.2", + "eslint-visitor-keys": "^3.4.3", "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", @@ -8782,9 +8805,9 @@ } }, "eslint-visitor-keys": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", - "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, "espree": { @@ -8874,17 +8897,16 @@ "dev": true }, "expect": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", - "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.4.tgz", + "integrity": "sha512-F2W2UyQ8XYyftHT57dtfg8Ue3X5qLgm2sSug0ivvLRH/VKNRL/pDxg/TH7zVzbQB0tu80clNFy6LU7OS/VSEKA==", "dev": true, "requires": { - "@jest/expect-utils": "^29.6.2", - "@types/node": "*", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2" + "@jest/expect-utils": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3" } }, "fast-deep-equal": { @@ -9044,9 +9066,9 @@ "dev": true }, "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "optional": true }, @@ -9110,9 +9132,9 @@ } }, "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -9455,227 +9477,228 @@ } }, "jest": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", - "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.4.tgz", + "integrity": "sha512-tEFhVQFF/bzoYV1YuGyzLPZ6vlPrdfvDmmAxudA1dLEuiztqg2Rkx20vkKY32xiDROcD2KXlgZ7Cu8RPeEHRKw==", "dev": true, "requires": { - "@jest/core": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/core": "^29.6.4", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.6.2" + "jest-cli": "^29.6.4" } }, "jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.6.3.tgz", + "integrity": "sha512-G5wDnElqLa4/c66ma5PG9eRjE342lIbF6SUnTJi26C3J28Fv2TVY2rOyKB9YGbSA5ogwevgmxc4j4aVjrEK6Yg==", "dev": true, "requires": { "execa": "^5.0.0", + "jest-util": "^29.6.3", "p-limit": "^3.1.0" } }, "jest-circus": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", - "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.4.tgz", + "integrity": "sha512-YXNrRyntVUgDfZbjXWBMPslX1mQ8MrSG0oM/Y06j9EYubODIyHWP8hMUbjbZ19M3M+zamqEur7O80HODwACoJw==", "dev": true, "requires": { - "@jest/environment": "^29.6.2", - "@jest/expect": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/expect": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.2", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", + "jest-each": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-runtime": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", "p-limit": "^3.1.0", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", - "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.4.tgz", + "integrity": "sha512-+uMCQ7oizMmh8ZwRfZzKIEszFY9ksjjEQnTEMTaL7fYiL3Kw4XhqT9bYh+A4DQKUb67hZn2KbtEnDuHvcgK4pQ==", "dev": true, "requires": { - "@jest/core": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/core": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", + "jest-config": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "prompts": "^2.0.1", "yargs": "^17.3.1" } }, "jest-config": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", - "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.4.tgz", + "integrity": "sha512-JWohr3i9m2cVpBumQFv2akMEnFEPVOh+9L2xIBJhJ0zOaci2ZXuKJj0tgMKQCBZAKA09H049IR4HVS/43Qb19A==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.2", - "@jest/types": "^29.6.1", - "babel-jest": "^29.6.2", + "@jest/test-sequencer": "^29.6.4", + "@jest/types": "^29.6.3", + "babel-jest": "^29.6.4", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.2", - "jest-environment-node": "^29.6.2", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-runner": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", + "jest-circus": "^29.6.4", + "jest-environment-node": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-runner": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" } }, "jest-diff": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz", - "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.4.tgz", + "integrity": "sha512-9F48UxR9e4XOEZvoUXEHSWY4qC4zERJaOfrbBg9JpbJOO43R1vN76REt/aMGZoY6GD5g84nnJiBIVlscegefpw==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" } }, "jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.6.3.tgz", + "integrity": "sha512-2+H+GOTQBEm2+qFSQ7Ma+BvyV+waiIFxmZF5LdpBsAEjWX8QYjSCa4FrkIYtbfXUJJJnFCYrOtt6TZ+IAiTjBQ==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", - "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.3.tgz", + "integrity": "sha512-KoXfJ42k8cqbkfshW7sSHcdfnv5agDdHCPA87ZBdmHP+zJstTJc0ttQaJ/x7zK6noAL76hOuTIJ6ZkQRS5dcyg==", "dev": true, "requires": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.6.2", - "pretty-format": "^29.6.2" + "jest-get-type": "^29.6.3", + "jest-util": "^29.6.3", + "pretty-format": "^29.6.3" } }, "jest-environment-node": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz", - "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.4.tgz", + "integrity": "sha512-i7SbpH2dEIFGNmxGCpSc2w9cA4qVD+wfvg2ZnfQ7XVrKL0NA5uDVBIiGH8SR4F0dKEv/0qI5r+aDomDf04DpEQ==", "dev": true, "requires": { - "@jest/environment": "^29.6.2", - "@jest/fake-timers": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/fake-timers": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.2", - "jest-util": "^29.6.2" + "jest-mock": "^29.6.3", + "jest-util": "^29.6.3" } }, "jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true }, "jest-haste-map": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz", - "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.4.tgz", + "integrity": "sha512-12Ad+VNTDHxKf7k+M65sviyynRoZYuL1/GTuhEVb8RYsNSNln71nANRb/faSyWvx0j+gHcivChXHIoMJrGYjog==", "dev": true, "requires": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.2", - "jest-worker": "^29.6.2", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.6.3", + "jest-worker": "^29.6.4", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "jest-leak-detector": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", - "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.3.tgz", + "integrity": "sha512-0kfbESIHXYdhAdpLsW7xdwmYhLf1BRu4AA118/OxFm0Ho1b2RcTmO4oF6aAMaxpxdxnJ3zve2rgwzNBD4Zbm7Q==", "dev": true, "requires": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" } }, "jest-matcher-utils": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz", - "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.4.tgz", + "integrity": "sha512-KSzwyzGvK4HcfnserYqJHYi7sZVqdREJ9DMPAKVbS98JsIAvumihaNUbjrWw0St7p9IY7A9UskCW5MYlGmBQFQ==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.6.2", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" + "jest-diff": "^29.6.4", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" } }, "jest-message-util": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", - "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.3.tgz", + "integrity": "sha512-FtzaEEHzjDpQp51HX4UMkPZjy46ati4T5pEMyM6Ik48ztu4T9LQplZ6OsimHx7EuM9dfEh5HJa6D3trEftu3dA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz", - "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.3.tgz", + "integrity": "sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg==", "dev": true, "requires": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.6.2" + "jest-util": "^29.6.3" } }, "jest-pnp-resolver": { @@ -9686,101 +9709,101 @@ "requires": {} }, "jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true }, "jest-resolve": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", - "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.4.tgz", + "integrity": "sha512-fPRq+0vcxsuGlG0O3gyoqGTAxasagOxEuyoxHeyxaZbc9QNek0AmJWSkhjlMG+mTsj+8knc/mWb3fXlRNVih7Q==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", + "jest-haste-map": "^29.6.4", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", - "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.4.tgz", + "integrity": "sha512-7+6eAmr1ZBF3vOAJVsfLj1QdqeXG+WYhidfLHBRZqGN24MFRIiKG20ItpLw2qRAsW/D2ZUUmCNf6irUr/v6KHA==", "dev": true, "requires": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.2" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.6.4" } }, "jest-runner": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", - "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.4.tgz", + "integrity": "sha512-SDaLrMmtVlQYDuG0iSPYLycG8P9jLI+fRm8AF/xPKhYDB2g6xDWjXBrR5M8gEWsK6KVFlebpZ4QsrxdyIX1Jaw==", "dev": true, "requires": { - "@jest/console": "^29.6.2", - "@jest/environment": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/environment": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.2", - "jest-haste-map": "^29.6.2", - "jest-leak-detector": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-resolve": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-util": "^29.6.2", - "jest-watcher": "^29.6.2", - "jest-worker": "^29.6.2", + "jest-docblock": "^29.6.3", + "jest-environment-node": "^29.6.4", + "jest-haste-map": "^29.6.4", + "jest-leak-detector": "^29.6.3", + "jest-message-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-runtime": "^29.6.4", + "jest-util": "^29.6.3", + "jest-watcher": "^29.6.4", + "jest-worker": "^29.6.4", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", - "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.2", - "@jest/fake-timers": "^29.6.2", - "@jest/globals": "^29.6.2", - "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.4.tgz", + "integrity": "sha512-s/QxMBLvmwLdchKEjcLfwzP7h+jsHvNEtxGP5P+Fl1FMaJX2jMiIqe4rJw4tFprzCwuSvVUo9bn0uj4gNRXsbA==", + "dev": true, + "requires": { + "@jest/environment": "^29.6.4", + "@jest/fake-timers": "^29.6.4", + "@jest/globals": "^29.6.4", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-mock": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", + "jest-haste-map": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-mock": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", - "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.4.tgz", + "integrity": "sha512-VC1N8ED7+4uboUKGIDsbvNAZb6LakgIPgAF4RSpF13dN6YaMokfRqO+BaqK4zIh6X3JffgwbzuGqDEjHm/MrvA==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -9788,30 +9811,30 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/expect-utils": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.2", + "expect": "^29.6.4", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.2", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", + "jest-diff": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "semver": "^7.5.3" } }, "jest-util": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz", - "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz", + "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==", "dev": true, "requires": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -9820,17 +9843,17 @@ } }, "jest-validate": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz", - "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.3.tgz", + "integrity": "sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg==", "dev": true, "requires": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.6.2" + "pretty-format": "^29.6.3" }, "dependencies": { "camelcase": { @@ -9842,29 +9865,29 @@ } }, "jest-watcher": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", - "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.4.tgz", + "integrity": "sha512-oqUWvx6+On04ShsT00Ir9T4/FvBeEh2M9PTubgITPxDa739p4hoQweWPRGyYeaojgT0xTpZKF0Y/rSY1UgMxvQ==", "dev": true, "requires": { - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.2", + "jest-util": "^29.6.3", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz", - "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.4.tgz", + "integrity": "sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.6.2", + "jest-util": "^29.6.3", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -10026,9 +10049,9 @@ "dev": true }, "marked": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.2.tgz", - "integrity": "sha512-ADEBjnCHOrsLoV7JPvUNWtELZ0b4SeIALhrfxuA9uhS3hw2PCezROoFduIqMOjeagBPto732+YC5tZHBMQRdqg==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.5.tgz", + "integrity": "sha512-lwNAFTfXgqpt/XvK17a/8wY9/q6fcSPZT1aP6QW0u74VwaJF/Z9KbRcX23sWE4tODM+AolJNcUtErTkgOeFP/Q==", "dev": true }, "meow": { @@ -10153,12 +10176,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -10445,12 +10462,12 @@ "dev": true }, "pretty-format": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz", - "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.3.tgz", + "integrity": "sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==", "dev": true, "requires": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -11115,9 +11132,9 @@ "dev": true }, "typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index b840ffa585..fc8a2b5997 100644 --- a/package.json +++ b/package.json @@ -97,19 +97,19 @@ "devDependencies": { "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", - "@types/jest": "^29.5.3", - "@types/node": "^20.4.9", + "@types/jest": "^29.5.4", + "@types/node": "^20.5.7", "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^6.3.0", - "@typescript-eslint/parser": "^6.3.0", - "eslint": "^8.46.0", + "@typescript-eslint/eslint-plugin": "^6.4.1", + "@typescript-eslint/parser": "^6.4.1", + "eslint": "^8.48.0", "eslint-plugin-jest": "^27.2.3", - "jest": "^29.6.2", - "marked": "^7.0.2", + "jest": "^29.6.4", + "marked": "^7.0.5", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", - "typescript": "^5.1.6" + "typescript": "^5.2.2" } } From c2d63282e568e742a8d89c651f9dd55e24811689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 28 Aug 2023 16:55:26 +0200 Subject: [PATCH 153/525] 3.12.11 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c414b6e968..5b71808e96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.12.11 * Google Transport Feedback: Read Reference Time field as 24bits signed as per spec ([PR #1145](https://github.com/versatica/mediasoup/pull/1145)). diff --git a/package-lock.json b/package-lock.json index 804e5f81fa..f66196a75e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.10", + "version": "3.12.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.10", + "version": "3.12.11", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index fc8a2b5997..af6d8deff7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.10", + "version": "3.12.11", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From bdb976332373b0ed73394285a8e978e4db167afa Mon Sep 17 00:00:00 2001 From: Joshua Oladele Date: Wed, 30 Aug 2023 14:58:30 +0100 Subject: [PATCH 154/525] Upgrade rust toolchain version --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index b42ddcf07f..be838d8604 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.67.0" +channel = "1.72.0" components = ["rustfmt", "clippy"] From 92be2b30ca68fa3ff460ee2c99ebfe5b811d1651 Mon Sep 17 00:00:00 2001 From: Joshua Oladele Date: Wed, 30 Aug 2023 16:05:00 +0100 Subject: [PATCH 155/525] Fix clippy lints --- rust/src/ortc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/src/ortc.rs b/rust/src/ortc.rs index 489724b6ba..74a5ec8038 100644 --- a/rust/src/ortc.rs +++ b/rust/src/ortc.rs @@ -666,7 +666,7 @@ pub(crate) fn get_consumer_rtp_parameters( if let Some(matched_cap_codec) = remote_rtp_capabilities .codecs .iter() - .find(|cap_codec| match_codecs(cap_codec.deref().into(), (&codec).into(), true).is_ok()) + .find(|cap_codec| match_codecs((*cap_codec).into(), (&codec).into(), true).is_ok()) { *codec.rtcp_feedback_mut() = matched_cap_codec .rtcp_feedback() From 6794e6fe2a655e91c67a2b86a23bba9f81b3a3ed Mon Sep 17 00:00:00 2001 From: o-u-p Date: Sat, 2 Sep 2023 13:43:57 +0800 Subject: [PATCH 156/525] fix: template-id not allowed for destructor in c++20 (#1150) --- worker/src/RTC/RTCP/Feedback.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/RTCP/Feedback.cpp b/worker/src/RTC/RTCP/Feedback.cpp index 8d290e10e9..37178ead5e 100644 --- a/worker/src/RTC/RTCP/Feedback.cpp +++ b/worker/src/RTC/RTCP/Feedback.cpp @@ -61,7 +61,7 @@ namespace RTC } template - FeedbackPacket::~FeedbackPacket() + FeedbackPacket::~FeedbackPacket() { delete[] this->raw; } From 6278dbdb0722a105e96e4d01a7507331c8647422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 7 Sep 2023 10:13:29 +0200 Subject: [PATCH 157/525] 3.12.12 --- CHANGELOG.md | 5 + package-lock.json | 392 +++++++++++++++++++++++----------------------- package.json | 14 +- 3 files changed, 208 insertions(+), 203 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b71808e96..50c13f0b16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.12.12 + +* Support C++20 ([PR #1150](https://github.com/versatica/mediasoup/pull/1150) by @o-u-p). + + ### 3.12.11 * Google Transport Feedback: Read Reference Time field as 24bits signed as per spec ([PR #1145](https://github.com/versatica/mediasoup/pull/1145)). diff --git a/package-lock.json b/package-lock.json index f66196a75e..bf8cee8566 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.11", + "version": "3.12.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.11", + "version": "3.12.12", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -14,21 +14,21 @@ "h264-profile-level-id": "^1.0.1", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.1.15", + "tar": "^6.2.0", "uuid": "^9.0.0" }, "devDependencies": { "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", "@types/jest": "^29.5.4", - "@types/node": "^20.5.7", - "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^6.4.1", - "@typescript-eslint/parser": "^6.4.1", + "@types/node": "^20.5.9", + "@types/uuid": "^9.0.3", + "@typescript-eslint/eslint-plugin": "^6.6.0", + "@typescript-eslint/parser": "^6.6.0", "eslint": "^8.48.0", "eslint-plugin-jest": "^27.2.3", "jest": "^29.6.4", - "marked": "^7.0.5", + "marked": "^8.0.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -1526,9 +1526,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.5.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", - "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==", + "version": "20.5.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", + "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1550,9 +1550,9 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", - "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.3.tgz", + "integrity": "sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug==", "dev": true }, "node_modules/@types/yargs": { @@ -1571,16 +1571,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz", - "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.6.0.tgz", + "integrity": "sha512-CW9YDGTQnNYMIo5lMeuiIG08p4E0cXrXTbcZ2saT/ETE7dWUrNxlijsQeU04qAAKkILiLzdQz+cGFxCJjaZUmA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/type-utils": "6.4.1", - "@typescript-eslint/utils": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/type-utils": "6.6.0", + "@typescript-eslint/utils": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1606,13 +1606,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", - "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", + "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1" + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1623,9 +1623,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", - "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", + "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1636,13 +1636,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", - "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", + "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1663,17 +1663,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", - "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", + "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/typescript-estree": "6.4.1", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/typescript-estree": "6.6.0", "semver": "^7.5.4" }, "engines": { @@ -1688,12 +1688,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", - "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", + "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/types": "6.6.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1705,15 +1705,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz", - "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.6.0.tgz", + "integrity": "sha512-setq5aJgUwtzGrhW177/i+DMLqBaJbdwGj2CPIVFFLE0NCliy5ujIdLHd2D1ysmlmsjdL2GWW+hR85neEfc12w==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/typescript-estree": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4" }, "engines": { @@ -1733,13 +1733,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", - "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", + "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1" + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1750,9 +1750,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", - "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", + "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1763,13 +1763,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", - "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", + "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1790,12 +1790,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", - "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", + "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/types": "6.6.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1824,13 +1824,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz", - "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.6.0.tgz", + "integrity": "sha512-8m16fwAcEnQc69IpeDyokNO+D5spo0w1jepWWY2Q6y5ZKNuj5EhVQXjtVAeDDqvW6Yg7dhclbsz6rTtOvcwpHg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.4.1", - "@typescript-eslint/utils": "6.4.1", + "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/utils": "6.6.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1851,13 +1851,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", - "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", + "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1" + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1868,9 +1868,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", - "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", + "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1881,13 +1881,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", - "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", + "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1908,17 +1908,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", - "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", + "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/typescript-estree": "6.4.1", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/typescript-estree": "6.6.0", "semver": "^7.5.4" }, "engines": { @@ -1933,12 +1933,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", - "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", + "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/types": "6.6.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4727,9 +4727,9 @@ } }, "node_modules/marked": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.5.tgz", - "integrity": "sha512-lwNAFTfXgqpt/XvK17a/8wY9/q6fcSPZT1aP6QW0u74VwaJF/Z9KbRcX23sWE4tODM+AolJNcUtErTkgOeFP/Q==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-8.0.1.tgz", + "integrity": "sha512-eEbeEb/mJwh+sNLEhHOWtxMgjN/NEwZUBs1nkiIH2sTQTq07KmPMQ48ihyvo5+Ya56spVOPhunfGr6406crCVA==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -6075,9 +6075,9 @@ } }, "node_modules/tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -7798,9 +7798,9 @@ "dev": true }, "@types/node": { - "version": "20.5.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", - "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==", + "version": "20.5.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", + "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==", "dev": true }, "@types/normalize-package-data": { @@ -7822,9 +7822,9 @@ "dev": true }, "@types/uuid": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", - "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.3.tgz", + "integrity": "sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug==", "dev": true }, "@types/yargs": { @@ -7843,16 +7843,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz", - "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.6.0.tgz", + "integrity": "sha512-CW9YDGTQnNYMIo5lMeuiIG08p4E0cXrXTbcZ2saT/ETE7dWUrNxlijsQeU04qAAKkILiLzdQz+cGFxCJjaZUmA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/type-utils": "6.4.1", - "@typescript-eslint/utils": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/type-utils": "6.6.0", + "@typescript-eslint/utils": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7862,29 +7862,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", - "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", + "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1" + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0" } }, "@typescript-eslint/types": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", - "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", + "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", - "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", + "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7893,69 +7893,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", - "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", + "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/typescript-estree": "6.4.1", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/typescript-estree": "6.6.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", - "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", + "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/types": "6.6.0", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz", - "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.6.0.tgz", + "integrity": "sha512-setq5aJgUwtzGrhW177/i+DMLqBaJbdwGj2CPIVFFLE0NCliy5ujIdLHd2D1ysmlmsjdL2GWW+hR85neEfc12w==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/typescript-estree": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", - "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", + "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1" + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0" } }, "@typescript-eslint/types": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", - "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", + "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", - "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", + "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7964,12 +7964,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", - "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", + "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/types": "6.6.0", "eslint-visitor-keys": "^3.4.1" } } @@ -7986,41 +7986,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz", - "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.6.0.tgz", + "integrity": "sha512-8m16fwAcEnQc69IpeDyokNO+D5spo0w1jepWWY2Q6y5ZKNuj5EhVQXjtVAeDDqvW6Yg7dhclbsz6rTtOvcwpHg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.4.1", - "@typescript-eslint/utils": "6.4.1", + "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/utils": "6.6.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", - "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", + "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1" + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0" } }, "@typescript-eslint/types": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", - "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", + "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", - "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", + "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8029,27 +8029,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", - "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", + "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/typescript-estree": "6.4.1", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/typescript-estree": "6.6.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", - "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", + "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.4.1", + "@typescript-eslint/types": "6.6.0", "eslint-visitor-keys": "^3.4.1" } } @@ -10049,9 +10049,9 @@ "dev": true }, "marked": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.5.tgz", - "integrity": "sha512-lwNAFTfXgqpt/XvK17a/8wY9/q6fcSPZT1aP6QW0u74VwaJF/Z9KbRcX23sWE4tODM+AolJNcUtErTkgOeFP/Q==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-8.0.1.tgz", + "integrity": "sha512-eEbeEb/mJwh+sNLEhHOWtxMgjN/NEwZUBs1nkiIH2sTQTq07KmPMQ48ihyvo5+Ya56spVOPhunfGr6406crCVA==", "dev": true }, "meow": { @@ -10968,9 +10968,9 @@ "dev": true }, "tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", diff --git a/package.json b/package.json index af6d8deff7..8f46f74c82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.11", + "version": "3.12.12", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -91,21 +91,21 @@ "h264-profile-level-id": "^1.0.1", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.1.15", + "tar": "^6.2.0", "uuid": "^9.0.0" }, "devDependencies": { "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", "@types/jest": "^29.5.4", - "@types/node": "^20.5.7", - "@types/uuid": "^9.0.2", - "@typescript-eslint/eslint-plugin": "^6.4.1", - "@typescript-eslint/parser": "^6.4.1", + "@types/node": "^20.5.9", + "@types/uuid": "^9.0.3", + "@typescript-eslint/eslint-plugin": "^6.6.0", + "@typescript-eslint/parser": "^6.6.0", "eslint": "^8.48.0", "eslint-plugin-jest": "^27.2.3", "jest": "^29.6.4", - "marked": "^7.0.5", + "marked": "^8.0.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From ce94ced9a77400d899178848397091102784b128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 7 Sep 2023 17:31:37 +0200 Subject: [PATCH 158/525] npm-scripts.mjs: do not use recursive:true in replaceVersion() --- npm-scripts.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 0522a1f930..433d309d1b 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -265,7 +265,7 @@ function replaceVersion() const files = fs.readdirSync('node/lib', { withFileTypes : true, - recursive : true + recursive : false }); for (const file of files) From 8c0026bf2b924b5ed6770dc69e0ad0f714b3a8e2 Mon Sep 17 00:00:00 2001 From: Arush Kurundodi <69193694+arcinston@users.noreply.github.com> Date: Wed, 20 Sep 2023 18:52:24 +0530 Subject: [PATCH 159/525] bump up meson from 1.1.0 to 1.2.1 (#1163) --- worker/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/Makefile b/worker/Makefile index af74457eb5..45e39f5496 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -20,7 +20,7 @@ PIP_DIR = $(MEDIASOUP_OUT_DIR)/pip INSTALL_DIR ?= $(MEDIASOUP_OUT_DIR)/$(MEDIASOUP_BUILDTYPE) BUILD_DIR ?= $(INSTALL_DIR)/build MESON ?= $(PIP_DIR)/bin/meson -MESON_VERSION ?= 1.1.0 +MESON_VERSION ?= 1.2.1 # `MESON_ARGS` can be used to provide extra configuration parameters to Meson, # such as adding defines or changing optimization options. For instance, use # `MESON_ARGS="-Dms_log_trace=true -Dms_log_file_line=true" npm i` to compile From 97bf4c3f50cf048ac1232da23d4954ee78ef1f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 20 Sep 2023 15:30:05 +0200 Subject: [PATCH 160/525] Update NPM deps --- package-lock.json | 1486 +++++++++++++++++++++++---------------------- package.json | 20 +- 2 files changed, 772 insertions(+), 734 deletions(-) diff --git a/package-lock.json b/package-lock.json index bf8cee8566..6278781734 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,20 +15,20 @@ "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0", - "uuid": "^9.0.0" + "uuid": "^9.0.1" }, "devDependencies": { "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", - "@types/jest": "^29.5.4", - "@types/node": "^20.5.9", - "@types/uuid": "^9.0.3", - "@typescript-eslint/eslint-plugin": "^6.6.0", - "@typescript-eslint/parser": "^6.6.0", - "eslint": "^8.48.0", - "eslint-plugin-jest": "^27.2.3", - "jest": "^29.6.4", - "marked": "^8.0.1", + "@types/jest": "^29.5.5", + "@types/node": "^20.6.3", + "@types/uuid": "^9.0.4", + "@typescript-eslint/eslint-plugin": "^6.7.2", + "@typescript-eslint/parser": "^6.7.2", + "eslint": "^8.49.0", + "eslint-plugin-jest": "^27.4.0", + "jest": "^29.7.0", + "marked": "^9.0.3", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -702,18 +702,18 @@ } }, "node_modules/@eslint/js": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", - "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", + "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -852,16 +852,16 @@ } }, "node_modules/@jest/console": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.4.tgz", - "integrity": "sha512-wNK6gC0Ha9QeEPSkeJedQuTQqxZYnDPuDcDhVuVatRvMkL4D0VTvFVZj+Yuh6caG2aOfzkUZ36KtCmLNtR02hw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.3", - "jest-util": "^29.6.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -869,15 +869,15 @@ } }, "node_modules/@jest/core": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.4.tgz", - "integrity": "sha512-U/vq5ccNTSVgYH7mHnodHmCffGWHJnz/E1BEWlLuK5pM4FZmGfBn/nrJGLjUsSmyx3otCeqc1T31F4y08AMDLg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "dependencies": { - "@jest/console": "^29.6.4", - "@jest/reporters": "^29.6.4", - "@jest/test-result": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", @@ -885,21 +885,21 @@ "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.6.3", - "jest-config": "^29.6.4", - "jest-haste-map": "^29.6.4", - "jest-message-util": "^29.6.3", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.6.4", - "jest-resolve-dependencies": "^29.6.4", - "jest-runner": "^29.6.4", - "jest-runtime": "^29.6.4", - "jest-snapshot": "^29.6.4", - "jest-util": "^29.6.3", - "jest-validate": "^29.6.3", - "jest-watcher": "^29.6.4", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -916,37 +916,37 @@ } }, "node_modules/@jest/environment": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.4.tgz", - "integrity": "sha512-sQ0SULEjA1XUTHmkBRl7A1dyITM9yb1yb3ZNKPX3KlTd6IG7mWUe3e2yfExtC2Zz1Q+mMckOLHmL/qLiuQJrBQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.6.4", + "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.3" + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.4.tgz", - "integrity": "sha512-Warhsa7d23+3X5bLbrbYvaehcgX5TLYhI03JKoedTiI8uJU4IhqYBWF7OSSgUyz4IgLpUYPkK0AehA5/fRclAA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "dependencies": { - "expect": "^29.6.4", - "jest-snapshot": "^29.6.4" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.4.tgz", - "integrity": "sha512-FEhkJhqtvBwgSpiTrocquJCdXPsyvNKcl/n7A3u7X4pVoF4bswm11c9d4AV+kfq2Gpv/mM8x7E7DsRvH+djkrg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "dependencies": { "jest-get-type": "^29.6.3" @@ -956,47 +956,47 @@ } }, "node_modules/@jest/fake-timers": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.4.tgz", - "integrity": "sha512-6UkCwzoBK60edXIIWb0/KWkuj7R7Qq91vVInOe3De6DSpaEiqjKcJw4F7XUet24Wupahj9J6PlR09JqJ5ySDHw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.3", - "jest-mock": "^29.6.3", - "jest-util": "^29.6.3" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.4.tgz", - "integrity": "sha512-wVIn5bdtjlChhXAzVXavcY/3PEjf4VqM174BM3eGL5kMxLiZD5CLnbmkEyA1Dwh9q8XjP6E8RwjBsY/iCWrWsA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.4", - "@jest/expect": "^29.6.4", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", "@jest/types": "^29.6.3", - "jest-mock": "^29.6.3" + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.4.tgz", - "integrity": "sha512-sxUjWxm7QdchdrD3NfWKrL8FBsortZeibSJv4XLjESOOjSUOkjQcb0ZHJwfhEGIvBvTluTzfG2yZWZhkrXJu8g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.4", - "@jest/test-result": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", @@ -1010,9 +1010,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.3", - "jest-util": "^29.6.3", - "jest-worker": "^29.6.4", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -1073,12 +1073,12 @@ } }, "node_modules/@jest/test-result": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.4.tgz", - "integrity": "sha512-uQ1C0AUEN90/dsyEirgMLlouROgSY+Wc/JanVVk0OiUKa5UFh7sJpMEM3aoUBAz2BRNvUJ8j3d294WFuRxSyOQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "dependencies": { - "@jest/console": "^29.6.4", + "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" @@ -1088,14 +1088,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.4.tgz", - "integrity": "sha512-E84M6LbpcRq3fT4ckfKs9ryVanwkaIB0Ws9bw3/yP4seRLg/VaCZ/LgW0MCq5wwk4/iP/qnilD41aj2fsw2RMg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.4", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.4", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -1103,9 +1103,9 @@ } }, "node_modules/@jest/transform": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.4.tgz", - "integrity": "sha512-8thgRSiXUqtr/pPGY/OsyHuMjGyhVnWrFAwoxmIemlBuiMyU1WFs0tXoNxzcr4A4uErs/ABre76SGmrr5ab/AA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -1116,9 +1116,9 @@ "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.4", + "jest-haste-map": "^29.7.0", "jest-regex-util": "^29.6.3", - "jest-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1498,9 +1498,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.4", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.4.tgz", - "integrity": "sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==", + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1526,9 +1526,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.5.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", - "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==", + "version": "20.6.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz", + "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1550,9 +1550,9 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.3.tgz", - "integrity": "sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.4.tgz", + "integrity": "sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==", "dev": true }, "node_modules/@types/yargs": { @@ -1571,16 +1571,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.6.0.tgz", - "integrity": "sha512-CW9YDGTQnNYMIo5lMeuiIG08p4E0cXrXTbcZ2saT/ETE7dWUrNxlijsQeU04qAAKkILiLzdQz+cGFxCJjaZUmA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz", + "integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/type-utils": "6.6.0", - "@typescript-eslint/utils": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/type-utils": "6.7.2", + "@typescript-eslint/utils": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1606,13 +1606,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", - "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0" + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1623,9 +1623,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", - "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1636,13 +1636,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", - "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1663,17 +1663,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", - "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", + "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", "semver": "^7.5.4" }, "engines": { @@ -1688,12 +1688,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", - "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/types": "6.7.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1705,15 +1705,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.6.0.tgz", - "integrity": "sha512-setq5aJgUwtzGrhW177/i+DMLqBaJbdwGj2CPIVFFLE0NCliy5ujIdLHd2D1ysmlmsjdL2GWW+hR85neEfc12w==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz", + "integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/typescript-estree": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4" }, "engines": { @@ -1733,13 +1733,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", - "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0" + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1750,9 +1750,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", - "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1763,13 +1763,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", - "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1790,12 +1790,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", - "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/types": "6.7.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1824,13 +1824,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.6.0.tgz", - "integrity": "sha512-8m16fwAcEnQc69IpeDyokNO+D5spo0w1jepWWY2Q6y5ZKNuj5EhVQXjtVAeDDqvW6Yg7dhclbsz6rTtOvcwpHg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz", + "integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.6.0", - "@typescript-eslint/utils": "6.6.0", + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/utils": "6.7.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1851,13 +1851,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", - "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0" + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1868,9 +1868,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", - "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1881,13 +1881,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", - "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1908,17 +1908,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", - "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", + "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", "semver": "^7.5.4" }, "engines": { @@ -1933,12 +1933,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", - "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/types": "6.7.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2158,12 +2158,12 @@ } }, "node_modules/babel-jest": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz", - "integrity": "sha512-meLj23UlSLddj6PC+YTOFRgDAtjnZom8w/ACsrx0gtPtv5cJZk0A5Unk5bV4wixD7XaPCN1fQvpww8czkZURmw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "dependencies": { - "@jest/transform": "^29.6.4", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.6.3", @@ -2578,6 +2578,27 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2906,16 +2927,16 @@ } }, "node_modules/eslint": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", - "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", + "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.48.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/js": "8.49.0", + "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.12.4", @@ -2960,9 +2981,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", - "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.0.tgz", + "integrity": "sha512-ukVeKmMPAUA5SWjHenvyyXnirKfHKMdOsTZdn5tZx5EW05HGVQwBohigjFZGGj3zuv1cV6hc82FvWv6LdIbkgg==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -3157,16 +3178,16 @@ } }, "node_modules/expect": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.4.tgz", - "integrity": "sha512-F2W2UyQ8XYyftHT57dtfg8Ue3X5qLgm2sSug0ivvLRH/VKNRL/pDxg/TH7zVzbQB0tu80clNFy6LU7OS/VSEKA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.6.4", + "@jest/expect-utils": "^29.7.0", "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.6.4", - "jest-message-util": "^29.6.3", - "jest-util": "^29.6.3" + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3975,15 +3996,15 @@ } }, "node_modules/jest": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.4.tgz", - "integrity": "sha512-tEFhVQFF/bzoYV1YuGyzLPZ6vlPrdfvDmmAxudA1dLEuiztqg2Rkx20vkKY32xiDROcD2KXlgZ7Cu8RPeEHRKw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "dependencies": { - "@jest/core": "^29.6.4", + "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.6.4" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" @@ -4001,13 +4022,13 @@ } }, "node_modules/jest-changed-files": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.6.3.tgz", - "integrity": "sha512-G5wDnElqLa4/c66ma5PG9eRjE342lIbF6SUnTJi26C3J28Fv2TVY2rOyKB9YGbSA5ogwevgmxc4j4aVjrEK6Yg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "dependencies": { "execa": "^5.0.0", - "jest-util": "^29.6.3", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" }, "engines": { @@ -4015,28 +4036,28 @@ } }, "node_modules/jest-circus": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.4.tgz", - "integrity": "sha512-YXNrRyntVUgDfZbjXWBMPslX1mQ8MrSG0oM/Y06j9EYubODIyHWP8hMUbjbZ19M3M+zamqEur7O80HODwACoJw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.4", - "@jest/expect": "^29.6.4", - "@jest/test-result": "^29.6.4", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.3", - "jest-matcher-utils": "^29.6.4", - "jest-message-util": "^29.6.3", - "jest-runtime": "^29.6.4", - "jest-snapshot": "^29.6.4", - "jest-util": "^29.6.3", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -4046,22 +4067,21 @@ } }, "node_modules/jest-cli": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.4.tgz", - "integrity": "sha512-+uMCQ7oizMmh8ZwRfZzKIEszFY9ksjjEQnTEMTaL7fYiL3Kw4XhqT9bYh+A4DQKUb67hZn2KbtEnDuHvcgK4pQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "dependencies": { - "@jest/core": "^29.6.4", - "@jest/test-result": "^29.6.4", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.4", - "jest-util": "^29.6.3", - "jest-validate": "^29.6.3", - "prompts": "^2.0.1", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "yargs": "^17.3.1" }, "bin": { @@ -4080,31 +4100,31 @@ } }, "node_modules/jest-config": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.4.tgz", - "integrity": "sha512-JWohr3i9m2cVpBumQFv2akMEnFEPVOh+9L2xIBJhJ0zOaci2ZXuKJj0tgMKQCBZAKA09H049IR4HVS/43Qb19A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.4", + "@jest/test-sequencer": "^29.7.0", "@jest/types": "^29.6.3", - "babel-jest": "^29.6.4", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.4", - "jest-environment-node": "^29.6.4", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", "jest-get-type": "^29.6.3", "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.6.4", - "jest-runner": "^29.6.4", - "jest-util": "^29.6.3", - "jest-validate": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -4125,24 +4145,24 @@ } }, "node_modules/jest-diff": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.4.tgz", - "integrity": "sha512-9F48UxR9e4XOEZvoUXEHSWY4qC4zERJaOfrbBg9JpbJOO43R1vN76REt/aMGZoY6GD5g84nnJiBIVlscegefpw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", "jest-get-type": "^29.6.3", - "pretty-format": "^29.6.3" + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.6.3.tgz", - "integrity": "sha512-2+H+GOTQBEm2+qFSQ7Ma+BvyV+waiIFxmZF5LdpBsAEjWX8QYjSCa4FrkIYtbfXUJJJnFCYrOtt6TZ+IAiTjBQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" @@ -4152,33 +4172,33 @@ } }, "node_modules/jest-each": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.3.tgz", - "integrity": "sha512-KoXfJ42k8cqbkfshW7sSHcdfnv5agDdHCPA87ZBdmHP+zJstTJc0ttQaJ/x7zK6noAL76hOuTIJ6ZkQRS5dcyg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", "jest-get-type": "^29.6.3", - "jest-util": "^29.6.3", - "pretty-format": "^29.6.3" + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.4.tgz", - "integrity": "sha512-i7SbpH2dEIFGNmxGCpSc2w9cA4qVD+wfvg2ZnfQ7XVrKL0NA5uDVBIiGH8SR4F0dKEv/0qI5r+aDomDf04DpEQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.4", - "@jest/fake-timers": "^29.6.4", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.3", - "jest-util": "^29.6.3" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4194,9 +4214,9 @@ } }, "node_modules/jest-haste-map": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.4.tgz", - "integrity": "sha512-12Ad+VNTDHxKf7k+M65sviyynRoZYuL1/GTuhEVb8RYsNSNln71nANRb/faSyWvx0j+gHcivChXHIoMJrGYjog==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", @@ -4206,8 +4226,8 @@ "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.6.3", - "jest-util": "^29.6.3", - "jest-worker": "^29.6.4", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -4219,37 +4239,37 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.3.tgz", - "integrity": "sha512-0kfbESIHXYdhAdpLsW7xdwmYhLf1BRu4AA118/OxFm0Ho1b2RcTmO4oF6aAMaxpxdxnJ3zve2rgwzNBD4Zbm7Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "dependencies": { "jest-get-type": "^29.6.3", - "pretty-format": "^29.6.3" + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.4.tgz", - "integrity": "sha512-KSzwyzGvK4HcfnserYqJHYi7sZVqdREJ9DMPAKVbS98JsIAvumihaNUbjrWw0St7p9IY7A9UskCW5MYlGmBQFQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.6.4", + "jest-diff": "^29.7.0", "jest-get-type": "^29.6.3", - "pretty-format": "^29.6.3" + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.3.tgz", - "integrity": "sha512-FtzaEEHzjDpQp51HX4UMkPZjy46ati4T5pEMyM6Ik48ztu4T9LQplZ6OsimHx7EuM9dfEh5HJa6D3trEftu3dA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", @@ -4258,7 +4278,7 @@ "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -4267,14 +4287,14 @@ } }, "node_modules/jest-mock": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.3.tgz", - "integrity": "sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.6.3" + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4307,17 +4327,17 @@ } }, "node_modules/jest-resolve": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.4.tgz", - "integrity": "sha512-fPRq+0vcxsuGlG0O3gyoqGTAxasagOxEuyoxHeyxaZbc9QNek0AmJWSkhjlMG+mTsj+8knc/mWb3fXlRNVih7Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.4", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.3", - "jest-validate": "^29.6.3", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -4327,43 +4347,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.4.tgz", - "integrity": "sha512-7+6eAmr1ZBF3vOAJVsfLj1QdqeXG+WYhidfLHBRZqGN24MFRIiKG20ItpLw2qRAsW/D2ZUUmCNf6irUr/v6KHA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "dependencies": { "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.6.4" + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.4.tgz", - "integrity": "sha512-SDaLrMmtVlQYDuG0iSPYLycG8P9jLI+fRm8AF/xPKhYDB2g6xDWjXBrR5M8gEWsK6KVFlebpZ4QsrxdyIX1Jaw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "dependencies": { - "@jest/console": "^29.6.4", - "@jest/environment": "^29.6.4", - "@jest/test-result": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.6.3", - "jest-environment-node": "^29.6.4", - "jest-haste-map": "^29.6.4", - "jest-leak-detector": "^29.6.3", - "jest-message-util": "^29.6.3", - "jest-resolve": "^29.6.4", - "jest-runtime": "^29.6.4", - "jest-util": "^29.6.3", - "jest-watcher": "^29.6.4", - "jest-worker": "^29.6.4", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -4372,17 +4392,17 @@ } }, "node_modules/jest-runtime": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.4.tgz", - "integrity": "sha512-s/QxMBLvmwLdchKEjcLfwzP7h+jsHvNEtxGP5P+Fl1FMaJX2jMiIqe4rJw4tFprzCwuSvVUo9bn0uj4gNRXsbA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.4", - "@jest/fake-timers": "^29.6.4", - "@jest/globals": "^29.6.4", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", @@ -4390,13 +4410,13 @@ "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.4", - "jest-message-util": "^29.6.3", - "jest-mock": "^29.6.3", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.6.4", - "jest-snapshot": "^29.6.4", - "jest-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -4405,9 +4425,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.4.tgz", - "integrity": "sha512-VC1N8ED7+4uboUKGIDsbvNAZb6LakgIPgAF4RSpF13dN6YaMokfRqO+BaqK4zIh6X3JffgwbzuGqDEjHm/MrvA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -4415,20 +4435,20 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.4", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.4", + "jest-diff": "^29.7.0", "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.6.4", - "jest-message-util": "^29.6.3", - "jest-util": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "semver": "^7.5.3" }, "engines": { @@ -4436,9 +4456,9 @@ } }, "node_modules/jest-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz", - "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", @@ -4453,9 +4473,9 @@ } }, "node_modules/jest-validate": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.3.tgz", - "integrity": "sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", @@ -4463,7 +4483,7 @@ "chalk": "^4.0.0", "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.6.3" + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4482,18 +4502,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.4.tgz", - "integrity": "sha512-oqUWvx6+On04ShsT00Ir9T4/FvBeEh2M9PTubgITPxDa739p4hoQweWPRGyYeaojgT0xTpZKF0Y/rSY1UgMxvQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.4", + "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.3", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { @@ -4501,13 +4521,13 @@ } }, "node_modules/jest-worker": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.4.tgz", - "integrity": "sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.6.3", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4727,9 +4747,9 @@ } }, "node_modules/marked": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-8.0.1.tgz", - "integrity": "sha512-eEbeEb/mJwh+sNLEhHOWtxMgjN/NEwZUBs1nkiIH2sTQTq07KmPMQ48ihyvo5+Ya56spVOPhunfGr6406crCVA==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.0.3.tgz", + "integrity": "sha512-pI/k4nzBG1PEq1J3XFEHxVvjicfjl8rgaMaqclouGSMPhk7Q3Ejb2ZRxx/ZQOcQ1909HzVoWCFYq6oLgtL4BpQ==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -5314,9 +5334,9 @@ } }, "node_modules/pretty-format": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.3.tgz", - "integrity": "sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { "@jest/schemas": "^29.6.3", @@ -5368,9 +5388,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", "dev": true, "funding": [ { @@ -5645,9 +5665,9 @@ } }, "node_modules/resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", "dev": true, "dependencies": { "is-core-module": "^2.13.0", @@ -6420,9 +6440,13 @@ "dev": true }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -7127,15 +7151,15 @@ } }, "@eslint/js": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", - "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", + "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", "dev": true }, "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -7239,29 +7263,29 @@ "dev": true }, "@jest/console": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.4.tgz", - "integrity": "sha512-wNK6gC0Ha9QeEPSkeJedQuTQqxZYnDPuDcDhVuVatRvMkL4D0VTvFVZj+Yuh6caG2aOfzkUZ36KtCmLNtR02hw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "requires": { "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.3", - "jest-util": "^29.6.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.4.tgz", - "integrity": "sha512-U/vq5ccNTSVgYH7mHnodHmCffGWHJnz/E1BEWlLuK5pM4FZmGfBn/nrJGLjUsSmyx3otCeqc1T31F4y08AMDLg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "requires": { - "@jest/console": "^29.6.4", - "@jest/reporters": "^29.6.4", - "@jest/test-result": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", @@ -7269,92 +7293,92 @@ "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.6.3", - "jest-config": "^29.6.4", - "jest-haste-map": "^29.6.4", - "jest-message-util": "^29.6.3", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.6.4", - "jest-resolve-dependencies": "^29.6.4", - "jest-runner": "^29.6.4", - "jest-runtime": "^29.6.4", - "jest-snapshot": "^29.6.4", - "jest-util": "^29.6.3", - "jest-validate": "^29.6.3", - "jest-watcher": "^29.6.4", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.4.tgz", - "integrity": "sha512-sQ0SULEjA1XUTHmkBRl7A1dyITM9yb1yb3ZNKPX3KlTd6IG7mWUe3e2yfExtC2Zz1Q+mMckOLHmL/qLiuQJrBQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "requires": { - "@jest/fake-timers": "^29.6.4", + "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.3" + "jest-mock": "^29.7.0" } }, "@jest/expect": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.4.tgz", - "integrity": "sha512-Warhsa7d23+3X5bLbrbYvaehcgX5TLYhI03JKoedTiI8uJU4IhqYBWF7OSSgUyz4IgLpUYPkK0AehA5/fRclAA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "requires": { - "expect": "^29.6.4", - "jest-snapshot": "^29.6.4" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" } }, "@jest/expect-utils": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.4.tgz", - "integrity": "sha512-FEhkJhqtvBwgSpiTrocquJCdXPsyvNKcl/n7A3u7X4pVoF4bswm11c9d4AV+kfq2Gpv/mM8x7E7DsRvH+djkrg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "requires": { "jest-get-type": "^29.6.3" } }, "@jest/fake-timers": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.4.tgz", - "integrity": "sha512-6UkCwzoBK60edXIIWb0/KWkuj7R7Qq91vVInOe3De6DSpaEiqjKcJw4F7XUet24Wupahj9J6PlR09JqJ5ySDHw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "requires": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.3", - "jest-mock": "^29.6.3", - "jest-util": "^29.6.3" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" } }, "@jest/globals": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.4.tgz", - "integrity": "sha512-wVIn5bdtjlChhXAzVXavcY/3PEjf4VqM174BM3eGL5kMxLiZD5CLnbmkEyA1Dwh9q8XjP6E8RwjBsY/iCWrWsA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "requires": { - "@jest/environment": "^29.6.4", - "@jest/expect": "^29.6.4", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", "@jest/types": "^29.6.3", - "jest-mock": "^29.6.3" + "jest-mock": "^29.7.0" } }, "@jest/reporters": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.4.tgz", - "integrity": "sha512-sxUjWxm7QdchdrD3NfWKrL8FBsortZeibSJv4XLjESOOjSUOkjQcb0ZHJwfhEGIvBvTluTzfG2yZWZhkrXJu8g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.4", - "@jest/test-result": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", @@ -7368,9 +7392,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.3", - "jest-util": "^29.6.3", - "jest-worker": "^29.6.4", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -7413,33 +7437,33 @@ } }, "@jest/test-result": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.4.tgz", - "integrity": "sha512-uQ1C0AUEN90/dsyEirgMLlouROgSY+Wc/JanVVk0OiUKa5UFh7sJpMEM3aoUBAz2BRNvUJ8j3d294WFuRxSyOQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "requires": { - "@jest/console": "^29.6.4", + "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.4.tgz", - "integrity": "sha512-E84M6LbpcRq3fT4ckfKs9ryVanwkaIB0Ws9bw3/yP4seRLg/VaCZ/LgW0MCq5wwk4/iP/qnilD41aj2fsw2RMg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "requires": { - "@jest/test-result": "^29.6.4", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.4", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.4.tgz", - "integrity": "sha512-8thgRSiXUqtr/pPGY/OsyHuMjGyhVnWrFAwoxmIemlBuiMyU1WFs0tXoNxzcr4A4uErs/ABre76SGmrr5ab/AA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -7450,9 +7474,9 @@ "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.4", + "jest-haste-map": "^29.7.0", "jest-regex-util": "^29.6.3", - "jest-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -7770,9 +7794,9 @@ } }, "@types/jest": { - "version": "29.5.4", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.4.tgz", - "integrity": "sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==", + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", "dev": true, "requires": { "expect": "^29.0.0", @@ -7798,9 +7822,9 @@ "dev": true }, "@types/node": { - "version": "20.5.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", - "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==", + "version": "20.6.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz", + "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==", "dev": true }, "@types/normalize-package-data": { @@ -7822,9 +7846,9 @@ "dev": true }, "@types/uuid": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.3.tgz", - "integrity": "sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.4.tgz", + "integrity": "sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==", "dev": true }, "@types/yargs": { @@ -7843,16 +7867,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.6.0.tgz", - "integrity": "sha512-CW9YDGTQnNYMIo5lMeuiIG08p4E0cXrXTbcZ2saT/ETE7dWUrNxlijsQeU04qAAKkILiLzdQz+cGFxCJjaZUmA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz", + "integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/type-utils": "6.6.0", - "@typescript-eslint/utils": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/type-utils": "6.7.2", + "@typescript-eslint/utils": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7862,29 +7886,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", - "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0" + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" } }, "@typescript-eslint/types": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", - "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", - "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7893,69 +7917,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", - "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", + "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", - "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/types": "6.7.2", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.6.0.tgz", - "integrity": "sha512-setq5aJgUwtzGrhW177/i+DMLqBaJbdwGj2CPIVFFLE0NCliy5ujIdLHd2D1ysmlmsjdL2GWW+hR85neEfc12w==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz", + "integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/typescript-estree": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", - "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0" + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" } }, "@typescript-eslint/types": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", - "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", - "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7964,12 +7988,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", - "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/types": "6.7.2", "eslint-visitor-keys": "^3.4.1" } } @@ -7986,41 +8010,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.6.0.tgz", - "integrity": "sha512-8m16fwAcEnQc69IpeDyokNO+D5spo0w1jepWWY2Q6y5ZKNuj5EhVQXjtVAeDDqvW6Yg7dhclbsz6rTtOvcwpHg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz", + "integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.6.0", - "@typescript-eslint/utils": "6.6.0", + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/utils": "6.7.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", - "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0" + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" } }, "@typescript-eslint/types": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", - "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", - "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8029,27 +8053,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", - "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", + "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", - "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/types": "6.7.2", "eslint-visitor-keys": "^3.4.1" } } @@ -8188,12 +8212,12 @@ "dev": true }, "babel-jest": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz", - "integrity": "sha512-meLj23UlSLddj6PC+YTOFRgDAtjnZom8w/ACsrx0gtPtv5cJZk0A5Unk5bV4wixD7XaPCN1fQvpww8czkZURmw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "requires": { - "@jest/transform": "^29.6.4", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.6.3", @@ -8492,6 +8516,21 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -8723,16 +8762,16 @@ "dev": true }, "eslint": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", - "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", + "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.48.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/js": "8.49.0", + "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.12.4", @@ -8786,9 +8825,9 @@ } }, "eslint-plugin-jest": { - "version": "27.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", - "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.0.tgz", + "integrity": "sha512-ukVeKmMPAUA5SWjHenvyyXnirKfHKMdOsTZdn5tZx5EW05HGVQwBohigjFZGGj3zuv1cV6hc82FvWv6LdIbkgg==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" @@ -8897,16 +8936,16 @@ "dev": true }, "expect": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.4.tgz", - "integrity": "sha512-F2W2UyQ8XYyftHT57dtfg8Ue3X5qLgm2sSug0ivvLRH/VKNRL/pDxg/TH7zVzbQB0tu80clNFy6LU7OS/VSEKA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "requires": { - "@jest/expect-utils": "^29.6.4", + "@jest/expect-utils": "^29.7.0", "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.6.4", - "jest-message-util": "^29.6.3", - "jest-util": "^29.6.3" + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" } }, "fast-deep-equal": { @@ -9477,152 +9516,151 @@ } }, "jest": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.4.tgz", - "integrity": "sha512-tEFhVQFF/bzoYV1YuGyzLPZ6vlPrdfvDmmAxudA1dLEuiztqg2Rkx20vkKY32xiDROcD2KXlgZ7Cu8RPeEHRKw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "requires": { - "@jest/core": "^29.6.4", + "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.6.4" + "jest-cli": "^29.7.0" } }, "jest-changed-files": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.6.3.tgz", - "integrity": "sha512-G5wDnElqLa4/c66ma5PG9eRjE342lIbF6SUnTJi26C3J28Fv2TVY2rOyKB9YGbSA5ogwevgmxc4j4aVjrEK6Yg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "requires": { "execa": "^5.0.0", - "jest-util": "^29.6.3", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" } }, "jest-circus": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.4.tgz", - "integrity": "sha512-YXNrRyntVUgDfZbjXWBMPslX1mQ8MrSG0oM/Y06j9EYubODIyHWP8hMUbjbZ19M3M+zamqEur7O80HODwACoJw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "requires": { - "@jest/environment": "^29.6.4", - "@jest/expect": "^29.6.4", - "@jest/test-result": "^29.6.4", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.3", - "jest-matcher-utils": "^29.6.4", - "jest-message-util": "^29.6.3", - "jest-runtime": "^29.6.4", - "jest-snapshot": "^29.6.4", - "jest-util": "^29.6.3", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.4.tgz", - "integrity": "sha512-+uMCQ7oizMmh8ZwRfZzKIEszFY9ksjjEQnTEMTaL7fYiL3Kw4XhqT9bYh+A4DQKUb67hZn2KbtEnDuHvcgK4pQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "requires": { - "@jest/core": "^29.6.4", - "@jest/test-result": "^29.6.4", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.4", - "jest-util": "^29.6.3", - "jest-validate": "^29.6.3", - "prompts": "^2.0.1", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "yargs": "^17.3.1" } }, "jest-config": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.4.tgz", - "integrity": "sha512-JWohr3i9m2cVpBumQFv2akMEnFEPVOh+9L2xIBJhJ0zOaci2ZXuKJj0tgMKQCBZAKA09H049IR4HVS/43Qb19A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.4", + "@jest/test-sequencer": "^29.7.0", "@jest/types": "^29.6.3", - "babel-jest": "^29.6.4", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.4", - "jest-environment-node": "^29.6.4", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", "jest-get-type": "^29.6.3", "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.6.4", - "jest-runner": "^29.6.4", - "jest-util": "^29.6.3", - "jest-validate": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" } }, "jest-diff": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.4.tgz", - "integrity": "sha512-9F48UxR9e4XOEZvoUXEHSWY4qC4zERJaOfrbBg9JpbJOO43R1vN76REt/aMGZoY6GD5g84nnJiBIVlscegefpw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "requires": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", "jest-get-type": "^29.6.3", - "pretty-format": "^29.6.3" + "pretty-format": "^29.7.0" } }, "jest-docblock": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.6.3.tgz", - "integrity": "sha512-2+H+GOTQBEm2+qFSQ7Ma+BvyV+waiIFxmZF5LdpBsAEjWX8QYjSCa4FrkIYtbfXUJJJnFCYrOtt6TZ+IAiTjBQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.3.tgz", - "integrity": "sha512-KoXfJ42k8cqbkfshW7sSHcdfnv5agDdHCPA87ZBdmHP+zJstTJc0ttQaJ/x7zK6noAL76hOuTIJ6ZkQRS5dcyg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "requires": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", "jest-get-type": "^29.6.3", - "jest-util": "^29.6.3", - "pretty-format": "^29.6.3" + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" } }, "jest-environment-node": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.4.tgz", - "integrity": "sha512-i7SbpH2dEIFGNmxGCpSc2w9cA4qVD+wfvg2ZnfQ7XVrKL0NA5uDVBIiGH8SR4F0dKEv/0qI5r+aDomDf04DpEQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "requires": { - "@jest/environment": "^29.6.4", - "@jest/fake-timers": "^29.6.4", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.3", - "jest-util": "^29.6.3" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" } }, "jest-get-type": { @@ -9632,9 +9670,9 @@ "dev": true }, "jest-haste-map": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.4.tgz", - "integrity": "sha512-12Ad+VNTDHxKf7k+M65sviyynRoZYuL1/GTuhEVb8RYsNSNln71nANRb/faSyWvx0j+gHcivChXHIoMJrGYjog==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "requires": { "@jest/types": "^29.6.3", @@ -9645,38 +9683,38 @@ "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.6.3", - "jest-util": "^29.6.3", - "jest-worker": "^29.6.4", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "jest-leak-detector": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.3.tgz", - "integrity": "sha512-0kfbESIHXYdhAdpLsW7xdwmYhLf1BRu4AA118/OxFm0Ho1b2RcTmO4oF6aAMaxpxdxnJ3zve2rgwzNBD4Zbm7Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "requires": { "jest-get-type": "^29.6.3", - "pretty-format": "^29.6.3" + "pretty-format": "^29.7.0" } }, "jest-matcher-utils": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.4.tgz", - "integrity": "sha512-KSzwyzGvK4HcfnserYqJHYi7sZVqdREJ9DMPAKVbS98JsIAvumihaNUbjrWw0St7p9IY7A9UskCW5MYlGmBQFQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.6.4", + "jest-diff": "^29.7.0", "jest-get-type": "^29.6.3", - "pretty-format": "^29.6.3" + "pretty-format": "^29.7.0" } }, "jest-message-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.3.tgz", - "integrity": "sha512-FtzaEEHzjDpQp51HX4UMkPZjy46ati4T5pEMyM6Ik48ztu4T9LQplZ6OsimHx7EuM9dfEh5HJa6D3trEftu3dA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", @@ -9685,20 +9723,20 @@ "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.3.tgz", - "integrity": "sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "requires": { "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.6.3" + "jest-util": "^29.7.0" } }, "jest-pnp-resolver": { @@ -9715,73 +9753,73 @@ "dev": true }, "jest-resolve": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.4.tgz", - "integrity": "sha512-fPRq+0vcxsuGlG0O3gyoqGTAxasagOxEuyoxHeyxaZbc9QNek0AmJWSkhjlMG+mTsj+8knc/mWb3fXlRNVih7Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.4", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.3", - "jest-validate": "^29.6.3", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.4.tgz", - "integrity": "sha512-7+6eAmr1ZBF3vOAJVsfLj1QdqeXG+WYhidfLHBRZqGN24MFRIiKG20ItpLw2qRAsW/D2ZUUmCNf6irUr/v6KHA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "requires": { "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.6.4" + "jest-snapshot": "^29.7.0" } }, "jest-runner": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.4.tgz", - "integrity": "sha512-SDaLrMmtVlQYDuG0iSPYLycG8P9jLI+fRm8AF/xPKhYDB2g6xDWjXBrR5M8gEWsK6KVFlebpZ4QsrxdyIX1Jaw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "requires": { - "@jest/console": "^29.6.4", - "@jest/environment": "^29.6.4", - "@jest/test-result": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.6.3", - "jest-environment-node": "^29.6.4", - "jest-haste-map": "^29.6.4", - "jest-leak-detector": "^29.6.3", - "jest-message-util": "^29.6.3", - "jest-resolve": "^29.6.4", - "jest-runtime": "^29.6.4", - "jest-util": "^29.6.3", - "jest-watcher": "^29.6.4", - "jest-worker": "^29.6.4", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.4.tgz", - "integrity": "sha512-s/QxMBLvmwLdchKEjcLfwzP7h+jsHvNEtxGP5P+Fl1FMaJX2jMiIqe4rJw4tFprzCwuSvVUo9bn0uj4gNRXsbA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "requires": { - "@jest/environment": "^29.6.4", - "@jest/fake-timers": "^29.6.4", - "@jest/globals": "^29.6.4", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", @@ -9789,21 +9827,21 @@ "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.4", - "jest-message-util": "^29.6.3", - "jest-mock": "^29.6.3", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.6.4", - "jest-snapshot": "^29.6.4", - "jest-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.4.tgz", - "integrity": "sha512-VC1N8ED7+4uboUKGIDsbvNAZb6LakgIPgAF4RSpF13dN6YaMokfRqO+BaqK4zIh6X3JffgwbzuGqDEjHm/MrvA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -9811,27 +9849,27 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.4", - "@jest/transform": "^29.6.4", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.4", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.4", + "jest-diff": "^29.7.0", "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.6.4", - "jest-message-util": "^29.6.3", - "jest-util": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "semver": "^7.5.3" } }, "jest-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz", - "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "requires": { "@jest/types": "^29.6.3", @@ -9843,9 +9881,9 @@ } }, "jest-validate": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.3.tgz", - "integrity": "sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "requires": { "@jest/types": "^29.6.3", @@ -9853,7 +9891,7 @@ "chalk": "^4.0.0", "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.6.3" + "pretty-format": "^29.7.0" }, "dependencies": { "camelcase": { @@ -9865,29 +9903,29 @@ } }, "jest-watcher": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.4.tgz", - "integrity": "sha512-oqUWvx6+On04ShsT00Ir9T4/FvBeEh2M9PTubgITPxDa739p4hoQweWPRGyYeaojgT0xTpZKF0Y/rSY1UgMxvQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "requires": { - "@jest/test-result": "^29.6.4", + "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.3", + "jest-util": "^29.7.0", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.4.tgz", - "integrity": "sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.6.3", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -10049,9 +10087,9 @@ "dev": true }, "marked": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-8.0.1.tgz", - "integrity": "sha512-eEbeEb/mJwh+sNLEhHOWtxMgjN/NEwZUBs1nkiIH2sTQTq07KmPMQ48ihyvo5+Ya56spVOPhunfGr6406crCVA==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.0.3.tgz", + "integrity": "sha512-pI/k4nzBG1PEq1J3XFEHxVvjicfjl8rgaMaqclouGSMPhk7Q3Ejb2ZRxx/ZQOcQ1909HzVoWCFYq6oLgtL4BpQ==", "dev": true }, "meow": { @@ -10462,9 +10500,9 @@ "dev": true }, "pretty-format": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.3.tgz", - "integrity": "sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "requires": { "@jest/schemas": "^29.6.3", @@ -10503,9 +10541,9 @@ "dev": true }, "pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", "dev": true }, "queue-microtask": { @@ -10672,9 +10710,9 @@ "dev": true }, "resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", "dev": true, "requires": { "is-core-module": "^2.13.0", @@ -11184,9 +11222,9 @@ "dev": true }, "uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, "v8-to-istanbul": { "version": "9.1.0", diff --git a/package.json b/package.json index 8f46f74c82..9b02267788 100644 --- a/package.json +++ b/package.json @@ -92,20 +92,20 @@ "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0", - "uuid": "^9.0.0" + "uuid": "^9.0.1" }, "devDependencies": { "@octokit/rest": "^20.0.1", "@types/debug": "^4.1.8", - "@types/jest": "^29.5.4", - "@types/node": "^20.5.9", - "@types/uuid": "^9.0.3", - "@typescript-eslint/eslint-plugin": "^6.6.0", - "@typescript-eslint/parser": "^6.6.0", - "eslint": "^8.48.0", - "eslint-plugin-jest": "^27.2.3", - "jest": "^29.6.4", - "marked": "^8.0.1", + "@types/jest": "^29.5.5", + "@types/node": "^20.6.3", + "@types/uuid": "^9.0.4", + "@typescript-eslint/eslint-plugin": "^6.7.2", + "@typescript-eslint/parser": "^6.7.2", + "eslint": "^8.49.0", + "eslint-plugin-jest": "^27.4.0", + "jest": "^29.7.0", + "marked": "^9.0.3", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From b8f51bf5bea6956296edddc76164db5111fa7694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 20 Sep 2023 15:31:01 +0200 Subject: [PATCH 161/525] 3.12.13 --- CHANGELOG.md | 5 +++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50c13f0b16..02ea1d2922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.12.13 + +* Bump up Meson from 1.1.0 to 1.2.1 (fixes Xcode 15 build issues) ([PR #1163](https://github.com/versatica/mediasoup/pull/1163) by @arcinston). + + ### 3.12.12 * Support C++20 ([PR #1150](https://github.com/versatica/mediasoup/pull/1150) by @o-u-p). diff --git a/package-lock.json b/package-lock.json index 6278781734..340df4ccae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.12", + "version": "3.12.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.12", + "version": "3.12.13", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 9b02267788..9f9c7e98b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.12", + "version": "3.12.13", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From f56b20be605272e5905bc9e17a9b8218518dbdc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 9 Oct 2023 20:25:42 +0200 Subject: [PATCH 162/525] Update NPM deps --- package-lock.json | 572 ++++++++++++++++++++++++++-------------------- package.json | 18 +- 2 files changed, 336 insertions(+), 254 deletions(-) diff --git a/package-lock.json b/package-lock.json index 340df4ccae..67afac7486 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,17 +18,17 @@ "uuid": "^9.0.1" }, "devDependencies": { - "@octokit/rest": "^20.0.1", - "@types/debug": "^4.1.8", + "@octokit/rest": "^20.0.2", + "@types/debug": "^4.1.9", "@types/jest": "^29.5.5", - "@types/node": "^20.6.3", - "@types/uuid": "^9.0.4", - "@typescript-eslint/eslint-plugin": "^6.7.2", - "@typescript-eslint/parser": "^6.7.2", - "eslint": "^8.49.0", - "eslint-plugin-jest": "^27.4.0", + "@types/node": "^20.8.4", + "@types/uuid": "^9.0.5", + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", + "eslint": "^8.51.0", + "eslint-plugin-jest": "^27.4.2", "jest": "^29.7.0", - "marked": "^9.0.3", + "marked": "^9.1.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -702,9 +702,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", - "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1289,12 +1289,12 @@ "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-8.0.0.tgz", - "integrity": "sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", + "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", "dev": true, "dependencies": { - "@octokit/types": "^11.0.0" + "@octokit/types": "^12.0.0" }, "engines": { "node": ">= 18" @@ -1303,6 +1303,21 @@ "@octokit/core": ">=5" } }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", + "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^19.0.0" + } + }, "node_modules/@octokit/plugin-request-log": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", @@ -1316,12 +1331,12 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-9.0.0.tgz", - "integrity": "sha512-KquMF/VB1IkKNiVnzJKspY5mFgGyLd7HzdJfVEGTJFzqu9BRFNWt+nwTCMuUiWc72gLQhRWYubTwOkQj+w/1PA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", + "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", "dev": true, "dependencies": { - "@octokit/types": "^11.0.0" + "@octokit/types": "^12.0.0" }, "engines": { "node": ">= 18" @@ -1330,6 +1345,21 @@ "@octokit/core": ">=5" } }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", + "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "dev": true + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^19.0.0" + } + }, "node_modules/@octokit/request": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", @@ -1361,15 +1391,15 @@ } }, "node_modules/@octokit/rest": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.1.tgz", - "integrity": "sha512-wROV21RwHQIMNb2Dgd4+pY+dVy1Dwmp85pBrgr6YRRDYRBu9Gb+D73f4Bl2EukZSj5hInq2Tui9o7gAQpc2k2Q==", + "version": "20.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", + "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", "dev": true, "dependencies": { "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^8.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^9.0.0" + "@octokit/plugin-rest-endpoint-methods": "^10.0.0" }, "engines": { "node": ">= 18" @@ -1456,9 +1486,9 @@ } }, "node_modules/@types/debug": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", + "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", "dev": true, "dependencies": { "@types/ms": "*" @@ -1526,10 +1556,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.6.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz", - "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==", - "dev": true + "version": "20.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.4.tgz", + "integrity": "sha512-ZVPnqU58giiCjSxjVUESDtdPk4QR5WQhhINbc9UBrKLU68MX5BF6kbQzTrkwbolyr0X8ChBpXfavr5mZFKZQ5A==", + "dev": true, + "dependencies": { + "undici-types": "~5.25.1" + } }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -1550,9 +1583,9 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.4.tgz", - "integrity": "sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", + "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==", "dev": true }, "node_modules/@types/yargs": { @@ -1571,16 +1604,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz", - "integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.5.tgz", + "integrity": "sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.2", - "@typescript-eslint/type-utils": "6.7.2", - "@typescript-eslint/utils": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/type-utils": "6.7.5", + "@typescript-eslint/utils": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1606,13 +1639,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", - "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1623,9 +1656,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", - "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1636,13 +1669,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", - "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1663,17 +1696,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", - "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", + "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.2", - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", "semver": "^7.5.4" }, "engines": { @@ -1688,12 +1721,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", - "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/types": "6.7.5", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1705,15 +1738,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz", - "integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.5.tgz", + "integrity": "sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.7.2", - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/typescript-estree": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4" }, "engines": { @@ -1733,13 +1766,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", - "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1750,9 +1783,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", - "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1763,13 +1796,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", - "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1790,12 +1823,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", - "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/types": "6.7.5", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1824,13 +1857,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz", - "integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.5.tgz", + "integrity": "sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.7.2", - "@typescript-eslint/utils": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/utils": "6.7.5", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1851,13 +1884,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", - "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1868,9 +1901,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", - "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1881,13 +1914,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", - "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1908,17 +1941,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", - "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", + "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.2", - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", "semver": "^7.5.4" }, "engines": { @@ -1933,12 +1966,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", - "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/types": "6.7.5", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2927,15 +2960,15 @@ } }, "node_modules/eslint": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", - "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.49.0", + "@eslint/js": "8.51.0", "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2981,9 +3014,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.0.tgz", - "integrity": "sha512-ukVeKmMPAUA5SWjHenvyyXnirKfHKMdOsTZdn5tZx5EW05HGVQwBohigjFZGGj3zuv1cV6hc82FvWv6LdIbkgg==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.2.tgz", + "integrity": "sha512-3Nfvv3wbq2+PZlRTf2oaAWXWwbdBejFRBR2O8tAO67o+P8zno+QGbcDYaAXODlreXVg+9gvWhKKmG2rgfb8GEg==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -4747,9 +4780,9 @@ } }, "node_modules/marked": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.0.3.tgz", - "integrity": "sha512-pI/k4nzBG1PEq1J3XFEHxVvjicfjl8rgaMaqclouGSMPhk7Q3Ejb2ZRxx/ZQOcQ1909HzVoWCFYq6oLgtL4BpQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.0.tgz", + "integrity": "sha512-VZjm0PM5DMv7WodqOUps3g6Q7dmxs9YGiFUZ7a2majzQTTCgX+6S6NAJHPvOhgFBzYz8s4QZKWWMfZKFmsfOgA==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -6368,6 +6401,12 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "dev": true + }, "node_modules/unique-string": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", @@ -7151,9 +7190,9 @@ } }, "@eslint/js": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", - "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", "dev": true }, "@humanwhocodes/config-array": { @@ -7611,12 +7650,29 @@ "dev": true }, "@octokit/plugin-paginate-rest": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-8.0.0.tgz", - "integrity": "sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", + "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", "dev": true, "requires": { - "@octokit/types": "^11.0.0" + "@octokit/types": "^12.0.0" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", + "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "dev": true + }, + "@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dev": true, + "requires": { + "@octokit/openapi-types": "^19.0.0" + } + } } }, "@octokit/plugin-request-log": { @@ -7627,12 +7683,29 @@ "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-9.0.0.tgz", - "integrity": "sha512-KquMF/VB1IkKNiVnzJKspY5mFgGyLd7HzdJfVEGTJFzqu9BRFNWt+nwTCMuUiWc72gLQhRWYubTwOkQj+w/1PA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", + "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", "dev": true, "requires": { - "@octokit/types": "^11.0.0" + "@octokit/types": "^12.0.0" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", + "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "dev": true + }, + "@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dev": true, + "requires": { + "@octokit/openapi-types": "^19.0.0" + } + } } }, "@octokit/request": { @@ -7660,15 +7733,15 @@ } }, "@octokit/rest": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.1.tgz", - "integrity": "sha512-wROV21RwHQIMNb2Dgd4+pY+dVy1Dwmp85pBrgr6YRRDYRBu9Gb+D73f4Bl2EukZSj5hInq2Tui9o7gAQpc2k2Q==", + "version": "20.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", + "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", "dev": true, "requires": { "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^8.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^9.0.0" + "@octokit/plugin-rest-endpoint-methods": "^10.0.0" } }, "@octokit/types": { @@ -7752,9 +7825,9 @@ } }, "@types/debug": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", + "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", "dev": true, "requires": { "@types/ms": "*" @@ -7822,10 +7895,13 @@ "dev": true }, "@types/node": { - "version": "20.6.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz", - "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==", - "dev": true + "version": "20.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.4.tgz", + "integrity": "sha512-ZVPnqU58giiCjSxjVUESDtdPk4QR5WQhhINbc9UBrKLU68MX5BF6kbQzTrkwbolyr0X8ChBpXfavr5mZFKZQ5A==", + "dev": true, + "requires": { + "undici-types": "~5.25.1" + } }, "@types/normalize-package-data": { "version": "2.4.1", @@ -7846,9 +7922,9 @@ "dev": true }, "@types/uuid": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.4.tgz", - "integrity": "sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", + "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==", "dev": true }, "@types/yargs": { @@ -7867,16 +7943,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz", - "integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.5.tgz", + "integrity": "sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.2", - "@typescript-eslint/type-utils": "6.7.2", - "@typescript-eslint/utils": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/type-utils": "6.7.5", + "@typescript-eslint/utils": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7886,29 +7962,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", - "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" } }, "@typescript-eslint/types": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", - "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", - "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7917,69 +7993,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", - "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", + "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.2", - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", - "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/types": "6.7.5", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz", - "integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.5.tgz", + "integrity": "sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.7.2", - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/typescript-estree": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", - "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" } }, "@typescript-eslint/types": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", - "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", - "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7988,12 +8064,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", - "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/types": "6.7.5", "eslint-visitor-keys": "^3.4.1" } } @@ -8010,41 +8086,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz", - "integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.5.tgz", + "integrity": "sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.7.2", - "@typescript-eslint/utils": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/utils": "6.7.5", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", - "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" } }, "@typescript-eslint/types": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", - "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", - "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/visitor-keys": "6.7.2", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8053,27 +8129,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", - "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", + "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.2", - "@typescript-eslint/types": "6.7.2", - "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", - "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/types": "6.7.5", "eslint-visitor-keys": "^3.4.1" } } @@ -8762,15 +8838,15 @@ "dev": true }, "eslint": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", - "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.49.0", + "@eslint/js": "8.51.0", "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -8825,9 +8901,9 @@ } }, "eslint-plugin-jest": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.0.tgz", - "integrity": "sha512-ukVeKmMPAUA5SWjHenvyyXnirKfHKMdOsTZdn5tZx5EW05HGVQwBohigjFZGGj3zuv1cV6hc82FvWv6LdIbkgg==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.2.tgz", + "integrity": "sha512-3Nfvv3wbq2+PZlRTf2oaAWXWwbdBejFRBR2O8tAO67o+P8zno+QGbcDYaAXODlreXVg+9gvWhKKmG2rgfb8GEg==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" @@ -10087,9 +10163,9 @@ "dev": true }, "marked": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.0.3.tgz", - "integrity": "sha512-pI/k4nzBG1PEq1J3XFEHxVvjicfjl8rgaMaqclouGSMPhk7Q3Ejb2ZRxx/ZQOcQ1909HzVoWCFYq6oLgtL4BpQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.0.tgz", + "integrity": "sha512-VZjm0PM5DMv7WodqOUps3g6Q7dmxs9YGiFUZ7a2majzQTTCgX+6S6NAJHPvOhgFBzYz8s4QZKWWMfZKFmsfOgA==", "dev": true }, "meow": { @@ -11175,6 +11251,12 @@ "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true }, + "undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "dev": true + }, "unique-string": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", diff --git a/package.json b/package.json index 9f9c7e98b7..ba78a43b46 100644 --- a/package.json +++ b/package.json @@ -95,17 +95,17 @@ "uuid": "^9.0.1" }, "devDependencies": { - "@octokit/rest": "^20.0.1", - "@types/debug": "^4.1.8", + "@octokit/rest": "^20.0.2", + "@types/debug": "^4.1.9", "@types/jest": "^29.5.5", - "@types/node": "^20.6.3", - "@types/uuid": "^9.0.4", - "@typescript-eslint/eslint-plugin": "^6.7.2", - "@typescript-eslint/parser": "^6.7.2", - "eslint": "^8.49.0", - "eslint-plugin-jest": "^27.4.0", + "@types/node": "^20.8.4", + "@types/uuid": "^9.0.5", + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", + "eslint": "^8.51.0", + "eslint-plugin-jest": "^27.4.2", "jest": "^29.7.0", - "marked": "^9.0.3", + "marked": "^9.1.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From bd3e5c4ec101c61f6f5100561c3d9b572971e1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 16 Oct 2023 17:55:44 +0200 Subject: [PATCH 163/525] CI: Use Node.js version 20 (#1177) CI: Use Node.js version 20 --- .github/workflows/codeql.yml | 3 +++ .github/workflows/mediasoup-node.yaml | 4 ++-- .github/workflows/mediasoup-worker.yaml | 2 +- CHANGELOG.md | 5 +++++ worker/Dockerfile | 15 ++++++++++++--- 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9ec056a646..b26646fd42 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -36,6 +36,9 @@ jobs: # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + env: + MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: "true" + steps: - name: Checkout repository uses: actions/checkout@v3 diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 1baa7301f0..401e8def2a 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -18,9 +18,9 @@ jobs: - os: ubuntu-22.04 node: 20 - os: macos-12 - node: 18 + node: 20 - os: windows-2022 - node: 18 + node: 20 runs-on: ${{ matrix.ci.os }} diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 5e1ad512c8..f65fdef77c 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -37,7 +37,7 @@ jobs: cxx: cl # A single Node.js version should be fine for C++. node: - - 18 + - 20 runs-on: ${{ matrix.build.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 02ea1d2922..b5f49e6839 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* CI: Use Node.js version 20 ([PR #1177](https://github.com/versatica/mediasoup/pull/1177)). + + ### 3.12.13 * Bump up Meson from 1.1.0 to 1.2.1 (fixes Xcode 15 build issues) ([PR #1163](https://github.com/versatica/mediasoup/pull/1163) by @arcinston). diff --git a/worker/Dockerfile b/worker/Dockerfile index 06075a7e75..79afad2747 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -11,9 +11,18 @@ RUN \ libdbus-1-dev libboost-dev autoconf-archive bash-completion python3-yaml \ clang -# Install node 16. -RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - -RUN apt-get install -y nodejs +# Install node 20. + RUN set -x \ + && apt-get update \ + && apt-get install --yes ca-certificates curl gnupg \ + && mkdir -p /etc/apt/keyrings \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ + | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ + && NODE_MAJOR=20 \ + && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \ + > /etc/apt/sources.list.d/nodesource.list \ + && apt-get update \ + && apt-get install nodejs --yes # Make CC and CXX point to clang/clang++ installed above. ENV LANG="C.UTF-8" From d83ebafffb81bbea3e54f1467d103efe3c0760a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 12:10:39 +0200 Subject: [PATCH 164/525] Bump @babel/traverse from 7.20.1 to 7.23.2 (#1178) Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.20.1 to 7.23.2. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse) --- updated-dependencies: - dependency-name: "@babel/traverse" dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 366 ++++++++++++++++++++++++++++++---------------- 1 file changed, 242 insertions(+), 124 deletions(-) diff --git a/package-lock.json b/package-lock.json index 67afac7486..226bc2e4c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,17 +66,80 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.20.1", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.1.tgz", @@ -132,13 +195,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.4.tgz", - "integrity": "sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "dependencies": { - "@babel/types": "^7.20.2", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -187,34 +251,34 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -273,30 +337,30 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" @@ -326,13 +390,13 @@ } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -402,9 +466,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz", - "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -591,33 +655,33 @@ } }, "node_modules/@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.1.tgz", - "integrity": "sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.1", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.1", - "@babel/types": "^7.20.0", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -635,13 +699,13 @@ } }, "node_modules/@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -6710,12 +6774,65 @@ } }, "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "requires": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@babel/compat-data": { @@ -6762,13 +6879,14 @@ } }, "@babel/generator": { - "version": "7.20.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.4.tgz", - "integrity": "sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "requires": { - "@babel/types": "^7.20.2", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "dependencies": { @@ -6806,28 +6924,28 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true }, "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-module-imports": { @@ -6871,24 +6989,24 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true }, "@babel/helper-validator-option": { @@ -6909,13 +7027,13 @@ } }, "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "dependencies": { @@ -6972,9 +7090,9 @@ } }, "@babel/parser": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz", - "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -7104,30 +7222,30 @@ } }, "@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, "@babel/traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.1.tgz", - "integrity": "sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.1", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.1", - "@babel/types": "^7.20.0", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -7141,13 +7259,13 @@ } }, "@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, From ef1b6b066b3673a7aa7bbb9980df5b5eb12570f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 18 Oct 2023 12:37:14 +0200 Subject: [PATCH 165/525] Update NPM deps --- package-lock.json | 388 +++++++++++++++++++++++----------------------- package.json | 12 +- 2 files changed, 200 insertions(+), 200 deletions(-) diff --git a/package-lock.json b/package-lock.json index 226bc2e4c4..8c0b69406e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,16 +19,16 @@ }, "devDependencies": { "@octokit/rest": "^20.0.2", - "@types/debug": "^4.1.9", - "@types/jest": "^29.5.5", - "@types/node": "^20.8.4", + "@types/debug": "^4.1.10", + "@types/jest": "^29.5.6", + "@types/node": "^20.8.7", "@types/uuid": "^9.0.5", - "@typescript-eslint/eslint-plugin": "^6.7.5", - "@typescript-eslint/parser": "^6.7.5", + "@typescript-eslint/eslint-plugin": "^6.8.0", + "@typescript-eslint/parser": "^6.8.0", "eslint": "^8.51.0", "eslint-plugin-jest": "^27.4.2", "jest": "^29.7.0", - "marked": "^9.1.0", + "marked": "^9.1.2", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -1550,9 +1550,9 @@ } }, "node_modules/@types/debug": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", - "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.10.tgz", + "integrity": "sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==", "dev": true, "dependencies": { "@types/ms": "*" @@ -1592,9 +1592,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.5", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", - "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", + "version": "29.5.6", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", + "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1620,9 +1620,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.4.tgz", - "integrity": "sha512-ZVPnqU58giiCjSxjVUESDtdPk4QR5WQhhINbc9UBrKLU68MX5BF6kbQzTrkwbolyr0X8ChBpXfavr5mZFKZQ5A==", + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", "dev": true, "dependencies": { "undici-types": "~5.25.1" @@ -1668,16 +1668,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.5.tgz", - "integrity": "sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", + "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.5", - "@typescript-eslint/type-utils": "6.7.5", - "@typescript-eslint/utils": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/type-utils": "6.8.0", + "@typescript-eslint/utils": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1703,13 +1703,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", - "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", + "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5" + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1720,9 +1720,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", - "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", + "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1733,13 +1733,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", - "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", + "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1760,17 +1760,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", - "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", + "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.5", - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", "semver": "^7.5.4" }, "engines": { @@ -1785,12 +1785,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", - "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", + "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/types": "6.8.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1802,15 +1802,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.5.tgz", - "integrity": "sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", + "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.7.5", - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/typescript-estree": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4" }, "engines": { @@ -1830,13 +1830,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", - "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", + "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5" + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1847,9 +1847,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", - "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", + "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1860,13 +1860,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", - "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", + "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1887,12 +1887,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", - "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", + "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/types": "6.8.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1921,13 +1921,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.5.tgz", - "integrity": "sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", + "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.7.5", - "@typescript-eslint/utils": "6.7.5", + "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/utils": "6.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1948,13 +1948,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", - "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", + "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5" + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1965,9 +1965,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", - "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", + "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1978,13 +1978,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", - "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", + "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2005,17 +2005,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", - "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", + "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.5", - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", "semver": "^7.5.4" }, "engines": { @@ -2030,12 +2030,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", - "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", + "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/types": "6.8.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4844,9 +4844,9 @@ } }, "node_modules/marked": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.0.tgz", - "integrity": "sha512-VZjm0PM5DMv7WodqOUps3g6Q7dmxs9YGiFUZ7a2majzQTTCgX+6S6NAJHPvOhgFBzYz8s4QZKWWMfZKFmsfOgA==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.2.tgz", + "integrity": "sha512-qoKMJqK0w6vkLk8+KnKZAH6neUZSNaQqVZ/h2yZ9S7CbLuFHyS2viB0jnqcWF9UKjwsAbMrQtnQhdmdvOVOw9w==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -7943,9 +7943,9 @@ } }, "@types/debug": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", - "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.10.tgz", + "integrity": "sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==", "dev": true, "requires": { "@types/ms": "*" @@ -7985,9 +7985,9 @@ } }, "@types/jest": { - "version": "29.5.5", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", - "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", + "version": "29.5.6", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", + "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", "dev": true, "requires": { "expect": "^29.0.0", @@ -8013,9 +8013,9 @@ "dev": true }, "@types/node": { - "version": "20.8.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.4.tgz", - "integrity": "sha512-ZVPnqU58giiCjSxjVUESDtdPk4QR5WQhhINbc9UBrKLU68MX5BF6kbQzTrkwbolyr0X8ChBpXfavr5mZFKZQ5A==", + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", "dev": true, "requires": { "undici-types": "~5.25.1" @@ -8061,16 +8061,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.5.tgz", - "integrity": "sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", + "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.5", - "@typescript-eslint/type-utils": "6.7.5", - "@typescript-eslint/utils": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/type-utils": "6.8.0", + "@typescript-eslint/utils": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8080,29 +8080,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", - "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", + "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5" + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0" } }, "@typescript-eslint/types": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", - "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", + "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", - "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", + "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8111,69 +8111,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", - "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", + "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.5", - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", - "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", + "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/types": "6.8.0", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.5.tgz", - "integrity": "sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", + "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.7.5", - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/typescript-estree": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", - "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", + "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5" + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0" } }, "@typescript-eslint/types": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", - "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", + "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", - "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", + "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8182,12 +8182,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", - "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", + "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/types": "6.8.0", "eslint-visitor-keys": "^3.4.1" } } @@ -8204,41 +8204,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.5.tgz", - "integrity": "sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", + "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.7.5", - "@typescript-eslint/utils": "6.7.5", + "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/utils": "6.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", - "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", + "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5" + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0" } }, "@typescript-eslint/types": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", - "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", + "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", - "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", + "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/visitor-keys": "6.7.5", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8247,27 +8247,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", - "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", + "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.5", - "@typescript-eslint/types": "6.7.5", - "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", - "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", + "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/types": "6.8.0", "eslint-visitor-keys": "^3.4.1" } } @@ -10281,9 +10281,9 @@ "dev": true }, "marked": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.0.tgz", - "integrity": "sha512-VZjm0PM5DMv7WodqOUps3g6Q7dmxs9YGiFUZ7a2majzQTTCgX+6S6NAJHPvOhgFBzYz8s4QZKWWMfZKFmsfOgA==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.2.tgz", + "integrity": "sha512-qoKMJqK0w6vkLk8+KnKZAH6neUZSNaQqVZ/h2yZ9S7CbLuFHyS2viB0jnqcWF9UKjwsAbMrQtnQhdmdvOVOw9w==", "dev": true }, "meow": { diff --git a/package.json b/package.json index ba78a43b46..beccc9fa2e 100644 --- a/package.json +++ b/package.json @@ -96,16 +96,16 @@ }, "devDependencies": { "@octokit/rest": "^20.0.2", - "@types/debug": "^4.1.9", - "@types/jest": "^29.5.5", - "@types/node": "^20.8.4", + "@types/debug": "^4.1.10", + "@types/jest": "^29.5.6", + "@types/node": "^20.8.7", "@types/uuid": "^9.0.5", - "@typescript-eslint/eslint-plugin": "^6.7.5", - "@typescript-eslint/parser": "^6.7.5", + "@typescript-eslint/eslint-plugin": "^6.8.0", + "@typescript-eslint/parser": "^6.8.0", "eslint": "^8.51.0", "eslint-plugin-jest": "^27.4.2", "jest": "^29.7.0", - "marked": "^9.1.0", + "marked": "^9.1.2", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From acf7a56b310a1e42036b4a64d9036c2ebb8f22dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 19 Oct 2023 16:45:36 +0200 Subject: [PATCH 166/525] Use given PYTHON env variable (if given) when running worker/scripts/getmake.py (#1186) --- CHANGELOG.md | 1 + npm-scripts.mjs | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5f49e6839..cde1b12781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### NEXT * CI: Use Node.js version 20 ([PR #1177](https://github.com/versatica/mediasoup/pull/1177)). +* Use given `PYTHON` environment variable (if given) when running `worker/scripts/getmake.py` ([PR #1186](https://github.com/versatica/mediasoup/pull/1186)). ### 3.12.13 diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 433d309d1b..7ca9942e75 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -418,21 +418,34 @@ function installMsysMake() { logInfo('installMsysMake()'); - let res = spawnSync('where', [ 'python3.exe' ]); + let pythonPath; - if (res.status !== 0) + // If PYTHON environment variable is given, use it. + if (process.env.PYTHON) { - res = spawnSync('where', [ 'python.exe' ]); + pythonPath = process.env.PYTHON; + } + // Otherwise ensure python3.exe is available in the PATH. + else + { + let res = spawnSync('where', [ 'python3.exe' ]); if (res.status !== 0) { - logError('`installMsysMake() | cannot find Python executable'); + res = spawnSync('where', [ 'python.exe' ]); - exitWithError(); + if (res.status !== 0) + { + logError('`installMsysMake() | cannot find Python executable'); + + exitWithError(); + } } + + pythonPath = String(res.stdout).trim(); } - executeCmd(`${String(res.stdout).trim()} worker\\scripts\\getmake.py`); + executeCmd(`${pythonPath} worker\\scripts\\getmake.py`); } function ensureDir(dir) From e782b794ff9c4404e743bbf746652b04ef7b541e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 19 Oct 2023 16:50:15 +0200 Subject: [PATCH 167/525] 3.12.14 --- CHANGELOG.md | 2 +- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cde1b12781..e89ef10020 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.12.14 * CI: Use Node.js version 20 ([PR #1177](https://github.com/versatica/mediasoup/pull/1177)). * Use given `PYTHON` environment variable (if given) when running `worker/scripts/getmake.py` ([PR #1186](https://github.com/versatica/mediasoup/pull/1186)). diff --git a/package-lock.json b/package-lock.json index 8c0b69406e..a7a1ab5989 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.13", + "version": "3.12.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.13", + "version": "3.12.14", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -22,7 +22,7 @@ "@types/debug": "^4.1.10", "@types/jest": "^29.5.6", "@types/node": "^20.8.7", - "@types/uuid": "^9.0.5", + "@types/uuid": "^9.0.6", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", "eslint": "^8.51.0", @@ -1647,9 +1647,9 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", - "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", + "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==", "dev": true }, "node_modules/@types/yargs": { @@ -8040,9 +8040,9 @@ "dev": true }, "@types/uuid": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", - "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", + "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==", "dev": true }, "@types/yargs": { diff --git a/package.json b/package.json index beccc9fa2e..17b6b4c303 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.13", + "version": "3.12.14", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -99,7 +99,7 @@ "@types/debug": "^4.1.10", "@types/jest": "^29.5.6", "@types/node": "^20.8.7", - "@types/uuid": "^9.0.5", + "@types/uuid": "^9.0.6", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", "eslint": "^8.51.0", From a3b13cc703b115e9e56ac49ab49d8852c43d766b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 20 Oct 2023 17:19:39 +0200 Subject: [PATCH 168/525] Fix NPM 'postinstall' task in Windows (#1187) --- npm-scripts.mjs | 4 +++- worker/build.rs | 28 +++++++++++++++++++++++----- worker/scripts/getmake.py | 15 +++++++++++++-- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 7ca9942e75..2089a6379e 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -445,7 +445,9 @@ function installMsysMake() pythonPath = String(res.stdout).trim(); } - executeCmd(`${pythonPath} worker\\scripts\\getmake.py`); + const dir = path.resolve('worker/out/msys'); + + executeCmd(`${pythonPath} worker\\scripts\\getmake.py --dir="${dir}"`); } function ensureDir(dir) diff --git a/worker/build.rs b/worker/build.rs index 7d2264bfaf..2caf96525b 100644 --- a/worker/build.rs +++ b/worker/build.rs @@ -16,9 +16,15 @@ fn main() { }; let out_dir = env::var("OUT_DIR").unwrap(); - // Force forward slashes on Windows too so that is plays well with our dumb `Makefile` + // Force forward slashes on Windows too so that is plays well with our dumb `Makefile`. let mediasoup_out_dir = format!("{}/out", out_dir.replace('\\', "/")); + // Store original PATH so we make `make clean-all` use it. This is because, in Windows, + // we may need to fetch `make` and we store it in out/msys and then we add out/msys/bin + // to the PATH, and that folder may contain rm.exe, so `make clean-all` would use + // that rm.exe and delete itself and make the task fail. + let original_path = env::var("PATH").unwrap(); + // Add C++ std lib #[cfg(target_os = "linux")] { @@ -78,25 +84,36 @@ fn main() { #[cfg(target_os = "windows")] { if !std::path::Path::new("worker/out/msys/bin/make.exe").exists() { - let python = if Command::new("where") - .arg("python3.exe") + let python = if let Ok(python) = env::var("PYTHON") { + python + } else if Command::new("where") + .arg("python3") .status() .expect("Failed to start") .success() { - "python3" + "python3".to_string() } else { - "python" + "python".to_string() }; + let dir = format!("{}/msys", mediasoup_out_dir.replace('\\', "/")); + if !Command::new(python) .arg("scripts\\getmake.py") + .arg("--dir") + .arg(dir.clone()) .status() .expect("Failed to start") .success() { panic!("Failed to install MSYS/make") } + + env::set_var( + "PATH", + format!("{}\\bin;{}", dir, env::var("PATH").unwrap()), + ); } env::set_var( @@ -161,6 +178,7 @@ fn main() { // Clean if !Command::new("make") .arg("clean-all") + .env("PATH", original_path) .env("MEDIASOUP_OUT_DIR", &mediasoup_out_dir) .spawn() .expect("Failed to start") diff --git a/worker/scripts/getmake.py b/worker/scripts/getmake.py index c6c0dbb9a3..50ec9ea7f1 100644 --- a/worker/scripts/getmake.py +++ b/worker/scripts/getmake.py @@ -1,10 +1,21 @@ -import io, hashlib, tarfile, urllib.request +import argparse, io, hashlib, tarfile, urllib.request + +argParser = argparse.ArgumentParser() + +argParser.add_argument( + '--dir', + type=str, + required=True, + help='absolute path of the directoy in which fetched content will be placed' +) + +args = argParser.parse_args() def get(url, digest): data = urllib.request.urlopen(url).read() assert hashlib.sha256(data).hexdigest() == digest tar = tarfile.open(fileobj=io.BytesIO(data)) - tar.extractall('worker/out/msys') + tar.extractall(args.dir) tar.close() get('https://sourceforge.net/projects/mingw/files/MSYS/Base/msys-core/msys-1.0.19-1/msysCORE-1.0.19-1-msys-1.0.19-bin.tar.xz/download', '8c4157d739a460f85563bc4451e9f1bbd42b13c4f63770d43b9f45a781f07858') From f8bc8ea7009122ceec025d99a5cdf4de984da0b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 20 Oct 2023 17:24:55 +0200 Subject: [PATCH 169/525] 3.12.15 --- CHANGELOG.md | 5 +++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e89ef10020..fa51a3c085 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.12.15 + +* Fix NPM "postinstall" task in Windows ([PR #1187](https://github.com/versatica/mediasoup/pull/1187)). + + ### 3.12.14 * CI: Use Node.js version 20 ([PR #1177](https://github.com/versatica/mediasoup/pull/1177)). diff --git a/package-lock.json b/package-lock.json index a7a1ab5989..a7b34424ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.14", + "version": "3.12.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.14", + "version": "3.12.15", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 17b6b4c303..364a425fd8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.14", + "version": "3.12.15", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 80d668f66951645b251936c78410fe02d87854b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 23 Oct 2023 09:41:10 +0200 Subject: [PATCH 170/525] Update NPM eslint deps --- package-lock.json | 90 +++++++++++++++++++++++++++-------------------- package.json | 4 +-- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/package-lock.json b/package-lock.json index a7b34424ac..5001aad936 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,8 +25,8 @@ "@types/uuid": "^9.0.6", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", - "eslint": "^8.51.0", - "eslint-plugin-jest": "^27.4.2", + "eslint": "^8.52.0", + "eslint-plugin-jest": "^27.4.3", "jest": "^29.7.0", "marked": "^9.1.2", "open-cli": "^7.2.0", @@ -766,21 +766,21 @@ } }, "node_modules/@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -802,9 +802,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -2129,6 +2129,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -3024,18 +3030,19 @@ } }, "node_modules/eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -3078,9 +3085,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.2.tgz", - "integrity": "sha512-3Nfvv3wbq2+PZlRTf2oaAWXWwbdBejFRBR2O8tAO67o+P8zno+QGbcDYaAXODlreXVg+9gvWhKKmG2rgfb8GEg==", + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.3.tgz", + "integrity": "sha512-7S6SmmsHsgIm06BAGCAxL+ABd9/IB3MWkz2pudj6Qqor2y1qQpWPfuFU4SG9pWj4xDjF0e+D7Llh5useuSzAZw==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -7308,18 +7315,18 @@ } }, "@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", "dev": true }, "@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" } @@ -7331,9 +7338,9 @@ "dev": true }, "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "@istanbuljs/load-nyc-config": { @@ -8320,6 +8327,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -8956,18 +8969,19 @@ "dev": true }, "eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -9019,9 +9033,9 @@ } }, "eslint-plugin-jest": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.2.tgz", - "integrity": "sha512-3Nfvv3wbq2+PZlRTf2oaAWXWwbdBejFRBR2O8tAO67o+P8zno+QGbcDYaAXODlreXVg+9gvWhKKmG2rgfb8GEg==", + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.3.tgz", + "integrity": "sha512-7S6SmmsHsgIm06BAGCAxL+ABd9/IB3MWkz2pudj6Qqor2y1qQpWPfuFU4SG9pWj4xDjF0e+D7Llh5useuSzAZw==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" diff --git a/package.json b/package.json index 364a425fd8..0b69321485 100644 --- a/package.json +++ b/package.json @@ -102,8 +102,8 @@ "@types/uuid": "^9.0.6", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", - "eslint": "^8.51.0", - "eslint-plugin-jest": "^27.4.2", + "eslint": "^8.52.0", + "eslint-plugin-jest": "^27.4.3", "jest": "^29.7.0", "marked": "^9.1.2", "open-cli": "^7.2.0", From b66673c66997e657ddd55a66dbf7a4132d70110c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 23 Oct 2023 09:47:52 +0200 Subject: [PATCH 171/525] Fix IceServer crash when client uses ICE renomination (#1182) --- CHANGELOG.md | 5 ++ worker/include/RTC/IceServer.hpp | 10 ++- worker/src/RTC/IceServer.cpp | 115 +++++++++++++++++++---------- worker/src/RTC/WebRtcTransport.cpp | 4 +- 4 files changed, 88 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa51a3c085..a9a9ff4a50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +* Fix `IceServer` crash when client uses ICE renomination ([PR #1182](https://github.com/versatica/mediasoup/pull/1182)). + + ### 3.12.15 * Fix NPM "postinstall" task in Windows ([PR #1187](https://github.com/versatica/mediasoup/pull/1187)). diff --git a/worker/include/RTC/IceServer.hpp b/worker/include/RTC/IceServer.hpp index 51fa85919d..b213189ff5 100644 --- a/worker/include/RTC/IceServer.hpp +++ b/worker/include/RTC/IceServer.hpp @@ -93,9 +93,11 @@ namespace RTC } bool IsValidTuple(const RTC::TransportTuple* tuple) const; void RemoveTuple(RTC::TransportTuple* tuple); - // This should be just called in 'connected' or completed' state - // and the given tuple must be an already valid tuple. - void ForceSelectedTuple(const RTC::TransportTuple* tuple); + /** + * This should be just called in 'connected' or 'completed' state and the + * given tuple must be an already valid tuple. + */ + void MayForceSelectedTuple(const RTC::TransportTuple* tuple); private: void HandleTuple( @@ -122,8 +124,8 @@ namespace RTC std::string password; std::string oldUsernameFragment; std::string oldPassword; - uint32_t remoteNomination{ 0u }; IceState state{ IceState::NEW }; + uint32_t remoteNomination{ 0u }; std::list tuples; RTC::TransportTuple* selectedTuple{ nullptr }; }; diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index fde3d25a1b..4cf1a6a924 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -220,9 +220,13 @@ namespace RTC // Authenticate the response. if (this->oldPassword.empty()) + { response->Authenticate(this->password); + } else + { response->Authenticate(this->oldPassword); + } // Send back. response->Serialize(StunSerializeBuffer); @@ -233,7 +237,9 @@ namespace RTC uint32_t nomination{ 0u }; if (packet->HasNomination()) + { nomination = packet->GetNomination(); + } // Handle the tuple. HandleTuple(tuple, packet->HasUseCandidate(), packet->HasNomination(), nomination); @@ -294,7 +300,9 @@ namespace RTC // If not found, ignore. if (!removedTuple) + { return; + } // Notify the listener. this->listener->OnIceServerTupleRemoved(this, removedTuple); @@ -319,24 +327,35 @@ namespace RTC { // Update state. this->state = IceState::DISCONNECTED; + + // Reset remote nomination. + this->remoteNomination = 0u; + // Notify the listener. this->listener->OnIceServerDisconnected(this); } } } - void IceServer::ForceSelectedTuple(const RTC::TransportTuple* tuple) + void IceServer::MayForceSelectedTuple(const RTC::TransportTuple* tuple) { MS_TRACE(); - MS_ASSERT( - this->selectedTuple, "cannot force the selected tuple if there was not a selected tuple"); + if (this->state != IceState::CONNECTED && this->state != IceState::COMPLETED) + { + MS_WARN_TAG(ice, "cannot force selected tuple if not in state 'connected' or 'completed'"); + + return; + } auto* storedTuple = HasTuple(tuple); - MS_ASSERT( - storedTuple, - "cannot force the selected tuple if the given tuple was not already a valid tuple"); + if (!storedTuple) + { + MS_WARN_TAG(ice, "cannot force selected tuple if the given tuple was not already a valid one"); + + return; + } // Mark it as selected tuple. SetSelectedTuple(storedTuple); @@ -351,10 +370,6 @@ namespace RTC { case IceState::NEW: { - // There should be no tuples. - MS_ASSERT( - this->tuples.empty(), "state is 'new' but there are %zu tuples", this->tuples.size()); - // There shouldn't be a selected tuple. MS_ASSERT(!this->selectedTuple, "state is 'new' but there is selected tuple"); @@ -373,8 +388,10 @@ namespace RTC // Mark it as selected tuple. SetSelectedTuple(storedTuple); + // Update state. this->state = IceState::CONNECTED; + // Notify the listener. this->listener->OnIceServerConnected(this); } @@ -395,11 +412,16 @@ namespace RTC // Mark it as selected tuple. SetSelectedTuple(storedTuple); + // Update state. this->state = IceState::COMPLETED; + // Update nomination. if (hasNomination && nomination > this->remoteNomination) + { this->remoteNomination = nomination; + } + // Notify the listener. this->listener->OnIceServerCompleted(this); } @@ -410,12 +432,6 @@ namespace RTC case IceState::DISCONNECTED: { - // There should be no tuples. - MS_ASSERT( - this->tuples.empty(), - "state is 'disconnected' but there are %zu tuples", - this->tuples.size()); - // There shouldn't be a selected tuple. MS_ASSERT(!this->selectedTuple, "state is 'disconnected' but there is selected tuple"); @@ -434,8 +450,10 @@ namespace RTC // Mark it as selected tuple. SetSelectedTuple(storedTuple); + // Update state. this->state = IceState::CONNECTED; + // Notify the listener. this->listener->OnIceServerConnected(this); } @@ -456,11 +474,16 @@ namespace RTC // Mark it as selected tuple. SetSelectedTuple(storedTuple); + // Update state. this->state = IceState::COMPLETED; + // Update nomination. if (hasNomination && nomination > this->remoteNomination) + { this->remoteNomination = nomination; + } + // Notify the listener. this->listener->OnIceServerCompleted(this); } @@ -479,9 +502,8 @@ namespace RTC if (!hasUseCandidate && !hasNomination) { - // If a new tuple store it. - if (!HasTuple(tuple)) - AddTuple(tuple); + // Store the tuple. + AddTuple(tuple); } else { @@ -493,21 +515,23 @@ namespace RTC hasNomination ? "true" : "false", nomination); - auto* storedTuple = HasTuple(tuple); - - // If a new tuple store it. - if (!storedTuple) - storedTuple = AddTuple(tuple); + // Store the tuple. + auto* storedTuple = AddTuple(tuple); if ((hasNomination && nomination > this->remoteNomination) || !hasNomination) { // Mark it as selected tuple. SetSelectedTuple(storedTuple); + // Update state. this->state = IceState::COMPLETED; + // Update nomination. if (hasNomination && nomination > this->remoteNomination) + { this->remoteNomination = nomination; + } + // Notify the listener. this->listener->OnIceServerCompleted(this); } @@ -526,25 +550,24 @@ namespace RTC if (!hasUseCandidate && !hasNomination) { - // If a new tuple store it. - if (!HasTuple(tuple)) - AddTuple(tuple); + // Store the tuple. + AddTuple(tuple); } else { - auto* storedTuple = HasTuple(tuple); - - // If a new tuple store it. - if (!storedTuple) - storedTuple = AddTuple(tuple); + // Store the tuple. + auto* storedTuple = AddTuple(tuple); if ((hasNomination && nomination > this->remoteNomination) || !hasNomination) { // Mark it as selected tuple. SetSelectedTuple(storedTuple); + // Update nomination. if (hasNomination && nomination > this->remoteNomination) + { this->remoteNomination = nomination; + } } } @@ -557,15 +580,26 @@ namespace RTC { MS_TRACE(); + auto* storedTuple = HasTuple(tuple); + + if (storedTuple) + { + MS_DEBUG_DEV('tuple already exists'); + + return storedTuple; + } + // Add the new tuple at the beginning of the list. this->tuples.push_front(*tuple); - auto* storedTuple = std::addressof(*this->tuples.begin()); + storedTuple = std::addressof(*this->tuples.begin()); // If it is UDP then we must store the remote address (until now it is // just a pointer that will be freed soon). if (storedTuple->GetProtocol() == TransportTuple::Protocol::UDP) + { storedTuple->StoreUdpRemoteAddress(); + } // Notify the listener. this->listener->OnIceServerTupleAdded(this, storedTuple); @@ -614,14 +648,11 @@ namespace RTC { MS_TRACE(); - // If there is no selected tuple yet then we know that the tuples list - // is empty. - if (!this->selectedTuple) - return nullptr; - - // Check the current selected tuple. - if (this->selectedTuple->Compare(tuple)) + // Check the current selected tuple (if any). + if (this->selectedTuple && this->selectedTuple->Compare(tuple)) + { return this->selectedTuple; + } // Otherwise check other stored tuples. for (const auto& it : this->tuples) @@ -629,7 +660,9 @@ namespace RTC auto* storedTuple = const_cast(std::addressof(it)); if (storedTuple->Compare(tuple)) + { return storedTuple; + } } return nullptr; @@ -641,7 +674,9 @@ namespace RTC // If already the selected tuple do nothing. if (storedTuple == this->selectedTuple) + { return; + } this->selectedTuple = storedTuple; diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 000b389dbb..4846006957 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -1058,7 +1058,7 @@ namespace RTC } // Trick for clients performing aggressive ICE regardless we are ICE-Lite. - this->iceServer->ForceSelectedTuple(tuple); + this->iceServer->MayForceSelectedTuple(tuple); // Check that DTLS status is 'connecting' or 'connected'. if ( @@ -1142,7 +1142,7 @@ namespace RTC } // Trick for clients performing aggressive ICE regardless we are ICE-Lite. - this->iceServer->ForceSelectedTuple(tuple); + this->iceServer->MayForceSelectedTuple(tuple); // Pass the packet to the parent transport. RTC::Transport::ReceiveRtpPacket(packet); From 43edb3acd467045fc557ad7ba1fd87c11072e24b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 23 Oct 2023 09:57:29 +0200 Subject: [PATCH 172/525] 3.12.16 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9a9ff4a50..8ae8f1d258 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.12.16 * Fix `IceServer` crash when client uses ICE renomination ([PR #1182](https://github.com/versatica/mediasoup/pull/1182)). diff --git a/package-lock.json b/package-lock.json index 5001aad936..cdc8eb48d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.15", + "version": "3.12.16", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.15", + "version": "3.12.16", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 0b69321485..4fbba54e1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.15", + "version": "3.12.16", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 0b4d4ef9f2bb0b9d117e48f707c970d406ee5022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 27 Oct 2023 13:43:53 +0200 Subject: [PATCH 173/525] Update mediasoup-rust versions (#1200) --- rust/CHANGELOG.md | 6 +++++- rust/Cargo.toml | 4 ++-- worker/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index 2e5fb0a19b..4b536cd586 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,12 +1,16 @@ # Changelog +# 0.12.0 + +* Updates from mediasoup TypeScript `3.11.9..=3.12.16`. + # 0.11.4 * Fix consuming data producer from direct transport by data consumer on non-direct transport. # 0.11.3 -* Updates from mediasoup TypeScript `3.10.13..=3.11.8`. +* Updates from mediasoup TypeScript `3.11.3..=3.11.8`. # 0.11.2 diff --git a/rust/Cargo.toml b/rust/Cargo.toml index c1042bed60..e84085947a 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup" -version = "0.11.4" +version = "0.12.0" description = "Cutting Edge WebRTC Video Conferencing in Rust" categories = ["api-bindings", "multimedia", "network-programming"] authors = ["Nazar Mokrynskyi "] @@ -45,7 +45,7 @@ version = "0.8.1" [dependencies.mediasoup-sys] path = "../worker" -version = "0.5.4" +version = "0.6.0" [dependencies.parking_lot] version = "0.12.1" diff --git a/worker/Cargo.toml b/worker/Cargo.toml index 3a58bc967b..c7b3ad6639 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup-sys" -version = "0.5.4" +version = "0.6.0" description = "FFI bindings to C++ libmediasoup-worker" authors = ["Nazar Mokrynskyi "] edition = "2021" From a7d46d816778729ff250c0d9aeae16ef5ca98682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Wed, 8 Nov 2023 11:00:08 +0100 Subject: [PATCH 174/525] flatbuffers (#1064) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flatbuffers WIP to remove JSON in favour of flatbuffers for as the worker communication format. - JSON parsing is CPU intensive. - JSON is not type safe. - flatbuffers does not parse the buffer. Reading the message takes 0ms. - flatbuffers is type safe since code (C++, Typescript, Rust, etc) is autogenerated out of the schema definitions. Extras that come along with this changes: - There is now a single Channel for worker communication. - Previously there were 2 (Channel and PayloadChannel) - Each message sent Node->Worker requires a single write() call to Channel. - Previously 2 calls per message were needed for Channel and 4 for PayloadChannel. - Each message sent Worker->Node previously executed two extra calls to memcpy that are not executed now. --------- Co-authored-by: Iñaki Baz Castillo Co-authored-by: Nazar Mokrynskyi --- .github/workflows/mediasoup-node.yaml | 6 +- .gitignore | 14 +- CHANGELOG.md | 10 + Cargo.lock | 2657 ++++++++++++ Cargo.toml | 1 + art/mediasoup-v3-architecture-01.svg | 2 +- node/.eslintignore | 1 + node/.eslintrc.js | 1 + node/src/ActiveSpeakerObserver.ts | 12 +- node/src/AudioLevelObserver.ts | 41 +- node/src/Channel.ts | 306 +- node/src/Consumer.ts | 667 ++- node/src/DataConsumer.ts | 414 +- node/src/DataProducer.ts | 227 +- node/src/DirectTransport.ts | 157 +- node/src/EnhancedEventEmitter.ts | 2 +- node/src/PayloadChannel.ts | 402 -- node/src/PipeTransport.ts | 302 +- node/src/PlainTransport.ts | 290 +- node/src/Producer.ts | 335 +- node/src/Router.ts | 690 ++- node/src/RtpObserver.ts | 61 +- node/src/RtpParameters.ts | 500 ++- node/src/RtpStream.ts | 141 + node/src/SctpParameters.ts | 63 + node/src/SrtpParameters.ts | 62 + node/src/Transport.ts | 919 +++- node/src/WebRtcServer.ts | 133 +- node/src/WebRtcTransport.ts | 497 ++- node/src/Worker.ts | 172 +- node/src/index.ts | 13 +- node/src/ortc.ts | 60 +- node/src/tests/test-ActiveSpeakerObserver.ts | 4 +- node/src/tests/test-AudioLevelObserver.ts | 4 +- node/src/tests/test-Consumer.ts | 197 +- node/src/tests/test-DataConsumer.ts | 85 +- node/src/tests/test-DataProducer.ts | 76 +- node/src/tests/test-DirectTransport.ts | 215 +- node/src/tests/test-PipeTransport.ts | 115 +- node/src/tests/test-PlainTransport.ts | 37 +- node/src/tests/test-Producer.ts | 159 +- node/src/tests/test-Router.ts | 17 +- node/src/tests/test-WebRtcServer.ts | 65 +- node/src/tests/test-WebRtcTransport.ts | 142 +- node/src/tests/test-Worker.ts | 53 +- node/src/tests/test-mediasoup.ts | 12 + node/src/tests/test-multiopus.ts | 4 +- node/src/tests/test-node-sctp.ts | 6 +- node/src/tests/test-ortc.ts | 9 +- node/src/types.ts | 10 + node/src/utils.ts | 187 +- npm-scripts.mjs | 126 +- package-lock.json | 530 ++- package.json | 27 +- rust/Cargo.toml | 6 +- rust/benches/direct_data.rs | 5 +- rust/benches/producer.rs | 286 ++ rust/examples/echo.rs | 13 +- rust/examples/multiopus.rs | 18 +- rust/examples/svc-simulcast.rs | 13 +- rust/examples/videoroom.rs | 6 +- rust/src/data_structures.rs | 337 +- rust/src/macros.rs | 14 +- rust/src/messages.rs | 3771 ++++++++++++++--- rust/src/ortc.rs | 61 +- rust/src/ortc/tests.rs | 3 - rust/src/prelude.rs | 14 +- rust/src/router.rs | 124 +- rust/src/router/active_speaker_observer.rs | 28 +- rust/src/router/audio_level_observer.rs | 39 +- rust/src/router/consumer.rs | 433 +- rust/src/router/consumer/tests.rs | 19 +- rust/src/router/data_consumer.rs | 350 +- rust/src/router/data_consumer/tests.rs | 22 +- rust/src/router/data_producer.rs | 158 +- rust/src/router/data_producer/tests.rs | 12 +- rust/src/router/direct_transport.rs | 239 +- rust/src/router/pipe_transport.rs | 220 +- rust/src/router/pipe_transport/tests.rs | 19 +- rust/src/router/plain_transport.rs | 254 +- rust/src/router/plain_transport/tests.rs | 8 +- rust/src/router/producer.rs | 342 +- rust/src/router/producer/tests.rs | 19 +- rust/src/router/transport.rs | 136 +- rust/src/router/webrtc_transport.rs | 332 +- rust/src/router/webrtc_transport/tests.rs | 82 +- rust/src/rtp_parameters.rs | 590 ++- rust/src/scalability_modes.rs | 2 +- rust/src/sctp_parameters.rs | 43 +- rust/src/srtp_parameters.rs | 37 + rust/src/webrtc_server.rs | 36 +- rust/src/webrtc_server/tests.rs | 14 +- rust/src/worker.rs | 65 +- rust/src/worker/channel.rs | 309 +- rust/src/worker/common.rs | 39 +- rust/src/worker/payload_channel.rs | 398 -- rust/src/worker/utils.rs | 33 +- rust/src/worker/utils/channel_read_fn.rs | 93 +- rust/src/worker/utils/channel_write_fn.rs | 73 +- rust/tests/integration/consumer.rs | 37 +- rust/tests/integration/data_consumer.rs | 42 +- rust/tests/integration/data_producer.rs | 79 +- rust/tests/integration/direct_transport.rs | 271 +- rust/tests/integration/multiopus.rs | 19 +- rust/tests/integration/pipe_transport.rs | 60 +- rust/tests/integration/plain_transport.rs | 96 +- rust/tests/integration/producer.rs | 33 +- rust/tests/integration/router.rs | 3 +- rust/tests/integration/smoke.rs | 23 +- rust/tests/integration/webrtc_server.rs | 119 +- rust/tests/integration/webrtc_transport.rs | 257 +- rust/tests/integration/worker.rs | 3 +- worker/.clang-format | 4 +- worker/.clang-tidy | 2 + worker/Cargo.toml | 12 + worker/Makefile | 10 +- worker/build.rs | 31 +- worker/deps/libwebrtc/meson.build | 3 +- worker/fbs/activeSpeakerObserver.fbs | 12 + worker/fbs/audioLevelObserver.fbs | 19 + worker/fbs/common.fbs | 33 + worker/fbs/consumer.fbs | 125 + worker/fbs/dataConsumer.fbs | 60 + worker/fbs/dataProducer.fbs | 34 + worker/fbs/directTransport.fbs | 22 + worker/fbs/log.fbs | 6 + worker/fbs/meson.build | 54 + worker/fbs/message.fbs | 20 + worker/fbs/notification.fbs | 83 + worker/fbs/pipeTransport.fbs | 34 + worker/fbs/plainTransport.fbs | 56 + worker/fbs/producer.fbs | 89 + worker/fbs/request.fbs | 129 + worker/fbs/response.fbs | 52 + worker/fbs/router.fbs | 60 + worker/fbs/rtpObserver.fbs | 10 + worker/fbs/rtpPacket.fbs | 21 + worker/fbs/rtpParameters.fbs | 128 + worker/fbs/rtpStream.fbs | 82 + worker/fbs/rtxStream.fbs | 16 + worker/fbs/sctpAssociation.fbs | 10 + worker/fbs/sctpParameters.fbs | 25 + worker/fbs/srtpParameters.fbs | 14 + worker/fbs/transport.fbs | 242 ++ worker/fbs/webRtcServer.fbs | 28 + worker/fbs/webRtcTransport.fbs | 137 + worker/fbs/worker.fbs | 57 + .../include/Channel/ChannelNotification.hpp | 33 + worker/include/Channel/ChannelNotifier.hpp | 47 +- worker/include/Channel/ChannelRequest.hpp | 112 +- worker/include/Channel/ChannelSocket.hpp | 30 +- worker/include/ChannelMessageRegistrator.hpp | 18 +- worker/include/DepUsrSCTP.hpp | 10 +- .../PayloadChannelNotification.hpp | 44 - .../PayloadChannel/PayloadChannelNotifier.hpp | 39 - .../PayloadChannel/PayloadChannelRequest.hpp | 57 - .../PayloadChannel/PayloadChannelSocket.hpp | 133 - worker/include/RTC/ActiveSpeakerObserver.hpp | 16 +- worker/include/RTC/AudioLevelObserver.hpp | 18 +- worker/include/RTC/Codecs/Tools.hpp | 10 - worker/include/RTC/Consumer.hpp | 21 +- worker/include/RTC/DataConsumer.hpp | 47 +- worker/include/RTC/DataProducer.hpp | 39 +- worker/include/RTC/DirectTransport.hpp | 17 +- worker/include/RTC/DtlsTransport.hpp | 55 +- worker/include/RTC/IceCandidate.hpp | 22 +- worker/include/RTC/IceServer.hpp | 7 +- worker/include/RTC/KeyFrameRequestManager.hpp | 18 +- worker/include/RTC/NackGenerator.hpp | 10 +- worker/include/RTC/Parameters.hpp | 9 +- worker/include/RTC/PipeConsumer.hpp | 15 +- worker/include/RTC/PipeTransport.hpp | 27 +- worker/include/RTC/PlainTransport.hpp | 35 +- worker/include/RTC/PortManager.hpp | 2 - worker/include/RTC/Producer.hpp | 25 +- worker/include/RTC/Router.hpp | 31 +- worker/include/RTC/RtpDictionaries.hpp | 74 +- worker/include/RTC/RtpListener.hpp | 6 +- worker/include/RTC/RtpObserver.hpp | 7 +- worker/include/RTC/RtpPacket.hpp | 8 +- worker/include/RTC/RtpStream.hpp | 12 +- worker/include/RTC/RtpStreamRecv.hpp | 13 +- worker/include/RTC/RtpStreamSend.hpp | 3 +- worker/include/RTC/RtxStream.hpp | 9 +- worker/include/RTC/SctpAssociation.hpp | 12 +- worker/include/RTC/SctpDictionaries.hpp | 10 +- worker/include/RTC/SctpListener.hpp | 6 +- worker/include/RTC/Shared.hpp | 5 +- worker/include/RTC/SimpleConsumer.hpp | 12 +- worker/include/RTC/SimulcastConsumer.hpp | 12 +- worker/include/RTC/SrtpSession.hpp | 6 +- worker/include/RTC/SvcConsumer.hpp | 11 +- worker/include/RTC/TcpConnection.hpp | 8 +- worker/include/RTC/TcpServer.hpp | 10 +- worker/include/RTC/Transport.hpp | 95 +- .../RTC/TransportCongestionControlClient.hpp | 10 +- .../RTC/TransportCongestionControlServer.hpp | 10 +- worker/include/RTC/TransportTuple.hpp | 10 +- worker/include/RTC/UdpSocket.hpp | 6 +- worker/include/RTC/WebRtcServer.hpp | 23 +- worker/include/RTC/WebRtcTransport.hpp | 31 +- worker/include/Utils.hpp | 25 - worker/include/Worker.hpp | 49 +- worker/include/common.hpp | 25 +- .../{SignalsHandler.hpp => SignalHandle.hpp} | 12 +- ...ionHandler.hpp => TcpConnectionHandle.hpp} | 20 +- ...pServerHandler.hpp => TcpServerHandle.hpp} | 28 +- .../handles/{Timer.hpp => TimerHandle.hpp} | 16 +- ...pSocketHandler.hpp => UdpSocketHandle.hpp} | 24 +- ...mSocket.hpp => UnixStreamSocketHandle.hpp} | 20 +- worker/include/lib.hpp | 6 +- worker/meson.build | 42 +- worker/scripts/package-lock.json | 11 +- worker/scripts/package.json | 5 +- worker/src/Channel/ChannelNotification.cpp | 45 + worker/src/Channel/ChannelNotifier.cpp | 53 - worker/src/Channel/ChannelRequest.cpp | 248 +- worker/src/Channel/ChannelSocket.cpp | 152 +- worker/src/ChannelMessageRegistrator.cpp | 98 +- worker/src/DepUsrSCTP.cpp | 4 +- .../PayloadChannelNotification.cpp | 80 - .../PayloadChannel/PayloadChannelNotifier.cpp | 43 - .../PayloadChannel/PayloadChannelRequest.cpp | 165 - .../PayloadChannel/PayloadChannelSocket.cpp | 539 --- worker/src/RTC/ActiveSpeakerObserver.cpp | 37 +- worker/src/RTC/AudioLevelObserver.cpp | 76 +- worker/src/RTC/Consumer.cpp | 390 +- worker/src/RTC/DataConsumer.cpp | 404 +- worker/src/RTC/DataProducer.cpp | 233 +- worker/src/RTC/DirectTransport.cpp | 134 +- worker/src/RTC/DtlsTransport.cpp | 414 +- worker/src/RTC/IceCandidate.cpp | 95 +- worker/src/RTC/IceServer.cpp | 37 + worker/src/RTC/KeyFrameRequestManager.cpp | 14 +- worker/src/RTC/NackGenerator.cpp | 4 +- worker/src/RTC/PipeConsumer.cpp | 70 +- worker/src/RTC/PipeTransport.cpp | 301 +- worker/src/RTC/PlainTransport.cpp | 590 +-- worker/src/RTC/PortManager.cpp | 51 - worker/src/RTC/Producer.cpp | 603 ++- worker/src/RTC/Router.cpp | 392 +- worker/src/RTC/RtpDictionaries/Media.cpp | 66 - worker/src/RTC/RtpDictionaries/Parameters.cpp | 133 +- .../src/RTC/RtpDictionaries/RtcpFeedback.cpp | 30 +- .../RTC/RtpDictionaries/RtcpParameters.cpp | 44 +- .../RTC/RtpDictionaries/RtpCodecMimeType.cpp | 3 - .../RtpDictionaries/RtpCodecParameters.cpp | 108 +- .../RtpDictionaries/RtpEncodingParameters.cpp | 119 +- .../RtpHeaderExtensionParameters.cpp | 56 +- .../RtpDictionaries/RtpHeaderExtensionUri.cpp | 88 +- .../src/RTC/RtpDictionaries/RtpParameters.cpp | 186 +- .../RTC/RtpDictionaries/RtpRtxParameters.cpp | 28 +- worker/src/RTC/RtpListener.cpp | 28 +- worker/src/RTC/RtpObserver.cpp | 34 +- worker/src/RTC/RtpPacket.cpp | 79 +- worker/src/RTC/RtpStream.cpp | 117 +- worker/src/RTC/RtpStreamRecv.cpp | 39 +- worker/src/RTC/RtpStreamSend.cpp | 21 +- worker/src/RTC/RtxStream.cpp | 27 +- worker/src/RTC/SctpAssociation.cpp | 45 +- .../SctpDictionaries/SctpStreamParameters.cpp | 62 +- worker/src/RTC/SctpListener.cpp | 14 +- worker/src/RTC/Shared.cpp | 8 +- worker/src/RTC/SimpleConsumer.cpp | 89 +- worker/src/RTC/SimulcastConsumer.cpp | 182 +- worker/src/RTC/SrtpSession.cpp | 36 + worker/src/RTC/SvcConsumer.cpp | 180 +- worker/src/RTC/TcpConnection.cpp | 6 +- worker/src/RTC/TcpServer.cpp | 6 +- worker/src/RTC/Transport.cpp | 1087 ++--- .../RTC/TransportCongestionControlClient.cpp | 4 +- .../RTC/TransportCongestionControlServer.cpp | 4 +- worker/src/RTC/TransportTuple.cpp | 66 +- worker/src/RTC/UdpSocket.cpp | 4 +- worker/src/RTC/WebRtcServer.cpp | 281 +- worker/src/RTC/WebRtcTransport.cpp | 672 ++- worker/src/Settings.cpp | 23 +- worker/src/Utils/String.cpp | 39 - worker/src/Worker.cpp | 332 +- .../{SignalsHandler.cpp => SignalHandle.cpp} | 24 +- ...ionHandler.cpp => TcpConnectionHandle.cpp} | 76 +- ...pServerHandler.cpp => TcpServerHandle.cpp} | 112 +- .../handles/{Timer.cpp => TimerHandle.cpp} | 22 +- ...pSocketHandler.cpp => UdpSocketHandle.cpp} | 128 +- ...mSocket.cpp => UnixStreamSocketHandle.cpp} | 131 +- worker/src/lib.cpp | 41 +- worker/src/lib.rs | 43 +- worker/src/main.cpp | 4 - worker/subprojects/flatbuffers.wrap | 14 + worker/subprojects/nlohmann_json.wrap | 10 - worker/test/src/RTC/TestRtpPacketH264Svc.cpp | 1 + worker/test/src/Utils/TestJson.cpp | 105 - worker/test/src/Utils/TestString.cpp | 37 - 293 files changed, 24096 insertions(+), 11024 deletions(-) create mode 100644 Cargo.lock create mode 100644 node/.eslintignore delete mode 100644 node/src/PayloadChannel.ts create mode 100644 node/src/RtpStream.ts create mode 100644 rust/benches/producer.rs delete mode 100644 rust/src/worker/payload_channel.rs create mode 100644 worker/fbs/activeSpeakerObserver.fbs create mode 100644 worker/fbs/audioLevelObserver.fbs create mode 100644 worker/fbs/common.fbs create mode 100644 worker/fbs/consumer.fbs create mode 100644 worker/fbs/dataConsumer.fbs create mode 100644 worker/fbs/dataProducer.fbs create mode 100644 worker/fbs/directTransport.fbs create mode 100644 worker/fbs/log.fbs create mode 100644 worker/fbs/meson.build create mode 100644 worker/fbs/message.fbs create mode 100644 worker/fbs/notification.fbs create mode 100644 worker/fbs/pipeTransport.fbs create mode 100644 worker/fbs/plainTransport.fbs create mode 100644 worker/fbs/producer.fbs create mode 100644 worker/fbs/request.fbs create mode 100644 worker/fbs/response.fbs create mode 100644 worker/fbs/router.fbs create mode 100644 worker/fbs/rtpObserver.fbs create mode 100644 worker/fbs/rtpPacket.fbs create mode 100644 worker/fbs/rtpParameters.fbs create mode 100644 worker/fbs/rtpStream.fbs create mode 100644 worker/fbs/rtxStream.fbs create mode 100644 worker/fbs/sctpAssociation.fbs create mode 100644 worker/fbs/sctpParameters.fbs create mode 100644 worker/fbs/srtpParameters.fbs create mode 100644 worker/fbs/transport.fbs create mode 100644 worker/fbs/webRtcServer.fbs create mode 100644 worker/fbs/webRtcTransport.fbs create mode 100644 worker/fbs/worker.fbs create mode 100644 worker/include/Channel/ChannelNotification.hpp delete mode 100644 worker/include/PayloadChannel/PayloadChannelNotification.hpp delete mode 100644 worker/include/PayloadChannel/PayloadChannelNotifier.hpp delete mode 100644 worker/include/PayloadChannel/PayloadChannelRequest.hpp delete mode 100644 worker/include/PayloadChannel/PayloadChannelSocket.hpp rename worker/include/handles/{SignalsHandler.hpp => SignalHandle.hpp} (68%) rename worker/include/handles/{TcpConnectionHandler.hpp => TcpConnectionHandle.hpp} (85%) rename worker/include/handles/{TcpServerHandler.hpp => TcpServerHandle.hpp} (61%) rename worker/include/handles/{Timer.hpp => TimerHandle.hpp} (72%) rename worker/include/handles/{UdpSocketHandler.hpp => UdpSocketHandle.hpp} (77%) rename worker/include/handles/{UnixStreamSocket.hpp => UnixStreamSocketHandle.hpp} (70%) create mode 100644 worker/src/Channel/ChannelNotification.cpp delete mode 100644 worker/src/PayloadChannel/PayloadChannelNotification.cpp delete mode 100644 worker/src/PayloadChannel/PayloadChannelNotifier.cpp delete mode 100644 worker/src/PayloadChannel/PayloadChannelRequest.cpp delete mode 100644 worker/src/PayloadChannel/PayloadChannelSocket.cpp delete mode 100644 worker/src/RTC/RtpDictionaries/Media.cpp rename worker/src/handles/{SignalsHandler.cpp => SignalHandle.cpp} (77%) rename worker/src/handles/{TcpConnectionHandler.cpp => TcpConnectionHandle.cpp} (87%) rename worker/src/handles/{TcpServerHandler.cpp => TcpServerHandle.cpp} (58%) rename worker/src/handles/{Timer.cpp => TimerHandle.cpp} (84%) rename worker/src/handles/{UdpSocketHandler.cpp => UdpSocketHandle.cpp} (70%) rename worker/src/handles/{UnixStreamSocket.cpp => UnixStreamSocketHandle.cpp} (69%) create mode 100644 worker/subprojects/flatbuffers.wrap delete mode 100644 worker/subprojects/nlohmann_json.wrap delete mode 100644 worker/test/src/Utils/TestJson.cpp diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 401e8def2a..7fdfaef856 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -13,6 +13,8 @@ jobs: strategy: matrix: ci: + - os: ubuntu-20.04 + node: 16 - os: ubuntu-20.04 node: 18 - os: ubuntu-22.04 @@ -45,6 +47,8 @@ jobs: restore-keys: | ${{ matrix.ci.os }}-node- - - run: npm ci + # NOTE: Add --force since otherwise `npm ci` fails in Node 26 because + # @octokit/auth-token dev dependency requires Node >= 16. + - run: npm ci --force - run: npm run lint:node - run: npm run test:node diff --git a/.gitignore b/.gitignore index 366e4c3de8..abbaa0f7f2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,15 +7,18 @@ ## Node. /node_modules /node/lib +# flatc generated files. +/node/src/fbs ## Rust. -/Cargo.lock /rust/examples-frontend/*/node_modules /rust/examples-frontend/*/package-lock.json /target ## Worker. /worker/scripts/node_modules +# Flatc generated files. +/worker/include/FBS /worker/prebuild # Vistual Studio generated Stuff. /worker/**/Debug @@ -30,14 +33,5 @@ ## Others. /coverage /.cache -/NO_GIT -*.swp -*.swo -.DS_Store -# Vistual Studio Code stuff. -/.vscode -# JetBrains IDE stuff. -/.idea - # Packaged module. *.tgz diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ae8f1d258..f3a1d4891a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ # Changelog +### Next + +* Switch from JSON based messages to `flatbuffers` ([PR #1064](https://github.com/versatica/mediasoup/pull/1064)). +* Add `ListenInfo` in all transports and send/recv buffer size options ([PR #1084](https://github.com/versatica/mediasoup/pull/1084)). +* Add optional `rtcpListenInfo` in `PlainTransportOptions` ([PR #1099](https://github.com/versatica/mediasoup/pull/1099)). +* Add pause/resume API in `DataProducer` and `DataConsumer` ([PR #1104](https://github.com/versatica/mediasoup/pull/1104)). +* DataChannel subchannels feature ([PR #1152](https://github.com/versatica/mediasoup/pull/1152)). +* `Worker`: Make DTLS fragment stay within MTU size range ([PR #1156](https://github.com/versatica/mediasoup/pull/1156), based on [PR #1143](https://github.com/versatica/mediasoup/pull/1143) by @vpnts-se). + + ### 3.12.16 * Fix `IceServer` crash when client uses ICE renomination ([PR #1182](https://github.com/versatica/mediasoup/pull/1182)). diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..b08783920d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2657 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "actix" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cba56612922b907719d4a01cf11c8d5b458e7d3dba946d0435f20f58d6795ed2" +dependencies = [ + "actix-macros", + "actix-rt", + "actix_derive", + "bitflags 2.4.0", + "bytes", + "crossbeam-channel", + "futures-core", + "futures-sink", + "futures-task", + "futures-util", + "log", + "once_cell", + "parking_lot 0.12.1", + "pin-project-lite", + "smallvec", + "tokio", + "tokio-util", +] + +[[package]] +name = "actix-codec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8" +dependencies = [ + "bitflags 1.3.2", + "bytes", + "futures-core", + "futures-sink", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "actix-http" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92ef85799cba03f76e4f7c10f533e66d87c9a7e7055f3391f09000ad8351bc9" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "ahash 0.8.3", + "base64", + "bitflags 2.4.0", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "futures-core", + "http", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand 0.8.5", + "sha1", + "smallvec", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn 2.0.32", +] + +[[package]] +name = "actix-router" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" +dependencies = [ + "bytestring", + "http", + "regex", + "serde", + "tracing", +] + +[[package]] +name = "actix-rt" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" +dependencies = [ + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "socket2 0.5.3", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" +dependencies = [ + "futures-core", + "paste 1.0.14", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4a5b5e29603ca8c94a77c65cf874718ceb60292c5a5c3e5f4ace041af462b9" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "ahash 0.8.3", + "bytes", + "bytestring", + "cfg-if", + "derive_more", + "encoding_rs", + "futures-core", + "futures-util", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2 0.5.3", + "time", + "url", +] + +[[package]] +name = "actix-web-actors" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6e9ccc371cfddbed7aa842256a4abc7a6dcac9f3fce392fe1d0f68cfd136b2" +dependencies = [ + "actix", + "actix-codec", + "actix-http", + "actix-web", + "bytes", + "bytestring", + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "actix-web-codegen" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "actix_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c7db3d5a9718568e4cf4a537cfd7070e6e6ff7481510d0237fb529ac850f6d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +dependencies = [ + "getrandom 0.2.10", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom 0.2.10", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +dependencies = [ + "memchr", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "array-init-cursor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7d0a018de4f6aa429b9d33d69edf69072b1c5b1cb8d3e4a5f7ef898fc3eb76" + +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + +[[package]] +name = "askama" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb98f10f371286b177db5eeb9a6e5396609555686a35e1d4f7b9a9c6d8af0139" +dependencies = [ + "askama_derive", + "askama_escape", + "askama_shared", +] + +[[package]] +name = "askama_derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87bf87e6e8b47264efa9bde63d6225c6276a52e05e91bf37eaa8afd0032d6b71" +dependencies = [ + "askama_shared", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "askama_escape" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" + +[[package]] +name = "askama_shared" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf722b94118a07fcbc6640190f247334027685d4e218b794dbfe17c32bf38ed0" +dependencies = [ + "askama_escape", + "humansize", + "mime", + "mime_guess", + "nom", + "num-traits", + "percent-encoding", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", + "toml", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix 0.37.23", + "slab", + "socket2 0.4.9", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-oneshot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec7c75bcbcb0139e9177f30692fd617405ca4e0c27802e128d53171f7042e2c" +dependencies = [ + "futures-micro", +] + +[[package]] +name = "async-task" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" + +[[package]] +name = "async-trait" +version = "0.1.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "atomic-take" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8ab6b55fe97976e46f91ddbed8d147d966475dc29b2032757ba47e02376fbc3" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "bitpattern" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc436c543b5fd522e5428d65c88e7bfb538ba267dad95cfb9d8fb8a465b0935" +dependencies = [ + "paste 0.1.18", + "proc-macro2", + "quote", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "bytestring" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae" +dependencies = [ + "bytes", +] + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" + +[[package]] +name = "ciborium-ll" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "bitflags 1.3.2", + "clap_lex", + "indexmap 1.9.3", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "codespan" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3362992a0d9f1dd7c3d0e89e0ab2bb540b7a95fea8cd798090e758fda2899b5e" +dependencies = [ + "codespan-reporting", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "concurrent-queue" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "criterion" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +dependencies = [ + "anes", + "atty", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deranged" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "ena" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +dependencies = [ + "log", +] + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener-primitives" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5384093b4255393cc8c42f0fc3dd4f19977ad3b1025f968257854895a993028c" +dependencies = [ + "nohash-hasher", + "parking_lot 0.11.2", + "smallvec", +] + +[[package]] +name = "eyre" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-micro" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b460264b3593d68b16a7bc35f7bc226ddfebdf9a1c8db1ed95d5cc6b7168c826" +dependencies = [ + "pin-project-lite", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "h264-profile-level-id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12ebc03fc4f14b7ddc94da90cfb28ba3edee2d926798a9eef89f8a27bbdbca5" +dependencies = [ + "bitpattern", + "log", + "once_cell", + "thiserror", +] + +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + +[[package]] +name = "hash_hasher" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74721d007512d0cb3338cd20f0654ac913920061a4c4d0d8708edb3f2a698c0c" + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.7", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humansize" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown 0.14.2", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.2", + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.2", + "rustix 0.38.13", + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lalrpop" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" +dependencies = [ + "ascii-canvas", + "bit-set", + "diff", + "ena", + "is-terminal", + "itertools", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax 0.7.5", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" +dependencies = [ + "regex", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + +[[package]] +name = "local-channel" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c" +dependencies = [ + "futures-core", + "futures-sink", + "futures-util", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", + "serde", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "logos" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf8b031682c67a8e3d5446840f9573eb7fe26efe7ec8d195c9ac4c0647c502f1" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" +dependencies = [ + "beef", + "fnv", + "proc-macro2", + "quote", + "regex-syntax 0.6.29", + "syn 1.0.109", +] + +[[package]] +name = "lru" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" + +[[package]] +name = "mediasoup" +version = "0.12.0" +dependencies = [ + "actix", + "actix-web", + "actix-web-actors", + "async-channel", + "async-executor", + "async-io", + "async-lock", + "async-oneshot", + "async-trait", + "atomic-take", + "criterion", + "env_logger", + "event-listener-primitives", + "fastrand", + "futures-lite", + "h264-profile-level-id", + "hash_hasher", + "log", + "lru", + "mediasoup-sys", + "nohash-hasher", + "once_cell", + "parking_lot 0.12.1", + "planus", + "portpicker", + "regex", + "serde", + "serde_json", + "serde_repr", + "thiserror", + "uuid", +] + +[[package]] +name = "mediasoup-sys" +version = "0.6.0" +dependencies = [ + "planus", + "planus-codegen", + "planus-translation", + "serde", +] + +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.2", + "libc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "os_str_bytes" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" + +[[package]] +name = "parking" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.8", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" +dependencies = [ + "paste-impl", + "proc-macro-hack", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "paste-impl" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" +dependencies = [ + "proc-macro-hack", +] + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap 2.0.2", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "planus" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cbec589fda965e8d0cf7dddaa87d37ae5ccaed0c43986e8faf5998f24ef82f5" +dependencies = [ + "array-init-cursor", + "hashbrown 0.13.2", +] + +[[package]] +name = "planus-codegen" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d1bb11066c61d46d6d8f21d342d300f06d08bcce15f88399fdd40e1341c421" +dependencies = [ + "askama", + "eyre", + "heck", + "planus-types", + "random_color", + "thiserror", + "vec_map", +] + +[[package]] +name = "planus-lexer" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecb00082b1324541f02f323585333e88ed3bf90cdbad3741e52eabf166fbcd6" +dependencies = [ + "codespan", + "derive_more", + "logos", +] + +[[package]] +name = "planus-translation" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7bd8ffea859844a23ea28d58354e9e466f3454981b368ba7d8226edac50398b" +dependencies = [ + "atty", + "bitflags 2.4.0", + "codespan", + "codespan-reporting", + "indexmap 1.9.3", + "lalrpop", + "lalrpop-util", + "num-traits", + "planus-lexer", + "planus-types", + "string-interner", +] + +[[package]] +name = "planus-types" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10306bda3579cc7a43537cb3f81212d93ce4fea32a219d9c0a7788d8c5d8e114" +dependencies = [ + "codespan", + "indexmap 1.9.3", + "lalrpop-util", + "planus-lexer", + "string-interner", +] + +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" + +[[package]] +name = "plotters-svg" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys", +] + +[[package]] +name = "portpicker" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be97d76faf1bfab666e1375477b23fde79eccf0276e9b63b92a39d676a889ba9" +dependencies = [ + "rand 0.8.5", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.10", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "random_color" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5f34bd6526786b2ce5141fd37a4084b5da1ebae74595b5b0d05482a7cef7181" +dependencies = [ + "rand 0.7.3", +] + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.10", + "redox_syscall 0.2.16", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.37.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "0.38.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys 0.4.10", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + +[[package]] +name = "serde" +version = "1.0.190" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.190" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "serde_json" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc66a619ed80bf7a0f6b17dd063a84b88f6dea1813737cf469aef1d081142c2" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "string-interner" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e2531d8525b29b514d25e275a43581320d587b86db302b9a7e464bac579648" +dependencies = [ + "cfg-if", + "hashbrown 0.11.2", + "serde", +] + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot 0.12.1", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "thiserror" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "time" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" +dependencies = [ + "deranged", + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot 0.12.1", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.5.3", + "windows-sys", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +dependencies = [ + "getrandom 0.2.10", + "serde", +] + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.32", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index efb0f433ee..fac71da63a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "rust", "worker" diff --git a/art/mediasoup-v3-architecture-01.svg b/art/mediasoup-v3-architecture-01.svg index 9613ddb17f..89966d0f70 100644 --- a/art/mediasoup-v3-architecture-01.svg +++ b/art/mediasoup-v3-architecture-01.svg @@ -1,2 +1,2 @@ -
Host
Host
Worker 1
Worker 1
WebRtcTransport
WebRtcTransport
Audio Producer
Audio Producer
Video Producer
Video Producer
PlainRtpTransport
PlainRtpTransport
Video Producer
Video Producer
PipeTransport
PipeTransport
Video Consumer
Video Consumer
SRTPSRTP
Participant
(mic/webcam on)
Participant<br>(mic/webcam on)<br>
Participant
(viewer)
[Not supported by viewer]
RTP
FFmpeg
(recording)
[Not supported by viewer]
GStreamer
(mp4 broadcaster)
GStreamer<br>(mp4 broadcaster)<br>
RTP
Router 2
Router 2
Router 1
Router 1
Worker 2
Worker 2
PipeTransport
PipeTransport
Video Consumer
Video Consumer
Router 3
Router 3
PipeTransport
PipeTransport
Video Producer
Video Producer
Worker 3
Worker 3
PipeTransport
PipeTransport
Video Producer
Video Producer
Router 4
Router 4
RTPRTP
Participant
(viewer)
[Not supported by viewer]
Participant
(viewer)
[Not supported by viewer]
SRTPSRTPSRTP
Participant
(viewer)
[Not supported by viewer]
WebRtcTransport
WebRtcTransport
Video Consumer
Video Consumer
WebRtcTransport
WebRtcTransport
Video Consumer
Video Consumer
WebRtcTransport
WebRtcTransport
Video Consumer
Video Consumer
WebRtcTransport
WebRtcTransport
Video Consumer
Video Consumer
Participant
(viewer)
[Not supported by viewer]
SRTP
WebRtcTransport
WebRtcTransport
Audio Consumer
Audio Consumer
Video Consumer
Video Consumer
PlainRtpTransport
PlainRtpTransport
Audio Consumer
Audio Consumer
\ No newline at end of file +
Host
Host
Worker 1
Worker 1
WebRtcTransport
WebRtcTransport
Audio Producer
Audio Producer
Video Producer
Video Producer
PlainTransport
PlainTransport
Video Producer
Video Producer
PipeTransport
PipeTransport
Video Consumer
Video Consumer
SRTPSRTP
Participant
(mic/webcam on)
Participant<br>(mic/webcam on)<br>
Participant
(viewer)
[Not supported by viewer]
RTP
FFmpeg
(recording)
[Not supported by viewer]
GStreamer
(mp4 broadcaster)
GStreamer<br>(mp4 broadcaster)<br>
RTP
Router 2
Router 2
Router 1
Router 1
Worker 2
Worker 2
PipeTransport
PipeTransport
Video Consumer
Video Consumer
Router 3
Router 3
PipeTransport
PipeTransport
Video Producer
Video Producer
Worker 3
Worker 3
PipeTransport
PipeTransport
Video Producer
Video Producer
Router 4
Router 4
RTPRTP
Participant
(viewer)
[Not supported by viewer]
Participant
(viewer)
[Not supported by viewer]
SRTPSRTPSRTP
Participant
(viewer)
[Not supported by viewer]
WebRtcTransport
WebRtcTransport
Video Consumer
Video Consumer
WebRtcTransport
WebRtcTransport
Video Consumer
Video Consumer
WebRtcTransport
WebRtcTransport
Video Consumer
Video Consumer
WebRtcTransport
WebRtcTransport
Video Consumer
Video Consumer
Participant
(viewer)
[Not supported by viewer]
SRTP
WebRtcTransport
WebRtcTransport
Audio Consumer
Audio Consumer
Video Consumer
Video Consumer
PlainTransport
PlainTransport
Audio Consumer
Audio Consumer
diff --git a/node/.eslintignore b/node/.eslintignore new file mode 100644 index 0000000000..7eadde52eb --- /dev/null +++ b/node/.eslintignore @@ -0,0 +1 @@ +/node/src/fbs diff --git a/node/.eslintrc.js b/node/.eslintrc.js index 61a42372e6..e541c5acd6 100644 --- a/node/.eslintrc.js +++ b/node/.eslintrc.js @@ -183,6 +183,7 @@ const eslintConfig = } ], 'space-in-parens' : [ 2, 'never' ], + 'space-infix-ops' : [ 2, { 'int32Hint': false } ], 'spaced-comment' : [ 2, 'always' ], 'strict' : 2, 'valid-typeof' : 2, diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index cee690b240..5a7aefbc66 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -8,6 +8,8 @@ import { } from './RtpObserver'; import { Producer } from './Producer'; import { AppData } from './types'; +import { Event, Notification } from './fbs/notification'; +import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; export type ActiveSpeakerObserverOptions = { @@ -65,13 +67,17 @@ export class ActiveSpeakerObserver + this.channel.on(this.internal.rtpObserverId, (event: Event, data?: Notification) => { switch (event) { - case 'dominantspeaker': + case Event.ACTIVESPEAKEROBSERVER_DOMINANT_SPEAKER: { - const producer = this.getProducerById(data.producerId); + const notification = new FbsActiveSpeakerObserver.DominantSpeakerNotification(); + + data!.body(notification); + + const producer = this.getProducerById(notification.producerId()!); if (!producer) { diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index 03cd7789d5..1dda1ca4b8 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -8,6 +8,9 @@ import { } from './RtpObserver'; import { Producer } from './Producer'; import { AppData } from './types'; +import * as utils from './utils'; +import { Event, Notification } from './fbs/notification'; +import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; export type AudioLevelObserverOptions = { @@ -87,22 +90,27 @@ export class AudioLevelObserver + this.channel.on(this.internal.rtpObserverId, (event: Event, data?: Notification) => { switch (event) { - case 'volumes': + case Event.AUDIOLEVELOBSERVER_VOLUMES: { + const notification = new FbsAudioLevelObserver.VolumesNotification(); + + data!.body(notification); + // Get the corresponding Producer instance and remove entries with // no Producer (it may have been closed in the meanwhile). - const volumes: AudioLevelObserverVolume[] = data - .map(({ producerId, volume }: { producerId: string; volume: number }) => ( - { - producer : this.getProducerById(producerId), - volume - } - )) - .filter(({ producer }: { producer: Producer }) => producer); + const volumes: AudioLevelObserverVolume[] = + utils.parseVector(notification, 'volumes', parseVolume) + .map(({ producerId, volume }: { producerId: string; volume: number }) => ( + { + producer : this.getProducerById(producerId)!, + volume + } + )) + .filter(({ producer }: { producer: Producer }) => producer); if (volumes.length > 0) { @@ -115,7 +123,7 @@ export class AudioLevelObserver + notify( + event: Event, + bodyType?: NotificationBody, + bodyOffset?: number, + handlerId?: string + ): void { - this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1); + logger.debug('notify() [event:%s]', Event[event]); - const id = this.#nextId; + if (this.#closed) + { + throw new InvalidStateError('Channel closed'); + } - logger.debug('request() [method:%s, id:%s]', method, id); + const handlerIdOffset = this.#bufferBuilder.createString(handlerId); + + let notificationOffset: number; + + if (bodyType && bodyOffset) + { + notificationOffset = Notification.createNotification( + this.#bufferBuilder, handlerIdOffset, event, bodyType, bodyOffset); + } + else + { + notificationOffset = Notification.createNotification( + this.#bufferBuilder, handlerIdOffset, event, NotificationBody.NONE, 0); + } + + const messageOffset = Message.createMessage( + this.#bufferBuilder, + MessageBody.Notification, + notificationOffset + ); + + // Finalizes the buffer and adds a 4 byte prefix with the size of the buffer. + this.#bufferBuilder.finishSizePrefixed(messageOffset); + + // Create a new buffer with this data so multiple contiguous flatbuffers + // do not point to the builder buffer overriding others info. + const buffer = new Uint8Array(this.#bufferBuilder.asUint8Array()); + + // Clear the buffer builder so it's reused for the next request. + this.#bufferBuilder.clear(); + + if (buffer.byteLength > MESSAGE_MAX_LEN) + { + throw new Error('Channel request too big'); + } + + try + { + // This may throw if closed or remote side ended. + this.#producerSocket.write(buffer, 'binary'); + } + catch (error) + { + logger.warn('notify() | sending notification failed: %s', String(error)); + + return; + } + } + async request( + method: Method, + bodyType?: RequestBody, + bodyOffset?: number, + handlerId?: string): Promise + { if (this.#closed) { throw new InvalidStateError('Channel closed'); } - const request = `${id}:${method}:${handlerId}:${JSON.stringify(data)}`; + this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1); + + const id = this.#nextId; + + const handlerIdOffset = this.#bufferBuilder.createString(handlerId ?? ''); + + let requestOffset: number; - if (Buffer.byteLength(request) > MESSAGE_MAX_LEN) + if (bodyType && bodyOffset) + { + requestOffset = Request.createRequest( + this.#bufferBuilder, id, method, handlerIdOffset, bodyType, bodyOffset); + } + else + { + requestOffset = Request.createRequest( + this.#bufferBuilder, id, method, handlerIdOffset, RequestBody.NONE, 0); + } + + const messageOffset = Message.createMessage( + this.#bufferBuilder, + MessageBody.Request, + requestOffset + ); + + // Finalizes the buffer and adds a 4 byte prefix with the size of the buffer. + this.#bufferBuilder.finishSizePrefixed(messageOffset); + + // Create a new buffer with this data so multiple contiguous flatbuffers + // do not point to the builder buffer overriding others info. + const buffer = new Uint8Array(this.#bufferBuilder.asUint8Array()); + + // Clear the buffer builder so it's reused for the next request. + this.#bufferBuilder.clear(); + + if (buffer.byteLength > MESSAGE_MAX_LEN) { throw new Error('Channel request too big'); } // This may throw if closed or remote side ended. - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(request)).buffer)); - this.#producerSocket.write(request); + this.#producerSocket.write(buffer, 'binary'); return new Promise((pResolve, pReject) => { const sent: Sent = { id : id, - method : method, + method : Method[method], resolve : (data2) => { if (!this.#sents.delete(id)) @@ -285,67 +404,90 @@ export class Channel extends EnhancedEventEmitter }); } - private processMessage(msg: any): void + private processResponse(response: Response): void { - // If a response, retrieve its associated request. - if (msg.id) + const sent = this.#sents.get(response.id()); + + if (!sent) { - const sent = this.#sents.get(msg.id); + logger.error( + 'received response does not match any sent request [id:%s]', response.id); - if (!sent) - { - logger.error( - 'received response does not match any sent request [id:%s]', msg.id); + return; + } - return; - } + if (response.accepted()) + { + logger.debug( + 'request succeeded [method:%s, id:%s]', sent.method, sent.id); - if (msg.accepted) - { - logger.debug( - 'request succeeded [method:%s, id:%s]', sent.method, sent.id); + sent.resolve(response); + } + else if (response.error()) + { + logger.warn( + 'request failed [method:%s, id:%s]: %s', + sent.method, sent.id, response.reason()); - sent.resolve(msg.data); - } - else if (msg.error) + switch (response.error()!) { - logger.warn( - 'request failed [method:%s, id:%s]: %s', - sent.method, sent.id, msg.reason); - - switch (msg.error) - { - case 'TypeError': - sent.reject(new TypeError(msg.reason)); - break; + case 'TypeError': + sent.reject(new TypeError(response.reason()!)); + break; - default: - sent.reject(new Error(msg.reason)); - } - } - else - { - logger.error( - 'received response is not accepted nor rejected [method:%s, id:%s]', - sent.method, sent.id); + default: + sent.reject(new Error(response.reason()!)); } } - // If a notification emit it to the corresponding entity. - else if (msg.targetId && msg.event) - { - // Due to how Promises work, it may happen that we receive a response - // from the worker followed by a notification from the worker. If we - // emit the notification immediately it may reach its target **before** - // the response, destroying the ordered delivery. So we must wait a bit - // here. - // See https://github.com/versatica/mediasoup/issues/510 - setImmediate(() => this.emit(String(msg.targetId), msg.event, msg.data)); - } - // Otherwise unexpected message. else { logger.error( - 'received message is not a response nor a notification'); + 'received response is not accepted nor rejected [method:%s, id:%s]', + sent.method, sent.id); + } + } + + private processNotification(notification: Notification): void + { + // Due to how Promises work, it may happen that we receive a response + // from the worker followed by a notification from the worker. If we + // emit the notification immediately it may reach its target **before** + // the response, destroying the ordered delivery. So we must wait a bit + // here. + // See https://github.com/versatica/mediasoup/issues/510 + setImmediate(() => this.emit( + notification.handlerId()!, + notification.event(), + notification) + ); + } + + private processLog(pid: number, log: Log): void + { + const logData = log.data()!; + + switch (logData[0]) + { + // 'D' (a debug log). + case 'D': + logger.debug(`[pid:${pid}] ${logData.slice(1)}`); + break; + + // 'W' (a warn log). + case 'W': + logger.warn(`[pid:${pid}] ${logData.slice(1)}`); + break; + + // 'E' (a error log). + case 'E': + logger.error(`[pid:${pid}] ${logData.slice(1)}`); + break; + + // 'X' (a dump log). + case 'X': + // eslint-disable-next-line no-console + console.log(logData.slice(1)); + break; } } } diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index bcf09e3c20..0a9d60d832 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -1,15 +1,29 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; import { ProducerStat } from './Producer'; import { MediaKind, RtpCapabilities, - RtpParameters + RtpEncodingParameters, + RtpParameters, + parseRtpEncodingParameters, + parseRtpParameters } from './RtpParameters'; +import { parseRtpStreamStats, RtpStreamSendStats } from './RtpStream'; import { AppData } from './types'; +import * as utils from './utils'; +import { Event, Notification } from './fbs/notification'; +import { TraceDirection as FbsTraceDirection } from './fbs/common'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsConsumer from './fbs/consumer'; +import * as FbsConsumerTraceInfo from './fbs/consumer/trace-info'; +import * as FbsRtpStream from './fbs/rtp-stream'; +import * as FbsRtxStream from './fbs/rtx-stream'; +import { Type as FbsRtpParametersType } from './fbs/rtp-parameters'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; export type ConsumerOptions = { @@ -24,7 +38,7 @@ export type ConsumerOptions = rtpCapabilities: RtpCapabilities; /** - * Whether the Consumer must start in paused mode. Default false. + * Whether the consumer must start in paused mode. Default false. * * When creating a video Consumer, it's recommended to set paused to true, * then transmit the Consumer parameters to the consuming endpoint and, once @@ -65,7 +79,7 @@ export type ConsumerOptions = * Whether this Consumer should ignore DTX packets (only valid for Opus codec). * If set, DTX packets are not forwarded to the remote Consumer. */ - ignoreDtx?: Boolean; + ignoreDtx?: boolean; /** * Whether this Consumer should consume all RTP streams generated by the @@ -142,30 +156,7 @@ export type ConsumerLayers = temporalLayer?: number; }; -export type ConsumerStat = -{ - // Common to all RtpStreams. - type: string; - timestamp: number; - ssrc: number; - rtxSsrc?: number; - kind: string; - mimeType: string; - packetsLost: number; - fractionLost: number; - packetsDiscarded: number; - packetsRetransmitted: number; - packetsRepaired: number; - nackCount: number; - nackPacketCount: number; - pliCount: number; - firCount: number; - score: number; - packetCount: number; - byteCount: number; - bitrate: number; - roundTripTime?: number; -}; +export type ConsumerStat = RtpStreamSendStats; /** * Consumer type. @@ -197,6 +188,38 @@ export type ConsumerObserverEvents = trace: [ConsumerTraceEventData]; }; +export type SimpleConsumerDump = BaseConsumerDump & +{ + type: string; + rtpStream: RtpStreamDump; +}; + +export type SimulcastConsumerDump = BaseConsumerDump & +{ + type: string; + rtpStream: RtpStreamDump; + preferredSpatialLayer: number; + targetSpatialLayer: number; + currentSpatialLayer: number; + preferredTemporalLayer: number; + targetTemporalLayer: number; + currentTemporalLayer: number; +}; + +export type SvcConsumerDump = SimulcastConsumerDump; + +export type PipeConsumerDump = BaseConsumerDump & +{ + type: string; + rtpStreams: RtpStreamDump[]; +}; + +export type ConsumerDump = + SimpleConsumerDump | + SimulcastConsumerDump | + SvcConsumerDump | + PipeConsumerDump; + type ConsumerInternal = TransportInternal & { consumerId: string; @@ -210,6 +233,62 @@ type ConsumerData = type: ConsumerType; }; +type BaseConsumerDump = +{ + id: string; + producerId: string; + kind: MediaKind; + rtpParameters: RtpParameters; + consumableRtpEncodings?: RtpEncodingParameters[]; + supportedCodecPayloadTypes: number[]; + traceEventTypes: string[]; + paused: boolean; + producerPaused: boolean; + priority: number; +}; + +type RtpStreamParameters = +{ + encodingIdx: number; + ssrc: number; + payloadType: number; + mimeType: string; + clockRate: number; + rid?: string; + cname: string; + rtxSsrc?: number; + rtxPayloadType?: number; + useNack: boolean; + usePli: boolean; + useFir: boolean; + useInBandFec: boolean; + useDtx: boolean; + spatialLayers: number; + temporalLayers: number; +}; + +type RtpStreamDump = +{ + params: RtpStreamParameters; + score: number; + rtxStream?: RtxStreamDump; +}; + +type RtxStreamParameters = +{ + ssrc: number; + payloadType: number; + mimeType: string; + clockRate: number; + rrid?: string; + cname: string; +}; + +type RtxStreamDump = +{ + params: RtxStreamParameters; +}; + const logger = new Logger('Consumer'); export class Consumer @@ -224,9 +303,6 @@ export class Consumer // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -262,7 +338,6 @@ export class Consumer internal, data, channel, - payloadChannel, appData, paused, producerPaused, @@ -273,7 +348,6 @@ export class Consumer internal: ConsumerInternal; data: ConsumerData; channel: Channel; - payloadChannel: PayloadChannel; appData?: ConsumerAppData; paused: boolean; producerPaused: boolean; @@ -288,12 +362,11 @@ export class Consumer this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; - this.#appData = appData || {} as ConsumerAppData; this.#paused = paused; this.#producerPaused = producerPaused; this.#score = score; this.#preferredLayers = preferredLayers; + this.#appData = appData || {} as ConsumerAppData; this.handleWorkerNotifications(); } @@ -443,12 +516,18 @@ export class Consumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.consumerId); - this.#payloadChannel.removeAllListeners(this.#internal.consumerId); - const reqData = { consumerId: this.#internal.consumerId }; + /* Build Request. */ + const requestOffset = new FbsTransport.CloseConsumerRequestT( + this.#internal.consumerId + ).pack(this.#channel.bufferBuilder); - this.#channel.request('transport.closeConsumer', this.#internal.transportId, reqData) - .catch(() => {}); + this.#channel.request( + FbsRequest.Method.TRANSPORT_CLOSE_CONSUMER, + FbsRequest.Body.Transport_CloseConsumerRequest, + requestOffset, + this.#internal.transportId + ).catch(() => {}); this.emit('@close'); @@ -474,7 +553,6 @@ export class Consumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.consumerId); - this.#payloadChannel.removeAllListeners(this.#internal.consumerId); this.safeEmit('transportclose'); @@ -485,11 +563,23 @@ export class Consumer /** * Dump Consumer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('consumer.dump', this.#internal.consumerId); + const response = await this.#channel.request( + FbsRequest.Method.CONSUMER_DUMP, + undefined, + undefined, + this.#internal.consumerId + ); + + /* Decode Response. */ + const data = new FbsConsumer.DumpResponse(); + + response.body(data); + + return parseConsumerDumpResponse(data); } /** @@ -499,7 +589,19 @@ export class Consumer { logger.debug('getStats()'); - return this.#channel.request('consumer.getStats', this.#internal.consumerId); + const response = await this.#channel.request( + FbsRequest.Method.CONSUMER_GET_STATS, + undefined, + undefined, + this.#internal.consumerId + ); + + /* Decode Response. */ + const data = new FbsConsumer.GetStatsResponse(); + + response.body(data); + + return parseConsumerStats(data); } /** @@ -511,7 +613,12 @@ export class Consumer const wasPaused = this.#paused || this.#producerPaused; - await this.#channel.request('consumer.pause', this.#internal.consumerId); + await this.#channel.request( + FbsRequest.Method.CONSUMER_PAUSE, + undefined, + undefined, + this.#internal.consumerId + ); this.#paused = true; @@ -531,7 +638,12 @@ export class Consumer const wasPaused = this.#paused || this.#producerPaused; - await this.#channel.request('consumer.resume', this.#internal.consumerId); + await this.#channel.request( + FbsRequest.Method.CONSUMER_RESUME, + undefined, + undefined, + this.#internal.consumerId + ); this.#paused = false; @@ -554,12 +666,55 @@ export class Consumer { logger.debug('setPreferredLayers()'); - const reqData = { spatialLayer, temporalLayer }; + if (typeof spatialLayer !== 'number') + { + throw new TypeError('spatialLayer must be a number'); + } + if (temporalLayer && typeof temporalLayer !== 'number') + { + throw new TypeError('if given, temporalLayer must be a number'); + } + + const builder = this.#channel.bufferBuilder; + + const preferredLayersOffset = FbsConsumer.ConsumerLayers.createConsumerLayers( + builder, + spatialLayer, + temporalLayer !== undefined ? temporalLayer : null); + const requestOffset = + FbsConsumer.SetPreferredLayersRequest.createSetPreferredLayersRequest( + builder, preferredLayersOffset); + + const response = await this.#channel.request( + FbsRequest.Method.CONSUMER_SET_PREFERRED_LAYERS, + FbsRequest.Body.Consumer_SetPreferredLayersRequest, + requestOffset, + this.#internal.consumerId + ); + + /* Decode Response. */ + const data = new FbsConsumer.SetPreferredLayersResponse(); - const data = await this.#channel.request( - 'consumer.setPreferredLayers', this.#internal.consumerId, reqData); + let preferredLayers: ConsumerLayers | undefined; - this.#preferredLayers = data || undefined; + // Response is empty for non Simulcast Consumers. + if (response.body(data)) + { + const status = data.unpack(); + + if (status.preferredLayers) + { + preferredLayers = + { + spatialLayer : status.preferredLayers.spatialLayer, + temporalLayer : status.preferredLayers.temporalLayer !== null ? + status.preferredLayers.temporalLayer : + undefined + }; + } + } + + this.#preferredLayers = preferredLayers; } /** @@ -569,12 +724,29 @@ export class Consumer { logger.debug('setPriority()'); - const reqData = { priority }; + if (typeof priority !== 'number' || priority < 0) + { + throw new TypeError('priority must be a positive number'); + } + + const requestOffset = + FbsConsumer.SetPriorityRequest.createSetPriorityRequest( + this.#channel.bufferBuilder, priority); + + const response = await this.#channel.request( + FbsRequest.Method.CONSUMER_SET_PRIORITY, + FbsRequest.Body.Consumer_SetPriorityRequest, + requestOffset, + this.#internal.consumerId + ); + + const data = new FbsConsumer.SetPriorityResponse(); - const data = await this.#channel.request( - 'consumer.setPriority', this.#internal.consumerId, reqData); + response.body(data); - this.#priority = data.priority; + const status = data.unpack(); + + this.#priority = status.priority; } /** @@ -584,12 +756,7 @@ export class Consumer { logger.debug('unsetPriority()'); - const reqData = { priority: 1 }; - - const data = await this.#channel.request( - 'consumer.setPriority', this.#internal.consumerId, reqData); - - this.#priority = data.priority; + await this.setPriority(1); } /** @@ -599,7 +766,12 @@ export class Consumer { logger.debug('requestKeyFrame()'); - await this.#channel.request('consumer.requestKeyFrame', this.#internal.consumerId); + await this.#channel.request( + FbsRequest.Method.CONSUMER_REQUEST_KEY_FRAME, + undefined, + undefined, + this.#internal.consumerId + ); } /** @@ -609,19 +781,50 @@ export class Consumer { logger.debug('enableTraceEvent()'); - const reqData = { types }; + if (!Array.isArray(types)) + { + throw new TypeError('types must be an array'); + } + if (types.find((type) => typeof type !== 'string')) + { + throw new TypeError('every type must be a string'); + } + + // Convert event types. + const fbsEventTypes: FbsConsumer.TraceEventType[] = []; + + for (const eventType of types) + { + try + { + fbsEventTypes.push(consumerTraceEventTypeToFbs(eventType)); + } + catch (error) + { + logger.warn('enableTraceEvent() | [error:${error}]'); + } + } + + /* Build Request. */ + const requestOffset = new FbsConsumer.EnableTraceEventRequestT( + fbsEventTypes + ).pack(this.#channel.bufferBuilder); await this.#channel.request( - 'consumer.enableTraceEvent', this.#internal.consumerId, reqData); + FbsRequest.Method.CONSUMER_ENABLE_TRACE_EVENT, + FbsRequest.Body.Consumer_EnableTraceEventRequest, + requestOffset, + this.#internal.consumerId + ); } private handleWorkerNotifications(): void { - this.#channel.on(this.#internal.consumerId, (event: string, data?: any) => + this.#channel.on(this.#internal.consumerId, (event: Event, data?: Notification) => { switch (event) { - case 'producerclose': + case Event.CONSUMER_PRODUCER_CLOSE: { if (this.#closed) { @@ -632,7 +835,6 @@ export class Consumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.consumerId); - this.#payloadChannel.removeAllListeners(this.#internal.consumerId); this.emit('@producerclose'); this.safeEmit('producerclose'); @@ -643,7 +845,7 @@ export class Consumer break; } - case 'producerpause': + case Event.CONSUMER_PRODUCER_PAUSE: { if (this.#producerPaused) { @@ -665,7 +867,7 @@ export class Consumer break; } - case 'producerresume': + case Event.CONSUMER_PRODUCER_RESUME: { if (!this.#producerPaused) { @@ -687,9 +889,13 @@ export class Consumer break; } - case 'score': + case Event.CONSUMER_SCORE: { - const score = data as ConsumerScore; + const notification = new FbsConsumer.ScoreNotification(); + + data!.body(notification); + + const score: ConsumerScore = notification!.score()!.unpack(); this.#score = score; @@ -701,9 +907,15 @@ export class Consumer break; } - case 'layerschange': + case Event.CONSUMER_LAYERS_CHANGE: { - const layers = data as ConsumerLayers | undefined; + const notification = new FbsConsumer.LayersChangeNotification()!; + + data!.body(notification); + + const layers: ConsumerLayers | undefined = notification.layers() ? + parseConsumerLayers(notification.layers()!) : + undefined; this.#currentLayers = layers; @@ -715,9 +927,18 @@ export class Consumer break; } - case 'trace': + case Event.CONSUMER_TRACE: { - const trace = data as ConsumerTraceEventData; + const notification = new FbsConsumer.TraceNotification(); + + data!.body(notification); + + const trace: ConsumerTraceEventData = parseTraceEventData(notification); + + this.safeEmit('trace', trace); + + // Emit observer event. + this.observer.safeEmit('trace', trace); this.safeEmit('trace', trace); @@ -727,38 +948,294 @@ export class Consumer break; } + case Event.CONSUMER_RTP: + { + if (this.#closed) + { + break; + } + + const notification = new FbsConsumer.RtpNotification(); + + data!.body(notification); + + this.safeEmit('rtp', Buffer.from(notification.dataArray()!)); + + break; + } + default: { logger.error('ignoring unknown event "%s"', event); } } }); + } +} - this.#payloadChannel.on( - this.#internal.consumerId, - (event: string, data: any | undefined, payload: Buffer) => - { - switch (event) - { - case 'rtp': - { - if (this.#closed) - { - break; - } +export function parseTraceEventData( + trace: FbsConsumer.TraceNotification +): ConsumerTraceEventData +{ + let info: any; - const packet = payload; + if (trace.infoType() !== FbsConsumer.TraceInfo.NONE) + { + const accessor = trace.info.bind(trace); - this.safeEmit('rtp', packet); + info = FbsConsumerTraceInfo.unionToTraceInfo(trace.infoType(), accessor); - break; - } + trace.info(info); + } - default: - { - logger.error('ignoring unknown event "%s"', event); - } - } - }); + return { + type : consumerTraceEventTypeFromFbs(trace.type()), + timestamp : Number(trace.timestamp()), + direction : trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', + info : info ? info.unpack() : undefined + }; +} + +function consumerTraceEventTypeToFbs(eventType: ConsumerTraceEventType) + : FbsConsumer.TraceEventType +{ + switch (eventType) + { + case 'keyframe': + return FbsConsumer.TraceEventType.KEYFRAME; + case 'fir': + return FbsConsumer.TraceEventType.FIR; + case 'nack': + return FbsConsumer.TraceEventType.NACK; + case 'pli': + return FbsConsumer.TraceEventType.PLI; + case 'rtp': + return FbsConsumer.TraceEventType.RTP; + default: + throw new TypeError(`invalid ConsumerTraceEventType: ${eventType}`); } } + +function consumerTraceEventTypeFromFbs(traceType: FbsConsumer.TraceEventType) + : ConsumerTraceEventType +{ + switch (traceType) + { + case FbsConsumer.TraceEventType.KEYFRAME: + return 'keyframe'; + case FbsConsumer.TraceEventType.FIR: + return 'fir'; + case FbsConsumer.TraceEventType.NACK: + return 'nack'; + case FbsConsumer.TraceEventType.PLI: + return 'pli'; + case FbsConsumer.TraceEventType.RTP: + return 'rtp'; + default: + throw new TypeError(`invalid FbsConsumer.TraceEventType: ${traceType}`); + } +} + +function parseConsumerLayers(data: FbsConsumer.ConsumerLayers): ConsumerLayers +{ + const spatialLayer = data.spatialLayer(); + const temporalLayer = data.temporalLayer() !== null ? data.temporalLayer()! : undefined; + + return { + spatialLayer, + temporalLayer + }; +} + +function parseRtpStreamParameters(data: FbsRtpStream.Params): RtpStreamParameters +{ + return { + encodingIdx : data.encodingIdx(), + ssrc : data.ssrc(), + payloadType : data.payloadType(), + mimeType : data.mimeType()!, + clockRate : data.clockRate(), + rid : data.rid()!.length > 0 ? data.rid()! : undefined, + cname : data.cname()!, + rtxSsrc : data.rtxSsrc() !== null ? data.rtxSsrc()! : undefined, + rtxPayloadType : data.rtxPayloadType() !== null ? data.rtxPayloadType()! : undefined, + useNack : data.useNack(), + usePli : data.usePli(), + useFir : data.useFir(), + useInBandFec : data.useInBandFec(), + useDtx : data.useDtx(), + spatialLayers : data.spatialLayers(), + temporalLayers : data.temporalLayers() + }; +} + +function parseRtxStreamParameters(data: FbsRtxStream.Params): RtxStreamParameters +{ + return { + ssrc : data.ssrc(), + payloadType : data.payloadType(), + mimeType : data.mimeType()!, + clockRate : data.clockRate(), + rrid : data.rrid()!.length > 0 ? data.rrid()! : undefined, + cname : data.cname()! + }; +} + +function parseRtxStream(data: FbsRtxStream.RtxDump): RtxStreamDump +{ + const params = parseRtxStreamParameters(data.params()!); + + return { + params + }; +} + +function parseRtpStream(data: FbsRtpStream.Dump): RtpStreamDump +{ + const params = parseRtpStreamParameters(data.params()!); + + let rtxStream: RtxStreamDump | undefined; + + if (data.rtxStream()) + { + rtxStream = parseRtxStream(data.rtxStream()!); + } + + return { + params, + score : data.score(), + rtxStream + }; +} + +function parseBaseConsumerDump(data: FbsConsumer.BaseConsumerDump): BaseConsumerDump +{ + return { + id : data.id()!, + producerId : data.producerId()!, + kind : data.kind() === FbsRtpParameters.MediaKind.AUDIO ? + 'audio' : + 'video', + rtpParameters : parseRtpParameters(data.rtpParameters()!), + consumableRtpEncodings : data.consumableRtpEncodingsLength() > 0 ? + utils.parseVector(data, 'consumableRtpEncodings', parseRtpEncodingParameters) : + undefined, + traceEventTypes : utils.parseVector(data, 'traceEventTypes', consumerTraceEventTypeFromFbs), + supportedCodecPayloadTypes : utils.parseVector(data, 'supportedCodecPayloadTypes'), + paused : data.paused(), + producerPaused : data.producerPaused(), + priority : data.priority() + }; +} + +function parseSimpleConsumerDump(data: FbsConsumer.ConsumerDump): SimpleConsumerDump +{ + const base = parseBaseConsumerDump(data.base()!); + const rtpStream = parseRtpStream(data.rtpStreams(0)!); + + return { + ...base, + type : 'simple', + rtpStream + }; +} + +function parseSimulcastConsumerDump( + data: FbsConsumer.ConsumerDump +) : SimulcastConsumerDump +{ + const base = parseBaseConsumerDump(data.base()!); + const rtpStream = parseRtpStream(data.rtpStreams(0)!); + + return { + ...base, + type : 'simulcast', + rtpStream, + preferredSpatialLayer : data.preferredSpatialLayer()!, + targetSpatialLayer : data.targetSpatialLayer()!, + currentSpatialLayer : data.currentSpatialLayer()!, + preferredTemporalLayer : data.preferredTemporalLayer()!, + targetTemporalLayer : data.targetTemporalLayer()!, + currentTemporalLayer : data.currentTemporalLayer()! + }; +} + +function parseSvcConsumerDump( + data: FbsConsumer.ConsumerDump +) : SvcConsumerDump +{ + const dump = parseSimulcastConsumerDump(data); + + dump.type = 'svc'; + + return dump; +} + +function parsePipeConsumerDump( + data: FbsConsumer.ConsumerDump +) : PipeConsumerDump +{ + const base = parseBaseConsumerDump(data.base()!); + const rtpStreams = utils.parseVector(data, 'rtpStreams', parseRtpStream); + + return { + ...base, + type : 'pipe', + rtpStreams + }; +} + +function parseConsumerDumpResponse(data: FbsConsumer.DumpResponse): ConsumerDump +{ + const type = data.data()!.base()!.type(); + + switch (type) + { + case FbsRtpParametersType.SIMPLE: + { + const dump = new FbsConsumer.ConsumerDump(); + + data.data(dump); + + return parseSimpleConsumerDump(dump); + } + + case FbsRtpParametersType.SIMULCAST: + { + const dump = new FbsConsumer.ConsumerDump(); + + data.data(dump); + + return parseSimulcastConsumerDump(dump); + } + + case FbsRtpParametersType.SVC: + { + const dump = new FbsConsumer.ConsumerDump(); + + data.data(dump); + + return parseSvcConsumerDump(dump); + } + + case FbsRtpParametersType.PIPE: + { + const dump = new FbsConsumer.ConsumerDump(); + + data.data(dump); + + return parsePipeConsumerDump(dump); + } + + default: + { + throw new TypeError(`invalid Consumer type: ${type}`); + } + } +} + +function parseConsumerStats(binary: FbsConsumer.GetStatsResponse) + : Array +{ + return utils.parseVector(binary, 'stats', parseRtpStreamStats); +} diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index a85413c38f..17a41dd41d 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -1,10 +1,15 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; -import { SctpStreamParameters } from './SctpParameters'; +import { parseSctpStreamParameters, SctpStreamParameters } from './SctpParameters'; import { AppData } from './types'; +import * as utils from './utils'; +import { Event, Notification } from './fbs/notification'; +import * as FbsTransport from './fbs/transport'; +import * as FbsRequest from './fbs/request'; +import * as FbsDataConsumer from './fbs/data-consumer'; +import * as FbsDataProducer from './fbs/data-producer'; export type DataConsumerOptions = { @@ -37,6 +42,18 @@ export type DataConsumerOptions = */ maxRetransmits?: number; + /** + * Whether the data consumer must start in paused mode. Default false. + */ + paused?: boolean; + + /** + * Subchannels this data consumer initially subscribes to. + * Only used in case this data consumer receives messages from a local data + * producer that specifies subchannel(s) when calling send(). + */ + subchannels?: number[]; + /** * Custom application data. */ @@ -63,6 +80,8 @@ export type DataConsumerEvents = { transportclose: []; dataproducerclose: []; + dataproducerpause: []; + dataproducerresume: []; message: [Buffer, number]; sctpsendbufferfull: []; bufferedamountlow: [number]; @@ -74,6 +93,16 @@ export type DataConsumerEvents = export type DataConsumerObserverEvents = { close: []; + pause: []; + resume: []; +}; + +type DataConsumerDump = DataConsumerData & +{ + id: string; + paused: boolean; + dataProducerPaused: boolean; + subchannels: number[]; }; type DataConsumerInternal = TransportInternal & @@ -88,6 +117,7 @@ type DataConsumerData = sctpStreamParameters?: SctpStreamParameters; label: string; protocol: string; + bufferedAmountLowThreshold: number; }; const logger = new Logger('DataConsumer'); @@ -104,12 +134,18 @@ export class DataConsumer // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; + // Paused flag. + #paused = false; + + // Associated DataProducer paused flag. + #dataProducerPaused = false; + + // Subchannels subscribed to. + #subchannels: number[]; + // Custom app data. #appData: DataConsumerAppData; @@ -124,14 +160,18 @@ export class DataConsumer internal, data, channel, - payloadChannel, + paused, + dataProducerPaused, + subchannels, appData }: { internal: DataConsumerInternal; data: DataConsumerData; channel: Channel; - payloadChannel: PayloadChannel; + paused: boolean; + dataProducerPaused: boolean; + subchannels: number[]; appData?: DataConsumerAppData; } ) @@ -143,7 +183,9 @@ export class DataConsumer this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; + this.#paused = paused; + this.#dataProducerPaused = dataProducerPaused; + this.#subchannels = subchannels; this.#appData = appData || {} as DataConsumerAppData; this.handleWorkerNotifications(); @@ -205,6 +247,30 @@ export class DataConsumer return this.#data.protocol; } + /** + * Whether the DataConsumer is paused. + */ + get paused(): boolean + { + return this.#paused; + } + + /** + * Whether the associate DataProducer is paused. + */ + get dataProducerPaused(): boolean + { + return this.#dataProducerPaused; + } + + /** + * Get current subchannels this data consumer is subscribed to. + */ + get subchannels(): number[] + { + return Array.from(this.#subchannels); + } + /** * App custom data. */ @@ -245,12 +311,18 @@ export class DataConsumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataConsumerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataConsumerId); - const reqData = { dataConsumerId: this.#internal.dataConsumerId }; + /* Build Request. */ + const requestOffset = new FbsTransport.CloseDataConsumerRequestT( + this.#internal.dataConsumerId + ).pack(this.#channel.bufferBuilder); - this.#channel.request('transport.closeDataConsumer', this.#internal.transportId, reqData) - .catch(() => {}); + this.#channel.request( + FbsRequest.Method.TRANSPORT_CLOSE_DATACONSUMER, + FbsRequest.Body.Transport_CloseDataConsumerRequest, + requestOffset, + this.#internal.transportId + ).catch(() => {}); this.emit('@close'); @@ -276,7 +348,6 @@ export class DataConsumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataConsumerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataConsumerId); this.safeEmit('transportclose'); @@ -287,11 +358,23 @@ export class DataConsumer /** * Dump DataConsumer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('dataConsumer.dump', this.#internal.dataConsumerId); + const response = await this.#channel.request( + FbsRequest.Method.DATACONSUMER_DUMP, + undefined, + undefined, + this.#internal.dataConsumerId + ); + + /* Decode Response. */ + const dumpResponse = new FbsDataConsumer.DumpResponse(); + + response.body(dumpResponse); + + return parseDataConsumerDumpResponse(dumpResponse); } /** @@ -301,7 +384,69 @@ export class DataConsumer { logger.debug('getStats()'); - return this.#channel.request('dataConsumer.getStats', this.#internal.dataConsumerId); + const response = await this.#channel.request( + FbsRequest.Method.DATACONSUMER_GET_STATS, + undefined, + undefined, + this.#internal.dataConsumerId + ); + + /* Decode Response. */ + const data = new FbsDataConsumer.GetStatsResponse(); + + response.body(data); + + return [ parseDataConsumerStats(data) ]; + } + + /** + * Pause the DataConsumer. + */ + async pause(): Promise + { + logger.debug('pause()'); + + const wasPaused = this.#paused; + + await this.#channel.request( + FbsRequest.Method.DATACONSUMER_PAUSE, + undefined, + undefined, + this.#internal.dataConsumerId + ); + + this.#paused = true; + + // Emit observer event. + if (!wasPaused) + { + this.#observer.safeEmit('pause'); + } + } + + /** + * Resume the DataConsumer. + */ + async resume(): Promise + { + logger.debug('resume()'); + + const wasPaused = this.#paused; + + await this.#channel.request( + FbsRequest.Method.DATACONSUMER_RESUME, + undefined, + undefined, + this.#internal.dataConsumerId + ); + + this.#paused = false; + + // Emit observer event. + if (wasPaused) + { + this.#observer.safeEmit('resume'); + } } /** @@ -311,10 +456,16 @@ export class DataConsumer { logger.debug('setBufferedAmountLowThreshold() [threshold:%s]', threshold); - const reqData = { threshold }; + /* Build Request. */ + const requestOffset = FbsDataConsumer.SetBufferedAmountLowThresholdRequest. + createSetBufferedAmountLowThresholdRequest(this.#channel.bufferBuilder, threshold); await this.#channel.request( - 'dataConsumer.setBufferedAmountLowThreshold', this.#internal.dataConsumerId, reqData); + FbsRequest.Method.DATACONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, + FbsRequest.Body.DataConsumer_SetBufferedAmountLowThresholdRequest, + requestOffset, + this.#internal.dataConsumerId + ); } /** @@ -360,10 +511,29 @@ export class DataConsumer message = Buffer.alloc(1); } - const requestData = String(ppid); + const builder = this.#channel.bufferBuilder; + + let dataOffset = 0; + + if (typeof message === 'string') + { + message = Buffer.from(message); + } + + dataOffset = FbsDataConsumer.SendRequest.createDataVector(builder, message); + + const requestOffset = FbsDataConsumer.SendRequest.createSendRequest( + builder, + ppid, + dataOffset + ); - await this.#payloadChannel.request( - 'dataConsumer.send', this.#internal.dataConsumerId, requestData, message); + await this.#channel.request( + FbsRequest.Method.DATACONSUMER_SEND, + FbsRequest.Body.DataConsumer_SendRequest, + requestOffset, + this.#internal.dataConsumerId + ); } /** @@ -373,19 +543,55 @@ export class DataConsumer { logger.debug('getBufferedAmount()'); - const { bufferedAmount } = - await this.#channel.request('dataConsumer.getBufferedAmount', this.#internal.dataConsumerId); + const response = await this.#channel.request( + FbsRequest.Method.DATACONSUMER_GET_BUFFERED_AMOUNT, + undefined, + undefined, + this.#internal.dataConsumerId + ); + + const data = new FbsDataConsumer.GetBufferedAmountResponse(); + + response.body(data); + + return data.bufferedAmount(); + } + + /** + * Set subchannels. + */ + async setSubchannels(subchannels: number[]): Promise + { + logger.debug('setSubchannels()'); + + /* Build Request. */ + const requestOffset = new FbsDataConsumer.SetSubchannelsRequestT( + subchannels + ).pack(this.#channel.bufferBuilder); + + const response = await this.#channel.request( + FbsRequest.Method.DATACONSUMER_SET_SUBCHANNELS, + FbsRequest.Body.DataConsumer_SetSubchannelsRequest, + requestOffset, + this.#internal.dataConsumerId + ); + + /* Decode Response. */ + const data = new FbsDataConsumer.SetSubchannelsResponse(); - return bufferedAmount; + response.body(data); + + // Update subchannels. + this.#subchannels = utils.parseVector(data, 'subchannels'); } private handleWorkerNotifications(): void { - this.#channel.on(this.#internal.dataConsumerId, (event: string, data: any) => + this.#channel.on(this.#internal.dataConsumerId, (event: Event, data?: Notification) => { switch (event) { - case 'dataproducerclose': + case Event.DATACONSUMER_DATAPRODUCER_CLOSE: { if (this.#closed) { @@ -396,7 +602,6 @@ export class DataConsumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataConsumerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataConsumerId); this.emit('@dataproducerclose'); this.safeEmit('dataproducerclose'); @@ -407,55 +612,154 @@ export class DataConsumer break; } - case 'sctpsendbufferfull': + case Event.DATACONSUMER_DATAPRODUCER_PAUSE: { - this.safeEmit('sctpsendbufferfull'); + if (this.#dataProducerPaused) + { + break; + } + + const wasPaused = this.#paused || this.#dataProducerPaused; + + this.#dataProducerPaused = true; + + this.safeEmit('dataproducerpause'); + + // Emit observer event. + if (!wasPaused) + { + this.#observer.safeEmit('pause'); + } break; } - case 'bufferedamountlow': + case Event.DATACONSUMER_DATAPRODUCER_RESUME: { - const { bufferedAmount } = data as { bufferedAmount: number }; + if (!this.#dataProducerPaused) + { + break; + } - this.safeEmit('bufferedamountlow', bufferedAmount); + const wasPaused = this.#paused || this.#dataProducerPaused; + + this.#dataProducerPaused = false; + + this.safeEmit('dataproducerresume'); + + // Emit observer event. + if (wasPaused && !this.#paused) + { + this.#observer.safeEmit('resume'); + } break; } - default: + case Event.DATACONSUMER_SCTP_SENDBUFFER_FULL: { - logger.error('ignoring unknown event "%s" in channel listener', event); + this.safeEmit('sctpsendbufferfull'); + + break; } - } - }); - this.#payloadChannel.on( - this.#internal.dataConsumerId, - (event: string, data: any | undefined, payload: Buffer) => - { - switch (event) + case Event.DATACONSUMER_BUFFERED_AMOUNT_LOW: { - case 'message': - { - if (this.#closed) - { - break; - } + const notification = new FbsDataConsumer.BufferedAmountLowNotification(); - const ppid = data.ppid as number; - const message = payload; + data!.body(notification); - this.safeEmit('message', message, ppid); + const bufferedAmount = notification.bufferedAmount(); - break; - } + this.safeEmit('bufferedamountlow', bufferedAmount); + + break; + } - default: + case Event.DATACONSUMER_MESSAGE: + { + if (this.#closed) { - logger.error('ignoring unknown event "%s" in payload channel listener', event); + break; } + + const notification = new FbsDataConsumer.MessageNotification(); + + data!.body(notification); + + this.safeEmit( + 'message', + Buffer.from(notification.dataArray()!), + notification.ppid() + ); + + break; + } + + default: + { + logger.error('ignoring unknown event "%s" in channel listener', event); } - }); + } + }); + } +} + +export function dataConsumerTypeToFbs(type: DataConsumerType): FbsDataProducer.Type +{ + switch (type) + { + case 'sctp': + return FbsDataProducer.Type.SCTP; + case 'direct': + return FbsDataProducer.Type.DIRECT; + default: + throw new TypeError('invalid DataConsumerType: ${type}'); + } +} + +export function dataConsumerTypeFromFbs(type: FbsDataProducer.Type): DataConsumerType +{ + switch (type) + { + case FbsDataProducer.Type.SCTP: + return 'sctp'; + case FbsDataProducer.Type.DIRECT: + return 'direct'; } } + +export function parseDataConsumerDumpResponse( + data: FbsDataConsumer.DumpResponse +): DataConsumerDump +{ + return { + id : data.id()!, + dataProducerId : data.dataProducerId()!, + type : dataConsumerTypeFromFbs(data.type()), + sctpStreamParameters : data.sctpStreamParameters() !== null ? + parseSctpStreamParameters(data.sctpStreamParameters()!) : + undefined, + label : data.label()!, + protocol : data.protocol()!, + bufferedAmountLowThreshold : data.bufferedAmountLowThreshold(), + paused : data.paused(), + dataProducerPaused : data.dataProducerPaused(), + subchannels : utils.parseVector(data, 'subchannels') + }; +} + +function parseDataConsumerStats( + binary: FbsDataConsumer.GetStatsResponse +): DataConsumerStat +{ + return { + type : 'data-consumer', + timestamp : Number(binary.timestamp()), + label : binary.label()!, + protocol : binary.protocol()!, + messagesSent : Number(binary.messagesSent()), + bytesSent : Number(binary.bytesSent()), + bufferedAmount : binary.bufferedAmount() + }; +} diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 94320ab26d..26fc8efd81 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -1,10 +1,13 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; -import { SctpStreamParameters } from './SctpParameters'; +import { parseSctpStreamParameters, SctpStreamParameters } from './SctpParameters'; import { AppData } from './types'; +import * as FbsTransport from './fbs/transport'; +import * as FbsNotification from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsDataProducer from './fbs/data-producer'; export type DataProducerOptions = { @@ -29,6 +32,11 @@ export type DataProducerOptions = */ protocol?: string; + /** + * Whether the data producer must start in paused mode. Default false. + */ + paused?: boolean; + /** * Custom application data. */ @@ -60,6 +68,14 @@ export type DataProducerEvents = export type DataProducerObserverEvents = { close: []; + pause: []; + resume: []; +}; + +type DataProducerDump = DataProducerData & +{ + id: string; + paused: boolean; }; type DataProducerInternal = TransportInternal & @@ -89,12 +105,12 @@ export class DataProducer // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; + // Paused flag. + #paused = false; + // Custom app data. #appData: DataProducerAppData; @@ -109,14 +125,14 @@ export class DataProducer internal, data, channel, - payloadChannel, + paused, appData }: { internal: DataProducerInternal; data: DataProducerData; channel: Channel; - payloadChannel: PayloadChannel; + paused: boolean; appData?: DataProducerAppData; } ) @@ -128,7 +144,7 @@ export class DataProducer this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; + this.#paused = paused; this.#appData = appData || {} as DataProducerAppData; this.handleWorkerNotifications(); @@ -182,6 +198,14 @@ export class DataProducer return this.#data.protocol; } + /** + * Whether the DataProducer is paused. + */ + get paused(): boolean + { + return this.#paused; + } + /** * App custom data. */ @@ -222,12 +246,18 @@ export class DataProducer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataProducerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataProducerId); - const reqData = { dataProducerId: this.#internal.dataProducerId }; + /* Build Request. */ + const requestOffset = new FbsTransport.CloseDataProducerRequestT( + this.#internal.dataProducerId + ).pack(this.#channel.bufferBuilder); - this.#channel.request('transport.closeDataProducer', this.#internal.transportId, reqData) - .catch(() => {}); + this.#channel.request( + FbsRequest.Method.TRANSPORT_CLOSE_DATAPRODUCER, + FbsRequest.Body.Transport_CloseDataProducerRequest, + requestOffset, + this.#internal.transportId + ).catch(() => {}); this.emit('@close'); @@ -253,7 +283,6 @@ export class DataProducer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataProducerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataProducerId); this.safeEmit('transportclose'); @@ -264,11 +293,23 @@ export class DataProducer /** * Dump DataProducer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('dataProducer.dump', this.#internal.dataProducerId); + const response = await this.#channel.request( + FbsRequest.Method.DATAPRODUCER_DUMP, + undefined, + undefined, + this.#internal.dataProducerId + ); + + /* Decode Response. */ + const produceResponse = new FbsDataProducer.DumpResponse(); + + response.body(produceResponse); + + return parseDataProducerDumpResponse(produceResponse); } /** @@ -278,13 +319,80 @@ export class DataProducer { logger.debug('getStats()'); - return this.#channel.request('dataProducer.getStats', this.#internal.dataProducerId); + const response = await this.#channel.request( + FbsRequest.Method.DATAPRODUCER_GET_STATS, + undefined, + undefined, + this.#internal.dataProducerId + ); + + /* Decode Response. */ + const data = new FbsDataProducer.GetStatsResponse(); + + response.body(data); + + return [ parseDataProducerStats(data) ]; + } + + /** + * Pause the DataProducer. + */ + async pause(): Promise + { + logger.debug('pause()'); + + const wasPaused = this.#paused; + + await this.#channel.request( + FbsRequest.Method.DATAPRODUCER_PAUSE, + undefined, + undefined, + this.#internal.dataProducerId + ); + + this.#paused = true; + + // Emit observer event. + if (!wasPaused) + { + this.#observer.safeEmit('pause'); + } + } + + /** + * Resume the DataProducer. + */ + async resume(): Promise + { + logger.debug('resume()'); + + const wasPaused = this.#paused; + + await this.#channel.request( + FbsRequest.Method.DATAPRODUCER_RESUME, + undefined, + undefined, + this.#internal.dataProducerId + ); + + this.#paused = false; + + // Emit observer event. + if (wasPaused) + { + this.#observer.safeEmit('resume'); + } } /** * Send data (just valid for DataProducers created on a DirectTransport). */ - send(message: string | Buffer, ppid?: number): void + send( + message: string | Buffer, + ppid?: number, + subchannels?: number[], + requiredSubchannel?: number + ): void { if (typeof message !== 'string' && !Buffer.isBuffer(message)) { @@ -324,10 +432,35 @@ export class DataProducer message = Buffer.alloc(1); } - const notifData = String(ppid); + const builder = this.#channel.bufferBuilder; + + let dataOffset = 0; + + const subchannelsOffset = FbsDataProducer.SendNotification.createSubchannelsVector( + builder, subchannels ?? [] + ); + + if (typeof message === 'string') + { + message = Buffer.from(message); + } - this.#payloadChannel.notify( - 'dataProducer.send', this.#internal.dataProducerId, notifData, message); + dataOffset = FbsDataProducer.SendNotification.createDataVector(builder, message); + + const notificationOffset = FbsDataProducer.SendNotification.createSendNotification( + builder, + ppid, + dataOffset, + subchannelsOffset, + requiredSubchannel ?? null + ); + + this.#channel.notify( + FbsNotification.Event.DATAPRODUCER_SEND, + FbsNotification.Body.DataProducer_SendNotification, + notificationOffset, + this.#internal.dataProducerId + ); } private handleWorkerNotifications(): void @@ -335,3 +468,57 @@ export class DataProducer // No need to subscribe to any event. } } + +export function dataProducerTypeToFbs(type: DataProducerType): FbsDataProducer.Type +{ + switch (type) + { + case 'sctp': + return FbsDataProducer.Type.SCTP; + case 'direct': + return FbsDataProducer.Type.DIRECT; + default: + throw new TypeError('invalid DataConsumerType: ${type}'); + } +} + +export function dataProducerTypeFromFbs(type: FbsDataProducer.Type): DataProducerType +{ + switch (type) + { + case FbsDataProducer.Type.SCTP: + return 'sctp'; + case FbsDataProducer.Type.DIRECT: + return 'direct'; + } +} + +export function parseDataProducerDumpResponse( + data: FbsDataProducer.DumpResponse +): DataProducerDump +{ + return { + id : data.id()!, + type : dataProducerTypeFromFbs(data.type()), + sctpStreamParameters : data.sctpStreamParameters() !== null ? + parseSctpStreamParameters(data.sctpStreamParameters()!) : + undefined, + label : data.label()!, + protocol : data.protocol()!, + paused : data.paused() + }; +} + +function parseDataProducerStats( + binary: FbsDataProducer.GetStatsResponse +): DataProducerStat +{ + return { + type : 'data-producer', + timestamp : Number(binary.timestamp()), + label : binary.label()!, + protocol : binary.protocol()!, + messagesReceived : Number(binary.messagesReceived()), + bytesReceived : Number(binary.bytesReceived()) + }; +} diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 3775f02eb5..99da02ede9 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -1,14 +1,23 @@ import { Logger } from './Logger'; import { UnsupportedError } from './errors'; import { + BaseTransportDump, + BaseTransportStats, + parseBaseTransportDump, + parseBaseTransportStats, + parseTransportTraceEventData, Transport, - TransportTraceEventData, TransportEvents, TransportObserverEvents, TransportConstructorOptions } from './Transport'; import { SctpParameters } from './SctpParameters'; import { AppData } from './types'; +import { Event, Notification } from './fbs/notification'; +import * as FbsDirectTransport from './fbs/direct-transport'; +import * as FbsTransport from './fbs/transport'; +import * as FbsNotification from './fbs/notification'; +import * as FbsRequest from './fbs/request'; export type DirectTransportOptions = { @@ -24,29 +33,11 @@ export type DirectTransportOptions super.routerClosed(); } + /** + * Dump Transport. + */ + async dump(): Promise + { + logger.debug('dump()'); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_DUMP, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsDirectTransport.DumpResponse(); + + response.body(data); + + return parseDirectTransportDumpResponse(data); + } + /** * Get DirectTransport stats. * @@ -135,7 +148,19 @@ export class DirectTransport { logger.debug('getStats()'); - return this.channel.request('transport.getStats', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_GET_STATS, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsDirectTransport.GetStatsResponse(); + + response.body(data); + + return [ parseGetStatsResponse(data) ]; } /** @@ -188,19 +213,37 @@ export class DirectTransport throw new TypeError('rtcpPacket must be a Buffer'); } - this.payloadChannel.notify( - 'transport.sendRtcp', this.internal.transportId, undefined, rtcpPacket); + const builder = this.channel.bufferBuilder; + const dataOffset = + FbsTransport.SendRtcpNotification.createDataVector(builder, rtcpPacket); + const notificationOffset = + FbsTransport.SendRtcpNotification.createSendRtcpNotification( + builder, + dataOffset + ); + + this.channel.notify( + FbsNotification.Event.TRANSPORT_SEND_RTCP, + FbsNotification.Body.Transport_SendRtcpNotification, + notificationOffset, + this.internal.transportId + ); + } private handleWorkerNotifications(): void { - this.channel.on(this.internal.transportId, (event: string, data?: any) => + this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => { switch (event) { - case 'trace': + case Event.TRANSPORT_TRACE: { - const trace = data as TransportTraceEventData; + const notification = new FbsTransport.TraceNotification(); + + data!.body(notification); + + const trace = parseTransportTraceEventData(notification); this.safeEmit('trace', trace); @@ -210,38 +253,46 @@ export class DirectTransport break; } + case Event.DIRECTTRANSPORT_RTCP: + { + if (this.closed) + { + break; + } + + const notification = new FbsDirectTransport.RtcpNotification(); + + data!.body(notification); + + this.safeEmit('rtcp', Buffer.from(notification.dataArray()!)); + + break; + } + default: { logger.error('ignoring unknown event "%s"', event); } } }); + } +} - this.payloadChannel.on( - this.internal.transportId, - (event: string, data: any | undefined, payload: Buffer) => - { - switch (event) - { - case 'rtcp': - { - if (this.closed) - { - break; - } - - const packet = payload; - - this.safeEmit('rtcp', packet); +export function parseDirectTransportDumpResponse( + binary: FbsDirectTransport.DumpResponse +): BaseTransportDump +{ + return parseBaseTransportDump(binary.base()!); +} - break; - } +function parseGetStatsResponse( + binary: FbsDirectTransport.GetStatsResponse +):DirectTransportStat +{ + const base = parseBaseTransportStats(binary.base()!); - default: - { - logger.error('ignoring unknown event "%s"', event); - } - } - }); - } + return { + ...base, + type : 'direct-transport' + }; } diff --git a/node/src/EnhancedEventEmitter.ts b/node/src/EnhancedEventEmitter.ts index b6b1dc0eab..f2e3a057d5 100644 --- a/node/src/EnhancedEventEmitter.ts +++ b/node/src/EnhancedEventEmitter.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from 'events'; +import { EventEmitter } from 'node:events'; import { Logger } from './Logger'; const logger = new Logger('EnhancedEventEmitter'); diff --git a/node/src/PayloadChannel.ts b/node/src/PayloadChannel.ts deleted file mode 100644 index d8f8074703..0000000000 --- a/node/src/PayloadChannel.ts +++ /dev/null @@ -1,402 +0,0 @@ -import * as os from 'os'; -import { Duplex } from 'stream'; -import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; -import { InvalidStateError } from './errors'; - -const littleEndian = os.endianness() == 'LE'; -const logger = new Logger('PayloadChannel'); - -type Sent = -{ - id: number; - method: string; - resolve: (data?: any) => void; - reject: (error: Error) => void; - close: () => void; -}; - -// Binary length for a 4194304 bytes payload. -const MESSAGE_MAX_LEN = 4194308; -const PAYLOAD_MAX_LEN = 4194304; - -export class PayloadChannel extends EnhancedEventEmitter -{ - // Closed flag. - #closed = false; - - // Unix Socket instance for sending messages to the worker process. - readonly #producerSocket: Duplex; - - // Unix Socket instance for receiving messages to the worker process. - readonly #consumerSocket: Duplex; - - // Next id for messages sent to the worker process. - #nextId = 0; - - // Map of pending sent requests. - readonly #sents: Map = new Map(); - - // Buffer for reading messages from the worker. - #recvBuffer = Buffer.alloc(0); - - // Ongoing notification (waiting for its payload). - #ongoingNotification?: { targetId: string; event: string; data?: any }; - - /** - * @private - */ - constructor( - { - producerSocket, - consumerSocket - }: - { - producerSocket: any; - consumerSocket: any; - }) - { - super(); - - logger.debug('constructor()'); - - this.#producerSocket = producerSocket as Duplex; - this.#consumerSocket = consumerSocket as Duplex; - - // Read PayloadChannel notifications from the worker. - this.#consumerSocket.on('data', (buffer: Buffer) => - { - if (!this.#recvBuffer.length) - { - this.#recvBuffer = buffer; - } - else - { - this.#recvBuffer = Buffer.concat( - [ this.#recvBuffer, buffer ], - this.#recvBuffer.length + buffer.length); - } - - if (this.#recvBuffer.length > PAYLOAD_MAX_LEN) - { - logger.error('receiving buffer is full, discarding all data in it'); - - // Reset the buffer and exit. - this.#recvBuffer = Buffer.alloc(0); - - return; - } - - let msgStart = 0; - - while (true) // eslint-disable-line no-constant-condition - { - const readLen = this.#recvBuffer.length - msgStart; - - if (readLen < 4) - { - // Incomplete data. - break; - } - - const dataView = new DataView( - this.#recvBuffer.buffer, - this.#recvBuffer.byteOffset + msgStart); - const msgLen = dataView.getUint32(0, littleEndian); - - if (readLen < 4 + msgLen) - { - // Incomplete data. - break; - } - - const payload = this.#recvBuffer.subarray(msgStart + 4, msgStart + 4 + msgLen); - - msgStart += 4 + msgLen; - - this.processData(payload); - } - - if (msgStart != 0) - { - this.#recvBuffer = this.#recvBuffer.slice(msgStart); - } - }); - - this.#consumerSocket.on('end', () => ( - logger.debug('Consumer PayloadChannel ended by the worker process') - )); - - this.#consumerSocket.on('error', (error) => ( - logger.error('Consumer PayloadChannel error: %s', String(error)) - )); - - this.#producerSocket.on('end', () => ( - logger.debug('Producer PayloadChannel ended by the worker process') - )); - - this.#producerSocket.on('error', (error) => ( - logger.error('Producer PayloadChannel error: %s', String(error)) - )); - } - - /** - * @private - */ - close(): void - { - if (this.#closed) - { - return; - } - - logger.debug('close()'); - - this.#closed = true; - - // Remove event listeners but leave a fake 'error' handler to avoid - // propagation. - this.#consumerSocket.removeAllListeners('end'); - this.#consumerSocket.removeAllListeners('error'); - this.#consumerSocket.on('error', () => {}); - - this.#producerSocket.removeAllListeners('end'); - this.#producerSocket.removeAllListeners('error'); - this.#producerSocket.on('error', () => {}); - - // Destroy the socket after a while to allow pending incoming messages. - setTimeout(() => - { - try { this.#producerSocket.destroy(); } - catch (error) {} - try { this.#consumerSocket.destroy(); } - catch (error) {} - }, 200); - } - - /** - * @private - */ - notify( - event: string, - handlerId: string, - data: string | undefined, - payload: string | Buffer - ): void - { - logger.debug('notify() [event:%s]', event); - - if (this.#closed) - { - throw new InvalidStateError('PayloadChannel closed'); - } - - const notification = `n:${event}:${handlerId}:${data}`; - - if (Buffer.byteLength(notification) > MESSAGE_MAX_LEN) - { - throw new Error('PayloadChannel notification too big'); - } - else if (Buffer.byteLength(payload) > MESSAGE_MAX_LEN) - { - throw new Error('PayloadChannel payload too big'); - } - - try - { - // This may throw if closed or remote side ended. - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(notification)).buffer)); - this.#producerSocket.write(notification); - } - catch (error) - { - logger.warn('notify() | sending notification failed: %s', String(error)); - - return; - } - - try - { - // This may throw if closed or remote side ended. - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(payload)).buffer)); - this.#producerSocket.write(payload); - } - catch (error) - { - logger.warn('notify() | sending payload failed: %s', String(error)); - - return; - } - } - - /** - * @private - */ - async request( - method: string, - handlerId: string, - data: string, - payload: string | Buffer): Promise - { - this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1); - - const id = this.#nextId; - - logger.debug('request() [method:%s, id:%s]', method, id); - - if (this.#closed) - { - throw new InvalidStateError('PayloadChannel closed'); - } - - const request = `r:${id}:${method}:${handlerId}:${data}`; - - if (Buffer.byteLength(request) > MESSAGE_MAX_LEN) - { - throw new Error('PayloadChannel request too big'); - } - else if (Buffer.byteLength(payload) > MESSAGE_MAX_LEN) - { - throw new Error('PayloadChannel payload too big'); - } - - // This may throw if closed or remote side ended. - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(request)).buffer)); - this.#producerSocket.write(request); - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(payload)).buffer)); - this.#producerSocket.write(payload); - - return new Promise((pResolve, pReject) => - { - const sent: Sent = - { - id : id, - method : method, - resolve : (data2) => - { - if (!this.#sents.delete(id)) - { - return; - } - - pResolve(data2); - }, - reject : (error) => - { - if (!this.#sents.delete(id)) - { - return; - } - - pReject(error); - }, - close : () => - { - pReject(new InvalidStateError('PayloadChannel closed')); - } - }; - - // Add sent stuff to the map. - this.#sents.set(id, sent); - }); - } - - private processData(data: Buffer): void - { - if (!this.#ongoingNotification) - { - let msg; - - try - { - msg = JSON.parse(data.toString('utf8')); - } - catch (error) - { - logger.error( - 'received invalid data from the worker process: %s', - String(error)); - - return; - } - - // If a response, retrieve its associated request. - if (msg.id) - { - const sent = this.#sents.get(msg.id); - - if (!sent) - { - logger.error( - 'received response does not match any sent request [id:%s]', msg.id); - - return; - } - - if (msg.accepted) - { - logger.debug( - 'request succeeded [method:%s, id:%s]', sent.method, sent.id); - - sent.resolve(msg.data); - } - else if (msg.error) - { - logger.warn( - 'request failed [method:%s, id:%s]: %s', - sent.method, sent.id, msg.reason); - - switch (msg.error) - { - case 'TypeError': - sent.reject(new TypeError(msg.reason)); - break; - - default: - sent.reject(new Error(msg.reason)); - } - } - else - { - logger.error( - 'received response is not accepted nor rejected [method:%s, id:%s]', - sent.method, sent.id); - } - } - // If a notification, create the ongoing notification instance. - else if (msg.targetId && msg.event) - { - this.#ongoingNotification = - { - targetId : String(msg.targetId), - event : msg.event, - data : msg.data - }; - } - else - { - logger.error('received data is not a notification nor a response'); - - return; - } - } - else - { - const payload = data as Buffer; - - // Emit the corresponding event. - this.emit( - this.#ongoingNotification.targetId, - this.#ongoingNotification.event, - this.#ongoingNotification.data, - payload); - - // Unset ongoing notification. - this.#ongoingNotification = undefined; - } - } -} diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index 90185d46a0..d0cd72d8cd 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -1,22 +1,50 @@ -import { v4 as uuidv4 } from 'uuid'; +import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import * as ortc from './ortc'; import { + BaseTransportDump, + BaseTransportStats, + parseBaseTransportDump, + parseBaseTransportStats, + parseSctpState, + parseTuple, + parseTransportTraceEventData, Transport, + TransportListenInfo, TransportListenIp, TransportTuple, - TransportTraceEventData, TransportEvents, TransportObserverEvents, TransportConstructorOptions, SctpState } from './Transport'; import { Consumer, ConsumerType } from './Consumer'; +import { Producer } from './Producer'; +import { RtpParameters, serializeRtpEncodingParameters, serializeRtpParameters } from './RtpParameters'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; -import { SrtpParameters } from './SrtpParameters'; -import { AppData } from './types'; +import { + parseSrtpParameters, + serializeSrtpParameters, + SrtpParameters +} from './SrtpParameters'; +import { AppData, Either } from './types'; +import { generateUUIDv4 } from './utils'; +import { MediaKind as FbsMediaKind } from './fbs/rtp-parameters/media-kind'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; +import { Event, Notification } from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsPipeTransport from './fbs/pipe-transport'; + +type PipeTransportListenInfo = +{ + /** + * Listening info. + */ + listenInfo: TransportListenInfo; +}; -export type PipeTransportOptions = +type PipeTransportListenIp = { /** * Listening IP address. @@ -28,7 +56,12 @@ export type PipeTransportOptions * range. */ port?: number; +}; + +type PipeTransportListen = Either; +export type PipeTransportOptions = +{ /** * Create a SCTP association. Default false. */ @@ -69,33 +102,11 @@ export type PipeTransportOptions * Custom application data. */ appData?: PipeTransportAppData; -}; +} & PipeTransportListen; -export type PipeTransportStat = +export type PipeTransportStat = BaseTransportStats & { - // Common to all Transports. type: string; - transportId: string; - timestamp: number; - sctpState?: SctpState; - bytesReceived: number; - recvBitrate: number; - bytesSent: number; - sendBitrate: number; - rtpBytesReceived: number; - rtpRecvBitrate: number; - rtpBytesSent: number; - rtpSendBitrate: number; - rtxBytesReceived: number; - rtxRecvBitrate: number; - rtxBytesSent: number; - rtxSendBitrate: number; - probationBytesSent: number; - probationSendBitrate: number; - availableOutgoingBitrate?: number; - availableIncomingBitrate?: number; - maxIncomingBitrate?: number; - // PipeTransport specific. tuple: TransportTuple; }; @@ -137,6 +148,13 @@ export type PipeTransportData = srtpParameters?: SrtpParameters; }; +export type PipeTransportDump = BaseTransportDump & +{ + tuple: TransportTuple; + rtx: boolean; + srtpParameters?: SrtpParameters; +}; + const logger = new Logger('PipeTransport'); export class PipeTransport @@ -250,7 +268,19 @@ export class PipeTransport { logger.debug('getStats()'); - return this.channel.request('transport.getStats', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_GET_STATS, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPipeTransport.GetStatsResponse(); + + response.body(data); + + return [ parseGetStatsResponse(data) ]; } /** @@ -273,13 +303,31 @@ export class PipeTransport { logger.debug('connect()'); - const reqData = { ip, port, srtpParameters }; + const requestOffset = createConnectRequest({ + builder : this.channel.bufferBuilder, + ip, + port, + srtpParameters + }); - const data = - await this.channel.request('transport.connect', this.internal.transportId, reqData); + // Wait for response. + const response = await this.channel.request( + FbsRequest.Method.PIPETRANSPORT_CONNECT, + FbsRequest.Body.PipeTransport_ConnectRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPipeTransport.ConnectResponse(); + + response.body(data); // Update data. - this.#data.tuple = data.tuple; + if (data.tuple()) + { + this.#data.tuple = parseTuple(data.tuple()!); + } } /** @@ -320,18 +368,28 @@ export class PipeTransport } ); - const reqData = - { - consumerId : uuidv4(), - producerId, - kind : producer.kind, - rtpParameters, - type : 'pipe', - consumableRtpEncodings : producer.consumableRtpParameters.encodings - }; + const consumerId = generateUUIDv4(); - const status = - await this.channel.request('transport.consume', this.internal.transportId, reqData); + const consumeRequestOffset = createConsumeRequest({ + builder : this.channel.bufferBuilder, + consumerId, + producer, + rtpParameters + }); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_CONSUME, + FbsRequest.Body.Transport_ConsumeRequest, + consumeRequestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const consumeResponse = new FbsTransport.ConsumeResponse(); + + response.body(consumeResponse); + + const status = consumeResponse.unpack(); const data = { @@ -346,11 +404,10 @@ export class PipeTransport internal : { ...this.internal, - consumerId : reqData.consumerId + consumerId }, data, channel : this.channel, - payloadChannel : this.payloadChannel, appData, paused : status.paused, producerPaused : status.producerPaused @@ -368,13 +425,17 @@ export class PipeTransport private handleWorkerNotifications(): void { - this.channel.on(this.internal.transportId, (event: string, data?: any) => + this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => { switch (event) { - case 'sctpstatechange': + case Event.TRANSPORT_SCTP_STATE_CHANGE: { - const sctpState = data.sctpState as SctpState; + const notification = new FbsTransport.SctpStateChangeNotification(); + + data!.body(notification); + + const sctpState = parseSctpState(notification.sctpState()); this.#data.sctpState = sctpState; @@ -386,9 +447,13 @@ export class PipeTransport break; } - case 'trace': + case Event.TRANSPORT_TRACE: { - const trace = data as TransportTraceEventData; + const notification = new FbsTransport.TraceNotification(); + + data!.body(notification); + + const trace = parseTransportTraceEventData(notification); this.safeEmit('trace', trace); @@ -406,3 +471,136 @@ export class PipeTransport }); } } + +/* + * flatbuffers helpers. + */ + +export function parsePipeTransportDumpResponse( + binary: FbsPipeTransport.DumpResponse +): PipeTransportDump +{ + // Retrieve BaseTransportDump. + const baseTransportDump = parseBaseTransportDump(binary.base()!); + // Retrieve RTP Tuple. + const tuple = parseTuple(binary.tuple()!); + + // Retrieve SRTP Parameters. + let srtpParameters: SrtpParameters | undefined; + + if (binary.srtpParameters()) + { + srtpParameters = parseSrtpParameters(binary.srtpParameters()!); + } + + return { + ...baseTransportDump, + tuple : tuple, + rtx : binary.rtx(), + srtpParameters : srtpParameters + }; +} + +function parseGetStatsResponse( + binary: FbsPipeTransport.GetStatsResponse +):PipeTransportStat +{ + const base = parseBaseTransportStats(binary.base()!); + + return { + ...base, + type : 'pipe-transport', + tuple : parseTuple(binary.tuple()!) + }; +} + +function createConsumeRequest({ + builder, + consumerId, + producer, + rtpParameters +} : { + builder: flatbuffers.Builder; + consumerId: string; + producer: Producer; + rtpParameters: RtpParameters; +}): number +{ + // Build the request. + const producerIdOffset = builder.createString(producer.id); + const consumerIdOffset = builder.createString(consumerId); + const rtpParametersOffset = serializeRtpParameters(builder, rtpParameters); + let consumableRtpEncodingsOffset: number | undefined; + + if (producer.consumableRtpParameters.encodings) + { + consumableRtpEncodingsOffset = serializeRtpEncodingParameters( + builder, producer.consumableRtpParameters.encodings + ); + } + + const ConsumeRequest = FbsTransport.ConsumeRequest; + + // Create Consume Request. + ConsumeRequest.startConsumeRequest(builder); + ConsumeRequest.addConsumerId(builder, consumerIdOffset); + ConsumeRequest.addProducerId(builder, producerIdOffset); + ConsumeRequest.addKind( + builder, producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO); + ConsumeRequest.addRtpParameters(builder, rtpParametersOffset); + ConsumeRequest.addType(builder, FbsRtpParameters.Type.PIPE); + + if (consumableRtpEncodingsOffset) + { + ConsumeRequest.addConsumableRtpEncodings(builder, consumableRtpEncodingsOffset); + } + + return ConsumeRequest.endConsumeRequest(builder); +} + +function createConnectRequest( + { + builder, + ip, + port, + srtpParameters + }: + { + builder: flatbuffers.Builder; + ip?: string; + port?: number; + srtpParameters?: SrtpParameters; + } +): number +{ + let ipOffset = 0; + let srtpParametersOffset = 0; + + if (ip) + { + ipOffset = builder.createString(ip); + } + + // Serialize SrtpParameters. + if (srtpParameters) + { + srtpParametersOffset = serializeSrtpParameters(builder, srtpParameters); + } + + // Create PlainTransportConnectData. + FbsPipeTransport.ConnectRequest.startConnectRequest(builder); + FbsPipeTransport.ConnectRequest.addIp(builder, ipOffset); + + if (typeof port === 'number') + { + FbsPipeTransport.ConnectRequest.addPort(builder, port); + } + if (srtpParameters) + { + FbsPipeTransport.ConnectRequest.addSrtpParameters( + builder, srtpParametersOffset + ); + } + + return FbsPipeTransport.ConnectRequest.endConnectRequest(builder); +} diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index e20fe1500d..2852b30485 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -1,19 +1,49 @@ +import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { + parseSctpState, + BaseTransportDump, + BaseTransportStats, + parseTuple, + parseBaseTransportDump, + parseBaseTransportStats, + parseTransportTraceEventData, Transport, + TransportListenInfo, TransportListenIp, TransportTuple, - TransportTraceEventData, TransportEvents, TransportObserverEvents, TransportConstructorOptions, SctpState } from './Transport'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; -import { SrtpParameters, SrtpCryptoSuite } from './SrtpParameters'; -import { AppData } from './types'; +import { + parseSrtpParameters, + serializeSrtpParameters, + SrtpParameters, + SrtpCryptoSuite +} from './SrtpParameters'; +import { AppData, Either } from './types'; +import { Event, Notification } from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsPlainTransport from './fbs/plain-transport'; + +type PlainTransportListenInfo = +{ + /** + * Listening info. + */ + listenInfo: TransportListenInfo; -export type PlainTransportOptions = + /** + * Optional listening info for RTCP. + */ + rtcpListenInfo?: TransportListenInfo; +}; + +type PlainTransportListenIp = { /** * Listening IP address. @@ -25,7 +55,12 @@ export type PlainTransportOptions; +export type PlainTransportOptions = +{ /** * Use RTCP-mux (RTP and RTCP in the same port). Default true. */ @@ -77,33 +112,11 @@ export type PlainTransportOptions @@ -255,6 +277,28 @@ export class PlainTransport super.routerClosed(); } + /** + * Dump Transport. + */ + async dump(): Promise + { + logger.debug('dump()'); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_DUMP, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPlainTransport.DumpResponse(); + + response.body(data); + + return parsePlainTransportDumpResponse(data); + } + /** * Get PlainTransport stats. * @@ -264,7 +308,19 @@ export class PlainTransport { logger.debug('getStats()'); - return this.channel.request('transport.getStats', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_GET_STATS, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPlainTransport.GetStatsResponse(); + + response.body(data); + + return [ parseGetStatsResponse(data) ]; } /** @@ -289,34 +345,58 @@ export class PlainTransport { logger.debug('connect()'); - const reqData = { ip, port, rtcpPort, srtpParameters }; + const requestOffset = createConnectRequest({ + builder : this.channel.bufferBuilder, + ip, + port, + rtcpPort, + srtpParameters + }); - const data = - await this.channel.request('transport.connect', this.internal.transportId, reqData); + // Wait for response. + const response = await this.channel.request( + FbsRequest.Method.PLAINTRANSPORT_CONNECT, + FbsRequest.Body.PlainTransport_ConnectRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPlainTransport.ConnectResponse(); + + response.body(data); // Update data. - if (data.tuple) + if (data.tuple()) { - this.#data.tuple = data.tuple; + this.#data.tuple = parseTuple(data.tuple()!); } - if (data.rtcpTuple) + if (data.rtcpTuple()) { - this.#data.rtcpTuple = data.rtcpTuple; + this.#data.rtcpTuple = parseTuple(data.rtcpTuple()!); } - this.#data.srtpParameters = data.srtpParameters; + if (data.srtpParameters()) + { + this.#data.srtpParameters = parseSrtpParameters( + data.srtpParameters()!); + } } private handleWorkerNotifications(): void { - this.channel.on(this.internal.transportId, (event: string, data?: any) => + this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => { switch (event) { - case 'tuple': + case Event.PLAINTRANSPORT_TUPLE: { - const tuple = data.tuple as TransportTuple; + const notification = new FbsPlainTransport.TupleNotification(); + + data!.body(notification); + + const tuple = parseTuple(notification.tuple()!); this.#data.tuple = tuple; @@ -328,9 +408,13 @@ export class PlainTransport break; } - case 'rtcptuple': + case Event.PLAINTRANSPORT_RTCP_TUPLE: { - const rtcpTuple = data.rtcpTuple as TransportTuple; + const notification = new FbsPlainTransport.RtcpTupleNotification(); + + data!.body(notification); + + const rtcpTuple = parseTuple(notification.tuple()!); this.#data.rtcpTuple = rtcpTuple; @@ -342,9 +426,13 @@ export class PlainTransport break; } - case 'sctpstatechange': + case Event.TRANSPORT_SCTP_STATE_CHANGE: { - const sctpState = data.sctpState as SctpState; + const notification = new FbsTransport.SctpStateChangeNotification(); + + data!.body(notification); + + const sctpState = parseSctpState(notification.sctpState()); this.#data.sctpState = sctpState; @@ -356,9 +444,13 @@ export class PlainTransport break; } - case 'trace': + case Event.TRANSPORT_TRACE: { - const trace = data as TransportTraceEventData; + const notification = new FbsTransport.TraceNotification(); + + data!.body(notification); + + const trace = parseTransportTraceEventData(notification); this.safeEmit('trace', trace); @@ -376,3 +468,109 @@ export class PlainTransport }); } } + +export function parsePlainTransportDumpResponse( + binary: FbsPlainTransport.DumpResponse +): PlainTransportDump +{ + // Retrieve BaseTransportDump. + const baseTransportDump = parseBaseTransportDump(binary.base()!); + // Retrieve RTP Tuple. + const tuple = parseTuple(binary.tuple()!); + + // Retrieve RTCP Tuple. + let rtcpTuple: TransportTuple | undefined; + + if (binary.rtcpTuple()) + { + rtcpTuple = parseTuple(binary.rtcpTuple()!); + } + + // Retrieve SRTP Parameters. + let srtpParameters: SrtpParameters | undefined; + + if (binary.srtpParameters()) + { + srtpParameters = parseSrtpParameters(binary.srtpParameters()!); + } + + return { + ...baseTransportDump, + rtcpMux : binary.rtcpMux(), + comedia : binary.comedia(), + tuple : tuple, + rtcpTuple : rtcpTuple, + srtpParameters : srtpParameters + }; +} + +function parseGetStatsResponse( + binary: FbsPlainTransport.GetStatsResponse +):PlainTransportStat +{ + const base = parseBaseTransportStats(binary.base()!); + + return { + ...base, + type : 'plain-rtp-transport', + rtcpMux : binary.rtcpMux(), + comedia : binary.comedia(), + tuple : parseTuple(binary.tuple()!), + rtcpTuple : binary.rtcpTuple() ? + parseTuple(binary.rtcpTuple()!) : + undefined + }; +} + +function createConnectRequest( + { + builder, + ip, + port, + rtcpPort, + srtpParameters + }: + { + builder : flatbuffers.Builder; + ip?: string; + port?: number; + rtcpPort?: number; + srtpParameters?: SrtpParameters; + } +): number +{ + let ipOffset = 0; + let srtpParametersOffset = 0; + + if (ip) + { + ipOffset = builder.createString(ip); + } + + // Serialize SrtpParameters. + if (srtpParameters) + { + srtpParametersOffset = serializeSrtpParameters(builder, srtpParameters); + } + + // Create PlainTransportConnectData. + FbsPlainTransport.ConnectRequest.startConnectRequest(builder); + FbsPlainTransport.ConnectRequest.addIp(builder, ipOffset); + + if (typeof port === 'number') + { + FbsPlainTransport.ConnectRequest.addPort(builder, port); + } + if (typeof rtcpPort === 'number') + { + FbsPlainTransport.ConnectRequest.addRtcpPort(builder, rtcpPort); + } + if (srtpParameters) + { + FbsPlainTransport.ConnectRequest.addSrtpParameters( + builder, srtpParametersOffset + ); + } + + return FbsPlainTransport.ConnectRequest.endConnectRequest(builder); +} diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 2d152ffb40..d145bcf156 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -1,10 +1,19 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; -import { MediaKind, RtpParameters } from './RtpParameters'; +import { MediaKind, RtpParameters, parseRtpParameters } from './RtpParameters'; +import { Event, Notification } from './fbs/notification'; +import { parseRtpStreamRecvStats, RtpStreamRecvStats } from './RtpStream'; import { AppData } from './types'; +import * as utils from './utils'; +import { TraceDirection as FbsTraceDirection } from './fbs/common'; +import * as FbsNotification from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsProducer from './fbs/producer'; +import * as FbsProducerTraceInfo from './fbs/producer/trace-info'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; export type ProducerOptions = { @@ -107,35 +116,7 @@ export type ProducerVideoOrientation = rotation: number; }; -export type ProducerStat = -{ - // Common to all RtpStreams. - type: string; - timestamp: number; - ssrc: number; - rtxSsrc?: number; - rid?: string; - kind: string; - mimeType: string; - packetsLost: number; - fractionLost: number; - packetsDiscarded: number; - packetsRetransmitted: number; - packetsRepaired: number; - nackCount: number; - nackPacketCount: number; - pliCount: number; - firCount: number; - score: number; - packetCount: number; - byteCount: number; - bitrate: number; - roundTripTime?: number; - rtxPacketsDiscarded?: number; - // RtpStreamRecv specific. - jitter: number; - bitrateByLayer?: any; -}; +export type ProducerStat = RtpStreamRecvStats; /** * Producer type. @@ -162,6 +143,18 @@ export type ProducerObserverEvents = trace: [ProducerTraceEventData]; }; +type ProducerDump = +{ + id: string; + kind: string; + type: ProducerType; + rtpParameters: RtpParameters; + rtpMapping: any; + rtpStreams: any; + traceEventTypes: string[]; + paused: boolean; +}; + type ProducerInternal = TransportInternal & { producerId: string; @@ -189,18 +182,15 @@ export class Producer // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; - // Custom app data. - #appData: ProducerAppData; - // Paused flag. #paused = false; + // Custom app data. + #appData: ProducerAppData; + // Current score. #score: ProducerScore[] = []; @@ -215,7 +205,6 @@ export class Producer internal, data, channel, - payloadChannel, appData, paused }: @@ -223,7 +212,6 @@ export class Producer internal: ProducerInternal; data: ProducerData; channel: Channel; - payloadChannel: PayloadChannel; appData?: ProducerAppData; paused: boolean; } @@ -236,9 +224,8 @@ export class Producer this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; - this.#appData = appData || {} as ProducerAppData; this.#paused = paused; + this.#appData = appData || {} as ProducerAppData; this.handleWorkerNotifications(); } @@ -358,12 +345,18 @@ export class Producer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.producerId); - this.#payloadChannel.removeAllListeners(this.#internal.producerId); - const reqData = { producerId: this.#internal.producerId }; + /* Build Request. */ + const requestOffset = new FbsTransport.CloseProducerRequestT( + this.#internal.producerId + ).pack(this.#channel.bufferBuilder); - this.#channel.request('transport.closeProducer', this.#internal.transportId, reqData) - .catch(() => {}); + this.#channel.request( + FbsRequest.Method.TRANSPORT_CLOSE_PRODUCER, + FbsRequest.Body.Transport_CloseProducerRequest, + requestOffset, + this.#internal.transportId + ).catch(() => {}); this.emit('@close'); @@ -389,7 +382,6 @@ export class Producer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.producerId); - this.#payloadChannel.removeAllListeners(this.#internal.producerId); this.safeEmit('transportclose'); @@ -400,11 +392,23 @@ export class Producer /** * Dump Producer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('producer.dump', this.#internal.producerId); + const response = await this.#channel.request( + FbsRequest.Method.PRODUCER_DUMP, + undefined, + undefined, + this.#internal.producerId + ); + + /* Decode Response. */ + const dumpResponse = new FbsProducer.DumpResponse(); + + response.body(dumpResponse); + + return parseProducerDump(dumpResponse); } /** @@ -414,7 +418,19 @@ export class Producer { logger.debug('getStats()'); - return this.#channel.request('producer.getStats', this.#internal.producerId); + const response = await this.#channel.request( + FbsRequest.Method.PRODUCER_GET_STATS, + undefined, + undefined, + this.#internal.producerId + ); + + /* Decode Response. */ + const data = new FbsProducer.GetStatsResponse(); + + response.body(data); + + return parseProducerStats(data); } /** @@ -426,7 +442,12 @@ export class Producer const wasPaused = this.#paused; - await this.#channel.request('producer.pause', this.#internal.producerId); + await this.#channel.request( + FbsRequest.Method.PRODUCER_PAUSE, + undefined, + undefined, + this.#internal.producerId + ); this.#paused = true; @@ -446,7 +467,12 @@ export class Producer const wasPaused = this.#paused; - await this.#channel.request('producer.resume', this.#internal.producerId); + await this.#channel.request( + FbsRequest.Method.PRODUCER_RESUME, + undefined, + undefined, + this.#internal.producerId + ); this.#paused = false; @@ -464,10 +490,41 @@ export class Producer { logger.debug('enableTraceEvent()'); - const reqData = { types }; + if (!Array.isArray(types)) + { + throw new TypeError('types must be an array'); + } + if (types.find((type) => typeof type !== 'string')) + { + throw new TypeError('every type must be a string'); + } + + // Convert event types. + const fbsEventTypes: FbsProducer.TraceEventType[] = []; + + for (const eventType of types) + { + try + { + fbsEventTypes.push(producerTraceEventTypeToFbs(eventType)); + } + catch (error) + { + logger.warn('enableTraceEvent() | [error:${error}]'); + } + } + + /* Build Request. */ + const requestOffset = new FbsProducer.EnableTraceEventRequestT( + fbsEventTypes + ).pack(this.#channel.bufferBuilder); await this.#channel.request( - 'producer.enableTraceEvent', this.#internal.producerId, reqData); + FbsRequest.Method.PRODUCER_ENABLE_TRACE_EVENT, + FbsRequest.Body.Producer_EnableTraceEventRequest, + requestOffset, + this.#internal.producerId + ); } /** @@ -480,19 +537,36 @@ export class Producer throw new TypeError('rtpPacket must be a Buffer'); } - this.#payloadChannel.notify( - 'producer.send', this.#internal.producerId, undefined, rtpPacket); + const builder = this.#channel.bufferBuilder; + const dataOffset = FbsProducer.SendNotification.createDataVector(builder, rtpPacket); + const notificationOffset = FbsProducer.SendNotification.createSendNotification( + builder, + dataOffset + ); + + this.#channel.notify( + FbsNotification.Event.PRODUCER_SEND, + FbsNotification.Body.Producer_SendNotification, + notificationOffset, + this.#internal.producerId + ); } private handleWorkerNotifications(): void { - this.#channel.on(this.#internal.producerId, (event: string, data?: any) => + this.#channel.on(this.#internal.producerId, (event: Event, data?: Notification) => { switch (event) { - case 'score': + case Event.PRODUCER_SCORE: { - const score = data as ProducerScore[]; + const notification = new FbsProducer.ScoreNotification(); + + data!.body(notification); + + const score: ProducerScore[] = utils.parseVector( + notification, 'scores', parseProducerScore + ); this.#score = score; @@ -504,9 +578,13 @@ export class Producer break; } - case 'videoorientationchange': + case Event.PRODUCER_VIDEO_ORIENTATION_CHANGE: { - const videoOrientation = data as ProducerVideoOrientation; + const notification = new FbsProducer.VideoOrientationChangeNotification(); + + data!.body(notification); + + const videoOrientation: ProducerVideoOrientation = notification.unpack(); this.safeEmit('videoorientationchange', videoOrientation); @@ -516,9 +594,13 @@ export class Producer break; } - case 'trace': + case Event.PRODUCER_TRACE: { - const trace = data as ProducerTraceEventData; + const notification = new FbsProducer.TraceNotification(); + + data!.body(notification); + + const trace: ProducerTraceEventData = parseTraceEventData(notification); this.safeEmit('trace', trace); @@ -536,3 +618,132 @@ export class Producer }); } } + +export function producerTypeFromFbs(type: FbsRtpParameters.Type): ProducerType +{ + switch (type) + { + case FbsRtpParameters.Type.SIMPLE: + return 'simple'; + case FbsRtpParameters.Type.SIMULCAST: + return 'simulcast'; + case FbsRtpParameters.Type.SVC: + return 'svc'; + default: + throw new TypeError(`invalid FbsRtpParameters.Type: ${type}`); + } +} + +export function producerTypeToFbs(type: ProducerType): FbsRtpParameters.Type +{ + switch (type) + { + case 'simple': + return FbsRtpParameters.Type.SIMPLE; + + case 'simulcast': + return FbsRtpParameters.Type.SIMULCAST; + + case 'svc': + return FbsRtpParameters.Type.SVC; + } +} + +function producerTraceEventTypeToFbs(eventType: ProducerTraceEventType) + : FbsProducer.TraceEventType +{ + switch (eventType) + { + case 'keyframe': + return FbsProducer.TraceEventType.KEYFRAME; + case 'fir': + return FbsProducer.TraceEventType.FIR; + case 'nack': + return FbsProducer.TraceEventType.NACK; + case 'pli': + return FbsProducer.TraceEventType.PLI; + case 'rtp': + return FbsProducer.TraceEventType.RTP; + default: + throw new TypeError(`invalid ProducerTraceEventType: ${eventType}`); + } +} + +function producerTraceEventTypeFromFbs(eventType: FbsProducer.TraceEventType) + : ProducerTraceEventType +{ + switch (eventType) + { + case FbsProducer.TraceEventType.KEYFRAME: + return 'keyframe'; + case FbsProducer.TraceEventType.FIR: + return 'fir'; + case FbsProducer.TraceEventType.NACK: + return 'nack'; + case FbsProducer.TraceEventType.PLI: + return 'pli'; + case FbsProducer.TraceEventType.RTP: + return 'rtp'; + } +} + +export function parseProducerDump( + data: FbsProducer.DumpResponse +): ProducerDump +{ + return { + id : data.id()!, + kind : data.kind() === FbsRtpParameters.MediaKind.AUDIO ? 'audio' : 'video', + type : producerTypeFromFbs(data.type()), + rtpParameters : parseRtpParameters(data.rtpParameters()!), + // NOTE: optional values are represented with null instead of undefined. + // TODO: Make flatbuffers TS return undefined instead of null. + rtpMapping : data.rtpMapping() ? data.rtpMapping()!.unpack() : undefined, + // NOTE: optional values are represented with null instead of undefined. + // TODO: Make flatbuffers TS return undefined instead of null. + rtpStreams : data.rtpStreamsLength() > 0 ? + utils.parseVector(data, 'rtpStreams', (rtpStream: any) => rtpStream.unpack()) : + undefined, + traceEventTypes : utils.parseVector(data, 'traceEventTypes', producerTraceEventTypeFromFbs), + paused : data.paused() + }; +} + +function parseProducerStats(binary: FbsProducer.GetStatsResponse): ProducerStat[] +{ + return utils.parseVector(binary, 'stats', parseRtpStreamRecvStats); +} + +function parseProducerScore( + binary: FbsProducer.Score +): ProducerScore +{ + return { + ssrc : binary.ssrc(), + rid : binary.rid() ?? undefined, + score : binary.score() + }; +} + +function parseTraceEventData( + trace: FbsProducer.TraceNotification +): ProducerTraceEventData +{ + let info: any; + + if (trace.infoType() !== FbsProducer.TraceInfo.NONE) + { + const accessor = trace.info.bind(trace); + + info = FbsProducerTraceInfo.unionToTraceInfo(trace.infoType(), accessor); + + trace.info(info); + } + + return { + type : producerTraceEventTypeFromFbs(trace.type()), + timestamp : Number(trace.timestamp()), + direction : trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', + info : info ? info.unpack() : undefined + }; +} diff --git a/node/src/Router.ts b/node/src/Router.ts index dd4c685b7d..edecf0ce4b 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -1,15 +1,18 @@ -import { v4 as uuidv4 } from 'uuid'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import * as ortc from './ortc'; import { InvalidStateError } from './errors'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; -import { Transport, TransportListenIp } from './Transport'; -import { WebRtcTransport, WebRtcTransportOptions } from './WebRtcTransport'; -import { PlainTransport, PlainTransportOptions } from './PlainTransport'; -import { PipeTransport, PipeTransportOptions } from './PipeTransport'; -import { DirectTransport, DirectTransportOptions } from './DirectTransport'; +import { + Transport, + TransportListenInfo, + TransportListenIp, + TransportProtocol +} from './Transport'; +import { WebRtcTransport, WebRtcTransportOptions, parseWebRtcTransportDumpResponse } from './WebRtcTransport'; +import { PlainTransport, PlainTransportOptions, parsePlainTransportDumpResponse } from './PlainTransport'; +import { PipeTransport, PipeTransportOptions, parsePipeTransportDumpResponse } from './PipeTransport'; +import { DirectTransport, DirectTransportOptions, parseDirectTransportDumpResponse } from './DirectTransport'; import { Producer } from './Producer'; import { Consumer } from './Consumer'; import { DataProducer } from './DataProducer'; @@ -18,8 +21,22 @@ import { RtpObserver } from './RtpObserver'; import { ActiveSpeakerObserver, ActiveSpeakerObserverOptions } from './ActiveSpeakerObserver'; import { AudioLevelObserver, AudioLevelObserverOptions } from './AudioLevelObserver'; import { RtpCapabilities, RtpCodecCapability } from './RtpParameters'; +import { cryptoSuiteToFbs } from './SrtpParameters'; import { NumSctpStreams } from './SctpParameters'; -import { AppData } from './types'; +import { AppData, Either } from './types'; +import { generateUUIDv4, parseVector, parseStringStringVector, parseStringStringArrayVector } from './utils'; +import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; +import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; +import * as FbsRequest from './fbs/request'; +import * as FbsWorker from './fbs/worker'; +import * as FbsRouter from './fbs/router'; +import * as FbsTransport from './fbs/transport'; +import { Protocol as FbsTransportProtocol } from './fbs/transport/protocol'; +import * as FbsWebRtcTransport from './fbs/web-rtc-transport'; +import * as FbsPlainTransport from './fbs/plain-transport'; +import * as FbsPipeTransport from './fbs/pipe-transport'; +import * as FbsDirectTransport from './fbs/direct-transport'; +import * as FbsSctpParameters from './fbs/sctp-parameters'; export type RouterOptions = { @@ -34,6 +51,22 @@ export type RouterOptions = appData?: RouterAppData; }; +type PipeToRouterListenInfo = +{ + listenInfo: TransportListenInfo; +}; + +type PipeToRouterListenIp = +{ + /** + * IP used in the PipeTransport pair. Default '127.0.0.1'. + */ + listenIp?: TransportListenIp | string; +}; + +type PipeToRouterListen = + Either; + export type PipeToRouterOptions = { /** @@ -51,11 +84,6 @@ export type PipeToRouterOptions = */ router: Router; - /** - * IP used in the PipeTransport pair. Default '127.0.0.1'. - */ - listenIp?: TransportListenIp | string; - /** * Create a SCTP association. Default true. */ @@ -75,7 +103,7 @@ export type PipeToRouterOptions = * Enable SRTP. */ enableSrtp?: boolean; -}; +} & PipeToRouterListen; export type PipeToRouterResult = { @@ -100,6 +128,42 @@ export type PipeToRouterResult = pipeDataProducer?: DataProducer; }; +export type RouterDump = +{ + /** + * The Router id. + */ + id: string; + /** + * Id of Transports. + */ + transportIds: string[]; + /** + * Id of RtpObservers. + */ + rtpObserverIds: string[]; + /** + * Array of Producer id and its respective Consumer ids. + */ + mapProducerIdConsumerIds: { key: string; values: string[] }[]; + /** + * Array of Consumer id and its Producer id. + */ + mapConsumerIdProducerId: {key: string; value: string}[]; + /** + * Array of Producer id and its respective Observer ids. + */ + mapProducerIdObserverIds: {key: string; values: string[]}[]; + /** + * Array of Producer id and its respective DataConsumer ids. + */ + mapDataProducerIdDataConsumerIds: {key: string; values: string[]}[]; + /** + * Array of DataConsumer id and its DataProducer id. + */ + mapDataConsumerIdDataProducerId: {key: string; value: string}[]; +}; + type PipeTransportPair = { [key: string]: PipeTransport; @@ -143,9 +207,6 @@ export class Router // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -180,14 +241,12 @@ export class Router internal, data, channel, - payloadChannel, appData }: { internal: RouterInternal; data: RouterData; channel: Channel; - payloadChannel: PayloadChannel; appData?: RouterAppData; } ) @@ -199,7 +258,6 @@ export class Router this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; this.#appData = appData || {} as RouterAppData; } @@ -274,9 +332,13 @@ export class Router this.#closed = true; - const reqData = { routerId: this.#internal.routerId }; + const requestOffset = new FbsWorker.CloseRouterRequestT( + this.#internal.routerId).pack(this.#channel.bufferBuilder); - this.#channel.request('worker.closeRouter', undefined, reqData) + this.#channel.request( + FbsRequest.Method.WORKER_CLOSE_ROUTER, + FbsRequest.Body.Worker_CloseRouterRequest, + requestOffset) .catch(() => {}); // Close every Transport. @@ -350,11 +412,24 @@ export class Router /** * Dump Router. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('router.dump', this.#internal.routerId); + // Send the request and wait for the response. + const response = await this.#channel.request( + FbsRequest.Method.ROUTER_DUMP, + undefined, + undefined, + this.#internal.routerId + ); + + /* Decode Response. */ + const dump = new FbsRouter.DumpResponse(); + + response.body(dump); + + return parseRouterDumpResponse(dump); } /** @@ -363,10 +438,11 @@ export class Router async createWebRtcTransport( { webRtcServer, + listenInfos, listenIps, port, - enableUdp = true, - enableTcp = false, + enableUdp, + enableTcp, preferUdp = false, preferTcp = false, initialAvailableOutgoingBitrate = 600000, @@ -380,69 +456,180 @@ export class Router { logger.debug('createWebRtcTransport()'); - if (!webRtcServer && !Array.isArray(listenIps)) + if (!webRtcServer && !Array.isArray(listenInfos) && !Array.isArray(listenIps)) { - throw new TypeError('missing webRtcServer and listenIps (one of them is mandatory)'); + throw new TypeError('missing webRtcServer, listenInfos and listenIps (one of them is mandatory)'); + } + else if (webRtcServer && listenInfos && listenIps) + { + throw new TypeError('only one of webRtcServer, listenInfos and listenIps must be given'); + } + else if ( + numSctpStreams && + (typeof numSctpStreams.OS !== 'number' || typeof numSctpStreams.MIS !== 'number') + ) + { + throw new TypeError('if given, numSctpStreams must contain OS and MIS'); } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } + // If webRtcServer is given, then do not force default values for enableUdp + // and enableTcp. Otherwise set them if unset. + if (webRtcServer) + { + enableUdp ??= true; + enableTcp ??= true; + } + else + { + enableUdp ??= true; + enableTcp ??= false; + } + + // Convert deprecated TransportListenIps to TransportListenInfos. if (listenIps) { + // Normalize IP strings to TransportListenIp objects. listenIps = listenIps.map((listenIp) => { - if (typeof listenIp === 'string' && listenIp) + if (typeof listenIp === 'string') { return { ip: listenIp }; } - else if (typeof listenIp === 'object') - { - return { - ip : listenIp.ip, - announcedIp : listenIp.announcedIp || undefined - }; - } else { - throw new TypeError('wrong listenIp'); + return listenIp; } }); + + listenInfos = []; + + const orderedProtocols: TransportProtocol[] = []; + + if (enableUdp && (!enableTcp || preferUdp)) + { + orderedProtocols.push('udp'); + + if (enableTcp) + { + orderedProtocols.push('tcp'); + } + } + else if (enableTcp && (!enableUdp || (preferTcp && !preferUdp))) + { + orderedProtocols.push('tcp'); + + if (enableUdp) + { + orderedProtocols.push('udp'); + } + } + + for (const listenIp of listenIps as TransportListenIp[]) + { + for (const protocol of orderedProtocols) + { + listenInfos.push( + { + protocol : protocol, + ip : listenIp.ip, + announcedIp : listenIp.announcedIp, + port : port + }); + } + } } - const reqData = + const transportId = generateUUIDv4(); + + /* Build Request. */ + let webRtcTransportListenServer: + FbsWebRtcTransport.ListenServerT | undefined; + let webRtcTransportListenIndividual: + FbsWebRtcTransport.ListenIndividualT | undefined; + + if (webRtcServer) { - transportId : uuidv4(), - webRtcServerId : webRtcServer ? webRtcServer.id : undefined, - listenIps, - port, - enableUdp, - enableTcp, - preferUdp, - preferTcp, + webRtcTransportListenServer = + new FbsWebRtcTransport.ListenServerT(webRtcServer.id); + } + else + { + const fbsListenInfos: FbsTransport.ListenInfoT[] = []; + + for (const listenInfo of listenInfos!) + { + fbsListenInfos.push(new FbsTransport.ListenInfoT( + listenInfo.protocol === 'udp' + ? FbsTransportProtocol.UDP + : FbsTransportProtocol.TCP, + listenInfo.ip, + listenInfo.announcedIp, + listenInfo.port, + listenInfo.sendBufferSize, + listenInfo.recvBufferSize + )); + } + + webRtcTransportListenIndividual = + new FbsWebRtcTransport.ListenIndividualT(fbsListenInfos); + } + + const baseTransportOptions = new FbsTransport.OptionsT( + undefined /* direct */, + undefined /* maxMessageSize */, initialAvailableOutgoingBitrate, enableSctp, - numSctpStreams, + new FbsSctpParameters.NumSctpStreamsT(numSctpStreams.OS, numSctpStreams.MIS), maxSctpMessageSize, sctpSendBufferSize, - isDataChannel : true - }; + true /* isDataChannel */ + ); + + const webRtcTransportOptions = new FbsWebRtcTransport.WebRtcTransportOptionsT( + baseTransportOptions, + webRtcServer ? + FbsWebRtcTransport.Listen.ListenServer : + FbsWebRtcTransport.Listen.ListenIndividual, + webRtcServer ? webRtcTransportListenServer : webRtcTransportListenIndividual, + enableUdp, + enableTcp, + preferUdp, + preferTcp + ); + + const requestOffset = new FbsRouter.CreateWebRtcTransportRequestT( + transportId, webRtcTransportOptions + ).pack(this.#channel.bufferBuilder); + + const response = await this.#channel.request( + webRtcServer + ? FbsRequest.Method.ROUTER_CREATE_WEBRTCTRANSPORT_WITH_SERVER + : FbsRequest.Method.ROUTER_CREATE_WEBRTCTRANSPORT, + FbsRequest.Body.Router_CreateWebRtcTransportRequest, + requestOffset, + this.#internal.routerId + ); - const data = webRtcServer - ? await this.#channel.request('router.createWebRtcTransportWithServer', this.#internal.routerId, reqData) - : await this.#channel.request('router.createWebRtcTransport', this.#internal.routerId, reqData); + /* Decode Response. */ + const data = new FbsWebRtcTransport.DumpResponse(); + + response.body(data); + + const webRtcTransportData = parseWebRtcTransportDumpResponse(data); const transport = new WebRtcTransport( { internal : { ...this.#internal, - transportId : reqData.transportId + transportId : transportId }, - data, + data : webRtcTransportData, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, getProducerById : (producerId: string): Producer | undefined => ( @@ -481,6 +668,8 @@ export class Router */ async createPlainTransport( { + listenInfo, + rtcpListenInfo, listenIp, port, rtcpMux = true, @@ -497,61 +686,114 @@ export class Router { logger.debug('createPlainTransport()'); - if (!listenIp) + if (!listenInfo && !listenIp) + { + throw new TypeError('missing listenInfo and listenIp (one of them is mandatory)'); + } + else if (listenInfo && listenIp) { - throw new TypeError('missing listenIp'); + throw new TypeError('only one of listenInfo and listenIp must be given'); } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } - if (typeof listenIp === 'string' && listenIp) + // If rtcpMux is enabled, ignore rtcpListenInfo. + if (rtcpMux) { - listenIp = { ip: listenIp }; + logger.warn('createPlainTransport() | ignoring given rtcpListenInfo since rtcpMux is enabled'); + + rtcpListenInfo = undefined; } - else if (typeof listenIp === 'object') + + // Convert deprecated TransportListenIps to TransportListenInfos. + if (listenIp) { - listenIp = + // Normalize IP string to TransportListenIp object. + if (typeof listenIp === 'string') + { + listenIp = { ip: listenIp }; + } + + listenInfo = { + protocol : 'udp', ip : listenIp.ip, - announcedIp : listenIp.announcedIp || undefined + announcedIp : listenIp.announcedIp, + port : port }; } - else - { - throw new TypeError('wrong listenIp'); - } - const reqData = - { - transportId : uuidv4(), - listenIp, - port, - rtcpMux, - comedia, + const transportId = generateUUIDv4(); + + /* Build Request. */ + const baseTransportOptions = new FbsTransport.OptionsT( + undefined /* direct */, + undefined /* maxMessageSize */, + undefined /* initialAvailableOutgoingBitrate */, enableSctp, - numSctpStreams, + new FbsSctpParameters.NumSctpStreamsT(numSctpStreams.OS, numSctpStreams.MIS), maxSctpMessageSize, sctpSendBufferSize, - isDataChannel : false, + false /* isDataChannel */ + ); + + const plainTransportOptions = new FbsPlainTransport.PlainTransportOptionsT( + baseTransportOptions, + new FbsTransport.ListenInfoT( + listenInfo!.protocol === 'udp' + ? FbsTransportProtocol.UDP + : FbsTransportProtocol.TCP, + listenInfo!.ip, + listenInfo!.announcedIp, + listenInfo!.port, + listenInfo!.sendBufferSize, + listenInfo!.recvBufferSize + ), + rtcpListenInfo ? new FbsTransport.ListenInfoT( + rtcpListenInfo.protocol === 'udp' + ? FbsTransportProtocol.UDP + : FbsTransportProtocol.TCP, + rtcpListenInfo.ip, + rtcpListenInfo.announcedIp, + rtcpListenInfo.port, + rtcpListenInfo.sendBufferSize, + rtcpListenInfo.recvBufferSize + ) : undefined, + rtcpMux, + comedia, enableSrtp, - srtpCryptoSuite - }; + cryptoSuiteToFbs(srtpCryptoSuite) + ); + + const requestOffset = new FbsRouter.CreatePlainTransportRequestT( + transportId, plainTransportOptions + ).pack(this.#channel.bufferBuilder); - const data = - await this.#channel.request('router.createPlainTransport', this.#internal.routerId, reqData); + const response = await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_PLAINTRANSPORT, + FbsRequest.Body.Router_CreatePlainTransportRequest, + requestOffset, + this.#internal.routerId + ); + + /* Decode Response. */ + const data = new FbsPlainTransport.DumpResponse(); + + response.body(data); + + const plainTransportData = parsePlainTransportDumpResponse(data); const transport = new PlainTransport( { internal : { ...this.#internal, - transportId : reqData.transportId + transportId : transportId }, - data, + data : plainTransportData, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, getProducerById : (producerId: string): Producer | undefined => ( @@ -585,6 +827,7 @@ export class Router */ async createPipeTransport( { + listenInfo, listenIp, port, enableSctp = false, @@ -599,59 +842,94 @@ export class Router { logger.debug('createPipeTransport()'); - if (!listenIp) + if (!listenInfo && !listenIp) { - throw new TypeError('missing listenIp'); + throw new TypeError('missing listenInfo and listenIp (one of them is mandatory)'); + } + else if (listenInfo && listenIp) + { + throw new TypeError('only one of listenInfo and listenIp must be given'); } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } - if (typeof listenIp === 'string' && listenIp) - { - listenIp = { ip: listenIp }; - } - else if (typeof listenIp === 'object') + // Convert deprecated TransportListenIps to TransportListenInfos. + if (listenIp) { - listenIp = + // Normalize IP string to TransportListenIp object. + if (typeof listenIp === 'string') + { + listenIp = { ip: listenIp }; + } + + listenInfo = { + protocol : 'udp', ip : listenIp.ip, - announcedIp : listenIp.announcedIp || undefined + announcedIp : listenIp.announcedIp, + port : port }; } - else - { - throw new TypeError('wrong listenIp'); - } - const reqData = - { - transportId : uuidv4(), - listenIp, - port, + const transportId = generateUUIDv4(); + + /* Build Request. */ + const baseTransportOptions = new FbsTransport.OptionsT( + undefined /* direct */, + undefined /* maxMessageSize */, + undefined /* initialAvailableOutgoingBitrate */, enableSctp, - numSctpStreams, + new FbsSctpParameters.NumSctpStreamsT(numSctpStreams.OS, numSctpStreams.MIS), maxSctpMessageSize, sctpSendBufferSize, - isDataChannel : false, + false /* isDataChannel */ + ); + + const pipeTransportOptions = new FbsPipeTransport.PipeTransportOptionsT( + baseTransportOptions, + new FbsTransport.ListenInfoT( + listenInfo!.protocol === 'udp' + ? FbsTransportProtocol.UDP + : FbsTransportProtocol.TCP, + listenInfo!.ip, + listenInfo!.announcedIp, + listenInfo!.port, + listenInfo!.sendBufferSize, + listenInfo!.recvBufferSize + ), enableRtx, enableSrtp - }; + ); + + const requestOffset = new FbsRouter.CreatePipeTransportRequestT( + transportId, pipeTransportOptions + ).pack(this.#channel.bufferBuilder); - const data = - await this.#channel.request('router.createPipeTransport', this.#internal.routerId, reqData); + const response = await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_PIPETRANSPORT, + FbsRequest.Body.Router_CreatePipeTransportRequest, + requestOffset, + this.#internal.routerId + ); + + /* Decode Response. */ + const data = new FbsPipeTransport.DumpResponse(); + + response.body(data); + + const plainTransportData = parsePipeTransportDumpResponse(data); const transport = new PipeTransport( { internal : { ...this.#internal, - transportId : reqData.transportId + transportId }, - data, + data : plainTransportData, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, getProducerById : (producerId: string): Producer | undefined => ( @@ -695,26 +973,60 @@ export class Router { logger.debug('createDirectTransport()'); - const reqData = + if (typeof maxMessageSize !== 'number' || maxMessageSize < 0) { - transportId : uuidv4(), - direct : true, - maxMessageSize - }; + throw new TypeError('if given, maxMessageSize must be a positive number'); + } + else if (appData && typeof appData !== 'object') + { + throw new TypeError('if given, appData must be an object'); + } + + const transportId = generateUUIDv4(); + + /* Build Request. */ + const baseTransportOptions = new FbsTransport.OptionsT( + true /* direct */, + maxMessageSize, + undefined /* initialAvailableOutgoingBitrate */, + undefined /* enableSctp */, + undefined /* numSctpStreams */, + undefined /* maxSctpMessageSize */, + undefined /* sctpSendBufferSize */, + undefined /* isDataChannel */ + ); + + const directTransportOptions = new FbsDirectTransport.DirectTransportOptionsT( + baseTransportOptions + ); - const data = - await this.#channel.request('router.createDirectTransport', this.#internal.routerId, reqData); + const requestOffset = new FbsRouter.CreateDirectTransportRequestT( + transportId, directTransportOptions + ).pack(this.#channel.bufferBuilder); + + const response = await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_DIRECTTRANSPORT, + FbsRequest.Body.Router_CreateDirectTransportRequest, + requestOffset, + this.#internal.routerId + ); + + /* Decode Response. */ + const data = new FbsDirectTransport.DumpResponse(); + + response.body(data); + + const directTransportData = parseDirectTransportDumpResponse(data); const transport = new DirectTransport( { internal : { ...this.#internal, - transportId : reqData.transportId + transportId : transportId }, - data, + data : directTransportData, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, getProducerById : (producerId: string): Producer | undefined => ( @@ -751,7 +1063,8 @@ export class Router producerId, dataProducerId, router, - listenIp = '127.0.0.1', + listenInfo, + listenIp, enableSctp = true, numSctpStreams = { OS: 1024, MIS: 1024 }, enableRtx = false, @@ -761,7 +1074,20 @@ export class Router { logger.debug('pipeToRouter()'); - if (!producerId && !dataProducerId) + if (!listenInfo && !listenIp) + { + listenInfo = + { + protocol : 'udp', + ip : '127.0.0.1' + }; + } + + if (listenInfo && listenIp) + { + throw new TypeError('only one of listenInfo and listenIp must be given'); + } + else if (!producerId && !dataProducerId) { throw new TypeError('missing producerId or dataProducerId'); } @@ -778,6 +1104,23 @@ export class Router throw new TypeError('cannot use this Router as destination'); } + // Convert deprecated TransportListenIps to TransportListenInfos. + if (listenIp) + { + // Normalize IP string to TransportListenIp object. + if (typeof listenIp === 'string') + { + listenIp = { ip: listenIp }; + } + + listenInfo = + { + protocol : 'udp', + ip : listenIp.ip, + announcedIp : listenIp.announcedIp + }; + } + let producer: Producer | undefined; let dataProducer: DataProducer | undefined; @@ -820,9 +1163,21 @@ export class Router Promise.all( [ this.createPipeTransport( - { listenIp, enableSctp, numSctpStreams, enableRtx, enableSrtp }), + { + listenInfo : listenInfo!, + enableSctp, + numSctpStreams, + enableRtx, + enableSrtp + }), router.createPipeTransport( - { listenIp, enableSctp, numSctpStreams, enableRtx, enableSrtp }) + { + listenInfo : listenInfo!, + enableSctp, + numSctpStreams, + enableRtx, + enableSrtp + }) ]) .then((pipeTransports) => { @@ -1076,28 +1431,44 @@ export class Router { logger.debug('createActiveSpeakerObserver()'); + if (typeof interval !== 'number') + { + throw new TypeError('if given, interval must be an number'); + } if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } - const reqData = - { - rtpObserverId : uuidv4(), - interval - }; + const rtpObserverId = generateUUIDv4(); - await this.#channel.request('router.createActiveSpeakerObserver', this.#internal.routerId, reqData); + /* Build Request. */ + const activeRtpObserverOptions = + new FbsActiveSpeakerObserver.ActiveSpeakerObserverOptionsT( + interval + ); + + const requestOffset = + new FbsRouter.CreateActiveSpeakerObserverRequestT( + rtpObserverId, + activeRtpObserverOptions + ).pack(this.#channel.bufferBuilder); + + await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_ACTIVESPEAKEROBSERVER, + FbsRequest.Body.Router_CreateActiveSpeakerObserverRequest, + requestOffset, + this.#internal.routerId + ); const activeSpeakerObserver = new ActiveSpeakerObserver( { internal : { ...this.#internal, - rtpObserverId : reqData.rtpObserverId + rtpObserverId : rtpObserverId }, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getProducerById : (producerId: string): Producer | undefined => ( this.#producers.get(producerId) @@ -1130,30 +1501,53 @@ export class Router { logger.debug('createAudioLevelObserver()'); + if (typeof maxEntries !== 'number' || maxEntries <= 0) + { + throw new TypeError('if given, maxEntries must be a positive number'); + } + if (typeof threshold !== 'number' || threshold < -127 || threshold > 0) + { + throw new TypeError('if given, threshole must be a negative number greater than -127'); + } + if (typeof interval !== 'number') + { + throw new TypeError('if given, interval must be an number'); + } if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } - const reqData = - { - rtpObserverId : uuidv4(), - maxEntries, - threshold, - interval - }; + const rtpObserverId = generateUUIDv4(); - await this.#channel.request('router.createAudioLevelObserver', this.#internal.routerId, reqData); + /* Build Request. */ + const audioLevelObserverOptions = + new FbsAudioLevelObserver.AudioLevelObserverOptionsT( + maxEntries, + threshold, + interval + ); + + const requestOffset = new FbsRouter.CreateAudioLevelObserverRequestT( + rtpObserverId, + audioLevelObserverOptions + ).pack(this.#channel.bufferBuilder); + + await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_AUDIOLEVELOBSERVER, + FbsRequest.Body.Router_CreateAudioLevelObserverRequest, + requestOffset, + this.#internal.routerId + ); const audioLevelObserver = new AudioLevelObserver( { internal : { ...this.#internal, - rtpObserverId : reqData.rtpObserverId + rtpObserverId : rtpObserverId }, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getProducerById : (producerId: string): Producer | undefined => ( this.#producers.get(producerId) @@ -1208,3 +1602,19 @@ export class Router } } } + +export function parseRouterDumpResponse( + binary: FbsRouter.DumpResponse +): RouterDump +{ + return { + id : binary.id()!, + transportIds : parseVector(binary, 'transportIds'), + rtpObserverIds : parseVector(binary, 'rtpObserverIds'), + mapProducerIdConsumerIds : parseStringStringArrayVector(binary, 'mapProducerIdConsumerIds'), + mapConsumerIdProducerId : parseStringStringVector(binary, 'mapConsumerIdProducerId'), + mapProducerIdObserverIds : parseStringStringArrayVector(binary, 'mapProducerIdObserverIds'), + mapDataProducerIdDataConsumerIds : parseStringStringArrayVector(binary, 'mapDataProducerIdDataConsumerIds'), + mapDataConsumerIdDataProducerId : parseStringStringVector(binary, 'mapDataConsumerIdDataProducerId') + }; +} diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 0eedb19626..4c3d64051c 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -1,10 +1,12 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { RouterInternal } from './Router'; import { Producer } from './Producer'; import { AppData } from './types'; +import * as FbsRequest from './fbs/request'; +import * as FbsRouter from './fbs/router'; +import * as FbsRtpObserver from './fbs/rtp-observer'; export type RtpObserverEvents = { @@ -26,7 +28,6 @@ export type RtpObserverConstructorOptions = { internal: RtpObserverObserverInternal; channel: Channel; - payloadChannel: PayloadChannel; appData?: RtpObserverAppData; getProducerById: (producerId: string) => Producer | undefined; }; @@ -57,9 +58,6 @@ export class RtpObserver // Channel instance. protected readonly channel: Channel; - // PayloadChannel instance. - protected readonly payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -83,7 +81,6 @@ export class RtpObserver { internal, channel, - payloadChannel, appData, getProducerById }: RtpObserverConstructorOptions @@ -95,7 +92,6 @@ export class RtpObserver this.internal = internal; this.channel = channel; - this.payloadChannel = payloadChannel; this.#appData = appData || {} as RtpObserverAppData; this.getProducerById = getProducerById; } @@ -164,12 +160,18 @@ export class RtpObserver // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.rtpObserverId); - this.payloadChannel.removeAllListeners(this.internal.rtpObserverId); - const reqData = { rtpObserverId: this.internal.rtpObserverId }; + /* Build Request. */ + const requestOffset = new FbsRouter.CloseRtpObserverRequestT( + this.internal.rtpObserverId + ).pack(this.channel.bufferBuilder); - this.channel.request('router.closeRtpObserver', this.internal.routerId, reqData) - .catch(() => {}); + this.channel.request( + FbsRequest.Method.ROUTER_CLOSE_RTPOBSERVER, + FbsRequest.Body.Router_CloseRtpObserverRequest, + requestOffset, + this.internal.routerId + ).catch(() => {}); this.emit('@close'); @@ -195,7 +197,6 @@ export class RtpObserver // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.rtpObserverId); - this.payloadChannel.removeAllListeners(this.internal.rtpObserverId); this.safeEmit('routerclose'); @@ -212,7 +213,12 @@ export class RtpObserver const wasPaused = this.#paused; - await this.channel.request('rtpObserver.pause', this.internal.rtpObserverId); + await this.channel.request( + FbsRequest.Method.RTPOBSERVER_PAUSE, + undefined, + undefined, + this.internal.rtpObserverId + ); this.#paused = true; @@ -232,7 +238,12 @@ export class RtpObserver const wasPaused = this.#paused; - await this.channel.request('rtpObserver.resume', this.internal.rtpObserverId); + await this.channel.request( + FbsRequest.Method.RTPOBSERVER_RESUME, + undefined, + undefined, + this.internal.rtpObserverId + ); this.#paused = false; @@ -257,9 +268,16 @@ export class RtpObserver throw Error(`Producer with id "${producerId}" not found`); } - const reqData = { producerId }; + const requestOffset = new FbsRtpObserver.AddProducerRequestT( + producerId + ).pack(this.channel.bufferBuilder); - await this.channel.request('rtpObserver.addProducer', this.internal.rtpObserverId, reqData); + await this.channel.request( + FbsRequest.Method.RTPOBSERVER_ADD_PRODUCER, + FbsRequest.Body.RtpObserver_AddProducerRequest, + requestOffset, + this.internal.rtpObserverId + ); // Emit observer event. this.#observer.safeEmit('addproducer', producer); @@ -279,9 +297,16 @@ export class RtpObserver throw Error(`Producer with id "${producerId}" not found`); } - const reqData = { producerId }; + const requestOffset = new FbsRtpObserver.RemoveProducerRequestT( + producerId + ).pack(this.channel.bufferBuilder); - await this.channel.request('rtpObserver.removeProducer', this.internal.rtpObserverId, reqData); + await this.channel.request( + FbsRequest.Method.RTPOBSERVER_REMOVE_PRODUCER, + FbsRequest.Body.RtpObserver_RemoveProducerRequest, + requestOffset, + this.internal.rtpObserverId + ); // Emit observer event. this.#observer.safeEmit('removeproducer', producer); diff --git a/node/src/RtpParameters.ts b/node/src/RtpParameters.ts index c26cc86b3f..95308b7a29 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/RtpParameters.ts @@ -1,3 +1,23 @@ +import * as flatbuffers from 'flatbuffers'; +import { + Boolean as FbsBoolean, + Double as FbsDouble, + Integer32 as FbsInteger32, + Integer32Array as FbsInteger32Array, + String as FbsString, + Parameter as FbsParameter, + RtcpFeedback as FbsRtcpFeedback, + RtcpParameters as FbsRtcpParameters, + RtpCodecParameters as FbsRtpCodecParameters, + RtpEncodingParameters as FbsRtpEncodingParameters, + RtpHeaderExtensionParameters as FbsRtpHeaderExtensionParameters, + RtpHeaderExtensionUri as FbsRtpHeaderExtensionUri, + RtpParameters as FbsRtpParameters, + Rtx as FbsRtx, + Value as FbsValue +} from './fbs/rtp-parameters'; +import * as utils from './utils'; + /** * The RTP capabilities define what mediasoup or an endpoint can receive at * media level. @@ -103,7 +123,7 @@ export type RtpHeaderExtension = /* * The URI of the RTP header extension, as defined in RFC 5285. */ - uri: string; + uri: RtpHeaderExtensionUri; /** * The preferred numeric identifier that goes in the RTP packet. Must be @@ -293,6 +313,19 @@ export type RtpEncodingParameters = maxBitrate?: number; }; +export type RtpHeaderExtensionUri = + 'urn:ietf:params:rtp-hdrext:sdes:mid' | + 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id' | + 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id' | + 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07' | + 'urn:ietf:params:rtp-hdrext:framemarking' | + 'urn:ietf:params:rtp-hdrext:ssrc-audio-level' | + 'urn:3gpp:video-orientation' | + 'urn:ietf:params:rtp-hdrext:toffset' | + 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' | + 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' | + 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time'; + /** * Defines a RTP header extension within the RTP parameters. The list of RTP * header extensions supported by mediasoup is defined in the @@ -306,7 +339,7 @@ export type RtpHeaderExtensionParameters = /** * The URI of the RTP header extension, as defined in RFC 5285. */ - uri: string; + uri: RtpHeaderExtensionUri; /** * The numeric identifier that goes in the RTP packet. Must be unique. @@ -345,9 +378,462 @@ export type RtcpParameters = * as specified in RFC 3550 (if false). Default true. */ reducedSize?: boolean; - - /** - * Whether RTCP-mux is used. Default true. - */ - mux?: boolean; }; + +export function serializeRtpParameters( + builder: flatbuffers.Builder, rtpParameters: RtpParameters +): number +{ + const codecs: number[] = []; + const headerExtensions: number[] = []; + + for (const codec of rtpParameters.codecs) + { + const mimeTypeOffset = builder.createString(codec.mimeType); + const parameters = serializeParameters(builder, codec.parameters); + const parametersOffset = + FbsRtpCodecParameters.createParametersVector(builder, parameters); + + const rtcpFeedback: number[] = []; + + for (const rtcp of codec.rtcpFeedback ?? []) + { + const typeOffset = builder.createString(rtcp.type); + const rtcpParametersOffset = builder.createString(rtcp.parameter); + + rtcpFeedback.push( + FbsRtcpFeedback.createRtcpFeedback(builder, typeOffset, rtcpParametersOffset)); + } + const rtcpFeedbackOffset = + FbsRtpCodecParameters.createRtcpFeedbackVector(builder, rtcpFeedback); + + codecs.push( + FbsRtpCodecParameters.createRtpCodecParameters( + builder, + mimeTypeOffset, + codec.payloadType, + codec.clockRate, + Number(codec.channels), + parametersOffset, + rtcpFeedbackOffset + )); + } + const codecsOffset = FbsRtpParameters.createCodecsVector(builder, codecs); + + // RtpHeaderExtensionParameters. + for (const headerExtension of rtpParameters.headerExtensions ?? []) + { + const uri = rtpHeaderExtensionUriToFbs(headerExtension.uri); + const parameters = serializeParameters(builder, headerExtension.parameters); + const parametersOffset = + FbsRtpCodecParameters.createParametersVector(builder, parameters); + + headerExtensions.push( + FbsRtpHeaderExtensionParameters.createRtpHeaderExtensionParameters( + builder, + uri, + headerExtension.id, + Boolean(headerExtension.encrypt), + parametersOffset)); + } + const headerExtensionsOffset = + FbsRtpParameters.createHeaderExtensionsVector(builder, headerExtensions); + + // RtpEncodingParameters. + const encodingsOffset = serializeRtpEncodingParameters(builder, rtpParameters.encodings ?? []); + + // RtcpParameters. + const { cname, reducedSize } = rtpParameters.rtcp ?? { reducedSize: true }; + const cnameOffset = builder.createString(cname); + + const rtcpOffset = FbsRtcpParameters.createRtcpParameters( + builder, cnameOffset, Boolean(reducedSize) + ); + + const midOffset = builder.createString(rtpParameters.mid); + + FbsRtpParameters.startRtpParameters(builder); + FbsRtpParameters.addMid(builder, midOffset); + FbsRtpParameters.addCodecs(builder, codecsOffset); + + FbsRtpParameters.addHeaderExtensions(builder, headerExtensionsOffset); + FbsRtpParameters.addEncodings(builder, encodingsOffset); + FbsRtpParameters.addRtcp(builder, rtcpOffset); + + return FbsRtpParameters.endRtpParameters(builder); +} + +export function serializeRtpEncodingParameters( + builder: flatbuffers.Builder, rtpEncodingParameters: RtpEncodingParameters[] = [] +): number +{ + const encodings: number[] = []; + + for (const encoding of rtpEncodingParameters) + { + // Prepare Rid. + const ridOffset = builder.createString(encoding.rid); + + // Prepare Rtx. + let rtxOffset: number | undefined; + + if (encoding.rtx) + { + rtxOffset = FbsRtx.createRtx(builder, encoding.rtx.ssrc); + } + + // Prepare scalability mode. + let scalabilityModeOffset: number | undefined; + + if (encoding.scalabilityMode) + { + scalabilityModeOffset = builder.createString(encoding.scalabilityMode); + } + + // Start serialization. + FbsRtpEncodingParameters.startRtpEncodingParameters(builder); + + // Add SSRC. + if (encoding.ssrc) + { + FbsRtpEncodingParameters.addSsrc(builder, encoding.ssrc); + } + + // Add Rid. + FbsRtpEncodingParameters.addRid(builder, ridOffset); + + // Add payload type. + if (encoding.codecPayloadType) + { + FbsRtpEncodingParameters.addCodecPayloadType(builder, encoding.codecPayloadType); + } + + // Add RTX. + if (rtxOffset) + { + FbsRtpEncodingParameters.addRtx(builder, rtxOffset); + } + + // Add DTX. + if (encoding.dtx !== undefined) + { + FbsRtpEncodingParameters.addDtx(builder, encoding.dtx); + } + + // Add scalability ode. + if (scalabilityModeOffset) + { + FbsRtpEncodingParameters.addScalabilityMode(builder, scalabilityModeOffset); + } + + // Add max bitrate. + if (encoding.maxBitrate !== undefined) + { + FbsRtpEncodingParameters.addMaxBitrate(builder, encoding.maxBitrate); + } + + // End serialization. + encodings.push(FbsRtpEncodingParameters.endRtpEncodingParameters(builder)); + } + + return FbsRtpParameters.createEncodingsVector(builder, encodings); +} + +export function serializeParameters( + builder: flatbuffers.Builder, parameters: any +):number[] +{ + const fbsParameters: number[] = []; + + for (const key of Object.keys(parameters)) + { + const value = parameters[key]; + const keyOffset = builder.createString(key); + let parameterOffset: number; + + if (typeof value === 'boolean') + { + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.Boolean, value === true ? 1 : 0 + ); + } + else if (typeof value === 'number') + { + // Integer. + if (value % 1 === 0) + { + const valueOffset = FbsInteger32.createInteger32(builder, value); + + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.Integer32, valueOffset + ); + } + // Float. + else + { + const valueOffset = FbsDouble.createDouble(builder, value); + + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.Double, valueOffset + ); + } + } + else if (typeof value === 'string') + { + const valueOffset = FbsString.createString(builder, builder.createString(value)); + + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.String, valueOffset + ); + } + else if (Array.isArray(value)) + { + const valueOffset = FbsInteger32Array.createValueVector(builder, value); + + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.Integer32Array, valueOffset + ); + } + else + { + throw new Error(`invalid parameter type [key:'${key}', value:${value}]`); + } + + fbsParameters.push(parameterOffset); + } + + return fbsParameters; +} + +export function parseRtcpFeedback(data: FbsRtcpFeedback): RtcpFeedback +{ + return { + type : data.type()!, + parameter : data.parameter() ?? undefined + }; +} + +export function parseParameters(data: any): any +{ + const parameters: any = {}; + + for (let i = 0; i < data.parametersLength(); i++) + { + const fbsParameter = data.parameters(i)!; + + switch (fbsParameter.valueType()) + { + case FbsValue.Boolean: + { + const value = new FbsBoolean(); + + fbsParameter.value(value); + + parameters[String(fbsParameter.name()!)] = value.value(); + + break; + } + + case FbsValue.Integer32: + { + const value = new FbsInteger32(); + + fbsParameter.value(value); + + parameters[String(fbsParameter.name()!)] = value.value(); + + break; + } + + case FbsValue.Double: + { + const value = new FbsDouble(); + + fbsParameter.value(value); + + parameters[String(fbsParameter.name()!)] = value.value(); + + break; + } + + case FbsValue.String: + { + const value = new FbsString(); + + fbsParameter.value(value); + + parameters[String(fbsParameter.name()!)] = value.value(); + + break; + } + + case FbsValue.Integer32Array: + { + const value = new FbsInteger32Array(); + + fbsParameter.value(value); + + parameters[String(fbsParameter.name()!)] = value.valueArray(); + + break; + } + } + } + + return parameters; +} + +export function parseRtpCodecParameters(data: FbsRtpCodecParameters): RtpCodecParameters +{ + const parameters = parseParameters(data); + + let rtcpFeedback: RtcpFeedback[] = []; + + if (data.rtcpFeedbackLength() > 0) + { + rtcpFeedback = utils.parseVector(data, 'rtcpFeedback', parseRtcpFeedback); + } + + return { + mimeType : data.mimeType()!, + payloadType : data.payloadType(), + clockRate : data.clockRate(), + channels : data.channels() ?? undefined, + parameters, + rtcpFeedback + }; +} + +export function rtpHeaderExtensionUriFromFbs(uri: FbsRtpHeaderExtensionUri): RtpHeaderExtensionUri +{ + switch (uri) + { + case FbsRtpHeaderExtensionUri.Mid: + return 'urn:ietf:params:rtp-hdrext:sdes:mid'; + case FbsRtpHeaderExtensionUri.RtpStreamId: + return 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id'; + case FbsRtpHeaderExtensionUri.RepairRtpStreamId: + return 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id'; + case FbsRtpHeaderExtensionUri.FrameMarkingDraft07: + return 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07'; + case FbsRtpHeaderExtensionUri.FrameMarking: + return 'urn:ietf:params:rtp-hdrext:framemarking'; + case FbsRtpHeaderExtensionUri.AudioLevel: + return 'urn:ietf:params:rtp-hdrext:ssrc-audio-level'; + case FbsRtpHeaderExtensionUri.VideoOrientation: + return 'urn:3gpp:video-orientation'; + case FbsRtpHeaderExtensionUri.TimeOffset: + return 'urn:ietf:params:rtp-hdrext:toffset'; + case FbsRtpHeaderExtensionUri.TransportWideCcDraft01: + return 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01'; + case FbsRtpHeaderExtensionUri.AbsSendTime: + return 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time'; + case FbsRtpHeaderExtensionUri.AbsCaptureTime: + return 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time'; + } +} + +export function rtpHeaderExtensionUriToFbs(uri: RtpHeaderExtensionUri): FbsRtpHeaderExtensionUri +{ + switch (uri) + { + case 'urn:ietf:params:rtp-hdrext:sdes:mid': + return FbsRtpHeaderExtensionUri.Mid; + case 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id': + return FbsRtpHeaderExtensionUri.RtpStreamId; + case 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id': + return FbsRtpHeaderExtensionUri.RepairRtpStreamId; + case 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07': + return FbsRtpHeaderExtensionUri.FrameMarkingDraft07; + case 'urn:ietf:params:rtp-hdrext:framemarking': + return FbsRtpHeaderExtensionUri.FrameMarking; + case 'urn:ietf:params:rtp-hdrext:ssrc-audio-level': + return FbsRtpHeaderExtensionUri.AudioLevel; + case 'urn:3gpp:video-orientation': + return FbsRtpHeaderExtensionUri.VideoOrientation; + case 'urn:ietf:params:rtp-hdrext:toffset': + return FbsRtpHeaderExtensionUri.TimeOffset; + case 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01': + return FbsRtpHeaderExtensionUri.TransportWideCcDraft01; + case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time': + return FbsRtpHeaderExtensionUri.AbsSendTime; + case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time': + return FbsRtpHeaderExtensionUri.AbsCaptureTime; + default: + throw new TypeError(`invalid RtpHeaderExtensionUri: ${uri}`); + } +} + +export function parseRtpHeaderExtensionParameters( + data: FbsRtpHeaderExtensionParameters): RtpHeaderExtensionParameters +{ + return { + uri : rtpHeaderExtensionUriFromFbs(data.uri()), + id : data.id(), + encrypt : data.encrypt(), + parameters : parseParameters(data) + }; +} + +export function parseRtpEncodingParameters( + data: FbsRtpEncodingParameters): RtpEncodingParameters +{ + return { + ssrc : data.ssrc() ?? undefined, + rid : data.rid() ?? undefined, + codecPayloadType : data.codecPayloadType() !== null ? + data.codecPayloadType()! : + undefined, + rtx : data.rtx() ? + { ssrc: data.rtx()!.ssrc()! } : + undefined, + dtx : data.dtx(), + scalabilityMode : data.scalabilityMode() ?? undefined, + maxBitrate : data.maxBitrate() !== null ? data.maxBitrate()! : undefined + }; +} + +export function parseRtpParameters(data: FbsRtpParameters): RtpParameters +{ + const codecs = utils.parseVector(data, 'codecs', parseRtpCodecParameters); + + let headerExtensions: RtpHeaderExtensionParameters[] = []; + + if (data.headerExtensionsLength() > 0) + { + headerExtensions = utils.parseVector( + data, + 'headerExtensions', + parseRtpHeaderExtensionParameters); + } + + let encodings: RtpEncodingParameters[] = []; + + if (data.encodingsLength() > 0) + { + encodings = utils.parseVector( + data, + 'encodings', + parseRtpEncodingParameters); + } + + let rtcp: RtcpParameters | undefined; + + if (data.rtcp()) + { + const fbsRtcp = data.rtcp()!; + + rtcp = { + cname : fbsRtcp.cname() ?? undefined, + reducedSize : fbsRtcp.reducedSize() + }; + } + + return { + mid : data.mid() ?? undefined, + codecs, + headerExtensions, + encodings, + rtcp + }; +} diff --git a/node/src/RtpStream.ts b/node/src/RtpStream.ts new file mode 100644 index 0000000000..ad863b19c2 --- /dev/null +++ b/node/src/RtpStream.ts @@ -0,0 +1,141 @@ +import * as FbsRtpStream from './fbs/rtp-stream'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; + +export type RtpStreamRecvStats = BaseRtpStreamStats & +{ + type: string; + jitter: number; + packetCount: number; + byteCount: number; + bitrate: number; + bitrateByLayer?: any; +}; + +export type RtpStreamSendStats = BaseRtpStreamStats & +{ + type: string; + packetCount: number; + byteCount: number; + bitrate: number; +}; + +type BaseRtpStreamStats = +{ + timestamp: number; + ssrc: number; + rtxSsrc?: number; + rid?: string; + kind: string; + mimeType: string; + packetsLost: number; + fractionLost: number; + packetsDiscarded: number; + packetsRetransmitted: number; + packetsRepaired: number; + nackCount: number; + nackPacketCount: number; + pliCount: number; + firCount: number; + score: number; + roundTripTime?: number; + rtxPacketsDiscarded?: number; +}; + +export function parseRtpStreamStats(binary: FbsRtpStream.Stats) + : RtpStreamRecvStats | RtpStreamSendStats +{ + if (binary.dataType() === FbsRtpStream.StatsData.RecvStats) + { + return parseRtpStreamRecvStats(binary); + } + else + { + return parseSendStreamStats(binary); + } +} + +export function parseRtpStreamRecvStats(binary: FbsRtpStream.Stats): RtpStreamRecvStats +{ + const recvStats = new FbsRtpStream.RecvStats(); + const baseStats = new FbsRtpStream.BaseStats(); + + binary.data(recvStats); + recvStats.base()!.data(baseStats); + + const base = parseBaseStreamStats(baseStats); + + return { + ...base, + type : 'inbound-rtp', + jitter : recvStats.jitter(), + byteCount : Number(recvStats.byteCount()), + packetCount : Number(recvStats.packetCount()), + bitrate : Number(recvStats.bitrate()), + bitrateByLayer : parseBitrateByLayer(recvStats) + }; +} + +export function parseSendStreamStats(binary: FbsRtpStream.Stats): RtpStreamSendStats +{ + const sendStats = new FbsRtpStream.SendStats(); + const baseStats = new FbsRtpStream.BaseStats(); + + binary.data(sendStats); + sendStats.base()!.data(baseStats); + + const base = parseBaseStreamStats(baseStats); + + return { + ...base, + type : 'outbound-rtp', + byteCount : Number(sendStats.byteCount()), + packetCount : Number(sendStats.packetCount()), + bitrate : Number(sendStats.bitrate()) + }; +} + +function parseBaseStreamStats(binary: FbsRtpStream.BaseStats): BaseRtpStreamStats +{ + return { + timestamp : Number(binary.timestamp()), + ssrc : binary.ssrc(), + rtxSsrc : binary.rtxSsrc() ?? undefined, + rid : binary.rid() ?? undefined, + kind : binary.kind() === FbsRtpParameters.MediaKind.AUDIO ? + 'audio' : + 'video', + mimeType : binary.mimeType()!, + packetsLost : Number(binary.packetsLost()), + fractionLost : Number(binary.fractionLost()), + packetsDiscarded : Number(binary.packetsDiscarded()), + packetsRetransmitted : Number(binary.packetsRetransmitted()), + packetsRepaired : Number(binary.packetsRepaired()), + nackCount : Number(binary.nackCount()), + nackPacketCount : Number(binary.nackPacketCount()), + pliCount : Number(binary.pliCount()), + firCount : Number(binary.firCount()), + score : binary.score(), + roundTripTime : binary.roundTripTime(), + rtxPacketsDiscarded : binary.rtxPacketsDiscarded() ? + Number(binary.rtxPacketsDiscarded()) : + undefined + }; +} + +function parseBitrateByLayer(binary: FbsRtpStream.RecvStats): any +{ + if (binary.bitrateByLayerLength() === 0) + { + return {}; + } + + const bitRateByLayer: {[key: string]: number} = {}; + + for (let i = 0; i < binary.bitrateByLayerLength(); ++i) + { + const layer: string = binary.bitrateByLayer(i)!.layer()!; + const bitrate = binary.bitrateByLayer(i)!.bitrate(); + + bitRateByLayer[layer] = Number(bitrate); + } +} diff --git a/node/src/SctpParameters.ts b/node/src/SctpParameters.ts index 82079d4516..54a878fb6a 100644 --- a/node/src/SctpParameters.ts +++ b/node/src/SctpParameters.ts @@ -1,3 +1,6 @@ +import * as flatbuffers from 'flatbuffers'; +import * as FbsSctpParameters from './fbs/sctp-parameters'; + export type SctpCapabilities = { numStreams: NumSctpStreams; @@ -93,3 +96,63 @@ export type SctpStreamParameters = */ maxRetransmits?: number; }; + +export type SctpParametersDump = +{ + port : number; + OS : number; + MIS : number; + maxMessageSize : number; + sendBufferSize : number; + sctpBufferedAmount : number; + isDataChannel : boolean; +}; + +export function parseSctpParametersDump( + binary: FbsSctpParameters.SctpParameters +): SctpParametersDump +{ + return { + port : binary.port(), + OS : binary.os(), + MIS : binary.mis(), + maxMessageSize : binary.maxMessageSize(), + sendBufferSize : binary.sendBufferSize(), + sctpBufferedAmount : binary.sctpBufferedAmount(), + isDataChannel : binary.isDataChannel() + }; +} + +export function serializeSctpStreamParameters( + builder: flatbuffers.Builder, + parameters: SctpStreamParameters +): number +{ + return FbsSctpParameters.SctpStreamParameters.createSctpStreamParameters( + builder, + parameters.streamId, + parameters.ordered!, + typeof parameters.maxPacketLifeTime === 'number' ? + parameters.maxPacketLifeTime : + null, + typeof parameters.maxRetransmits === 'number' ? + parameters.maxRetransmits : + null + ); +} + +export function parseSctpStreamParameters( + parameters: FbsSctpParameters.SctpStreamParameters +): SctpStreamParameters +{ + return { + streamId : parameters.streamId(), + ordered : parameters.ordered()!, + maxPacketLifeTime : parameters.maxPacketLifeTime() !== null ? + parameters.maxPacketLifeTime()! : + undefined, + maxRetransmits : parameters.maxRetransmits() !== null ? + parameters.maxRetransmits()! : + undefined + }; +} diff --git a/node/src/SrtpParameters.ts b/node/src/SrtpParameters.ts index 1cbddce46c..7c5937c05e 100644 --- a/node/src/SrtpParameters.ts +++ b/node/src/SrtpParameters.ts @@ -1,3 +1,6 @@ +import * as flatbuffers from 'flatbuffers'; +import * as FbsSrtpParameters from './fbs/srtp-parameters'; + /** * SRTP parameters. */ @@ -22,3 +25,62 @@ export type SrtpCryptoSuite = | 'AEAD_AES_128_GCM' | 'AES_CM_128_HMAC_SHA1_80' | 'AES_CM_128_HMAC_SHA1_32'; + +export function cryptoSuiteFromFbs(binary: FbsSrtpParameters.SrtpCryptoSuite): SrtpCryptoSuite +{ + switch (binary) + { + case FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_256_GCM: + return 'AEAD_AES_256_GCM'; + + case FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_128_GCM: + return 'AEAD_AES_128_GCM'; + + case FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80: + return 'AES_CM_128_HMAC_SHA1_80'; + + case FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32: + return 'AES_CM_128_HMAC_SHA1_32'; + } +} + +export function cryptoSuiteToFbs(cryptoSuite: SrtpCryptoSuite) + : FbsSrtpParameters.SrtpCryptoSuite +{ + switch (cryptoSuite) + { + case 'AEAD_AES_256_GCM': + return FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_256_GCM; + + case 'AEAD_AES_128_GCM': + return FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_128_GCM; + + case 'AES_CM_128_HMAC_SHA1_80': + return FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80; + + case 'AES_CM_128_HMAC_SHA1_32': + return FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32; + + default: + throw new TypeError(`invalid SrtpCryptoSuite: ${cryptoSuite}`); + } +} + +export function parseSrtpParameters(binary: FbsSrtpParameters.SrtpParameters): SrtpParameters +{ + return { + cryptoSuite : cryptoSuiteFromFbs(binary.cryptoSuite()), + keyBase64 : binary.keyBase64()! + }; +} + +export function serializeSrtpParameters( + builder:flatbuffers.Builder, srtpParameters:SrtpParameters +): number +{ + const keyBase64Offset = builder.createString(srtpParameters.keyBase64); + + return FbsSrtpParameters.SrtpParameters.createSrtpParameters( + builder, cryptoSuiteToFbs(srtpParameters.cryptoSuite), keyBase64Offset + ); +} diff --git a/node/src/Transport.ts b/node/src/Transport.ts index ddecd0d02b..7486cf8065 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -1,31 +1,93 @@ -import { v4 as uuidv4 } from 'uuid'; +import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; -import * as utils from './utils'; import * as ortc from './ortc'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { RouterInternal } from './Router'; import { WebRtcTransportData } from './WebRtcTransport'; import { PlainTransportData } from './PlainTransport'; import { PipeTransportData } from './PipeTransport'; import { DirectTransportData } from './DirectTransport'; -import { Producer, ProducerOptions } from './Producer'; -import { Consumer, ConsumerOptions, ConsumerType } from './Consumer'; +import { Producer, ProducerOptions, producerTypeFromFbs, producerTypeToFbs } from './Producer'; +import { Consumer, ConsumerLayers, ConsumerOptions, ConsumerType } from './Consumer'; import { DataProducer, DataProducerOptions, - DataProducerType + DataProducerType, + dataProducerTypeToFbs, + parseDataProducerDumpResponse } from './DataProducer'; import { DataConsumer, DataConsumerOptions, - DataConsumerType + DataConsumerType, + dataConsumerTypeToFbs, + parseDataConsumerDumpResponse } from './DataConsumer'; -import { RtpCapabilities } from './RtpParameters'; -import { SctpStreamParameters } from './SctpParameters'; +import { + MediaKind, + RtpCapabilities, + RtpParameters, + serializeRtpEncodingParameters, + serializeRtpParameters +} from './RtpParameters'; +import { + parseSctpParametersDump, + serializeSctpStreamParameters, + SctpParameters, + SctpStreamParameters +} from './SctpParameters'; import { AppData } from './types'; +import * as utils from './utils'; +import { TraceDirection as FbsTraceDirection } from './fbs/common'; +import * as FbsRequest from './fbs/request'; +import { MediaKind as FbsMediaKind } from './fbs/rtp-parameters/media-kind'; +import * as FbsConsumer from './fbs/consumer'; +import * as FbsDataConsumer from './fbs/data-consumer'; +import * as FbsDataProducer from './fbs/data-producer'; +import * as FbsTransport from './fbs/transport'; +import * as FbsRouter from './fbs/router'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; +import { SctpState as FbsSctpState } from './fbs/sctp-association/sctp-state'; + +export type TransportListenInfo = +{ + /** + * Network protocol. + */ + protocol: TransportProtocol; + + /** + * Listening IPv4 or IPv6. + */ + ip: string; + + /** + * Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with + * private IP). + */ + announcedIp?: string; + /** + * Listening port. + */ + port?: number; + + /** + * Send buffer size (bytes). + */ + sendBufferSize?: number; + + /** + * Recv buffer size (bytes). + */ + recvBufferSize?: number; +}; + +/** + * Use TransportListenInfo instead. + * @deprecated + */ export type TransportListenIp = { /** @@ -116,7 +178,6 @@ export type TransportConstructorOptions = internal: TransportInternal; data: TransportData; channel: Channel; - payloadChannel: PayloadChannel; appData?: TransportAppData; getRouterRtpCapabilities: () => RtpCapabilities; getProducerById: (producerId: string) => Producer | undefined; @@ -128,12 +189,76 @@ export type TransportInternal = RouterInternal & transportId: string; }; +export type BaseTransportDump = +{ + id : string; + direct : boolean; + producerIds : string[]; + consumerIds : string[]; + mapSsrcConsumerId : { key: number; value: string }[]; + mapRtxSsrcConsumerId : { key: number; value: string }[]; + recvRtpHeaderExtensions : RecvRtpHeaderExtensions; + rtpListener: RtpListenerDump; + maxMessageSize: number; + dataProducerIds : string[]; + dataConsumerIds : string[]; + sctpParameters? : SctpParameters; + sctpState? : SctpState; + sctpListener?: SctpListenerDump; + traceEventTypes? : string[]; +}; + +export type BaseTransportStats = +{ + transportId: string; + timestamp: number; + sctpState?: SctpState; + bytesReceived: number; + recvBitrate: number; + bytesSent: number; + sendBitrate: number; + rtpBytesReceived: number; + rtpRecvBitrate: number; + rtpBytesSent: number; + rtpSendBitrate: number; + rtxBytesReceived: number; + rtxRecvBitrate: number; + rtxBytesSent: number; + rtxSendBitrate: number; + probationBytesSent: number; + probationSendBitrate: number; + availableOutgoingBitrate?: number; + availableIncomingBitrate?: number; + maxIncomingBitrate?: number; +}; + type TransportData = | WebRtcTransportData | PlainTransportData | PipeTransportData | DirectTransportData; +type RtpListenerDump = +{ + ssrcTable : {key: number; value: string}[]; + midTable : {key: number; value: string}[]; + ridTable : {key: number; value: string}[]; +}; + +type SctpListenerDump = +{ + streamIdTable : {key: number; value: string}[]; +}; + +type RecvRtpHeaderExtensions = +{ + mid?: number; + rid?: number; + rrid?: number; + absSendTime?: number; + transportWideCc01?: number; +}; + const logger = new Logger('Transport'); export class Transport @@ -151,9 +276,6 @@ export class Transport // Channel instance. protected readonly channel: Channel; - // PayloadChannel instance. - protected readonly payloadChannel: PayloadChannel; - // Close flag. #closed = false; @@ -206,7 +328,6 @@ export class Transport internal, data, channel, - payloadChannel, appData, getRouterRtpCapabilities, getProducerById, @@ -221,7 +342,6 @@ export class Transport this.internal = internal; this.#data = data; this.channel = channel; - this.payloadChannel = payloadChannel; this.#appData = appData || {} as TransportAppData; this.#getRouterRtpCapabilities = getRouterRtpCapabilities; this.getProducerById = getProducerById; @@ -293,12 +413,18 @@ export class Transport // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.transportId); - this.payloadChannel.removeAllListeners(this.internal.transportId); - const reqData = { transportId: this.internal.transportId }; + /* Build Request. */ + const requestOffset = new FbsRouter.CloseTransportRequestT( + this.internal.transportId + ).pack(this.channel.bufferBuilder); - this.channel.request('router.closeTransport', this.internal.routerId, reqData) - .catch(() => {}); + this.channel.request( + FbsRequest.Method.ROUTER_CLOSE_TRANSPORT, + FbsRequest.Body.Router_CloseTransportRequest, + requestOffset, + this.internal.routerId + ).catch(() => {}); // Close every Producer. for (const producer of this.#producers.values()) @@ -359,7 +485,6 @@ export class Transport // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.transportId); - this.payloadChannel.removeAllListeners(this.internal.transportId); // Close every Producer. for (const producer of this.#producers.values()) @@ -420,7 +545,6 @@ export class Transport // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.transportId); - this.payloadChannel.removeAllListeners(this.internal.transportId); // Close every Producer. for (const producer of this.#producers.values()) @@ -469,12 +593,13 @@ export class Transport /** * Dump Transport. + * + * @abstract */ async dump(): Promise { - logger.debug('dump()'); - - return this.channel.request('transport.dump', this.internal.transportId); + // Should not happen. + throw new Error('method implemented in the subclass'); } /** @@ -485,7 +610,7 @@ export class Transport async getStats(): Promise { // Should not happen. - throw new Error('method not implemented in the subclass'); + throw new Error('method implemented in the subclass'); } /** @@ -497,7 +622,7 @@ export class Transport async connect(params: any): Promise { // Should not happen. - throw new Error('method not implemented in the subclass'); + throw new Error('method implemented in the subclass'); } /** @@ -507,10 +632,16 @@ export class Transport { logger.debug('setMaxIncomingBitrate() [bitrate:%s]', bitrate); - const reqData = { bitrate }; + /* Build Request. */ + const requestOffset = FbsTransport.SetMaxIncomingBitrateRequest + .createSetMaxIncomingBitrateRequest(this.channel.bufferBuilder, bitrate); await this.channel.request( - 'transport.setMaxIncomingBitrate', this.internal.transportId, reqData); + FbsRequest.Method.TRANSPORT_SET_MAX_INCOMING_BITRATE, + FbsRequest.Body.Transport_SetMaxIncomingBitrateRequest, + requestOffset, + this.internal.transportId + ); } /** @@ -520,10 +651,17 @@ export class Transport { logger.debug('setMaxOutgoingBitrate() [bitrate:%s]', bitrate); - const reqData = { bitrate }; + /* Build Request. */ + const requestOffset = new FbsTransport.SetMaxOutgoingBitrateRequestT( + bitrate + ).pack(this.channel.bufferBuilder); await this.channel.request( - 'transport.setMaxOutgoingBitrate', this.internal.transportId, reqData); + FbsRequest.Method.TRANSPORT_SET_MAX_OUTGOING_BITRATE, + FbsRequest.Body.Transport_SetMaxOutgoingBitrateRequest, + requestOffset, + this.internal.transportId + ); } /** @@ -533,10 +671,17 @@ export class Transport { logger.debug('setMinOutgoingBitrate() [bitrate:%s]', bitrate); - const reqData = { bitrate }; + /* Build Request. */ + const requestOffset = new FbsTransport.SetMinOutgoingBitrateRequestT( + bitrate + ).pack(this.channel.bufferBuilder); await this.channel.request( - 'transport.setMinOutgoingBitrate', this.internal.transportId, reqData); + FbsRequest.Method.TRANSPORT_SET_MIN_OUTGOING_BITRATE, + FbsRequest.Body.Transport_SetMinOutgoingBitrateRequest, + requestOffset, + this.internal.transportId + ); } /** @@ -591,11 +736,11 @@ export class Transport { this.#cnameForProducers = rtpParameters.rtcp.cname; } - // Otherwise if we don't have yet a CNAME for Producers and the RTP parameters - // do not include CNAME, create a random one. + // Otherwise if we don't have yet a CNAME for Producers and the RTP + // parameters do not include CNAME, create a random one. else if (!this.#cnameForProducers) { - this.#cnameForProducers = uuidv4().substr(0, 8); + this.#cnameForProducers = utils.generateUUIDv4().substr(0, 8); } // Override Producer's CNAME. @@ -613,24 +758,36 @@ export class Transport const consumableRtpParameters = ortc.getConsumableRtpParameters( kind, rtpParameters, routerRtpCapabilities, rtpMapping); - const reqData = - { - producerId : id || uuidv4(), + const producerId = id || utils.generateUUIDv4(); + const requestOffset = createProduceRequest({ + builder : this.channel.bufferBuilder, + producerId, kind, rtpParameters, rtpMapping, keyFrameRequestDelay, paused - }; + }); - const status = - await this.channel.request('transport.produce', this.internal.transportId, reqData); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_PRODUCE, + FbsRequest.Body.Transport_ProduceRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const produceResponse = new FbsTransport.ProduceResponse(); + + response.body(produceResponse); + + const status = produceResponse.unpack(); const data = { kind, rtpParameters, - type : status.type, + type : producerTypeFromFbs(status.type), consumableRtpParameters }; @@ -639,11 +796,10 @@ export class Transport internal : { ...this.internal, - producerId : reqData.producerId + producerId }, data, channel : this.channel, - payloadChannel : this.payloadChannel, appData, paused }); @@ -745,21 +901,31 @@ export class Transport } } - const reqData = - { - consumerId : uuidv4(), - producerId, - kind : producer.kind, + const consumerId = utils.generateUUIDv4(); + const requestOffset = createConsumeRequest({ + builder : this.channel.bufferBuilder, + producer, + consumerId, rtpParameters, - type : pipe ? 'pipe' : producer.type, - consumableRtpEncodings : producer.consumableRtpParameters.encodings, paused, preferredLayers, - ignoreDtx - }; + ignoreDtx, + pipe + }); - const status = - await this.channel.request('transport.consume', this.internal.transportId, reqData); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_CONSUME, + FbsRequest.Body.Transport_ConsumeRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const consumeResponse = new FbsTransport.ConsumeResponse(); + + response.body(consumeResponse); + + const status = consumeResponse.unpack(); const data = { @@ -774,16 +940,22 @@ export class Transport internal : { ...this.internal, - consumerId : reqData.consumerId + consumerId }, data, channel : this.channel, - payloadChannel : this.payloadChannel, appData, paused : status.paused, producerPaused : status.producerPaused, - score : status.score, - preferredLayers : status.preferredLayers + score : status.score ?? undefined, + preferredLayers : status.preferredLayers ? + { + spatialLayer : status.preferredLayers.spatialLayer, + temporalLayer : status.preferredLayers.temporalLayer !== null ? + status.preferredLayers.temporalLayer : + undefined + } : + undefined }); this.consumers.set(consumer.id, consumer); @@ -805,6 +977,7 @@ export class Transport sctpStreamParameters, label = '', protocol = '', + paused = false, appData }: DataProducerOptions = {} ): Promise> @@ -842,28 +1015,47 @@ export class Transport } } - const reqData = - { - dataProducerId : id || uuidv4(), + const dataProducerId = id || utils.generateUUIDv4(); + const requestOffset = createProduceDataRequest({ + builder : this.channel.bufferBuilder, + dataProducerId, type, sctpStreamParameters, label, - protocol - }; + protocol, + paused + }); - const data = - await this.channel.request('transport.produceData', this.internal.transportId, reqData); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_PRODUCE_DATA, + FbsRequest.Body.Transport_ProduceDataRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const produceDataResponse = new FbsDataProducer.DumpResponse(); + + response.body(produceDataResponse); + + const dump = parseDataProducerDumpResponse(produceDataResponse); const dataProducer = new DataProducer( { internal : { ...this.internal, - dataProducerId : reqData.dataProducerId + dataProducerId }, - data, - channel : this.channel, - payloadChannel : this.payloadChannel, + data : + { + type : dump.type, + sctpStreamParameters : dump.sctpStreamParameters, + label : dump.label, + protocol : dump.protocol + }, + channel : this.channel, + paused, appData }); @@ -885,15 +1077,17 @@ export class Transport /** * Create a DataConsumer. */ - async consumeData( + async consumeData( { dataProducerId, ordered, maxPacketLifeTime, maxRetransmits, + paused = false, + subchannels, appData - }: DataConsumerOptions - ): Promise> + }: DataConsumerOptions + ): Promise> { logger.debug('consumeData()'); @@ -923,7 +1117,7 @@ export class Transport { type = 'sctp'; sctpStreamParameters = - utils.clone(dataProducer.sctpStreamParameters) as SctpStreamParameters; + (utils.clone(dataProducer.sctpStreamParameters) ?? {}) as SctpStreamParameters; // Override if given. if (ordered !== undefined) @@ -964,30 +1158,54 @@ export class Transport } const { label, protocol } = dataProducer; + const dataConsumerId = utils.generateUUIDv4(); - const reqData = - { - dataConsumerId : uuidv4(), + const requestOffset = createConsumeDataRequest({ + builder : this.channel.bufferBuilder, + dataConsumerId, dataProducerId, type, sctpStreamParameters, label, - protocol - }; + protocol, + paused, + subchannels + }); - const data = - await this.channel.request('transport.consumeData', this.internal.transportId, reqData); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_CONSUME_DATA, + FbsRequest.Body.Transport_ConsumeDataRequest, + requestOffset, + this.internal.transportId + ); - const dataConsumer = new DataConsumer( + /* Decode Response. */ + const consumeDataResponse = new FbsDataConsumer.DumpResponse(); + + response.body(consumeDataResponse); + + const dump = parseDataConsumerDumpResponse(consumeDataResponse); + + const dataConsumer = new DataConsumer( { internal : { ...this.internal, - dataConsumerId : reqData.dataConsumerId + dataConsumerId }, - data, - channel : this.channel, - payloadChannel : this.payloadChannel, + data : + { + dataProducerId : dump.dataProducerId, + type : dump.type, + sctpStreamParameters : dump.sctpStreamParameters, + label : dump.label, + protocol : dump.protocol, + bufferedAmountLowThreshold : dump.bufferedAmountLowThreshold + }, + channel : this.channel, + paused : dump.paused, + subchannels : dump.subchannels, + dataProducerPaused : dump.dataProducerPaused, appData }); @@ -1022,12 +1240,43 @@ export class Transport */ async enableTraceEvent(types: TransportTraceEventType[] = []): Promise { - logger.debug('pause()'); + logger.debug('enableTraceEvent()'); - const reqData = { types }; + if (!Array.isArray(types)) + { + throw new TypeError('types must be an array'); + } + if (types.find((type) => typeof type !== 'string')) + { + throw new TypeError('every type must be a string'); + } + + // Convert event types. + const fbsEventTypes: FbsTransport.TraceEventType[] = []; + + for (const eventType of types) + { + try + { + fbsEventTypes.push(transportTraceEventTypeToFbs(eventType)); + } + catch (error) + { + // Ignore invalid event types. + } + } + + /* Build Request. */ + const requestOffset = new FbsTransport.EnableTraceEventRequestT( + fbsEventTypes + ).pack(this.channel.bufferBuilder); await this.channel.request( - 'transport.enableTraceEvent', this.internal.transportId, reqData); + FbsRequest.Method.TRANSPORT_ENABLE_TRACE_EVENT, + FbsRequest.Body.Transport_EnableTraceEventRequest, + requestOffset, + this.internal.transportId + ); } private getNextSctpStreamId(): number @@ -1064,3 +1313,495 @@ export class Transport throw new Error('no sctpStreamId available'); } } + +function transportTraceEventTypeToFbs(eventType: TransportTraceEventType) + : FbsTransport.TraceEventType +{ + switch (eventType) + { + case 'probation': + return FbsTransport.TraceEventType.PROBATION; + case 'bwe': + return FbsTransport.TraceEventType.BWE; + default: + throw new TypeError(`invalid TransportTraceEventType: ${eventType}`); + } +} + +function transportTraceEventTypeFromFbs(eventType: FbsTransport.TraceEventType) + : TransportTraceEventType +{ + switch (eventType) + { + case FbsTransport.TraceEventType.PROBATION: + return 'probation'; + case FbsTransport.TraceEventType.BWE: + return 'bwe'; + } +} + +export function parseSctpState(fbsSctpState: FbsSctpState): SctpState +{ + switch (fbsSctpState) + { + case FbsSctpState.NEW: + return 'new'; + case FbsSctpState.CONNECTING: + return 'connecting'; + case FbsSctpState.CONNECTED: + return 'connected'; + case FbsSctpState.FAILED: + return 'failed'; + case FbsSctpState.CLOSED: + return 'closed'; + default: + throw new TypeError(`invalid SctpState: ${fbsSctpState}`); + } +} + +export function parseProtocol(protocol: FbsTransport.Protocol): TransportProtocol +{ + switch (protocol) + { + case FbsTransport.Protocol.UDP: + return 'udp'; + + case FbsTransport.Protocol.TCP: + return 'tcp'; + } +} + +export function serializeProtocol(protocol: TransportProtocol): FbsTransport.Protocol +{ + switch (protocol) + { + case 'udp': + return FbsTransport.Protocol.UDP; + + case 'tcp': + return FbsTransport.Protocol.TCP; + } +} + +export function parseTuple(binary: FbsTransport.Tuple): TransportTuple +{ + return { + localIp : binary.localIp()!, + localPort : binary.localPort(), + remoteIp : binary.remoteIp() ?? undefined, + remotePort : binary.remotePort(), + protocol : parseProtocol(binary.protocol()) + }; +} + +export function parseBaseTransportDump( + binary: FbsTransport.Dump +): BaseTransportDump +{ + // Retrieve producerIds. + const producerIds = utils.parseVector(binary, 'producerIds'); + // Retrieve consumerIds. + const consumerIds = utils.parseVector(binary, 'consumerIds'); + // Retrieve map SSRC consumerId. + const mapSsrcConsumerId = utils.parseUint32StringVector(binary, 'mapSsrcConsumerId'); + // Retrieve map RTX SSRC consumerId. + const mapRtxSsrcConsumerId = utils.parseUint32StringVector(binary, 'mapRtxSsrcConsumerId'); + // Retrieve dataProducerIds. + const dataProducerIds = utils.parseVector(binary, 'dataProducerIds'); + // Retrieve dataConsumerIds. + const dataConsumerIds = utils.parseVector(binary, 'dataConsumerIds'); + // Retrieve recvRtpHeaderExtesions. + const recvRtpHeaderExtensions = parseRecvRtpHeaderExtensions(binary.recvRtpHeaderExtensions()!); + // Retrieve RtpListener. + const rtpListener = parseRtpListenerDump(binary.rtpListener()!); + + // Retrieve SctpParameters. + const fbsSctpParameters = binary.sctpParameters(); + let sctpParameters: SctpParameters | undefined; + + if (fbsSctpParameters) + { + sctpParameters = parseSctpParametersDump(fbsSctpParameters); + } + + // Retrieve sctpState. + const sctpState = binary.sctpState() === null ? undefined : parseSctpState(binary.sctpState()!); + + // Retrive sctpListener. + const sctpListener = binary.sctpListener() ? + parseSctpListenerDump(binary.sctpListener()!) : + undefined; + + // Retrieve traceEventTypes. + const traceEventTypes = utils.parseVector(binary, 'traceEventTypes', transportTraceEventTypeFromFbs); + + return { + id : binary.id()!, + direct : binary.direct(), + producerIds : producerIds, + consumerIds : consumerIds, + mapSsrcConsumerId : mapSsrcConsumerId, + mapRtxSsrcConsumerId : mapRtxSsrcConsumerId, + dataProducerIds : dataProducerIds, + dataConsumerIds : dataConsumerIds, + recvRtpHeaderExtensions : recvRtpHeaderExtensions, + rtpListener : rtpListener, + maxMessageSize : binary.maxMessageSize(), + sctpParameters : sctpParameters, + sctpState : sctpState, + sctpListener : sctpListener, + traceEventTypes : traceEventTypes + }; +} + +export function parseBaseTransportStats( + binary: FbsTransport.Stats +): BaseTransportStats +{ + const sctpState = binary.sctpState() === null ? undefined : parseSctpState(binary.sctpState()!); + + return { + transportId : binary.transportId()!, + timestamp : Number(binary.timestamp()), + sctpState, + bytesReceived : Number(binary.bytesReceived()), + recvBitrate : Number(binary.recvBitrate()), + bytesSent : Number(binary.bytesSent()), + sendBitrate : Number(binary.sendBitrate()), + rtpBytesReceived : Number(binary.rtpBytesReceived()), + rtpRecvBitrate : Number(binary.rtpRecvBitrate()), + rtpBytesSent : Number(binary.rtpBytesSent()), + rtpSendBitrate : Number(binary.rtpSendBitrate()), + rtxBytesReceived : Number(binary.rtxBytesReceived()), + rtxRecvBitrate : Number(binary.rtxRecvBitrate()), + rtxBytesSent : Number(binary.rtxBytesSent()), + rtxSendBitrate : Number(binary.rtxSendBitrate()), + probationBytesSent : Number(binary.probationBytesSent()), + probationSendBitrate : Number(binary.probationSendBitrate()), + availableOutgoingBitrate : Number(binary.availableOutgoingBitrate()), + availableIncomingBitrate : Number(binary.availableIncomingBitrate()), + maxIncomingBitrate : binary.maxIncomingBitrate() ? + Number(binary.maxIncomingBitrate()) : + undefined + }; +} + +export function parseTransportTraceEventData( + trace: FbsTransport.TraceNotification +): TransportTraceEventData +{ + switch (trace.type()) + { + case FbsTransport.TraceEventType.BWE: + { + const info = new FbsTransport.BweTraceInfo(); + + trace.info(info); + + return { + type : 'bwe', + timestamp : Number(trace.timestamp()), + direction : trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', + info : parseBweTraceInfo(info!) + }; + } + + case FbsTransport.TraceEventType.PROBATION: + { + return { + type : 'probation', + timestamp : Number(trace.timestamp()), + direction : trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', + info : {} + }; + } + } +} + +function parseRecvRtpHeaderExtensions(binary: FbsTransport.RecvRtpHeaderExtensions) + : RecvRtpHeaderExtensions +{ + return { + mid : binary.mid() !== null ? binary.mid()! : undefined, + rid : binary.rid() !== null ? binary.rid()! : undefined, + rrid : binary.rrid() !== null ? binary.rrid()! : undefined, + absSendTime : binary.absSendTime() !== null ? binary.absSendTime()! : undefined, + transportWideCc01 : binary.transportWideCc01() !== null ? + binary.transportWideCc01()! : + undefined + }; +} + +function parseBweTraceInfo(binary: FbsTransport.BweTraceInfo): +{ + desiredBitrate:number; + effectiveDesiredBitrate:number; + minBitrate:number; + maxBitrate:number; + startBitrate:number; + maxPaddingBitrate:number; + availableBitrate:number; + bweType:'transport-cc' | 'remb'; +} +{ + return { + desiredBitrate : binary.desiredBitrate(), + effectiveDesiredBitrate : binary.effectiveDesiredBitrate(), + minBitrate : binary.minBitrate(), + maxBitrate : binary.maxBitrate(), + startBitrate : binary.startBitrate(), + maxPaddingBitrate : binary.maxPaddingBitrate(), + availableBitrate : binary.availableBitrate(), + bweType : binary.bweType() === FbsTransport.BweType.TRANSPORT_CC ? + 'transport-cc' : + 'remb' + }; +} + +function createConsumeRequest({ + builder, + producer, + consumerId, + rtpParameters, + paused, + preferredLayers, + ignoreDtx, + pipe +} : { + builder: flatbuffers.Builder; + producer: Producer; + consumerId: string; + rtpParameters: RtpParameters; + paused: boolean; + preferredLayers?: ConsumerLayers; + ignoreDtx?: boolean; + pipe: boolean; +}): number +{ + const rtpParametersOffset = serializeRtpParameters(builder, rtpParameters); + const consumerIdOffset = builder.createString(consumerId); + const producerIdOffset = builder.createString(producer.id); + let consumableRtpEncodingsOffset: number | undefined; + let preferredLayersOffset: number | undefined; + + if (producer.consumableRtpParameters.encodings) + { + consumableRtpEncodingsOffset = serializeRtpEncodingParameters( + builder, producer.consumableRtpParameters.encodings + ); + } + + if (preferredLayers) + { + FbsConsumer.ConsumerLayers.startConsumerLayers(builder); + FbsConsumer.ConsumerLayers.addSpatialLayer(builder, preferredLayers.spatialLayer); + + if (preferredLayers.temporalLayer !== undefined) + { + FbsConsumer.ConsumerLayers.addTemporalLayer( + builder, preferredLayers.temporalLayer + ); + } + + preferredLayersOffset = FbsConsumer.ConsumerLayers.endConsumerLayers(builder); + } + + const ConsumeRequest = FbsTransport.ConsumeRequest; + + // Create Consume Request. + ConsumeRequest.startConsumeRequest(builder); + ConsumeRequest.addConsumerId(builder, consumerIdOffset); + ConsumeRequest.addProducerId(builder, producerIdOffset); + ConsumeRequest.addKind( + builder, producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO); + ConsumeRequest.addRtpParameters(builder, rtpParametersOffset); + ConsumeRequest.addType( + builder, + pipe ? FbsRtpParameters.Type.PIPE : producerTypeToFbs(producer.type) + ); + + if (consumableRtpEncodingsOffset) + { + ConsumeRequest.addConsumableRtpEncodings(builder, consumableRtpEncodingsOffset); + } + + ConsumeRequest.addPaused(builder, paused); + + if (preferredLayersOffset) + { + ConsumeRequest.addPreferredLayers(builder, preferredLayersOffset); + } + + ConsumeRequest.addIgnoreDtx(builder, Boolean(ignoreDtx)); + + return ConsumeRequest.endConsumeRequest(builder); +} + +function createProduceRequest({ + builder, + producerId, + kind, + rtpParameters, + rtpMapping, + keyFrameRequestDelay, + paused +} : { + builder : flatbuffers.Builder; + producerId: string; + kind: MediaKind; + rtpParameters: RtpParameters; + rtpMapping: ortc.RtpMapping; + keyFrameRequestDelay?: number; + paused: boolean; +}): number +{ + const producerIdOffset = builder.createString(producerId); + const rtpParametersOffset = serializeRtpParameters(builder, rtpParameters); + const rtpMappingOffset = ortc.serializeRtpMapping(builder, rtpMapping); + + FbsTransport.ProduceRequest.startProduceRequest(builder); + FbsTransport.ProduceRequest.addProducerId(builder, producerIdOffset); + FbsTransport.ProduceRequest.addKind( + builder, kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO); + FbsTransport.ProduceRequest.addRtpParameters(builder, rtpParametersOffset); + FbsTransport.ProduceRequest.addRtpMapping(builder, rtpMappingOffset); + FbsTransport.ProduceRequest.addKeyFrameRequestDelay(builder, keyFrameRequestDelay ?? 0); + FbsTransport.ProduceRequest.addPaused(builder, paused); + + return FbsTransport.ProduceRequest.endProduceRequest(builder); +} + +function createProduceDataRequest({ + builder, + dataProducerId, + type, + sctpStreamParameters, + label, + protocol, + paused +} : { + builder : flatbuffers.Builder; + dataProducerId: string; + type: DataProducerType; + sctpStreamParameters?: SctpStreamParameters; + label: string; + protocol: string; + paused: boolean; +}): number +{ + const dataProducerIdOffset = builder.createString(dataProducerId); + const labelOffset = builder.createString(label); + const protocolOffset = builder.createString(protocol); + + let sctpStreamParametersOffset = 0; + + if (sctpStreamParameters) + { + sctpStreamParametersOffset = serializeSctpStreamParameters( + builder, sctpStreamParameters + ); + } + + FbsTransport.ProduceDataRequest.startProduceDataRequest(builder); + FbsTransport.ProduceDataRequest.addDataProducerId(builder, dataProducerIdOffset); + FbsTransport.ProduceDataRequest.addType(builder, dataProducerTypeToFbs(type)); + + if (sctpStreamParametersOffset) + { + FbsTransport.ProduceDataRequest.addSctpStreamParameters( + builder, sctpStreamParametersOffset + ); + } + + FbsTransport.ProduceDataRequest.addLabel(builder, labelOffset); + FbsTransport.ProduceDataRequest.addProtocol(builder, protocolOffset); + FbsTransport.ProduceDataRequest.addPaused(builder, paused); + + return FbsTransport.ProduceDataRequest.endProduceDataRequest(builder); +} + +function createConsumeDataRequest({ + builder, + dataConsumerId, + dataProducerId, + type, + sctpStreamParameters, + label, + protocol, + paused, + subchannels = [] +} : { + builder: flatbuffers.Builder; + dataConsumerId: string; + dataProducerId: string; + type: DataConsumerType; + sctpStreamParameters?: SctpStreamParameters; + label: string; + protocol: string; + paused: boolean; + subchannels?: number[]; +}): number +{ + const dataConsumerIdOffset = builder.createString(dataConsumerId); + const dataProducerIdOffset = builder.createString(dataProducerId); + const labelOffset = builder.createString(label); + const protocolOffset = builder.createString(protocol); + + let sctpStreamParametersOffset = 0; + + if (sctpStreamParameters) + { + sctpStreamParametersOffset = serializeSctpStreamParameters( + builder, sctpStreamParameters + ); + } + + const subchannelsOffset = FbsTransport.ConsumeDataRequest.createSubchannelsVector( + builder, subchannels + ); + + FbsTransport.ConsumeDataRequest.startConsumeDataRequest(builder); + FbsTransport.ConsumeDataRequest.addDataConsumerId(builder, dataConsumerIdOffset); + FbsTransport.ConsumeDataRequest.addDataProducerId(builder, dataProducerIdOffset); + FbsTransport.ConsumeDataRequest.addType(builder, dataConsumerTypeToFbs(type)); + + if (sctpStreamParametersOffset) + { + FbsTransport.ConsumeDataRequest.addSctpStreamParameters( + builder, sctpStreamParametersOffset + ); + } + + FbsTransport.ConsumeDataRequest.addLabel(builder, labelOffset); + FbsTransport.ConsumeDataRequest.addProtocol(builder, protocolOffset); + FbsTransport.ConsumeDataRequest.addPaused(builder, paused); + FbsTransport.ConsumeDataRequest.addSubchannels(builder, subchannelsOffset); + + return FbsTransport.ConsumeDataRequest.endConsumeDataRequest(builder); +} + +function parseRtpListenerDump(binary: FbsTransport.RtpListener): RtpListenerDump +{ + // Retrieve ssrcTable. + const ssrcTable = utils.parseUint32StringVector(binary, 'ssrcTable'); + // Retrieve midTable. + const midTable = utils.parseUint32StringVector(binary, 'midTable'); + // Retrieve ridTable. + const ridTable = utils.parseUint32StringVector(binary, 'ridTable'); + + return { + ssrcTable, + midTable, + ridTable + }; +} + +function parseSctpListenerDump(binary: FbsTransport.SctpListener): SctpListenerDump +{ + // Retrieve streamIdTable. + const streamIdTable = utils.parseUint32StringVector(binary, 'streamIdTable'); + + return { + streamIdTable + }; +} diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 0db3346ded..ad45f9e179 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -1,16 +1,20 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { TransportProtocol } from './Transport'; +import { TransportListenInfo } from './Transport'; import { WebRtcTransport } from './WebRtcTransport'; import { AppData } from './types'; +import * as utils from './utils'; +import { Body as RequestBody, Method } from './fbs/request'; +import * as FbsWorker from './fbs/worker'; +import * as FbsWebRtcServer from './fbs/web-rtc-server'; export type WebRtcServerOptions = { /** * Listen infos. */ - listenInfos: WebRtcServerListenInfo[]; + listenInfos: TransportListenInfo[]; /** * Custom application data. @@ -18,32 +22,14 @@ export type WebRtcServerOptions = appData?: WebRtcServerAppData; }; -export type WebRtcServerListenInfo = -{ - /** - * Network protocol. - */ - protocol: TransportProtocol; - - /** - * Listening IPv4 or IPv6. - */ - ip: string; - - /** - * Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with - * private IP). - */ - announcedIp?: string; - - /** - * Listening port. - */ - port?: number; -}; +/** + * @deprecated + * Use TransportListenInfo instead. + */ +export type WebRtcServerListenInfo = TransportListenInfo; export type WebRtcServerEvents = -{ +{ workerclose: []; // Private events. '@close': []; @@ -56,6 +42,34 @@ export type WebRtcServerObserverEvents = webrtctransportunhandled: [WebRtcTransport]; }; +export type WebRtcServerDump = +{ + id: string; + udpSockets: IpPort[]; + tcpServers: IpPort[]; + webRtcTransportIds: string[]; + localIceUsernameFragments: IceUserNameFragment[]; + tupleHashes: TupleHash[]; +}; + +type IpPort = +{ + ip: string; + port: number; +}; + +type IceUserNameFragment = +{ + localIceUsernameFragment: string; + webRtcTransportId: string; +}; + +type TupleHash = +{ + tupleHash: number; + webRtcTransportId: string; +}; + type WebRtcServerInternal = { webRtcServerId: string; @@ -172,9 +186,14 @@ export class WebRtcServer this.#closed = true; - const reqData = { webRtcServerId: this.#internal.webRtcServerId }; + // Build the request. + const requestOffset = new FbsWorker.CloseWebRtcServerRequestT( + this.#internal.webRtcServerId).pack(this.#channel.bufferBuilder); - this.#channel.request('worker.closeWebRtcServer', undefined, reqData) + this.#channel.request( + Method.WORKER_WEBRTCSERVER_CLOSE, + RequestBody.Worker_CloseWebRtcServerRequest, + requestOffset) .catch(() => {}); // Close every WebRtcTransport. @@ -222,11 +241,19 @@ export class WebRtcServer /** * Dump WebRtcServer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('webRtcServer.dump', this.#internal.webRtcServerId); + const response = await this.#channel.request( + Method.WEBRTCSERVER_DUMP, undefined, undefined, this.#internal.webRtcServerId); + + /* Decode Response. */ + const dump = new FbsWebRtcServer.DumpResponse(); + + response.body(dump); + + return parseWebRtcServerDump(dump); } /** @@ -248,3 +275,49 @@ export class WebRtcServer }); } } + +function parseIpPort(binary: FbsWebRtcServer.IpPort): IpPort +{ + return { + ip : binary.ip()!, + port : binary.port() + }; +} + +function parseIceUserNameFragment(binary: FbsWebRtcServer.IceUserNameFragment): IceUserNameFragment +{ + return { + localIceUsernameFragment : binary.localIceUsernameFragment()!, + webRtcTransportId : binary.webRtcTransportId()! + }; +} + +function parseTupleHash(binary: FbsWebRtcServer.TupleHash): TupleHash +{ + return { + tupleHash : Number(binary.tupleHash()!), + webRtcTransportId : binary.webRtcTransportId()! + }; +} + +function parseWebRtcServerDump( + data: FbsWebRtcServer.DumpResponse +): WebRtcServerDump +{ + return { + id : data.id()!, + udpSockets : utils.parseVector( + data, 'udpSockets', parseIpPort + ), + tcpServers : utils.parseVector( + data, 'tcpServers', parseIpPort + ), + webRtcTransportIds : utils.parseVector(data, 'webRtcTransportIds'), + localIceUsernameFragments : utils.parseVector( + data, 'localIceUsernameFragments', parseIceUserNameFragment + ), + tupleHashes : utils.parseVector( + data, 'tupleHashes', parseTupleHash + ) + }; +} diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 422f15f208..96b5165035 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -1,10 +1,19 @@ +import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { + parseSctpState, + parseBaseTransportDump, + parseBaseTransportStats, + parseProtocol, + parseTransportTraceEventData, + parseTuple, + BaseTransportDump, + BaseTransportStats, Transport, + TransportListenInfo, TransportListenIp, TransportProtocol, TransportTuple, - TransportTraceEventData, TransportEvents, TransportObserverEvents, TransportConstructorOptions, @@ -12,17 +21,36 @@ import { } from './Transport'; import { WebRtcServer } from './WebRtcServer'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; -import { Either } from './utils'; -import { AppData } from './types'; +import { AppData, Either } from './types'; +import { parseVector } from './utils'; +import { Event, Notification } from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsWebRtcTransport from './fbs/web-rtc-transport'; +import { DtlsState as FbsDtlsState } from './fbs/web-rtc-transport/dtls-state'; +import { DtlsRole as FbsDtlsRole } from './fbs/web-rtc-transport/dtls-role'; +import { FingerprintAlgorithm as FbsFingerprintAlgorithm } from './fbs/web-rtc-transport/fingerprint-algorithm'; +import { IceState as FbsIceState } from './fbs/web-rtc-transport/ice-state'; +import { IceRole as FbsIceRole } from './fbs/web-rtc-transport/ice-role'; +import { IceCandidateType as FbsIceCandidateType } from './fbs/web-rtc-transport/ice-candidate-type'; +import { IceCandidateTcpType as FbsIceCandidateTcpType } from './fbs/web-rtc-transport/ice-candidate-tcp-type'; export type WebRtcTransportOptions = WebRtcTransportOptionsBase & WebRtcTransportListen; -export type WebRtcTransportListenIndividual = +type WebRtcTransportListenIndividualListenInfo = +{ + /** + * Listening info. + */ + listenInfos: TransportListenInfo[]; +}; + +type WebRtcTransportListenIndividualListenIp = { /** * Listening IP address or addresses in order of preference (first one is the - * preferred one). Mandatory unless webRtcServer is given. + * preferred one). */ listenIps: (TransportListenIp | string)[]; @@ -33,16 +61,18 @@ export type WebRtcTransportListenIndividual = port?: number; }; -export type WebRtcTransportListenServer = +type WebRtcTransportListenServer = { /** - * Instance of WebRtcServer. Mandatory unless listenIps is given. + * Instance of WebRtcServer. */ webRtcServer: WebRtcServer; }; -export type WebRtcTransportListen = - Either; +type WebRtcTransportListen = Either< + Either, + WebRtcTransportListenServer +>; export type WebRtcTransportOptionsBase = { @@ -52,7 +82,7 @@ export type WebRtcTransportOptionsBase = enableUdp?: boolean; /** - * Listen in TCP. Default false. + * Listen in TCP. Default true if webrtcServer is given, false otherwise. */ enableTcp?: boolean; @@ -113,8 +143,8 @@ export type IceCandidate = ip: string; protocol: TransportProtocol; port: number; - type: 'host'; - tcpType: 'passive' | undefined; + type: IceCandidateType; + tcpType?: IceCandidateTcpType; }; export type DtlsParameters = @@ -125,47 +155,36 @@ export type DtlsParameters = /** * The hash function algorithm (as defined in the "Hash function Textual Names" - * registry initially specified in RFC 4572 Section 8) and its corresponding - * certificate fingerprint value (in lowercase hex string as expressed utilizing - * the syntax of "fingerprint" in RFC 4572 Section 5). + * registry initially specified in RFC 4572 Section 8). + */ +export type FingerprintAlgorithm = 'sha-1'| 'sha-224'| 'sha-256'| 'sha-384'| 'sha-512'; + +/** + * The hash function algorithm and its corresponding certificate fingerprint + * value (in lowercase hex string as expressed utilizing the syntax of + * "fingerprint" in RFC 4572 Section 5). */ export type DtlsFingerprint = { - algorithm: string; + algorithm: FingerprintAlgorithm; value: string; }; +export type IceRole = 'controlled' | 'controlling'; + export type IceState = 'new' | 'connected' | 'completed' | 'disconnected' | 'closed'; +export type IceCandidateType = 'host'; + +export type IceCandidateTcpType = 'passive'; + export type DtlsRole = 'auto' | 'client' | 'server'; export type DtlsState = 'new' | 'connecting' | 'connected' | 'failed' | 'closed'; -export type WebRtcTransportStat = +export type WebRtcTransportStat = BaseTransportStats & { - // Common to all Transports. type: string; - transportId: string; - timestamp: number; - sctpState?: SctpState; - bytesReceived: number; - recvBitrate: number; - bytesSent: number; - sendBitrate: number; - rtpBytesReceived: number; - rtpRecvBitrate: number; - rtpBytesSent: number; - rtpSendBitrate: number; - rtxBytesReceived: number; - rtxRecvBitrate: number; - rtxBytesSent: number; - rtxSendBitrate: number; - probationBytesSent: number; - probationSendBitrate: number; - availableOutgoingBitrate?: number; - availableIncomingBitrate?: number; - maxIncomingBitrate?: number; - // WebRtcTransport specific. iceRole: string; iceState: IceState; iceSelectedTuple?: TransportTuple; @@ -208,6 +227,18 @@ export type WebRtcTransportData = sctpState?: SctpState; }; +type WebRtcTransportDump = BaseTransportDump & +{ + iceRole: 'controlled'; + iceParameters: IceParameters; + iceCandidates: IceCandidate[]; + iceState: IceState; + iceSelectedTuple?: TransportTuple; + dtlsParameters: DtlsParameters; + dtlsState: DtlsState; + dtlsRemoteCert?: string; +}; + const logger = new Logger('WebRtcTransport'); export class WebRtcTransport @@ -397,6 +428,28 @@ export class WebRtcTransport super.listenServerClosed(); } + /** + * Dump Transport. + */ + async dump(): Promise + { + logger.debug('dump()'); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_DUMP, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsWebRtcTransport.DumpResponse(); + + response.body(data); + + return parseWebRtcTransportDumpResponse(data); + } + /** * Get WebRtcTransport stats. * @@ -406,7 +459,19 @@ export class WebRtcTransport { logger.debug('getStats()'); - return this.channel.request('transport.getStats', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_GET_STATS, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsWebRtcTransport.GetStatsResponse(); + + response.body(data); + + return [ parseGetStatsResponse(data) ]; } /** @@ -418,13 +483,26 @@ export class WebRtcTransport { logger.debug('connect()'); - const reqData = { dtlsParameters }; + const requestOffset = createConnectRequest({ + builder : this.channel.bufferBuilder, + dtlsParameters + }); + + // Wait for response. + const response = await this.channel.request( + FbsRequest.Method.WEBRTCTRANSPORT_CONNECT, + FbsRequest.Body.WebRtcTransport_ConnectRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsWebRtcTransport.ConnectResponse(); - const data = - await this.channel.request('transport.connect', this.internal.transportId, reqData); + response.body(data); // Update data. - this.#data.dtlsParameters.role = data.dtlsLocalRole; + this.#data.dtlsParameters.role = dtlsRoleFromFbs(data.dtlsLocalRole()); } /** @@ -434,10 +512,24 @@ export class WebRtcTransport { logger.debug('restartIce()'); - const data = - await this.channel.request('transport.restartIce', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_RESTART_ICE, + undefined, + undefined, + this.internal.transportId + ); - const { iceParameters } = data; + /* Decode Response. */ + const restartIceResponse = new FbsTransport.RestartIceResponse(); + + response.body(restartIceResponse); + + const iceParameters = + { + usernameFragment : restartIceResponse.usernameFragment()!, + password : restartIceResponse.password()!, + iceLite : restartIceResponse.iceLite() + }; this.#data.iceParameters = iceParameters; @@ -446,13 +538,17 @@ export class WebRtcTransport private handleWorkerNotifications(): void { - this.channel.on(this.internal.transportId, (event: string, data?: any) => + this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => { switch (event) { - case 'icestatechange': + case Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE: { - const iceState = data.iceState as IceState; + const notification = new FbsWebRtcTransport.IceStateChangeNotification(); + + data!.body(notification); + + const iceState = iceStateFromFbs(notification.iceState()); this.#data.iceState = iceState; @@ -464,9 +560,14 @@ export class WebRtcTransport break; } - case 'iceselectedtuplechange': + case Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE: { - const iceSelectedTuple = data.iceSelectedTuple as TransportTuple; + const notification = + new FbsWebRtcTransport.IceSelectedTupleChangeNotification(); + + data!.body(notification); + + const iceSelectedTuple = parseTuple(notification.tuple()!); this.#data.iceSelectedTuple = iceSelectedTuple; @@ -478,16 +579,19 @@ export class WebRtcTransport break; } - case 'dtlsstatechange': + case Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE: { - const dtlsState = data.dtlsState as DtlsState; - const dtlsRemoteCert = data.dtlsRemoteCert as string; + const notification = new FbsWebRtcTransport.DtlsStateChangeNotification(); + + data!.body(notification); + + const dtlsState = dtlsStateFromFbs(notification.dtlsState()); this.#data.dtlsState = dtlsState; if (dtlsState === 'connected') { - this.#data.dtlsRemoteCert = dtlsRemoteCert; + this.#data.dtlsRemoteCert = notification.remoteCert()!; } this.safeEmit('dtlsstatechange', dtlsState); @@ -498,9 +602,13 @@ export class WebRtcTransport break; } - case 'sctpstatechange': + case Event.TRANSPORT_SCTP_STATE_CHANGE: { - const sctpState = data.sctpState as SctpState; + const notification = new FbsTransport.SctpStateChangeNotification(); + + data!.body(notification); + + const sctpState = parseSctpState(notification.sctpState()); this.#data.sctpState = sctpState; @@ -512,9 +620,13 @@ export class WebRtcTransport break; } - case 'trace': + case Event.TRANSPORT_TRACE: { - const trace = data as TransportTraceEventData; + const notification = new FbsTransport.TraceNotification(); + + data!.body(notification); + + const trace = parseTransportTraceEventData(notification); this.safeEmit('trace', trace); @@ -532,3 +644,268 @@ export class WebRtcTransport }); } } + +function iceStateFromFbs(fbsIceState: FbsIceState): IceState +{ + switch (fbsIceState) + { + case FbsIceState.NEW: + return 'new'; + case FbsIceState.CONNECTED: + return 'connected'; + case FbsIceState.COMPLETED: + return 'completed'; + case FbsIceState.DISCONNECTED: + return 'disconnected'; + } +} + +function iceRoleFromFbs(role: FbsIceRole): IceRole +{ + switch (role) + { + case FbsIceRole.CONTROLLED: + return 'controlled'; + case FbsIceRole.CONTROLLING: + return 'controlling'; + } +} + +function iceCandidateTypeFromFbs(type: FbsIceCandidateType): IceCandidateType +{ + switch (type) + { + case FbsIceCandidateType.HOST: + return 'host'; + } +} + +function iceCandidateTcpTypeFromFbs(type: FbsIceCandidateTcpType): IceCandidateTcpType +{ + switch (type) + { + case FbsIceCandidateTcpType.PASSIVE: + return 'passive'; + } +} + +function dtlsStateFromFbs(fbsDtlsState: FbsDtlsState): DtlsState +{ + switch (fbsDtlsState) + { + case FbsDtlsState.NEW: + return 'new'; + case FbsDtlsState.CONNECTING: + return 'connecting'; + case FbsDtlsState.CONNECTED: + return 'connected'; + case FbsDtlsState.FAILED: + return 'failed'; + case FbsDtlsState.CLOSED: + return 'closed'; + } +} + +function dtlsRoleFromFbs(role: FbsDtlsRole): DtlsRole +{ + switch (role) + { + case FbsDtlsRole.AUTO: + return 'auto'; + case FbsDtlsRole.CLIENT: + return 'client'; + case FbsDtlsRole.SERVER: + return 'server'; + } +} + +function fingerprintAlgorithmsFromFbs(algorithm: FbsFingerprintAlgorithm) + : FingerprintAlgorithm +{ + switch (algorithm) + { + case FbsFingerprintAlgorithm.SHA1: + return 'sha-1'; + case FbsFingerprintAlgorithm.SHA224: + return 'sha-224'; + case FbsFingerprintAlgorithm.SHA256: + return 'sha-256'; + case FbsFingerprintAlgorithm.SHA384: + return 'sha-384'; + case FbsFingerprintAlgorithm.SHA512: + return 'sha-512'; + } +} + +function fingerprintAlgorithmToFbs(algorithm: FingerprintAlgorithm) + : FbsFingerprintAlgorithm +{ + switch (algorithm) + { + case 'sha-1': + return FbsFingerprintAlgorithm.SHA1; + case 'sha-224': + return FbsFingerprintAlgorithm.SHA224; + case 'sha-256': + return FbsFingerprintAlgorithm.SHA256; + case 'sha-384': + return FbsFingerprintAlgorithm.SHA384; + case 'sha-512': + return FbsFingerprintAlgorithm.SHA512; + default: + throw new TypeError(`invalid FingerprintAlgorithm: ${algorithm}`); + } +} + +function dtlsRoleToFbs(role: DtlsRole): FbsDtlsRole +{ + switch (role) + { + case 'auto': + return FbsDtlsRole.AUTO; + case 'client': + return FbsDtlsRole.CLIENT; + case 'server': + return FbsDtlsRole.SERVER; + default: + throw new TypeError(`invalid DtlsRole: ${role}`); + } +} + +export function parseWebRtcTransportDumpResponse( + binary: FbsWebRtcTransport.DumpResponse +): WebRtcTransportDump +{ + // Retrieve BaseTransportDump. + const baseTransportDump = parseBaseTransportDump(binary.base()!); + // Retrieve ICE candidates. + const iceCandidates = parseVector(binary, 'iceCandidates', parseIceCandidate); + // Retrieve ICE parameters. + const iceParameters = parseIceParameters(binary.iceParameters()!); + // Retrieve DTLS parameters. + const dtlsParameters = parseDtlsParameters(binary.dtlsParameters()!); + + return { + ...baseTransportDump, + sctpParameters : baseTransportDump.sctpParameters, + sctpState : baseTransportDump.sctpState, + iceRole : 'controlled', + iceParameters : iceParameters, + iceCandidates : iceCandidates, + iceState : iceStateFromFbs(binary.iceState()), + dtlsParameters : dtlsParameters, + dtlsState : dtlsStateFromFbs(binary.dtlsState()) + }; +} + +function createConnectRequest( + { + builder, + dtlsParameters + }: + { + builder : flatbuffers.Builder; + dtlsParameters: DtlsParameters; + } +): number +{ + // Serialize DtlsParameters. This can throw. + const dtlsParametersOffset = serializeDtlsParameters(builder, dtlsParameters); + + // Create request. + return FbsWebRtcTransport.ConnectRequest.createConnectRequest( + builder, + dtlsParametersOffset); +} + +function parseGetStatsResponse( + binary: FbsWebRtcTransport.GetStatsResponse +):WebRtcTransportStat +{ + const base = parseBaseTransportStats(binary.base()!); + + return { + ...base, + type : 'webrtc-transport', + iceRole : iceRoleFromFbs(binary.iceRole()), + iceState : iceStateFromFbs(binary.iceState()), + iceSelectedTuple : binary.iceSelectedTuple() ? + parseTuple(binary.iceSelectedTuple()!) : + undefined, + dtlsState : dtlsStateFromFbs(binary.dtlsState()) + }; +} + +function parseIceCandidate(binary: FbsWebRtcTransport.IceCandidate): IceCandidate +{ + return { + foundation : binary.foundation()!, + priority : binary.priority(), + ip : binary.ip()!, + protocol : parseProtocol(binary.protocol()), + port : binary.port(), + type : iceCandidateTypeFromFbs(binary.type()), + tcpType : binary.tcpType() === null ? + undefined : + iceCandidateTcpTypeFromFbs(binary.tcpType()!) + }; +} + +function parseIceParameters(binary: FbsWebRtcTransport.IceParameters): IceParameters +{ + return { + usernameFragment : binary.usernameFragment()!, + password : binary.password()!, + iceLite : binary.iceLite() + }; +} + +function parseDtlsParameters(binary: FbsWebRtcTransport.DtlsParameters): DtlsParameters +{ + const fingerprints: DtlsFingerprint[] = []; + + for (let i = 0; i < binary.fingerprintsLength(); ++i) + { + const fbsFingerprint = binary.fingerprints(i)!; + const fingerPrint : DtlsFingerprint = + { + algorithm : fingerprintAlgorithmsFromFbs(fbsFingerprint.algorithm()), + value : fbsFingerprint.value()! + }; + + fingerprints.push(fingerPrint); + } + + return { + fingerprints : fingerprints, + role : binary.role() === null ? undefined : dtlsRoleFromFbs(binary.role()!) + }; +} + +function serializeDtlsParameters( + builder: flatbuffers.Builder, dtlsParameters: DtlsParameters +): number +{ + const fingerprints: number[] = []; + + for (const fingerprint of dtlsParameters.fingerprints) + { + const algorithm = fingerprintAlgorithmToFbs(fingerprint.algorithm); + const valueOffset = builder.createString(fingerprint.value); + const fingerprintOffset = FbsWebRtcTransport.Fingerprint.createFingerprint( + builder, algorithm, valueOffset); + + fingerprints.push(fingerprintOffset); + } + + const fingerprintsOffset = FbsWebRtcTransport.DtlsParameters.createFingerprintsVector( + builder, fingerprints); + const role = dtlsParameters.role !== undefined ? + dtlsRoleToFbs(dtlsParameters.role) : + FbsWebRtcTransport.DtlsRole.AUTO; + + return FbsWebRtcTransport.DtlsParameters.createDtlsParameters( + builder, + fingerprintsOffset, + role); +} diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 860bef53c1..d4e930970c 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -1,15 +1,20 @@ -import * as process from 'process'; -import * as path from 'path'; -import { spawn, ChildProcess } from 'child_process'; -import { v4 as uuidv4 } from 'uuid'; +import * as process from 'node:process'; +import * as path from 'node:path'; +import { spawn, ChildProcess } from 'node:child_process'; +import { version } from './'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import * as ortc from './ortc'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { Router, RouterOptions } from './Router'; import { WebRtcServer, WebRtcServerOptions } from './WebRtcServer'; import { AppData } from './types'; +import { generateUUIDv4, parseVector } from './utils'; +import { Event } from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsWorker from './fbs/worker'; +import * as FbsTransport from './fbs/transport'; +import { Protocol as FbsTransportProtocol } from './fbs/transport/protocol'; export type WorkerLogLevel = 'debug' | 'warn' | 'error' | 'none'; @@ -177,6 +182,18 @@ export type WorkerResourceUsage = /* eslint-enable camelcase */ }; +export type WorkerDump = +{ + pid : number; + webRtcServerIds : string[]; + routerIds : string[]; + channelMessageHandlers : + { + channelRequestHandlers : string[]; + channelNotificationHandlers : string[]; + }; +}; + export type WorkerEvents = { died: [Error]; @@ -216,9 +233,6 @@ export class Worker // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -321,7 +335,7 @@ export class Worker { env : { - MEDIASOUP_VERSION : '__MEDIASOUP_VERSION__', + MEDIASOUP_VERSION : version, // Let the worker process inherit all environment variables, useful // if a custom and not in the path GCC is used so the user can set // LD_LIBRARY_PATH environment variable for runtime. @@ -335,9 +349,7 @@ export class Worker // fd 2 (stderr) : Same as stdout. // fd 3 (channel) : Producer Channel fd. // fd 4 (channel) : Consumer Channel fd. - // fd 5 (channel) : Producer PayloadChannel fd. - // fd 6 (channel) : Consumer PayloadChannel fd. - stdio : [ 'ignore', 'pipe', 'pipe', 'pipe', 'pipe', 'pipe', 'pipe' ], + stdio : [ 'ignore', 'pipe', 'pipe', 'pipe', 'pipe' ], windowsHide : true }); @@ -350,23 +362,14 @@ export class Worker pid : this.#pid }); - this.#payloadChannel = new PayloadChannel( - { - // NOTE: TypeScript does not like more than 5 fds. - // @ts-ignore - producerSocket : this.#child.stdio[5], - // @ts-ignore - consumerSocket : this.#child.stdio[6] - }); - this.#appData = appData || {} as WorkerAppData; let spawnDone = false; // Listen for 'running' notification. - this.#channel.once(String(this.#pid), (event: string) => + this.#channel.once(String(this.#pid), (event: Event) => { - if (!spawnDone && event === 'running') + if (!spawnDone && event === Event.WORKER_RUNNING) { spawnDone = true; @@ -558,9 +561,6 @@ export class Worker // Close the Channel instance. this.#channel.close(); - // Close the PayloadChannel instance. - this.#payloadChannel.close(); - // Close every Router. for (const router of this.#routers) { @@ -582,11 +582,21 @@ export class Worker /** * Dump Worker. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('worker.dump'); + // Send the request and wait for the response. + const response = await this.#channel.request( + FbsRequest.Method.WORKER_DUMP + ); + + /* Decode Response. */ + const dump = new FbsWorker.DumpResponse(); + + response.body(dump); + + return parseWorkerDumpResponse(dump); } /** @@ -596,7 +606,37 @@ export class Worker { logger.debug('getResourceUsage()'); - return this.#channel.request('worker.getResourceUsage'); + const response = await this.#channel.request( + FbsRequest.Method.WORKER_GET_RESOURCE_USAGE + ); + + /* Decode Response. */ + const resourceUsage = new FbsWorker.ResourceUsageResponse(); + + response.body(resourceUsage); + + const ru = resourceUsage.unpack(); + + /* eslint-disable camelcase */ + return { + ru_utime : Number(ru.ruUtime), + ru_stime : Number(ru.ruStime), + ru_maxrss : Number(ru.ruMaxrss), + ru_ixrss : Number(ru.ruIxrss), + ru_idrss : Number(ru.ruIdrss), + ru_isrss : Number(ru.ruIsrss), + ru_minflt : Number(ru.ruMinflt), + ru_majflt : Number(ru.ruMajflt), + ru_nswap : Number(ru.ruNswap), + ru_inblock : Number(ru.ruInblock), + ru_oublock : Number(ru.ruOublock), + ru_msgsnd : Number(ru.ruMsgsnd), + ru_msgrcv : Number(ru.ruMsgrcv), + ru_nsignals : Number(ru.ruNsignals), + ru_nvcsw : Number(ru.ruNvcsw), + ru_nivcsw : Number(ru.ruNivcsw) + }; + /* eslint-enable camelcase */ } /** @@ -611,9 +651,15 @@ export class Worker { logger.debug('updateSettings()'); - const reqData = { logLevel, logTags }; + // Build the request. + const requestOffset = new FbsWorker.UpdateSettingsRequestT(logLevel, logTags) + .pack(this.#channel.bufferBuilder); - await this.#channel.request('worker.updateSettings', undefined, reqData); + await this.#channel.request( + FbsRequest.Method.WORKER_UPDATE_SETTINGS, + FbsRequest.Body.Worker_UpdateSettingsRequest, + requestOffset + ); } /** @@ -633,17 +679,38 @@ export class Worker throw new TypeError('if given, appData must be an object'); } - const reqData = + // Build the request. + const fbsListenInfos: FbsTransport.ListenInfoT[] = []; + + for (const listenInfo of listenInfos) { - webRtcServerId : uuidv4(), - listenInfos - }; + fbsListenInfos.push(new FbsTransport.ListenInfoT( + listenInfo.protocol === 'udp' + ? FbsTransportProtocol.UDP + : FbsTransportProtocol.TCP, + listenInfo.ip, + listenInfo.announcedIp, + listenInfo.port, + listenInfo.sendBufferSize, + listenInfo.recvBufferSize) + ); + } - await this.#channel.request('worker.createWebRtcServer', undefined, reqData); + const webRtcServerId = generateUUIDv4(); + + const createWebRtcServerRequestOffset = new FbsWorker.CreateWebRtcServerRequestT( + webRtcServerId, fbsListenInfos + ).pack(this.#channel.bufferBuilder); + + await this.#channel.request( + FbsRequest.Method.WORKER_CREATE_WEBRTCSERVER, + FbsRequest.Body.Worker_CreateWebRtcServerRequest, + createWebRtcServerRequestOffset + ); const webRtcServer = new WebRtcServer( { - internal : { webRtcServerId: reqData.webRtcServerId }, + internal : { webRtcServerId }, channel : this.#channel, appData }); @@ -676,20 +743,24 @@ export class Worker // This may throw. const rtpCapabilities = ortc.generateRouterRtpCapabilities(mediaCodecs); - const reqData = { routerId: uuidv4() }; + const routerId = generateUUIDv4(); + + // Get flatbuffer builder. + const createRouterRequestOffset = + new FbsWorker.CreateRouterRequestT(routerId).pack(this.#channel.bufferBuilder); - await this.#channel.request('worker.createRouter', undefined, reqData); + await this.#channel.request(FbsRequest.Method.WORKER_CREATE_ROUTER, + FbsRequest.Body.Worker_CreateRouterRequest, createRouterRequestOffset); const data = { rtpCapabilities }; const router = new Router( { internal : { - routerId : reqData.routerId + routerId }, data, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData }); @@ -717,9 +788,6 @@ export class Worker // Close the Channel instance. this.#channel.close(); - // Close the PayloadChannel instance. - this.#payloadChannel.close(); - // Close every Router. for (const router of this.#routers) { @@ -740,3 +808,19 @@ export class Worker this.#observer.safeEmit('close'); } } + +export function parseWorkerDumpResponse( + binary: FbsWorker.DumpResponse +): WorkerDump +{ + return { + pid : binary.pid()!, + webRtcServerIds : parseVector(binary, 'webRtcServerIds'), + routerIds : parseVector(binary, 'routerIds'), + channelMessageHandlers : + { + channelRequestHandlers : parseVector(binary.channelMessageHandlers()!, 'channelRequestHandlers'), + channelNotificationHandlers : parseVector(binary.channelMessageHandlers()!, 'channelNotificationHandlers') + } + }; +} diff --git a/node/src/index.ts b/node/src/index.ts index 06f30f7008..4277b665d9 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -1,3 +1,5 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { workerBin, Worker, WorkerSettings } from './Worker'; @@ -5,7 +7,6 @@ import * as utils from './utils'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; import { RtpCapabilities } from './RtpParameters'; import * as types from './types'; -import { AppData } from './types'; /** * Expose all types. @@ -15,15 +16,15 @@ export { types }; /** * Expose mediasoup version. */ -export const version = '__MEDIASOUP_VERSION__'; +export const { version } = JSON.parse(fs.readFileSync( + path.join(__dirname, '..', '..', 'package.json'), { encoding: 'utf-8' } +)); /** * Expose parseScalabilityMode() function. */ export { parse as parseScalabilityMode } from './scalabilityModes'; -const logger = new Logger(); - export type ObserverEvents = { newworker: [Worker]; @@ -41,10 +42,12 @@ export { observer }; */ export { workerBin }; +const logger = new Logger(); + /** * Create a Worker. */ -export async function createWorker( +export async function createWorker( { logLevel = 'error', logTags, diff --git a/node/src/ortc.ts b/node/src/ortc.ts index 6f229e6743..dad1cf9c1b 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -1,6 +1,5 @@ import * as h264 from 'h264-profile-level-id'; -import * as utils from './utils'; -import { UnsupportedError } from './errors'; +import * as flatbuffers from 'flatbuffers'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; import { parse as parseScalabilityMode } from './scalabilityModes'; import { @@ -21,8 +20,11 @@ import { SctpParameters, SctpStreamParameters } from './SctpParameters'; +import * as utils from './utils'; +import { UnsupportedError } from './errors'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; -type RtpMapping = +export type RtpMapping = { codecs: { @@ -1040,7 +1042,8 @@ export function getConsumableRtpParameters( } // Clone Producer encodings since we'll mangle them. - const consumableEncodings = utils.clone(params.encodings) as RtpEncodingParameters[]; + const consumableEncodings = + (utils.clone(params.encodings) ?? []) as RtpEncodingParameters[]; for (let i = 0; i < consumableEncodings.length; ++i) { @@ -1061,8 +1064,7 @@ export function getConsumableRtpParameters( consumableParams.rtcp = { cname : params.rtcp!.cname, - reducedSize : true, - mux : true + reducedSize : true }; return consumableParams; @@ -1139,7 +1141,7 @@ export function getConsumerRtpParameters( } const consumableCodecs = - utils.clone(consumableRtpParameters.codecs) as RtpCodecParameters[]; + (utils.clone(consumableRtpParameters.codecs) ?? []) as RtpCodecParameters[]; let rtxSupported = false; @@ -1167,7 +1169,7 @@ export function getConsumerRtpParameters( } // Must sanitize the list of matched codecs by removing useless RTX codecs. - for (let idx = consumerParams.codecs.length -1; idx >= 0; --idx) + for (let idx = consumerParams.codecs.length - 1; idx >= 0; --idx) { const codec = consumerParams.codecs[idx]; @@ -1294,7 +1296,7 @@ export function getConsumerRtpParameters( else { const consumableEncodings = - utils.clone(consumableRtpParameters.encodings) as RtpEncodingParameters[]; + (utils.clone(consumableRtpParameters.encodings) ?? []) as RtpEncodingParameters[]; const baseSsrc = utils.generateRandomNumber(); const baseRtxSsrc = utils.generateRandomNumber(); @@ -1346,7 +1348,7 @@ export function getPipeConsumerRtpParameters( }; const consumableCodecs = - utils.clone(consumableRtpParameters.codecs) as RtpCodecParameters[]; + (utils.clone(consumableRtpParameters.codecs) ?? []) as RtpCodecParameters[]; for (const codec of consumableCodecs) { @@ -1374,7 +1376,7 @@ export function getPipeConsumerRtpParameters( )); const consumableEncodings = - utils.clone(consumableRtpParameters.encodings) as RtpEncodingParameters[]; + (utils.clone(consumableRtpParameters.encodings) ?? []) as RtpEncodingParameters[]; const baseSsrc = utils.generateRandomNumber(); const baseRtxSsrc = utils.generateRandomNumber(); @@ -1517,3 +1519,39 @@ function matchCodecs( return true; } + +export function serializeRtpMapping( + builder: flatbuffers.Builder, rtpMapping: RtpMapping +): number +{ + const codecs: number[] = []; + + for (const codec of rtpMapping.codecs) + { + codecs.push( + FbsRtpParameters.CodecMapping.createCodecMapping( + builder, codec.payloadType, codec.mappedPayloadType) + ); + } + const codecsOffset = + FbsRtpParameters.RtpMapping.createCodecsVector(builder, codecs); + + const encodings: number[] = []; + + for (const encoding of rtpMapping.encodings) + { + encodings.push( + FbsRtpParameters.EncodingMapping.createEncodingMapping( + builder, + builder.createString(encoding.rid), + encoding.ssrc ?? null, + builder.createString(encoding.scalabilityMode), + encoding.mappedSsrc) + ); + } + const encodingsOffset = + FbsRtpParameters.RtpMapping.createEncodingsVector(builder, encodings); + + return FbsRtpParameters.RtpMapping.createRtpMapping( + builder, codecsOffset, encodingsOffset); +} diff --git a/node/src/tests/test-ActiveSpeakerObserver.ts b/node/src/tests/test-ActiveSpeakerObserver.ts index 248b8bf0d5..4da61e1753 100644 --- a/node/src/tests/test-ActiveSpeakerObserver.ts +++ b/node/src/tests/test-ActiveSpeakerObserver.ts @@ -1,7 +1,5 @@ import * as mediasoup from '../'; -const { createWorker } = mediasoup; - let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; let activeSpeakerObserver: mediasoup.types.ActiveSpeakerObserver; @@ -23,7 +21,7 @@ const mediaCodecs: mediasoup.types.RtpCodecCapability[] = beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter({ mediaCodecs }); }); diff --git a/node/src/tests/test-AudioLevelObserver.ts b/node/src/tests/test-AudioLevelObserver.ts index e82be0c7dd..77487218b8 100644 --- a/node/src/tests/test-AudioLevelObserver.ts +++ b/node/src/tests/test-AudioLevelObserver.ts @@ -1,7 +1,5 @@ import * as mediasoup from '../'; -const { createWorker } = mediasoup; - let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; let audioLevelObserver: mediasoup.types.AudioLevelObserver; @@ -23,7 +21,7 @@ const mediaCodecs: mediasoup.types.RtpCodecCapability[] = beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter({ mediaCodecs }); }); diff --git a/node/src/tests/test-Consumer.ts b/node/src/tests/test-Consumer.ts index 2749fa3486..3723019460 100644 --- a/node/src/tests/test-Consumer.ts +++ b/node/src/tests/test-Consumer.ts @@ -1,7 +1,8 @@ +import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; - -const { createWorker } = mediasoup; +import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; +import * as FbsConsumer from '../fbs/consumer'; let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; @@ -244,7 +245,7 @@ const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter({ mediaCodecs }); transport1 = await router.createWebRtcTransport( { @@ -317,13 +318,17 @@ test('transport.consume() succeeds', async () => expect(audioConsumer.currentLayers).toBeUndefined(); expect(audioConsumer.appData).toEqual({ baz: 'LOL' }); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : { [audioProducer.id]: [ audioConsumer.id ] }, - mapConsumerIdProducerId : { [audioConsumer.id]: audioProducer.id } - }); + let dump = await router.dump(); + + expect(dump.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining([ + { key: audioProducer.id, values: [ audioConsumer.id ] } + ])); + + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: audioConsumer.id, value: audioProducer.id } + ])); await expect(transport2.dump()) .resolves @@ -462,27 +467,36 @@ test('transport.consume() succeeds', async () => expect(videoPipeConsumer.currentLayers).toBeUndefined(); expect(videoPipeConsumer.appData).toBeUndefined; - const dump = await router.dump(); + dump = await router.dump(); - for (const key of Object.keys(dump.mapProducerIdConsumerIds)) + // Sort values for mapProducerIdConsumerIds. + expect(Array.isArray(dump.mapProducerIdConsumerIds)).toBe(true); + dump.mapProducerIdConsumerIds.forEach((entry: any) => { - dump.mapProducerIdConsumerIds[key] = dump.mapProducerIdConsumerIds[key].sort(); - } + entry.values = entry.values.sort(); + }); - expect(dump).toMatchObject( - { - mapProducerIdConsumerIds : - { - [audioProducer.id] : [ audioConsumer.id ], - [videoProducer.id] : [ videoConsumer.id, videoPipeConsumer.id ].sort() - }, - mapConsumerIdProducerId : - { - [audioConsumer.id] : audioProducer.id, - [videoConsumer.id] : videoProducer.id, - [videoPipeConsumer.id] : videoProducer.id - } - }); + expect(dump.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining([ + { key: audioProducer.id, values: [ audioConsumer.id ] } + ])); + expect(dump.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining([ + { key: videoProducer.id, values: [ videoConsumer.id, videoPipeConsumer.id ].sort() } + ])); + + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: audioConsumer.id, value: audioProducer.id } + ])); + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: videoConsumer.id, value: videoProducer.id } + ])); + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: videoPipeConsumer.id, value: videoProducer.id } + ])); await expect(transport2.dump()) .resolves @@ -641,7 +655,7 @@ test('consumer.dump() succeeds', async () => }); expect(data.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions.length).toBe(3); + expect(data.rtpParameters.headerExtensions!.length).toBe(3); expect(data.rtpParameters.headerExtensions).toEqual( [ { @@ -664,20 +678,22 @@ test('consumer.dump() succeeds', async () => } ]); expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings.length).toBe(1); + expect(data.rtpParameters.encodings!.length).toBe(1); expect(data.rtpParameters.encodings).toEqual( [ - { - codecPayloadType : 100, - ssrc : audioConsumer.rtpParameters.encodings?.[0].ssrc - } + expect.objectContaining( + { + codecPayloadType : 100, + ssrc : audioConsumer.rtpParameters.encodings?.[0].ssrc + }) ]); expect(data.type).toBe('simple'); expect(Array.isArray(data.consumableRtpEncodings)).toBe(true); - expect(data.consumableRtpEncodings.length).toBe(1); + expect(data.consumableRtpEncodings!.length).toBe(1); expect(data.consumableRtpEncodings).toEqual( [ - { ssrc: audioProducer.consumableRtpParameters.encodings?.[0].ssrc } + expect.objectContaining( + { ssrc: audioProducer.consumableRtpParameters.encodings?.[0].ssrc }) ]); expect(data.supportedCodecPayloadTypes).toEqual([ 100 ]); expect(data.paused).toBe(false); @@ -710,7 +726,7 @@ test('consumer.dump() succeeds', async () => { type: 'goog-remb' } ]); expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions.length).toBe(4); + expect(data.rtpParameters.headerExtensions!.length).toBe(4); expect(data.rtpParameters.headerExtensions).toEqual( [ { @@ -739,7 +755,7 @@ test('consumer.dump() succeeds', async () => } ]); expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings.length).toBe(1); + expect(data.rtpParameters.encodings!.length).toBe(1); expect(data.rtpParameters.encodings).toMatchObject( [ { @@ -753,14 +769,23 @@ test('consumer.dump() succeeds', async () => } ]); expect(Array.isArray(data.consumableRtpEncodings)).toBe(true); - expect(data.consumableRtpEncodings.length).toBe(4); - expect(data.consumableRtpEncodings).toEqual( - [ - { ssrc: videoProducer.consumableRtpParameters.encodings?.[0].ssrc }, - { ssrc: videoProducer.consumableRtpParameters.encodings?.[1].ssrc }, - { ssrc: videoProducer.consumableRtpParameters.encodings?.[2].ssrc }, - { ssrc: videoProducer.consumableRtpParameters.encodings?.[3].ssrc } - ]); + expect(data.consumableRtpEncodings!.length).toBe(4); + expect(data.consumableRtpEncodings![0]).toEqual( + expect.objectContaining( + { ssrc: videoProducer.consumableRtpParameters.encodings?.[0].ssrc }) + ); + expect(data.consumableRtpEncodings![1]).toEqual( + expect.objectContaining( + { ssrc: videoProducer.consumableRtpParameters.encodings?.[1].ssrc }) + ); + expect(data.consumableRtpEncodings![2]).toEqual( + expect.objectContaining( + { ssrc: videoProducer.consumableRtpParameters.encodings?.[2].ssrc }) + ); + expect(data.consumableRtpEncodings![3]).toEqual( + expect.objectContaining( + { ssrc: videoProducer.consumableRtpParameters.encodings?.[3].ssrc }) + ); expect(data.supportedCodecPayloadTypes).toEqual([ 103 ]); expect(data.paused).toBe(true); expect(data.producerPaused).toBe(true); @@ -877,26 +902,28 @@ test('consumer.unsetPriority() succeed', async () => test('consumer.enableTraceEvent() succeed', async () => { + let dump; + await audioConsumer.enableTraceEvent([ 'rtp', 'pli' ]); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ traceEventTypes: 'rtp,pli' }); + dump = await audioConsumer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([ 'rtp', 'pli' ])); await audioConsumer.enableTraceEvent([]); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ traceEventTypes: '' }); + dump = await audioConsumer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([])); // @ts-ignore await audioConsumer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ traceEventTypes: 'nack,fir' }); + dump = await audioConsumer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([ 'nack', 'fir' ])); await audioConsumer.enableTraceEvent(); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ traceEventTypes: '' }); + dump = await audioConsumer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([])); }, 2000); test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => @@ -946,12 +973,30 @@ test('Consumer emits "score"', async () => audioConsumer.on('score', onScore); - channel.emit(audioConsumer.id, 'score', { producer: 10, consumer: 9 }); - channel.emit(audioConsumer.id, 'score', { producer: 9, consumer: 9 }); - channel.emit(audioConsumer.id, 'score', { producer: 8, consumer: 8 }); + // Simulate a 'score' notification coming through the channel. + const builder = new flatbuffers.Builder(); + const consumerScore = new FbsConsumer.ConsumerScoreT(9, 10, [ 8 ]); + const consumerScoreNotification = new FbsConsumer.ScoreNotificationT(consumerScore); + const notificationOffset = Notification.createNotification( + builder, + builder.createString(audioConsumer.id), + Event.CONSUMER_SCORE, + NotificationBody.Consumer_ScoreNotification, + consumerScoreNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + const notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); + channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); + channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); expect(onScore).toHaveBeenCalledTimes(3); - expect(audioConsumer.score).toEqual({ producer: 8, consumer: 8 }); + expect(audioConsumer.score).toEqual( + { score: 9, producerScore: 10, producerScores: [ 8 ] }); }, 2000); test('consumer.close() succeeds', async () => @@ -964,19 +1009,27 @@ test('consumer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(audioConsumer.closed).toBe(true); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : { [audioProducer.id]: [] }, - mapConsumerIdProducerId : {} - }); + const routerDump = await router.dump(); + + expect(routerDump.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining([ + { key: audioProducer.id, values: [ ] } + ])); + + expect(routerDump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: videoConsumer.id, value: videoProducer.id } + ])); + expect(routerDump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: videoPipeConsumer.id, value: videoProducer.id } + ])); - const dump = await transport2.dump(); + const transportDump = await transport2.dump(); - dump.consumerIds = dump.consumerIds.sort(); + transportDump.consumerIds = transportDump.consumerIds.sort(); - expect(dump) + expect(transportDump) .toMatchObject( { id : transport2.id, diff --git a/node/src/tests/test-DataConsumer.ts b/node/src/tests/test-DataConsumer.ts index 08241fcf3e..b8a7181ed1 100644 --- a/node/src/tests/test-DataConsumer.ts +++ b/node/src/tests/test-DataConsumer.ts @@ -1,7 +1,5 @@ import * as mediasoup from '../'; -const { createWorker } = mediasoup; - let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; let transport1: mediasoup.types.WebRtcTransport; @@ -25,7 +23,7 @@ const dataProducerParameters: mediasoup.types.DataProducerOptions = beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter(); transport1 = await router.createWebRtcTransport( { @@ -53,6 +51,9 @@ test('transport.consumeData() succeeds', async () => { dataProducerId : dataProducer.id, maxPacketLifeTime : 4000, + // Valid values are 0...65535 so others and duplicated ones will be + // discarded. + subchannels : [ 0, 1, 1, 1, 2, 65535, 65536, 65537, 100 ], appData : { baz: 'LOL' } }); @@ -69,15 +70,21 @@ test('transport.consumeData() succeeds', async () => expect(dataConsumer1.sctpStreamParameters?.maxRetransmits).toBeUndefined(); expect(dataConsumer1.label).toBe('foo'); expect(dataConsumer1.protocol).toBe('bar'); + expect(dataConsumer1.paused).toBe(false); + expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 0, 1, 2, 100, 65535 ]); expect(dataConsumer1.appData).toEqual({ baz: 'LOL' }); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : { [dataProducer.id]: [ dataConsumer1.id ] }, - mapDataConsumerIdDataProducerId : { [dataConsumer1.id]: dataProducer.id } - }); + const dump = await router.dump(); + + expect(dump.mapDataProducerIdDataConsumerIds) + .toEqual(expect.arrayContaining([ + { key: dataProducer.id, values: [ dataConsumer1.id ] } + ])); + + expect(dump.mapDataConsumerIdDataProducerId) + .toEqual(expect.arrayContaining([ + { key: dataConsumer1.id, value: dataProducer.id } + ])); await expect(transport2.dump()) .resolves @@ -97,13 +104,14 @@ test('dataConsumer.dump() succeeds', async () => expect(data.dataProducerId).toBe(dataConsumer1.dataProducerId); expect(data.type).toBe('sctp'); expect(typeof data.sctpStreamParameters).toBe('object'); - expect(data.sctpStreamParameters.streamId) + expect(data.sctpStreamParameters!.streamId) .toBe(dataConsumer1.sctpStreamParameters?.streamId); - expect(data.sctpStreamParameters.ordered).toBe(false); - expect(data.sctpStreamParameters.maxPacketLifeTime).toBe(4000); - expect(data.sctpStreamParameters.maxRetransmits).toBeUndefined(); + expect(data.sctpStreamParameters!.ordered).toBe(false); + expect(data.sctpStreamParameters!.maxPacketLifeTime).toBe(4000); + expect(data.sctpStreamParameters!.maxRetransmits).toBeUndefined(); expect(data.label).toBe('foo'); expect(data.protocol).toBe('bar'); + expect(data.paused).toBe(false); }, 2000); test('dataConsumer.getStats() succeeds', async () => @@ -122,6 +130,13 @@ test('dataConsumer.getStats() succeeds', async () => ]); }, 2000); +test('dataConsumer.setSubchannels() succeeds', async () => +{ + await dataConsumer1.setSubchannels([ 999, 999, 998, 65536 ]); + + expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 0, 998, 999 ]); +}, 2000); + test('transport.consumeData() on a DirectTransport succeeds', async () => { const onObserverNewDataConsumer = jest.fn(); @@ -131,6 +146,7 @@ test('transport.consumeData() on a DirectTransport succeeds', async () => dataConsumer2 = await transport3.consumeData( { dataProducerId : dataProducer.id, + paused : true, appData : { hehe: 'HEHE' } }); @@ -143,6 +159,7 @@ test('transport.consumeData() on a DirectTransport succeeds', async () => expect(dataConsumer2.sctpStreamParameters).toBeUndefined(); expect(dataConsumer2.label).toBe('foo'); expect(dataConsumer2.protocol).toBe('bar'); + expect(dataConsumer2.paused).toBe(true); expect(dataConsumer2.appData).toEqual({ hehe: 'HEHE' }); await expect(transport3.dump()) @@ -165,6 +182,7 @@ test('dataConsumer.dump() on a DirectTransport succeeds', async () => expect(data.sctpStreamParameters).toBeUndefined(); expect(data.label).toBe('foo'); expect(data.protocol).toBe('bar'); + expect(data.paused).toBe(true); }, 2000); test('dataConsumer.getStats() on a DirectTransport succeeds', async () => @@ -183,6 +201,27 @@ test('dataConsumer.getStats() on a DirectTransport succeeds', async () => ]); }, 2000); +test('dataConsumer.pause() and resume() succeed', async () => +{ + let data; + + await dataConsumer1.pause(); + + expect(dataConsumer1.paused).toBe(true); + + data = await dataConsumer1.dump(); + + expect(data.paused).toBe(true); + + await dataConsumer1.resume(); + + expect(dataConsumer1.paused).toBe(false); + + data = await dataConsumer1.dump(); + + expect(data.paused).toBe(false); +}, 2000); + test('dataConsumer.close() succeeds', async () => { const onObserverClose = jest.fn(); @@ -193,13 +232,17 @@ test('dataConsumer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataConsumer1.closed).toBe(true); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : { [dataProducer.id]: [ dataConsumer2.id ] }, - mapDataConsumerIdDataProducerId : { [dataConsumer2.id]: dataProducer.id } - }); + const dump = await router.dump(); + + expect(dump.mapDataProducerIdDataConsumerIds) + .toEqual(expect.arrayContaining([ + { key: dataProducer.id, values: [ dataConsumer2.id ] } + ])); + + expect(dump.mapDataConsumerIdDataProducerId) + .toEqual(expect.arrayContaining([ + { key: dataConsumer2.id, value: dataProducer.id } + ])); await expect(transport2.dump()) .resolves diff --git a/node/src/tests/test-DataProducer.ts b/node/src/tests/test-DataProducer.ts index 711fde3d79..3918d20263 100644 --- a/node/src/tests/test-DataProducer.ts +++ b/node/src/tests/test-DataProducer.ts @@ -1,7 +1,5 @@ import * as mediasoup from '../'; -const { createWorker } = mediasoup; - let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; let transport1: mediasoup.types.WebRtcTransport; @@ -11,7 +9,7 @@ let dataProducer2: mediasoup.types.DataProducer; beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter(); transport1 = await router.createWebRtcTransport( { @@ -56,15 +54,17 @@ test('transport1.produceData() succeeds', async () => expect(dataProducer1.sctpStreamParameters?.maxRetransmits).toBeUndefined(); expect(dataProducer1.label).toBe('foo'); expect(dataProducer1.protocol).toBe('bar'); + expect(dataProducer1.paused).toBe(false); expect(dataProducer1.appData).toEqual({ foo: 1, bar: '2' }); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : { [dataProducer1.id]: [] }, - mapDataConsumerIdDataProducerId : {} - }); + const dump = await router.dump(); + + expect(dump.mapDataProducerIdDataConsumerIds) + .toEqual(expect.arrayContaining([ + { key: dataProducer1.id, values: [ ] } + ])); + + expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); await expect(transport1.dump()) .resolves @@ -91,6 +91,7 @@ test('transport2.produceData() succeeds', async () => }, label : 'foo', protocol : 'bar', + paused : true, appData : { foo: 1, bar: '2' } }); @@ -106,15 +107,17 @@ test('transport2.produceData() succeeds', async () => expect(dataProducer2.sctpStreamParameters?.maxRetransmits).toBe(3); expect(dataProducer2.label).toBe('foo'); expect(dataProducer2.protocol).toBe('bar'); + expect(dataProducer2.paused).toBe(true); expect(dataProducer2.appData).toEqual({ foo: 1, bar: '2' }); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : { [dataProducer2.id]: [] }, - mapDataConsumerIdDataProducerId : {} - }); + const dump = await router.dump(); + + expect(dump.mapDataProducerIdDataConsumerIds) + .toEqual(expect.arrayContaining([ + { key: dataProducer2.id, values: [ ] } + ])); + + expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); await expect(transport2.dump()) .resolves @@ -179,24 +182,26 @@ test('dataProducer.dump() succeeds', async () => expect(data.id).toBe(dataProducer1.id); expect(data.type).toBe('sctp'); expect(typeof data.sctpStreamParameters).toBe('object'); - expect(data.sctpStreamParameters.streamId).toBe(666); - expect(data.sctpStreamParameters.ordered).toBe(true); - expect(data.sctpStreamParameters.maxPacketLifeTime).toBeUndefined(); - expect(data.sctpStreamParameters.maxRetransmits).toBeUndefined(); + expect(data.sctpStreamParameters!.streamId).toBe(666); + expect(data.sctpStreamParameters!.ordered).toBe(true); + expect(data.sctpStreamParameters!.maxPacketLifeTime).toBeUndefined(); + expect(data.sctpStreamParameters!.maxRetransmits).toBeUndefined(); expect(data.label).toBe('foo'); expect(data.protocol).toBe('bar'); + expect(data.paused).toBe(false); data = await dataProducer2.dump(); expect(data.id).toBe(dataProducer2.id); expect(data.type).toBe('sctp'); expect(typeof data.sctpStreamParameters).toBe('object'); - expect(data.sctpStreamParameters.streamId).toBe(777); - expect(data.sctpStreamParameters.ordered).toBe(false); - expect(data.sctpStreamParameters.maxPacketLifeTime).toBeUndefined(); - expect(data.sctpStreamParameters.maxRetransmits).toBe(3); + expect(data.sctpStreamParameters!.streamId).toBe(777); + expect(data.sctpStreamParameters!.ordered).toBe(false); + expect(data.sctpStreamParameters!.maxPacketLifeTime).toBeUndefined(); + expect(data.sctpStreamParameters!.maxRetransmits).toBe(3); expect(data.label).toBe('foo'); expect(data.protocol).toBe('bar'); + expect(data.paused).toBe(true); }, 2000); test('dataProducer.getStats() succeeds', async () => @@ -228,6 +233,27 @@ test('dataProducer.getStats() succeeds', async () => ]); }, 2000); +test('dataProducer.pause() and resume() succeed', async () => +{ + let data; + + await dataProducer1.pause(); + + expect(dataProducer1.paused).toBe(true); + + data = await dataProducer1.dump(); + + expect(data.paused).toBe(true); + + await dataProducer1.resume(); + + expect(dataProducer1.paused).toBe(false); + + data = await dataProducer1.dump(); + + expect(data.paused).toBe(false); +}, 2000); + test('dataProducer.close() succeeds', async () => { const onObserverClose = jest.fn(); diff --git a/node/src/tests/test-DirectTransport.ts b/node/src/tests/test-DirectTransport.ts index 848d696ce7..2a8431ddc3 100644 --- a/node/src/tests/test-DirectTransport.ts +++ b/node/src/tests/test-DirectTransport.ts @@ -1,14 +1,12 @@ import * as mediasoup from '../'; -const { createWorker } = mediasoup; - let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; let transport: mediasoup.types.DirectTransport; beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter(); }); @@ -52,7 +50,7 @@ test('router.createDirectTransport() succeeds', async () => expect(data1.consumerIds).toEqual([]); expect(data1.dataProducerIds).toEqual([]); expect(data1.dataConsumerIds).toEqual([]); - expect(typeof data1.recvRtpHeaderExtensions).toBe('object'); + expect(data1.recvRtpHeaderExtensions).toBeDefined(); expect(typeof data1.rtpListener).toBe('object'); transport1.close(); @@ -117,20 +115,51 @@ test('dataProducer.send() succeeds', async () => dataProducerId : dataProducer.id }); const numMessages = 200; + const pauseSendingAtMessage = 10; + const resumeSendingAtMessage = 20; + const pauseReceivingAtMessage = 40; + const resumeReceivingAtMessage = 60; + const expectedReceivedNumMessages = + numMessages - + (resumeSendingAtMessage - pauseSendingAtMessage) - + (resumeReceivingAtMessage - pauseReceivingAtMessage); + let sentMessageBytes = 0; + let effectivelySentMessageBytes = 0; let recvMessageBytes = 0; let lastSentMessageId = 0; let lastRecvMessageId = 0; - await new Promise((resolve) => + // eslint-disable-next-line no-async-promise-executor + await new Promise(async (resolve) => { // Send messages over the sctpSendStream created above. - const interval = setInterval(() => + + sendNextMessage(); + + async function sendNextMessage() { const id = ++lastSentMessageId; let ppid; let message; + if (id === pauseSendingAtMessage) + { + await dataProducer.pause(); + } + else if (id === resumeSendingAtMessage) + { + await dataProducer.resume(); + } + else if (id === pauseReceivingAtMessage) + { + await dataConsumer.pause(); + } + else if (id === resumeReceivingAtMessage) + { + await dataConsumer.resume(); + } + // Send string (WebRTC DataChannel string). if (id < numMessages / 2) { @@ -143,13 +172,21 @@ test('dataProducer.send() succeeds', async () => } dataProducer.send(message, ppid); - sentMessageBytes += Buffer.from(message).byteLength; - if (id === numMessages) + const messageSize = Buffer.from(message).byteLength; + + sentMessageBytes += messageSize; + + if (!dataProducer.paused && !dataConsumer.paused) + { + effectivelySentMessageBytes += messageSize; + } + + if (id < numMessages) { - clearInterval(interval); + sendNextMessage(); } - }, 0); + } dataConsumer.on('message', (message, ppid) => { @@ -160,7 +197,6 @@ test('dataProducer.send() succeeds', async () => if (id === numMessages) { - clearInterval(interval); resolve(); } @@ -173,13 +209,13 @@ test('dataProducer.send() succeeds', async () => expect(ppid).toBe(53); // PPID of WebRTC DataChannel binary. } - expect(id).toBe(++lastRecvMessageId); + ++lastRecvMessageId; }); }); expect(lastSentMessageId).toBe(numMessages); - expect(lastRecvMessageId).toBe(numMessages); - expect(recvMessageBytes).toBe(sentMessageBytes); + expect(lastRecvMessageId).toBe(expectedReceivedNumMessages); + expect(recvMessageBytes).toBe(effectivelySentMessageBytes); await expect(dataProducer.getStats()) .resolves @@ -202,12 +238,161 @@ test('dataProducer.send() succeeds', async () => type : 'data-consumer', label : dataConsumer.label, protocol : dataConsumer.protocol, - messagesSent : numMessages, + messagesSent : expectedReceivedNumMessages, bytesSent : recvMessageBytes } ]); }, 5000); +test('dataProducer.send() with subchannels succeeds', async () => +{ + const transport2 = await router.createDirectTransport(); + const dataProducer = await transport2.produceData(); + const dataConsumer1 = await transport2.consumeData( + { + dataProducerId : dataProducer.id, + subchannels : [ 1, 11, 666 ] + }); + const dataConsumer2 = await transport2.consumeData( + { + dataProducerId : dataProducer.id, + subchannels : [ 2, 22, 666 ] + }); + const expectedReceivedNumMessages1 = 7; + const expectedReceivedNumMessages2 = 5; + const receivedMessages1: string[] = []; + const receivedMessages2: string[] = []; + + // eslint-disable-next-line no-async-promise-executor + await new Promise(async (resolve) => + { + // Must be received by dataConsumer1 and dataConsumer2. + dataProducer.send( + 'both', + /* ppid */ undefined, + /* subchannels */ undefined, + /* requiredSubchannel */ undefined + ); + + // Must be received by dataConsumer1 and dataConsumer2. + dataProducer.send( + 'both', + /* ppid */ undefined, + /* subchannels */ [ 1, 2 ], + /* requiredSubchannel */ undefined + ); + + // Must be received by dataConsumer1 and dataConsumer2. + dataProducer.send( + 'both', + /* ppid */ undefined, + /* subchannels */ [ 11, 22, 33 ], + /* requiredSubchannel */ 666 + ); + + // Must not be received by neither dataConsumer1 nor dataConsumer2. + dataProducer.send( + 'none', + /* ppid */ undefined, + /* subchannels */ [ 3 ], + /* requiredSubchannel */ 666 + ); + + // Must not be received by neither dataConsumer1 nor dataConsumer2. + dataProducer.send( + 'none', + /* ppid */ undefined, + /* subchannels */ [ 666 ], + /* requiredSubchannel */ 3 + ); + + // Must be received by dataConsumer1. + dataProducer.send( + 'dc1', + /* ppid */ undefined, + /* subchannels */ [ 1 ], + /* requiredSubchannel */ undefined + ); + + // Must be received by dataConsumer1. + dataProducer.send( + 'dc1', + /* ppid */ undefined, + /* subchannels */ [ 11 ], + /* requiredSubchannel */ 1 + ); + + // Must be received by dataConsumer1. + dataProducer.send( + 'dc1', + /* ppid */ undefined, + /* subchannels */ [ 666 ], + /* requiredSubchannel */ 11 + ); + + // Must be received by dataConsumer2. + dataProducer.send( + 'dc2', + /* ppid */ undefined, + /* subchannels */ [ 666 ], + /* requiredSubchannel */ 2 + ); + + // Make dataConsumer2 also subscribe to subchannel 1. + // NOTE: No need to await for this call. + void dataConsumer2.setSubchannels([ ...dataConsumer2.subchannels, 1 ]); + + // Must be received by dataConsumer1 and dataConsumer2. + dataProducer.send( + 'both', + /* ppid */ undefined, + /* subchannels */ [ 1 ], + /* requiredSubchannel */ 666 + ); + + dataConsumer1.on('message', (message) => + { + receivedMessages1.push(message.toString('utf8')); + + if ( + receivedMessages1.length === expectedReceivedNumMessages1 && + receivedMessages2.length === expectedReceivedNumMessages2 + ) + { + resolve(); + } + }); + + dataConsumer2.on('message', (message) => + { + receivedMessages2.push(message.toString('utf8')); + + if ( + receivedMessages1.length === expectedReceivedNumMessages1 && + receivedMessages2.length === expectedReceivedNumMessages2 + ) + { + resolve(); + } + }); + }); + + expect(receivedMessages1.length).toBe(expectedReceivedNumMessages1); + expect(receivedMessages2.length).toBe(expectedReceivedNumMessages2); + + for (const message of receivedMessages1) + { + expect([ 'both', 'dc1' ].includes(message)).toBe(true); + expect([ 'dc2' ].includes(message)).toBe(false); + } + + for (const message of receivedMessages2) + { + expect([ 'both', 'dc2' ].includes(message)).toBe(true); + expect([ 'dc1' ].includes(message)).toBe(false); + } +}, 5000); + test('DirectTransport methods reject if closed', async () => { const onObserverClose = jest.fn(); diff --git a/node/src/tests/test-PipeTransport.ts b/node/src/tests/test-PipeTransport.ts index 17153850de..af8dc9d06a 100644 --- a/node/src/tests/test-PipeTransport.ts +++ b/node/src/tests/test-PipeTransport.ts @@ -2,8 +2,6 @@ import * as pickPort from 'pick-port'; import * as mediasoup from '../'; -const { createWorker } = mediasoup; - let worker1: mediasoup.types.Worker; let worker2: mediasoup.types.Worker; let router1: mediasoup.types.Router; @@ -190,14 +188,14 @@ const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = beforeAll(async () => { - worker1 = await createWorker(); - worker2 = await createWorker(); + worker1 = await mediasoup.createWorker(); + worker2 = await mediasoup.createWorker(); router1 = await worker1.createRouter({ mediaCodecs }); router2 = await worker2.createRouter({ mediaCodecs }); transport1 = await router1.createWebRtcTransport( { - listenIps : [ '127.0.0.1' ], - enableSctp : true + listenInfos : [ { protocol: 'udp', ip: '127.0.0.1' } ], + enableSctp : true }); transport2 = await router2.createWebRtcTransport( { @@ -466,27 +464,45 @@ test('router.pipeToRouter() succeeds with video', async () => expect(pipeProducer.paused).toBe(true); }, 2000); -test('router.pipeToRouter() fails if both Routers belong to the same Worker', async () => +test('router.createPipeTransport() with wrong arguments rejects with TypeError', async () => { - const router1bis = await worker1.createRouter({ mediaCodecs }); + // @ts-ignore + await expect(router1.createPipeTransport({})) + .rejects + .toThrow(TypeError); - await expect(router1.pipeToRouter( + await expect(router1.createPipeTransport({ listenIp: '123' })) + .rejects + .toThrow(TypeError); + + // @ts-ignore + await expect(router1.createPipeTransport({ listenIp: [ '127.0.0.1' ] })) + .rejects + .toThrow(TypeError); + + await expect(router1.createPipeTransport( { - producerId : videoProducer.id, - router : router1bis + listenInfo : { protocol: 'tcp', ip: '127.0.0.1' } })) .rejects - .toThrow(Error); + .toThrow(TypeError); - router1bis.close(); + await expect(router1.createPipeTransport( + { + listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, + // @ts-ignore + appData : 'NOT-AN-OBJECT' + })) + .rejects + .toThrow(TypeError); }, 2000); test('router.createPipeTransport() with enableRtx succeeds', async () => { const pipeTransport = await router1.createPipeTransport( { - listenIp : '127.0.0.1', - enableRtx : true + listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, + enableRtx : true }); const pipeConsumer = @@ -564,12 +580,41 @@ test('router.createPipeTransport() with enableRtx succeeds', async () => pipeTransport.close(); }, 2000); -test('router.createPipeTransport() with invalid srtpParameters must fail', async () => +test('pipeTransport.connect() with valid SRTP parameters succeeds', async () => { const pipeTransport = await router1.createPipeTransport( { - listenIp : '127.0.0.1', - enableRtx : true + listenIp : '127.0.0.1', + enableSrtp : true + }); + + expect(typeof pipeTransport.srtpParameters).toBe('object'); + // The master length of AEAD_AES_256_GCM. + expect(pipeTransport.srtpParameters?.keyBase64.length).toBe(60); + + // Valid srtpParameters. + await expect(pipeTransport.connect( + { + ip : '127.0.0.2', + port : 9999, + srtpParameters : + { + cryptoSuite : 'AEAD_AES_256_GCM', + keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' + } + })) + .resolves + .toBeUndefined(); + + pipeTransport.close(); +}, 2000); + +test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', async () => +{ + const pipeTransport = await router1.createPipeTransport( + { + listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, + enableRtx : true }); expect(pipeTransport.srtpParameters).toBeUndefined(); @@ -602,7 +647,7 @@ test('router.createPipeTransport() with invalid srtpParameters must fail', async pipeTransport.close(); }); -test('router.createPipeTransport() with enableSrtp succeeds', async () => +test('pipeTransport.connect() with invalid srtpParameters fails', async () => { const pipeTransport = await router1.createPipeTransport( { @@ -708,20 +753,6 @@ test('router.createPipeTransport() with enableSrtp succeeds', async () => .rejects .toThrow(TypeError); - // Valid srtpParameters. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { - cryptoSuite : 'AEAD_AES_256_GCM', - keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' - } - })) - .resolves - .toBeUndefined(); - pipeTransport.close(); }, 2000); @@ -730,8 +761,7 @@ test('router.createPipeTransport() with fixed port succeeds', async () => const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const pipeTransport = await router1.createPipeTransport( { - listenIp : '127.0.0.1', - port + listenInfo : { protocol: 'udp', ip: '127.0.0.1', port } }); expect(pipeTransport.tuple.localPort).toEqual(port); @@ -845,6 +875,21 @@ test('producer.close() is transmitted to pipe Consumer', async () => expect(videoConsumer.closed).toBe(true); }, 2000); +test('router.pipeToRouter() fails if both Routers belong to the same Worker', async () => +{ + const router1bis = await worker1.createRouter({ mediaCodecs }); + + await expect(router1.pipeToRouter( + { + producerId : videoProducer.id, + router : router1bis + })) + .rejects + .toThrow(Error); + + router1bis.close(); +}, 2000); + test('router.pipeToRouter() succeeds with data', async () => { let dump; diff --git a/node/src/tests/test-PlainTransport.ts b/node/src/tests/test-PlainTransport.ts index bfa2553d9e..3e75c50586 100644 --- a/node/src/tests/test-PlainTransport.ts +++ b/node/src/tests/test-PlainTransport.ts @@ -2,8 +2,6 @@ import * as pickPort from 'pick-port'; import * as mediasoup from '../'; -const { createWorker } = mediasoup; - let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; let transport: mediasoup.types.PlainTransport; @@ -43,7 +41,7 @@ const mediaCodecs: mediasoup.types.RtpCodecCapability[] = beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter({ mediaCodecs }); }); @@ -53,8 +51,8 @@ beforeEach(async () => { transport = await router.createPlainTransport( { - listenIp : { ip: '127.0.0.1', announcedIp: '4.4.4.4' }, - rtcpMux : false + listenInfo : { protocol: 'udp', ip: '127.0.0.1', announcedIp: '4.4.4.4' }, + rtcpMux : false }); }); @@ -73,7 +71,7 @@ test('router.createPlainTransport() succeeds', async () => // Create a separate transport here. const transport1 = await router.createPlainTransport( { - listenIp : { ip: '127.0.0.1', announcedIp: '9.9.9.1' }, + listenInfo : { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, rtcpMux : true, enableSctp : true, appData : { foo: 'bar' } @@ -109,7 +107,7 @@ test('router.createPlainTransport() succeeds', async () => expect(data1.rtcpTuple).toEqual(transport1.rtcpTuple); expect(data1.sctpParameters).toEqual(transport1.sctpParameters); expect(data1.sctpState).toBe('new'); - expect(typeof data1.recvRtpHeaderExtensions).toBe('object'); + expect(data1.recvRtpHeaderExtensions).toBeDefined(); expect(typeof data1.rtpListener).toBe('object'); transport1.close(); @@ -119,10 +117,13 @@ test('router.createPlainTransport() succeeds', async () => expect(typeof anotherTransport).toBe('object'); + const rtpPort = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const rtcpPort = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const transport2 = await router.createPlainTransport( { - listenIp : '127.0.0.1', - rtcpMux : false + listenInfo : { protocol: 'udp', ip: '127.0.0.1', port: rtpPort }, + rtcpListenInfo : { protocol: 'udp', ip: '127.0.0.1', port: rtcpPort }, + rtcpMux : false }); expect(typeof transport2.id).toBe('string'); @@ -130,11 +131,11 @@ test('router.createPlainTransport() succeeds', async () => expect(transport2.appData).toEqual({}); expect(typeof transport2.tuple).toBe('object'); expect(transport2.tuple.localIp).toBe('127.0.0.1'); - expect(typeof transport2.tuple.localPort).toBe('number'); + expect(transport2.tuple.localPort).toBe(rtpPort); expect(transport2.tuple.protocol).toBe('udp'); expect(typeof transport2.rtcpTuple).toBe('object'); expect(transport2.rtcpTuple?.localIp).toBe('127.0.0.1'); - expect(typeof transport2.rtcpTuple?.localPort).toBe('number'); + expect(transport2.rtcpTuple?.localPort).toBe(rtcpPort); expect(transport2.rtcpTuple?.protocol).toBe('udp'); expect(transport2.sctpParameters).toBeUndefined(); expect(transport2.sctpState).toBeUndefined(); @@ -164,11 +165,18 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' .rejects .toThrow(TypeError); + await expect(router.createPipeTransport( + { + listenInfo : { protocol: 'tcp', ip: '127.0.0.1' } + })) + .rejects + .toThrow(TypeError); + await expect(router.createPlainTransport( { - listenIp : '127.0.0.1', + listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, // @ts-ignore - appData : 'NOT-AN-OBJECT' + appData : 'NOT-AN-OBJECT' })) .rejects .toThrow(TypeError); @@ -421,8 +429,7 @@ test('router.createPlainTransport() with fixed port succeeds', async () => const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const plainTransport = await router.createPlainTransport( { - listenIp : '127.0.0.1', - port + listenInfo : { protocol: 'udp', ip: '127.0.0.1', port } }); expect(plainTransport.tuple.localPort).toEqual(port); diff --git a/node/src/tests/test-Producer.ts b/node/src/tests/test-Producer.ts index 3c86e6680c..05b2a515f3 100644 --- a/node/src/tests/test-Producer.ts +++ b/node/src/tests/test-Producer.ts @@ -1,7 +1,8 @@ +import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; - -const { createWorker } = mediasoup; +import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; +import * as FbsProducer from '../fbs/producer'; let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; @@ -44,7 +45,7 @@ const mediaCodecs: mediasoup.types.RtpCodecCapability[] = beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter({ mediaCodecs }); transport1 = await router.createWebRtcTransport( { @@ -123,8 +124,8 @@ test('transport1.produce() succeeds', async () => .resolves .toMatchObject( { - mapProducerIdConsumerIds : { [audioProducer.id]: [] }, - mapConsumerIdProducerId : {} + mapProducerIdConsumerIds : [ { key: audioProducer.id, values: [] } ], + mapConsumerIdProducerId : [] }); await expect(transport1.dump()) @@ -213,20 +214,86 @@ test('transport2.produce() succeeds', async () => expect(videoProducer.score).toEqual([]); expect(videoProducer.appData).toEqual({ foo: 1, bar: '2' }); + const dump = await router.dump(); + + expect(dump.mapProducerIdConsumerIds) + .toEqual( + expect.arrayContaining([ + { key: videoProducer.id, values: [] } + ]) + ); + + expect(dump.mapConsumerIdProducerId.length).toBe(0); + + await expect(transport2.dump()) + .resolves + .toMatchObject( + { + id : transport2.id, + producerIds : [ videoProducer.id ], + consumerIds : [] + }); +}, 2000); + +test.only('transport1.produce() without header extensions and rtcp succeeds', async () => +{ + const onObserverNewProducer = jest.fn(); + + transport1.observer.once('newproducer', onObserverNewProducer); + + audioProducer = await transport1.produce( + { + kind : 'audio', + rtpParameters : + { + mid : 'AUDIO', + codecs : + [ + { + mimeType : 'audio/opus', + payloadType : 0, + clockRate : 48000, + channels : 2, + parameters : + { + useinbandfec : 1, + usedtx : 1, + foo : 222.222, + bar : '333' + } + } + ] + }, + appData : { foo: 1, bar: '2' } + }); + + expect(onObserverNewProducer).toHaveBeenCalledTimes(1); + expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer); + expect(typeof audioProducer.id).toBe('string'); + expect(audioProducer.closed).toBe(false); + expect(audioProducer.kind).toBe('audio'); + expect(typeof audioProducer.rtpParameters).toBe('object'); + expect(audioProducer.type).toBe('simple'); + // Private API. + expect(typeof audioProducer.consumableRtpParameters).toBe('object'); + expect(audioProducer.paused).toBe(false); + expect(audioProducer.score).toEqual([]); + expect(audioProducer.appData).toEqual({ foo: 1, bar: '2' }); + await expect(router.dump()) .resolves .toMatchObject( { - mapProducerIdConsumerIds : { [videoProducer.id]: [] }, - mapConsumerIdProducerId : {} + mapProducerIdConsumerIds : [ { key: audioProducer.id, values: [] } ], + mapConsumerIdProducerId : [] }); - await expect(transport2.dump()) + await expect(transport1.dump()) .resolves .toMatchObject( { - id : transport2.id, - producerIds : [ videoProducer.id ], + id : transport1.id, + producerIds : [ audioProducer.id ], consumerIds : [] }); }, 2000); @@ -520,7 +587,7 @@ test('producer.dump() succeeds', async () => }); expect(data.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions.length).toBe(2); + expect(data.rtpParameters.headerExtensions!.length).toBe(2); expect(data.rtpParameters.headerExtensions).toEqual( [ { @@ -537,11 +604,13 @@ test('producer.dump() succeeds', async () => } ]); expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings.length).toBe(1); - expect(data.rtpParameters.encodings).toEqual( - [ - { codecPayloadType: 0 } - ]); + expect(data.rtpParameters.encodings!.length).toBe(1); + expect(data.rtpParameters.encodings![0]).toEqual( + expect.objectContaining( + { + codecPayloadType : 0 + }) + ); expect(data.type).toBe('simple'); data = await videoProducer.dump(); @@ -575,7 +644,7 @@ test('producer.dump() succeeds', async () => expect(data.rtpParameters.codecs[1].parameters).toEqual({ apt: 112 }); expect(data.rtpParameters.codecs[1].rtcpFeedback).toEqual([]); expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions.length).toBe(2); + expect(data.rtpParameters.headerExtensions!.length).toBe(2); expect(data.rtpParameters.headerExtensions).toEqual( [ { @@ -592,7 +661,7 @@ test('producer.dump() succeeds', async () => } ]); expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings.length).toBe(4); + expect(data.rtpParameters.encodings!.length).toBe(4); expect(data.rtpParameters.encodings).toMatchObject( [ { @@ -638,26 +707,28 @@ test('producer.pause() and resume() succeed', async () => test('producer.enableTraceEvent() succeed', async () => { + let dump; + await audioProducer.enableTraceEvent([ 'rtp', 'pli' ]); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ traceEventTypes: 'rtp,pli' }); + dump = await audioProducer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([ 'rtp', 'pli' ])); await audioProducer.enableTraceEvent([]); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ traceEventTypes: '' }); + dump = await audioProducer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([])); // @ts-ignore await audioProducer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ traceEventTypes: 'nack,fir' }); + dump = await audioProducer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([ 'nack', 'fir' ])); await audioProducer.enableTraceEvent(); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ traceEventTypes: '' }); + dump = await audioProducer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([])); }, 2000); test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => @@ -686,12 +757,32 @@ test('Producer emits "score"', async () => videoProducer.on('score', onScore); - channel.emit(videoProducer.id, 'score', [ { ssrc: 11, score: 10 } ]); - channel.emit(videoProducer.id, 'score', [ { ssrc: 11, score: 9 }, { ssrc: 22, score: 8 } ]); - channel.emit(videoProducer.id, 'score', [ { ssrc: 11, score: 9 }, { ssrc: 22, score: 9 } ]); + // Simulate a 'score' notification coming through the channel. + const builder = new flatbuffers.Builder(); + const producerScoreNotification = new FbsProducer.ScoreNotificationT([ + new FbsProducer.ScoreT(/* encodingIdx */ 0, /* ssrc */ 11, /* rid */ undefined, /* score */ 10), + new FbsProducer.ScoreT(/* encodingIdx */ 1, /* ssrc */ 22, /* rid */ undefined, /* score */ 9) + ]); + const notificationOffset = Notification.createNotification( + builder, + builder.createString(videoProducer.id), + Event.PRODUCER_SCORE, + NotificationBody.Producer_ScoreNotification, + producerScoreNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + const notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); + channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); + channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); expect(onScore).toHaveBeenCalledTimes(3); - expect(videoProducer.score).toEqual([ { ssrc: 11, score: 9 }, { ssrc: 22, score: 9 } ]); + expect(videoProducer.score).toEqual( + [ { ssrc: 11, score: 10 }, { ssrc: 22, score: 9 } ]); }, 2000); test('producer.close() succeeds', async () => diff --git a/node/src/tests/test-Router.ts b/node/src/tests/test-Router.ts index 9d9941f2b4..d639115d57 100644 --- a/node/src/tests/test-Router.ts +++ b/node/src/tests/test-Router.ts @@ -1,8 +1,6 @@ import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; -const { createWorker } = mediasoup; - let worker: mediasoup.types.Worker; beforeEach(() => worker && !worker.closed && worker.close()); @@ -42,7 +40,7 @@ const mediaCodecs: mediasoup.types.RtpCodecCapability[] = test('worker.createRouter() succeeds', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); const onObserverNewRouter = jest.fn(); @@ -74,9 +72,8 @@ test('worker.createRouter() succeeds', async () => routerIds : [ router.id ], channelMessageHandlers : { - channelRequestHandlers : [ router.id ], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [ router.id ], + channelNotificationHandlers : [] } }); @@ -107,7 +104,7 @@ test('worker.createRouter() succeeds', async () => test('worker.createRouter() with wrong arguments rejects with TypeError', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); // @ts-ignore await expect(worker.createRouter({ mediaCodecs: {} })) @@ -124,7 +121,7 @@ test('worker.createRouter() with wrong arguments rejects with TypeError', async test('worker.createRouter() rejects with InvalidStateError if Worker is closed', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); worker.close(); @@ -135,7 +132,7 @@ test('worker.createRouter() rejects with InvalidStateError if Worker is closed', test('router.close() succeeds', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); const router = await worker.createRouter({ mediaCodecs }); const onObserverClose = jest.fn(); @@ -149,7 +146,7 @@ test('router.close() succeeds', async () => test('Router emits "workerclose" if Worker is closed', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); const router = await worker.createRouter({ mediaCodecs }); const onObserverClose = jest.fn(); diff --git a/node/src/tests/test-WebRtcServer.ts b/node/src/tests/test-WebRtcServer.ts index 072608590f..db5a6b2f2f 100644 --- a/node/src/tests/test-WebRtcServer.ts +++ b/node/src/tests/test-WebRtcServer.ts @@ -3,8 +3,6 @@ import * as pickPort from 'pick-port'; import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; -const { createWorker } = mediasoup; - let worker: mediasoup.types.Worker; beforeEach(() => worker && !worker.closed && worker.close()); @@ -12,7 +10,7 @@ afterEach(() => worker && !worker.closed && worker.close()); test('worker.createWebRtcServer() succeeds', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); const onObserverNewWebRtcServer = jest.fn(); @@ -55,9 +53,8 @@ test('worker.createWebRtcServer() succeeds', async () => routerIds : [], channelMessageHandlers : { - channelRequestHandlers : [ webRtcServer.id ], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [ webRtcServer.id ], + channelNotificationHandlers : [] } }); @@ -92,7 +89,7 @@ test('worker.createWebRtcServer() succeeds', async () => test('worker.createWebRtcServer() without specifying port succeeds', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); const onObserverNewWebRtcServer = jest.fn(); @@ -130,9 +127,8 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => routerIds : [], channelMessageHandlers : { - channelRequestHandlers : [ webRtcServer.id ], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [ webRtcServer.id ], + channelNotificationHandlers : [] } }); @@ -167,7 +163,7 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); // @ts-ignore await expect(worker.createWebRtcServer({})) @@ -182,7 +178,7 @@ test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', // @ts-ignore await expect(worker.createWebRtcServer({ listenInfos: [ 'NOT-AN-OBJECT' ] })) .rejects - .toThrow(TypeError); + .toThrow(Error); // Empty listenInfos so should fail. await expect(worker.createWebRtcServer({ listenInfos: [] })) @@ -194,8 +190,8 @@ test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', test('worker.createWebRtcServer() with unavailable listenInfos rejects with Error', async () => { - const worker1 = await createWorker(); - const worker2 = await createWorker(); + const worker1 = await mediasoup.createWorker(); + const worker2 = await mediasoup.createWorker(); const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); @@ -273,7 +269,7 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is closed', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); worker.close(); @@ -289,7 +285,7 @@ test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is cl test('webRtcServer.close() succeeds', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const webRtcServer = await worker.createWebRtcServer( @@ -307,7 +303,7 @@ test('webRtcServer.close() succeeds', async () => test('WebRtcServer emits "workerclose" if Worker is closed', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const webRtcServer = await worker.createWebRtcServer( @@ -330,7 +326,7 @@ test('WebRtcServer emits "workerclose" if Worker is closed', async () => test('router.createWebRtcTransport() with webRtcServer succeeds and transport is closed', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); @@ -358,7 +354,8 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is const transport = await router.createWebRtcTransport( { webRtcServer, - enableTcp : false, + // Let's disable UDP so resulting ICE candidates should only contain TCP. + enableUdp : false, appData : { foo: 'bar' } }); @@ -378,10 +375,10 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is expect(iceCandidates.length).toBe(1); expect(iceCandidates[0].ip).toBe('127.0.0.1'); - expect(iceCandidates[0].port).toBe(port1); - expect(iceCandidates[0].protocol).toBe('udp'); + expect(iceCandidates[0].port).toBe(port2); + expect(iceCandidates[0].protocol).toBe('tcp'); expect(iceCandidates[0].type).toBe('host'); - expect(iceCandidates[0].tcpType).toBeUndefined(); + expect(iceCandidates[0].tcpType).toBe('passive'); expect(transport.iceState).toBe('new'); expect(transport.iceSelectedTuple).toBeUndefined(); @@ -439,7 +436,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer is closed', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); @@ -462,9 +459,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer const transport = await router.createWebRtcTransport( { webRtcServer, - enableUdp : false, - enableTcp : true, - appData : { foo: 'bar' } + appData : { foo: 'bar' } }); expect(onObserverWebRtcTransportHandled).toHaveBeenCalledTimes(1); @@ -480,12 +475,17 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer const iceCandidates = transport.iceCandidates; - expect(iceCandidates.length).toBe(1); + expect(iceCandidates.length).toBe(2); expect(iceCandidates[0].ip).toBe('127.0.0.1'); - expect(iceCandidates[0].port).toBe(port2); - expect(iceCandidates[0].protocol).toBe('tcp'); + expect(iceCandidates[0].port).toBe(port1); + expect(iceCandidates[0].protocol).toBe('udp'); expect(iceCandidates[0].type).toBe('host'); - expect(iceCandidates[0].tcpType).toBe('passive'); + expect(iceCandidates[0].tcpType).toBeUndefined(); + expect(iceCandidates[1].ip).toBe('127.0.0.1'); + expect(iceCandidates[1].port).toBe(port2); + expect(iceCandidates[1].protocol).toBe('tcp'); + expect(iceCandidates[1].type).toBe('host'); + expect(iceCandidates[1].tcpType).toBe('passive'); expect(transport.iceState).toBe('new'); expect(transport.iceSelectedTuple).toBeUndefined(); @@ -572,9 +572,8 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer routerIds : [ router.id ], channelMessageHandlers : { - channelRequestHandlers : [ router.id ], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [ router.id ], + channelNotificationHandlers : [] } }); diff --git a/node/src/tests/test-WebRtcTransport.ts b/node/src/tests/test-WebRtcTransport.ts index bc49b9a168..7bb950eb08 100644 --- a/node/src/tests/test-WebRtcTransport.ts +++ b/node/src/tests/test-WebRtcTransport.ts @@ -1,8 +1,11 @@ // @ts-ignore import * as pickPort from 'pick-port'; +import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; - -const { createWorker } = mediasoup; +import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; +import * as FbsTransport from '../fbs/transport'; +import * as FbsWebRtcTransport from '../fbs/web-rtc-transport'; +import { serializeProtocol, TransportTuple } from '../Transport'; let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; @@ -42,7 +45,7 @@ const mediaCodecs: mediasoup.types.RtpCodecCapability[] = beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter({ mediaCodecs }); }); @@ -52,8 +55,7 @@ beforeEach(async () => { transport = await router.createWebRtcTransport( { - listenIps : [ { ip: '127.0.0.1', announcedIp: '9.9.9.1' } ], - enableTcp : false + listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } ] }); }); @@ -72,11 +74,14 @@ test('router.createWebRtcTransport() succeeds', async () => // Create a separate transport here. const transport1 = await router.createWebRtcTransport( { - listenIps : + listenInfos : [ - { ip: '127.0.0.1', announcedIp: '9.9.9.1' }, - { ip: '0.0.0.0', announcedIp: '9.9.9.2' }, - { ip: '127.0.0.1', announcedIp: undefined } + { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, + { protocol: 'tcp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, + { protocol: 'udp', ip: '0.0.0.0', announcedIp: '9.9.9.2' }, + { protocol: 'tcp', ip: '0.0.0.0', announcedIp: '9.9.9.2' }, + { protocol: 'udp', ip: '127.0.0.1', announcedIp: undefined }, + { protocol: 'tcp', ip: '127.0.0.1', announcedIp: undefined } ], enableTcp : true, preferUdp : true, @@ -133,9 +138,9 @@ test('router.createWebRtcTransport() succeeds', async () => expect(iceCandidates[5].type).toBe('host'); expect(iceCandidates[5].tcpType).toBe('passive'); expect(iceCandidates[0].priority).toBeGreaterThan(iceCandidates[1].priority); - expect(iceCandidates[2].priority).toBeGreaterThan(iceCandidates[1].priority); + expect(iceCandidates[1].priority).toBeGreaterThan(iceCandidates[2].priority); expect(iceCandidates[2].priority).toBeGreaterThan(iceCandidates[3].priority); - expect(iceCandidates[4].priority).toBeGreaterThan(iceCandidates[3].priority); + expect(iceCandidates[3].priority).toBeGreaterThan(iceCandidates[4].priority); expect(iceCandidates[4].priority).toBeGreaterThan(iceCandidates[5].priority); expect(transport1.iceState).toBe('new'); @@ -162,14 +167,16 @@ test('router.createWebRtcTransport() succeeds', async () => expect(data1.dtlsState).toBe(transport1.dtlsState); expect(data1.sctpParameters).toEqual(transport1.sctpParameters); expect(data1.sctpState).toBe(transport1.sctpState); - expect(typeof data1.recvRtpHeaderExtensions).toBe('object'); + expect(data1.recvRtpHeaderExtensions).toBeDefined(); expect(typeof data1.rtpListener).toBe('object'); transport1.close(); expect(transport1.closed).toBe(true); const anotherTransport = await router.createWebRtcTransport( - { listenIps: [ '127.0.0.1' ] }); + { + listenInfos : [ { protocol: 'udp', ip: '127.0.0.1' } ] + }); expect(typeof anotherTransport).toBe('object'); }, 2000); @@ -181,12 +188,13 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError .rejects .toThrow(TypeError); - await expect(router.createWebRtcTransport({ listenIps: [] })) + // @ts-ignore + await expect(router.createWebRtcTransport({ listenIps: [ 123 ] })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(router.createWebRtcTransport({ listenIps: [ 123 ] })) + await expect(router.createWebRtcTransport({ listenInfos: '127.0.0.1' })) .rejects .toThrow(TypeError); @@ -217,7 +225,10 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError test('router.createWebRtcTransport() with non bindable IP rejects with Error', async () => { - await expect(router.createWebRtcTransport({ listenIps: [ '8.8.8.8' ] })) + await expect(router.createWebRtcTransport( + { + listenInfos : [ { protocol: 'udp', ip: '8.8.8.8' } ] + })) .rejects .toThrow(Error); }, 2000); @@ -279,6 +290,11 @@ test('webRtcTransport.connect() succeeds', async () => expect(transport.dtlsParameters.role).toBe('server'); }, 2000); +/** + * When are we going to rely on the type system in the API? + * We are testing invalid type values which adds extra checks in the code that should be + * simply guarded by the type system. + */ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', async () => { let dtlsRemoteParameters: mediasoup.types.DtlsParameters; @@ -293,6 +309,7 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as fingerprints : [ { + // @ts-ignore. algorithm : 'sha-256000', value : '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD' } @@ -433,23 +450,23 @@ test('transport.enableTraceEvent() succeed', async () => await transport.enableTraceEvent([ 'foo', 'probation' ]); await expect(transport.dump()) .resolves - .toMatchObject({ traceEventTypes: 'probation' }); + .toMatchObject({ traceEventTypes: [ 'probation' ] }); await transport.enableTraceEvent([]); await expect(transport.dump()) .resolves - .toMatchObject({ traceEventTypes: '' }); + .toMatchObject({ traceEventTypes: [] }); // @ts-ignore await transport.enableTraceEvent([ 'probation', 'FOO', 'bwe', 'BAR' ]); await expect(transport.dump()) .resolves - .toMatchObject({ traceEventTypes: 'probation,bwe' }); + .toMatchObject({ traceEventTypes: [ 'probation', 'bwe' ] }); await transport.enableTraceEvent(); await expect(transport.dump()) .resolves - .toMatchObject({ traceEventTypes: '' }); + .toMatchObject({ traceEventTypes: [] }); }, 2000); test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', async () => @@ -478,14 +495,34 @@ test('WebRtcTransport events succeed', async () => transport.on('icestatechange', onIceStateChange); - channel.emit(transport.id, 'icestatechange', { iceState: 'completed' }); + // Simulate a 'iceselectedtuplechange' notification coming through the channel. + const builder = new flatbuffers.Builder(); + const iceStateChangeNotification = new FbsWebRtcTransport.IceStateChangeNotificationT( + FbsWebRtcTransport.IceState.COMPLETED); + + let notificationOffset = Notification.createNotification( + builder, + builder.createString(transport.id), + Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, + NotificationBody.WebRtcTransport_IceStateChangeNotification, + iceStateChangeNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + let notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit(transport.id, Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, notification); expect(onIceStateChange).toHaveBeenCalledTimes(1); expect(onIceStateChange).toHaveBeenCalledWith('completed'); expect(transport.iceState).toBe('completed'); + builder.clear(); + const onIceSelectedTuple = jest.fn(); - const iceSelectedTuple = + const iceSelectedTuple: TransportTuple = { localIp : '1.1.1.1', localPort : 1111, @@ -495,28 +532,66 @@ test('WebRtcTransport events succeed', async () => }; transport.on('iceselectedtuplechange', onIceSelectedTuple); - channel.emit(transport.id, 'iceselectedtuplechange', { iceSelectedTuple }); + + // Simulate a 'icestatechange' notification coming through the channel. + const iceSelectedTupleChangeNotification = + new FbsWebRtcTransport.IceSelectedTupleChangeNotificationT( + new FbsTransport.TupleT( + iceSelectedTuple.localIp, + iceSelectedTuple.localPort, + iceSelectedTuple.remoteIp, + iceSelectedTuple.remotePort, + serializeProtocol(iceSelectedTuple.protocol)) + ); + + notificationOffset = Notification.createNotification( + builder, + builder.createString(transport.id), + Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, + NotificationBody.WebRtcTransport_IceSelectedTupleChangeNotification, + iceSelectedTupleChangeNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit( + transport.id, Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, notification); expect(onIceSelectedTuple).toHaveBeenCalledTimes(1); expect(onIceSelectedTuple).toHaveBeenCalledWith(iceSelectedTuple); expect(transport.iceSelectedTuple).toEqual(iceSelectedTuple); + builder.clear(); + const onDtlsStateChange = jest.fn(); transport.on('dtlsstatechange', onDtlsStateChange); - channel.emit(transport.id, 'dtlsstatechange', { dtlsState: 'connecting' }); + + // Simulate a 'dtlsstatechange' notification coming through the channel. + const dtlsStateChangeNotification = new FbsWebRtcTransport.DtlsStateChangeNotificationT( + FbsWebRtcTransport.DtlsState.CONNECTING); + + notificationOffset = Notification.createNotification( + builder, + builder.createString(transport.id), + Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + NotificationBody.WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit(transport.id, Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, notification); expect(onDtlsStateChange).toHaveBeenCalledTimes(1); expect(onDtlsStateChange).toHaveBeenCalledWith('connecting'); expect(transport.dtlsState).toBe('connecting'); - - channel.emit( - transport.id, 'dtlsstatechange', { dtlsState: 'connected', dtlsRemoteCert: 'ABCD' }); - - expect(onDtlsStateChange).toHaveBeenCalledTimes(2); - expect(onDtlsStateChange).toHaveBeenCalledWith('connected'); - expect(transport.dtlsState).toBe('connected'); - expect(transport.dtlsRemoteCert).toBe('ABCD'); }, 2000); test('WebRtcTransport methods reject if closed', async () => @@ -569,8 +644,7 @@ test('router.createWebRtcTransport() with fixed port succeeds', async () => const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const webRtcTransport = await router.createWebRtcTransport( { - listenIps : [ '127.0.0.1' ], - port + listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port } ] }); expect(webRtcTransport.iceCandidates[0].port).toEqual(port); diff --git a/node/src/tests/test-Worker.ts b/node/src/tests/test-Worker.ts index 365e7fac05..65dd889f18 100644 --- a/node/src/tests/test-Worker.ts +++ b/node/src/tests/test-Worker.ts @@ -1,11 +1,9 @@ -import * as os from 'os'; -import * as process from 'process'; -import * as path from 'path'; +import * as os from 'node:os'; +import * as process from 'node:process'; +import * as path from 'node:path'; import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; -const { createWorker, observer } = mediasoup; - let worker: mediasoup.types.Worker; beforeEach(() => worker && !worker.closed && worker.close()); @@ -26,9 +24,9 @@ test('createWorker() succeeds', async () => { const onObserverNewWorker = jest.fn(); - observer.once('newworker', onObserverNewWorker); + mediasoup.observer.once('newworker', onObserverNewWorker); - worker = await createWorker(); + worker = await mediasoup.createWorker(); expect(onObserverNewWorker).toHaveBeenCalledTimes(1); expect(onObserverNewWorker).toHaveBeenCalledWith(worker); @@ -43,7 +41,7 @@ test('createWorker() succeeds', async () => expect(worker.died).toBe(false); // eslint-disable-next-line require-atomic-updates - worker = await createWorker<{ foo: number; bar?: string }>( + worker = await mediasoup.createWorker<{ foo: number; bar?: string }>( { logLevel : 'debug', logTags : [ 'info' ], @@ -69,36 +67,36 @@ test('createWorker() succeeds', async () => test('createWorker() with wrong settings rejects with TypeError', async () => { // @ts-ignore - await expect(createWorker({ logLevel: 'chicken' })) + await expect(mediasoup.createWorker({ logLevel: 'chicken' })) .rejects .toThrow(TypeError); - await expect(createWorker({ rtcMinPort: 1000, rtcMaxPort: 999 })) + await expect(mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 999 })) .rejects .toThrow(TypeError); // Port is from 0 to 65535. - await expect(createWorker({ rtcMinPort: 1000, rtcMaxPort: 65536 })) + await expect(mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 65536 })) .rejects .toThrow(TypeError); - await expect(createWorker({ dtlsCertificateFile: '/notfound/cert.pem' })) + await expect(mediasoup.createWorker({ dtlsCertificateFile: '/notfound/cert.pem' })) .rejects .toThrow(TypeError); - await expect(createWorker({ dtlsPrivateKeyFile: '/notfound/priv.pem' })) + await expect(mediasoup.createWorker({ dtlsPrivateKeyFile: '/notfound/priv.pem' })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(createWorker({ appData: 'NOT-AN-OBJECT' })) + await expect(mediasoup.createWorker({ appData: 'NOT-AN-OBJECT' })) .rejects .toThrow(TypeError); }, 2000); test('worker.updateSettings() succeeds', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); await expect(worker.updateSettings({ logLevel: 'debug', logTags: [ 'ice' ] })) .resolves @@ -109,7 +107,7 @@ test('worker.updateSettings() succeeds', async () => test('worker.updateSettings() with wrong settings rejects with TypeError', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); // @ts-ignore await expect(worker.updateSettings({ logLevel: 'chicken' })) @@ -121,7 +119,7 @@ test('worker.updateSettings() with wrong settings rejects with TypeError', async test('worker.updateSettings() rejects with InvalidStateError if closed', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); worker.close(); await expect(worker.updateSettings({ logLevel: 'error' })) @@ -133,7 +131,7 @@ test('worker.updateSettings() rejects with InvalidStateError if closed', async ( test('worker.dump() succeeds', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); await expect(worker.dump()) .resolves @@ -144,9 +142,8 @@ test('worker.dump() succeeds', async () => routerIds : [], channelMessageHandlers : { - channelRequestHandlers : [], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [], + channelNotificationHandlers : [] } }); @@ -155,7 +152,7 @@ test('worker.dump() succeeds', async () => test('worker.dump() rejects with InvalidStateError if closed', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); worker.close(); await expect(worker.dump()) @@ -167,7 +164,7 @@ test('worker.dump() rejects with InvalidStateError if closed', async () => test('worker.getResourceUsage() succeeds', async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); await expect(worker.getResourceUsage()) .resolves @@ -178,7 +175,7 @@ test('worker.getResourceUsage() succeeds', async () => test('worker.close() succeeds', async () => { - worker = await createWorker({ logLevel: 'warn' }); + worker = await mediasoup.createWorker({ logLevel: 'warn' }); const onObserverClose = jest.fn(); @@ -195,7 +192,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => let onDied: ReturnType; let onObserverClose: ReturnType; - worker = await createWorker({ logLevel: 'warn' }); + worker = await mediasoup.createWorker({ logLevel: 'warn' }); onDied = jest.fn(); onObserverClose = jest.fn(); @@ -231,7 +228,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => expect(worker.died).toBe(true); // eslint-disable-next-line require-atomic-updates - worker = await createWorker({ logLevel: 'warn' }); + worker = await mediasoup.createWorker({ logLevel: 'warn' }); onDied = jest.fn(); onObserverClose = jest.fn(); @@ -267,7 +264,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => expect(worker.died).toBe(true); // eslint-disable-next-line require-atomic-updates - worker = await createWorker({ logLevel: 'warn' }); + worker = await mediasoup.createWorker({ logLevel: 'warn' }); onDied = jest.fn(); onObserverClose = jest.fn(); @@ -312,7 +309,7 @@ test('worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () = return; } - worker = await createWorker({ logLevel: 'warn' }); + worker = await mediasoup.createWorker({ logLevel: 'warn' }); await new Promise((resolve, reject) => { diff --git a/node/src/tests/test-mediasoup.ts b/node/src/tests/test-mediasoup.ts index ea080b7bb6..0032e49322 100644 --- a/node/src/tests/test-mediasoup.ts +++ b/node/src/tests/test-mediasoup.ts @@ -1,10 +1,22 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; import * as mediasoup from '../'; +const PKG = JSON.parse(fs.readFileSync( + path.join(__dirname, '..', '..', '..', 'package.json'), { encoding: 'utf-8' }) +); + const { + version, getSupportedRtpCapabilities, parseScalabilityMode } = mediasoup; +test('mediasoup.version matches version field in package.json', () => +{ + expect(version).toBe(PKG.version); +}); + test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabilities', () => { const rtpCapabilities = getSupportedRtpCapabilities(); diff --git a/node/src/tests/test-multiopus.ts b/node/src/tests/test-multiopus.ts index b1e3a260ed..0cb4991239 100644 --- a/node/src/tests/test-multiopus.ts +++ b/node/src/tests/test-multiopus.ts @@ -1,8 +1,6 @@ import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; -const { createWorker } = mediasoup; - let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; let transport: mediasoup.types.WebRtcTransport; @@ -103,7 +101,7 @@ const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter({ mediaCodecs }); transport = await router.createWebRtcTransport( { diff --git a/node/src/tests/test-node-sctp.ts b/node/src/tests/test-node-sctp.ts index ae58c95ea7..8354a2fbf8 100644 --- a/node/src/tests/test-node-sctp.ts +++ b/node/src/tests/test-node-sctp.ts @@ -1,10 +1,8 @@ -import * as dgram from 'dgram'; +import * as dgram from 'node:dgram'; // @ts-ignore import * as sctp from 'sctp'; import * as mediasoup from '../'; -const { createWorker } = mediasoup; - // Set node-sctp default PMTU to 1200. sctp.defaults({ PMTU: 1200 }); @@ -20,7 +18,7 @@ let sctpSendStream: any; beforeAll(async () => { - worker = await createWorker(); + worker = await mediasoup.createWorker(); router = await worker.createRouter(); transport = await router.createPlainTransport( { diff --git a/node/src/tests/test-ortc.ts b/node/src/tests/test-ortc.ts index 8dbabfb25d..b1c4d4ca16 100644 --- a/node/src/tests/test-ortc.ts +++ b/node/src/tests/test-ortc.ts @@ -338,8 +338,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(consumableRtpParameters.rtcp).toEqual( { cname : rtpParameters.rtcp?.cname, - reducedSize : true, - mux : true + reducedSize : true }); const remoteRtpCapabilities: mediasoup.types.RtpCapabilities = @@ -504,8 +503,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(consumerRtpParameters.rtcp).toEqual( { cname : rtpParameters.rtcp?.cname, - reducedSize : true, - mux : true + reducedSize : true }); const pipeConsumerRtpParameters = ortc.getPipeConsumerRtpParameters( @@ -551,8 +549,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(pipeConsumerRtpParameters.rtcp).toEqual( { cname : rtpParameters.rtcp?.cname, - reducedSize : true, - mux : true + reducedSize : true }); }); diff --git a/node/src/types.ts b/node/src/types.ts index 7de0c0e72f..2ede7f2c10 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -23,3 +23,13 @@ export type AppData = { [key: string]: unknown; }; + +type Only = +{ + [P in keyof T]: T[P]; +} & +{ + [P in keyof U]?: never; +}; + +export type Either = Only | Only; diff --git a/node/src/utils.ts b/node/src/utils.ts index e91bea6604..6f9ad900d2 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -1,32 +1,193 @@ -import { randomInt } from 'crypto'; +import { randomUUID, randomInt } from 'node:crypto'; +import { ProducerType } from './Producer'; +import { Type as FbsRtpParametersType } from './fbs/rtp-parameters'; /** - * Clones the given object/array. + * Clones the given value. */ -export function clone(data: any): any +export function clone(value: T): T { - if (typeof data !== 'object') + if (value === undefined) { - return {}; + return undefined as unknown as T; } + else if (Number.isNaN(value)) + { + return NaN as unknown as T; + } + else if (typeof structuredClone === 'function') + { + // Available in Node >= 18. + return structuredClone(value); + } + else + { + return JSON.parse(JSON.stringify(value)); + } +} - return JSON.parse(JSON.stringify(data)); +/** + * Generates a random UUID v4. + */ +export function generateUUIDv4(): string +{ + return randomUUID(); } /** * Generates a random positive integer. */ -export function generateRandomNumber() +export function generateRandomNumber(): number { return randomInt(100_000_000, 999_999_999); } -type Only = +/** + * Get the flatbuffers RtpParameters type for a given Producer. + */ +export function getRtpParametersType( + producerType: ProducerType, pipe: boolean +): FbsRtpParametersType +{ + if (pipe) + { + return FbsRtpParametersType.PIPE; + } + + switch (producerType) + { + case 'simple': + return FbsRtpParametersType.SIMPLE; + + case 'simulcast': + return FbsRtpParametersType.SIMULCAST; + + case 'svc': + return FbsRtpParametersType.SVC; + } +} + +/** + * Parse flatbuffers vector into an array of the given type. + */ +export function parseVector( + binary: any, methodName: string, parseFn?: (binary2: any) => Type +): Type[] +{ + const array: Type[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) + { + if (parseFn) + { + array.push(parseFn(binary[methodName](i))); + } + else + { + array.push(binary[methodName](i)); + } + } + + return array; +} + +/** + * Parse flatbuffers vector of StringString into the corresponding array. + */ +export function parseStringStringVector( + binary: any, methodName: string +): { key: string; value: string }[] +{ + const array: { key: string; value: string }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) + { + const kv = binary[methodName](i)!; + + array.push({ key: kv.key(), value: kv.value() }); + } + + return array; +} + +/** + * Parse flatbuffers vector of StringUint8 into the corresponding array. + */ +export function parseStringUint8Vector( + binary: any, methodName: string +): {key: string; value: number}[] { - [P in keyof T]: T[P]; -} & + const array: {key: string; value: number}[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) + { + const kv = binary[methodName](i)!; + + array.push({ key: kv.key(), value: kv.value() }); + } + + return array; +} + +/** + * Parse flatbuffers vector of Uint16String into the corresponding array. + */ +export function parseUint16StringVector( + binary: any, methodName: string +): { key: number; value: string }[] { - [P in keyof U]?: never; -}; + const array: { key: number; value: string }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) + { + const kv = binary[methodName](i)!; -export type Either = Only | Only; + array.push({ key: kv.key(), value: kv.value() }); + } + + return array; +} + +/** + * Parse flatbuffers vector of Uint32String into the corresponding array. + */ +export function parseUint32StringVector( + binary: any, methodName: string +): { key: number; value: string }[] +{ + const array: { key: number; value: string }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) + { + const kv = binary[methodName](i)!; + + array.push({ key: kv.key(), value: kv.value() }); + } + + return array; +} + +/** + * Parse flatbuffers vector of StringStringArray into the corresponding array. + */ +export function parseStringStringArrayVector( + binary: any, methodName: string +): { key: string; values: string[] }[] +{ + const array: { key: string; values: string[] }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) + { + const kv = binary[methodName](i)!; + const values: string[] = []; + + for (let i2 = 0; i2 < kv.valuesLength(); ++i2) + { + values.push(kv.values(i2)!); + } + + array.push({ key: kv.key(), values }); + } + + return array; +} diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 2089a6379e..42b07a6b10 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -1,8 +1,8 @@ -import process from 'process'; -import os from 'os'; -import fs from 'fs'; -import path from 'path'; -import { execSync, spawnSync } from 'child_process'; +import process from 'node:process'; +import os from 'node:os'; +import fs from 'node:fs'; +import path from 'node:path'; +import { execSync, spawnSync } from 'node:child_process'; import fetch from 'node-fetch'; import tar from 'tar'; @@ -11,6 +11,7 @@ const IS_FREEBSD = os.platform() === 'freebsd'; const IS_WINDOWS = os.platform() === 'win32'; const MAYOR_VERSION = PKG.version.split('.')[0]; const MAKE = process.env.MAKE || (IS_FREEBSD ? 'gmake' : 'make'); +const FLATBUFFERS_VERSION = '23.3.3'; const WORKER_RELEASE_DIR = 'worker/out/Release'; const WORKER_RELEASE_BIN = IS_WINDOWS ? 'mediasoup-worker.exe' : 'mediasoup-worker'; const WORKER_RELEASE_BIN_PATH = `${WORKER_RELEASE_DIR}/${WORKER_RELEASE_BIN}`; @@ -31,19 +32,18 @@ async function run() // As per NPM documentation (https://docs.npmjs.com/cli/v9/using-npm/scripts) // `prepare` script: // - // - Runs BEFORE the package is packed, i.e. during `npm publish` and - // `npm pack`. + // - Runs BEFORE the package is packed, i.e. during `npm publish` and `npm pack`. // - Runs on local `npm install` without any arguments. // - NOTE: If a package being installed through git contains a `prepare` script, // its dependencies and devDependencies will be installed, and the `prepare` // script will be run, before the package is packaged and installed. // - // So here we compile TypeScript and flatbuffers to JavaScript. + // So here we generate flatbuffers definitions for TypeScript and compile + // TypeScript to JavaScript. case 'prepare': { - buildTypescript(/* force */ false); - - // TODO: Compile flatbuffers. + flatcNode(); + buildTypescript({ force: false }); break; } @@ -86,7 +86,11 @@ async function run() logInfo(`couldn't fetch any mediasoup-worker prebuilt binary, building it locally`); buildWorker(); - cleanWorkerArtifacts(); + + if (!process.env.MEDIASOUP_LOCAL_DEV) + { + cleanWorkerArtifacts(); + } } break; @@ -95,8 +99,7 @@ async function run() case 'typescript:build': { installNodeDeps(); - buildTypescript(/* force */ true); - replaceVersion(); + buildTypescript({ force: true }); break; } @@ -144,10 +147,23 @@ async function run() break; } + case 'flatc:node': + { + flatcNode(); + + break; + } + + case 'flatc:worker': + { + flatcWorker(); + + break; + } + case 'test:node': { - buildTypescript(/* force */ false); - replaceVersion(); + buildTypescript({ force: false }); testNode(); break; @@ -162,8 +178,7 @@ async function run() case 'coverage:node': { - buildTypescript(/* force */ false); - replaceVersion(); + buildTypescript({ force: false }); executeCmd('jest --coverage'); executeCmd('open-cli coverage/lcov-report/index.html'); @@ -258,31 +273,6 @@ async function run() } } -function replaceVersion() -{ - logInfo('replaceVersion()'); - - const files = fs.readdirSync('node/lib', - { - withFileTypes : true, - recursive : false - }); - - for (const file of files) - { - if (!file.isFile()) - { - continue; - } - - const filePath = path.join('node/lib', file.name); - const text = fs.readFileSync(filePath, { encoding: 'utf8' }); - const result = text.replace(/__MEDIASOUP_VERSION__/g, PKG.version); - - fs.writeFileSync(filePath, result, { encoding: 'utf8' }); - } -} - function deleteNodeLib() { if (!fs.existsSync('node/lib')) @@ -303,7 +293,7 @@ function deleteNodeLib() } } -function buildTypescript(force = false) +function buildTypescript({ force = false } = { force: false }) { if (!force && fs.existsSync('node/lib')) { @@ -351,7 +341,10 @@ function cleanWorkerArtifacts() if (IS_WINDOWS) { - executeCmd('rd /s /q worker\\out\\msys'); + if (fs.existsSync('worker/out/msys')) + { + executeCmd('rd /s /q worker\\out\\msys'); + } } } @@ -359,7 +352,7 @@ function lintNode() { logInfo('lintNode()'); - executeCmd('eslint -c node/.eslintrc.js --max-warnings 0 node/src node/.eslintrc.js npm-scripts.mjs worker/scripts/gulpfile.mjs'); + executeCmd('eslint -c node/.eslintrc.js --ignore-path node/.eslintignore --max-warnings 0 node/src node/.eslintrc.js npm-scripts.mjs worker/scripts/gulpfile.mjs'); } function lintWorker() @@ -369,6 +362,39 @@ function lintWorker() executeCmd(`${MAKE} lint -C worker`); } +function flatcNode() +{ + logInfo('flatcNode()'); + + // Build flatc if needed. + executeCmd(`${MAKE} -C worker flatc`); + + const buildType = process.env.MEDIASOUP_BUILDTYPE || 'Release'; + const extension = IS_WINDOWS ? '.exe' : ''; + const flatc = path.resolve(path.join( + 'worker', 'out', buildType, 'build', 'subprojects', `flatbuffers-${FLATBUFFERS_VERSION}`, `flatc${extension}`)); + const src = path.resolve(path.join('worker', 'fbs', '*.fbs')); + const out = path.resolve(path.join('node', 'src')); + const options = '--ts-no-import-ext --gen-object-api'; + const command = `${flatc} --ts ${options} -o ${out} `; + + if (IS_WINDOWS) + { + executeCmd(`for %f in (${src}) do ${command} %f`); + } + else + { + executeCmd(`for file in ${src}; do ${command} \$\{file\}; done`); + } +} + +function flatcWorker() +{ + logInfo('flatcWorker()'); + + executeCmd(`${MAKE} -C worker flatc`); +} + function testNode() { logInfo('testNode()'); @@ -405,8 +431,8 @@ function checkRelease() logInfo('checkRelease()'); installNodeDeps(); - buildTypescript(/* force */ true); - replaceVersion(); + flatcNode(); + buildTypescript({ force: true }); buildWorker(); lintNode(); lintWorker(); @@ -575,6 +601,10 @@ async function downloadPrebuiltWorker() env : {} } ); + + logInfo( + 'downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary is valid for current host' + ); } catch (error) { diff --git a/package-lock.json b/package-lock.json index cdc8eb48d6..8a46af3217 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,24 +11,23 @@ "license": "ISC", "dependencies": { "debug": "^4.3.4", + "flatbuffers": "^23.5.26", "h264-profile-level-id": "^1.0.1", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.2.0", - "uuid": "^9.0.1" + "tar": "^6.2.0" }, "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.10", - "@types/jest": "^29.5.6", - "@types/node": "^20.8.7", - "@types/uuid": "^9.0.6", - "@typescript-eslint/eslint-plugin": "^6.8.0", - "@typescript-eslint/parser": "^6.8.0", - "eslint": "^8.52.0", - "eslint-plugin-jest": "^27.4.3", + "@types/jest": "^29.5.7", + "@types/node": "^20.8.10", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", + "eslint": "^8.53.0", + "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^9.1.2", + "marked": "^9.1.5", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -743,9 +742,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -766,9 +765,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", - "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", + "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1592,9 +1591,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.6", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", - "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", + "version": "29.5.7", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.7.tgz", + "integrity": "sha512-HLyetab6KVPSiF+7pFcUyMeLsx25LDNDemw9mGsJBkai/oouwrjTycocSDYopMEwFhN2Y4s9oPyOCZNofgSt2g==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1620,12 +1619,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.8.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", + "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", "dev": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, "node_modules/@types/normalize-package-data": { @@ -1646,12 +1645,6 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "node_modules/@types/uuid": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", - "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==", - "dev": true - }, "node_modules/@types/yargs": { "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", @@ -1668,16 +1661,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", - "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", + "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/type-utils": "6.8.0", - "@typescript-eslint/utils": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/type-utils": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1703,13 +1696,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1720,9 +1713,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1733,13 +1726,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1760,17 +1753,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", - "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", + "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", "semver": "^7.5.4" }, "engines": { @@ -1785,12 +1778,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/types": "6.9.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1802,15 +1795,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", - "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", + "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4" }, "engines": { @@ -1830,13 +1823,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1847,9 +1840,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1860,13 +1853,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1887,12 +1880,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/types": "6.9.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1921,13 +1914,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", - "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", + "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/utils": "6.8.0", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/utils": "6.9.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1948,13 +1941,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1965,9 +1958,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1978,13 +1971,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2005,17 +1998,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", - "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", + "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", "semver": "^7.5.4" }, "engines": { @@ -2030,12 +2023,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/types": "6.9.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2136,9 +2129,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3030,15 +3023,15 @@ } }, "node_modules/eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", - "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", + "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.52.0", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.53.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -3085,9 +3078,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.4.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.3.tgz", - "integrity": "sha512-7S6SmmsHsgIm06BAGCAxL+ABd9/IB3MWkz2pudj6Qqor2y1qQpWPfuFU4SG9pWj4xDjF0e+D7Llh5useuSzAZw==", + "version": "27.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.0.tgz", + "integrity": "sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -3453,6 +3446,11 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/flatbuffers": { + "version": "23.5.26", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.5.26.tgz", + "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==" + }, "node_modules/flatted": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", @@ -3602,9 +3600,9 @@ } }, "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -4851,9 +4849,9 @@ } }, "node_modules/marked": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.2.tgz", - "integrity": "sha512-qoKMJqK0w6vkLk8+KnKZAH6neUZSNaQqVZ/h2yZ9S7CbLuFHyS2viB0jnqcWF9UKjwsAbMrQtnQhdmdvOVOw9w==", + "version": "9.1.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.5.tgz", + "integrity": "sha512-14QG3shv8Kg/xc0Yh6TNkMj90wXH9mmldi5941I2OevfJ/FQAFLEwtwU2/FfgSAOMlWHrEukWSGQf8MiVYNG2A==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -5483,9 +5481,9 @@ "dev": true }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -6473,9 +6471,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, "node_modules/unique-string": { @@ -6549,18 +6547,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", @@ -7298,9 +7284,9 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -7315,9 +7301,9 @@ } }, "@eslint/js": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", - "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", + "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", "dev": true }, "@humanwhocodes/config-array": { @@ -7992,9 +7978,9 @@ } }, "@types/jest": { - "version": "29.5.6", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", - "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", + "version": "29.5.7", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.7.tgz", + "integrity": "sha512-HLyetab6KVPSiF+7pFcUyMeLsx25LDNDemw9mGsJBkai/oouwrjTycocSDYopMEwFhN2Y4s9oPyOCZNofgSt2g==", "dev": true, "requires": { "expect": "^29.0.0", @@ -8020,12 +8006,12 @@ "dev": true }, "@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.8.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", + "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", "dev": true, "requires": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, "@types/normalize-package-data": { @@ -8046,12 +8032,6 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "@types/uuid": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", - "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==", - "dev": true - }, "@types/yargs": { "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", @@ -8068,16 +8048,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", - "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", + "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/type-utils": "6.8.0", - "@typescript-eslint/utils": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/type-utils": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8087,29 +8067,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" } }, "@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8118,69 +8098,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", - "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", + "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/types": "6.9.1", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", - "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", + "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" } }, "@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8189,12 +8169,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/types": "6.9.1", "eslint-visitor-keys": "^3.4.1" } } @@ -8211,41 +8191,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", - "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", + "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/utils": "6.8.0", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/utils": "6.9.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" } }, "@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8254,27 +8234,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", - "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", + "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/types": "6.9.1", "eslint-visitor-keys": "^3.4.1" } } @@ -8334,9 +8314,9 @@ "dev": true }, "acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true }, "acorn-jsx": { @@ -8969,15 +8949,15 @@ "dev": true }, "eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", - "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", + "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.52.0", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.53.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -9033,9 +9013,9 @@ } }, "eslint-plugin-jest": { - "version": "27.4.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.3.tgz", - "integrity": "sha512-7S6SmmsHsgIm06BAGCAxL+ABd9/IB3MWkz2pudj6Qqor2y1qQpWPfuFU4SG9pWj4xDjF0e+D7Llh5useuSzAZw==", + "version": "27.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.0.tgz", + "integrity": "sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" @@ -9274,6 +9254,11 @@ "rimraf": "^3.0.2" } }, + "flatbuffers": { + "version": "23.5.26", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.5.26.tgz", + "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==" + }, "flatted": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", @@ -9379,9 +9364,9 @@ } }, "globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -10295,9 +10280,9 @@ "dev": true }, "marked": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.2.tgz", - "integrity": "sha512-qoKMJqK0w6vkLk8+KnKZAH6neUZSNaQqVZ/h2yZ9S7CbLuFHyS2viB0jnqcWF9UKjwsAbMrQtnQhdmdvOVOw9w==", + "version": "9.1.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.5.tgz", + "integrity": "sha512-14QG3shv8Kg/xc0Yh6TNkMj90wXH9mmldi5941I2OevfJ/FQAFLEwtwU2/FfgSAOMlWHrEukWSGQf8MiVYNG2A==", "dev": true }, "meow": { @@ -10743,9 +10728,9 @@ "dev": true }, "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, "pure-rand": { @@ -11384,9 +11369,9 @@ "dev": true }, "undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, "unique-string": { @@ -11435,11 +11420,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, "v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", diff --git a/package.json b/package.json index 4fbba54e1b..b7af4b973b 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "files": [ "node/lib", "worker/deps/libwebrtc", + "worker/fbs", "worker/fuzzer/include", "worker/fuzzer/src", "worker/include", @@ -58,6 +59,9 @@ "lint:node": "node npm-scripts.mjs lint:node", "lint:worker": "node npm-scripts.mjs lint:worker", "format:worker": "node npm-scripts.mjs format:worker", + "flatc": "npm run flatc:node && npm run flatc:worker", + "flatc:node": "node npm-scripts.mjs flatc:node", + "flatc:worker": "node npm-scripts.mjs flatc:worker", "test": "npm run test:node && npm run test:worker", "test:node": "node npm-scripts.mjs test:node", "test:worker": "node npm-scripts.mjs test:worker", @@ -84,28 +88,31 @@ } ] }, + "coveragePathIgnorePatterns": [ + "node/src/fbs", + "node/src/tests" + ], "cacheDirectory": ".cache/jest" }, "dependencies": { "debug": "^4.3.4", + "flatbuffers": "^23.5.26", "h264-profile-level-id": "^1.0.1", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.2.0", - "uuid": "^9.0.1" + "tar": "^6.2.0" }, "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.10", - "@types/jest": "^29.5.6", - "@types/node": "^20.8.7", - "@types/uuid": "^9.0.6", - "@typescript-eslint/eslint-plugin": "^6.8.0", - "@typescript-eslint/parser": "^6.8.0", - "eslint": "^8.52.0", - "eslint-plugin-jest": "^27.4.3", + "@types/jest": "^29.5.7", + "@types/node": "^20.8.10", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", + "eslint": "^8.53.0", + "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^9.1.2", + "marked": "^9.1.5", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index e84085947a..968b5e3d45 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -35,6 +35,7 @@ hash_hasher = "2.0.3" log = "0.4.17" nohash-hasher = "0.2.0" once_cell = "1.16.0" +planus = "0.4.0" serde_json = "1.0.87" serde_repr = "0.1.9" thiserror = "1.0.37" @@ -58,7 +59,7 @@ version = "1.6.0" [dependencies.serde] features = ["derive"] -version = "1.0.147" +version = "1.0.190" [dependencies.uuid] features = ["serde", "v4"] @@ -80,3 +81,6 @@ version = "4.2.1" [[bench]] name = "direct_data" harness = false +[[bench]] +name = "producer" +harness = false diff --git a/rust/benches/direct_data.rs b/rust/benches/direct_data.rs index 8406a7acd3..0cea4d8fe0 100644 --- a/rust/benches/direct_data.rs +++ b/rust/benches/direct_data.rs @@ -19,7 +19,7 @@ async fn create_data_producer_consumer_pair( .produce_data(DataProducerOptions::new_direct()) .await?; let data_consumer = direct_transport - .consume_data(DataConsumerOptions::new_direct(data_producer.id())) + .consume_data(DataConsumerOptions::new_direct(data_producer.id(), None)) .await?; Ok((data_producer, data_consumer)) @@ -51,7 +51,8 @@ pub fn criterion_benchmark(c: &mut Criterion) { let _ = sender.send(()); }); - let _ = direct_data_producer.send(WebRtcMessage::Binary(Cow::from(data))); + let _ = + direct_data_producer.send(WebRtcMessage::Binary(Cow::from(data)), None, None); let _ = receiver.recv(); }) diff --git a/rust/benches/producer.rs b/rust/benches/producer.rs new file mode 100644 index 0000000000..a6a5e87c64 --- /dev/null +++ b/rust/benches/producer.rs @@ -0,0 +1,286 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use mediasoup::prelude::*; +use std::env; +use std::net::{IpAddr, Ipv4Addr}; +use std::num::{NonZeroU32, NonZeroU8}; + +fn create_ssrc() -> u32 { + fastrand::u32(100_000_000..999_999_999) +} + +fn media_codecs() -> Vec { + vec![ + RtpCodecCapability::Audio { + mime_type: MimeTypeAudio::Opus, + preferred_payload_type: None, + clock_rate: NonZeroU32::new(48000).unwrap(), + channels: NonZeroU8::new(2).unwrap(), + parameters: RtpCodecParametersParameters::from([("foo", "111".into())]), + rtcp_feedback: vec![], + }, + RtpCodecCapability::Video { + mime_type: MimeTypeVideo::Vp8, + preferred_payload_type: None, + clock_rate: NonZeroU32::new(90000).unwrap(), + parameters: RtpCodecParametersParameters::default(), + rtcp_feedback: vec![], + }, + RtpCodecCapability::Video { + mime_type: MimeTypeVideo::H264, + preferred_payload_type: None, + clock_rate: NonZeroU32::new(90000).unwrap(), + parameters: RtpCodecParametersParameters::from([ + ("level-asymmetry-allowed", 1_u32.into()), + ("packetization-mode", 1_u32.into()), + ("profile-level-id", "4d0032".into()), + ("foo", "bar".into()), + ]), + rtcp_feedback: vec![], + }, + ] +} + +async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { + { + let mut builder = env_logger::builder(); + if env::var(env_logger::DEFAULT_FILTER_ENV).is_err() { + builder.filter_level(log::LevelFilter::Off); + } + let _ = builder.is_test(true).try_init(); + } + + let worker_manager = WorkerManager::new(); + + let worker = worker_manager + .create_worker(WorkerSettings::default()) + .await + .expect("Failed to create worker"); + + let router = worker + .create_router(RouterOptions::new(media_codecs())) + .await + .expect("Failed to create router"); + + let transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); + + let transport_1 = router + .create_webrtc_transport(transport_options.clone()) + .await + .expect("Failed to create transport1"); + + let transport_2 = router + .create_webrtc_transport(transport_options) + .await + .expect("Failed to create transport2"); + + (worker, router, transport_1, transport_2) +} + +fn audio_producer_options() -> ProducerOptions { + ProducerOptions::new( + MediaKind::Audio, + RtpParameters { + mid: Some(fastrand::u32(100_000_000..999_999_999).to_string()), + codecs: vec![RtpCodecParameters::Audio { + mime_type: MimeTypeAudio::Opus, + payload_type: 0, + clock_rate: NonZeroU32::new(48000).unwrap(), + channels: NonZeroU8::new(2).unwrap(), + parameters: RtpCodecParametersParameters::from([ + ("useinbandfec", 1_u32.into()), + ("usedtx", 1_u32.into()), + ("foo", "222.222".into()), + ("bar", "333".into()), + ]), + rtcp_feedback: vec![], + }], + header_extensions: vec![ + RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::Mid, + id: 10, + encrypt: false, + }, + RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::AudioLevel, + id: 12, + encrypt: false, + }, + ], + // Missing encodings on purpose. + encodings: vec![], + rtcp: RtcpParameters { + cname: Some("audio-1".to_string()), + ..RtcpParameters::default() + }, + }, + ) +} + +fn video_producer_options() -> ProducerOptions { + ProducerOptions::new( + MediaKind::Video, + RtpParameters { + mid: Some(fastrand::u32(100_000_000..999_999_999).to_string()), + codecs: vec![ + RtpCodecParameters::Video { + mime_type: MimeTypeVideo::H264, + payload_type: 112, + clock_rate: NonZeroU32::new(90000).unwrap(), + parameters: RtpCodecParametersParameters::from([ + ("packetization-mode", 1_u32.into()), + ("profile-level-id", "4d0032".into()), + ]), + rtcp_feedback: vec![ + RtcpFeedback::Nack, + RtcpFeedback::NackPli, + RtcpFeedback::GoogRemb, + ], + }, + RtpCodecParameters::Video { + mime_type: MimeTypeVideo::Rtx, + payload_type: 113, + clock_rate: NonZeroU32::new(90000).unwrap(), + parameters: RtpCodecParametersParameters::from([("apt", 112u32.into())]), + rtcp_feedback: vec![], + }, + ], + header_extensions: vec![ + RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::Mid, + id: 10, + encrypt: false, + }, + RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::VideoOrientation, + id: 13, + encrypt: false, + }, + ], + encodings: vec![ + RtpEncodingParameters { + ssrc: Some(create_ssrc()), + rtx: Some(RtpEncodingParametersRtx { + ssrc: create_ssrc(), + }), + scalability_mode: "L1T3".parse().unwrap(), + ..RtpEncodingParameters::default() + }, + RtpEncodingParameters { + ssrc: Some(create_ssrc()), + rtx: Some(RtpEncodingParametersRtx { + ssrc: create_ssrc(), + }), + ..RtpEncodingParameters::default() + }, + RtpEncodingParameters { + ssrc: Some(create_ssrc()), + rtx: Some(RtpEncodingParametersRtx { + ssrc: create_ssrc(), + }), + ..RtpEncodingParameters::default() + }, + RtpEncodingParameters { + ssrc: Some(create_ssrc()), + rtx: Some(RtpEncodingParametersRtx { + ssrc: create_ssrc(), + }), + ..RtpEncodingParameters::default() + }, + ], + rtcp: RtcpParameters { + cname: Some("video-1".to_string()), + ..RtcpParameters::default() + }, + }, + ) +} + +pub fn criterion_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("producer"); + + { + let (_worker, _router, transport_1, _transport_2) = + futures_lite::future::block_on(async { init().await }); + + { + let audio_producer = futures_lite::future::block_on(async { + let (_worker, _router, transport_1, _transport_2) = init().await; + transport_1 + .produce(audio_producer_options()) + .await + .expect("Failed to produce audio") + }); + + group.bench_function("create/audio", |b| { + b.iter(|| { + let _ = futures_lite::future::block_on(async { + transport_1 + .produce(audio_producer_options()) + .await + .expect("Failed to produce audio") + }); + }) + }); + + group.bench_function("dump/audio", |b| { + b.iter(|| { + let _ = futures_lite::future::block_on(async { audio_producer.dump().await }); + }) + }); + + group.bench_function("stats/audio", |b| { + b.iter(|| { + let _ = + futures_lite::future::block_on(async { audio_producer.get_stats().await }); + }) + }); + } + + { + let video_producer = futures_lite::future::block_on(async { + let (_worker, _router, transport_1, _transport_2) = init().await; + transport_1 + .produce(video_producer_options()) + .await + .expect("Failed to produce video") + }); + + group.bench_function("create/video", |b| { + b.iter(|| { + let _ = futures_lite::future::block_on(async { + transport_1 + .produce(video_producer_options()) + .await + .expect("Failed to produce video") + }); + }) + }); + + group.bench_function("dump/video", |b| { + b.iter(|| { + let _ = futures_lite::future::block_on(async { video_producer.dump().await }); + }) + }); + + group.bench_function("stats/video", |b| { + b.iter(|| { + let _ = + futures_lite::future::block_on(async { video_producer.get_stats().await }); + }) + }); + } + } + + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/rust/examples/echo.rs b/rust/examples/echo.rs index 0a0c688b9f..fd8027d83c 100644 --- a/rust/examples/echo.rs +++ b/rust/examples/echo.rs @@ -181,10 +181,15 @@ impl EchoConnection { // We know that for echo example we'll need 2 transports, so we can create both right away. // This may not be the case for real-world applications or you may create this at a // different time and/or in different order. - let transport_options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); let producer_transport = router .create_webrtc_transport(transport_options.clone()) .await diff --git a/rust/examples/multiopus.rs b/rust/examples/multiopus.rs index 67e784335d..341c9d8a0c 100644 --- a/rust/examples/multiopus.rs +++ b/rust/examples/multiopus.rs @@ -145,9 +145,13 @@ impl EchoConnection { // For simplicity we will create plain transport for audio producer right away let plain_transport = router .create_plain_transport({ - let mut options = PlainTransportOptions::new(ListenIp { + let mut options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); options.comedia = true; @@ -225,12 +229,16 @@ impl EchoConnection { // it right away. This may not be the case for real-world applications or you may create // this at a different time and/or in different order. let consumer_transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .map_err(|error| format!("Failed to create consumer transport: {error}"))?; diff --git a/rust/examples/svc-simulcast.rs b/rust/examples/svc-simulcast.rs index 465bddac88..3cfd318b9b 100644 --- a/rust/examples/svc-simulcast.rs +++ b/rust/examples/svc-simulcast.rs @@ -201,10 +201,15 @@ impl SvcSimulcastConnection { // right away. // This may not be the case for real-world applications or you may create this at a // different time and/or in different order. - let transport_options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); let producer_transport = router .create_webrtc_transport(transport_options.clone()) .await diff --git a/rust/examples/videoroom.rs b/rust/examples/videoroom.rs index 369ae4f0da..ef818d8be2 100644 --- a/rust/examples/videoroom.rs +++ b/rust/examples/videoroom.rs @@ -496,9 +496,13 @@ mod participant { // right away. This may not be the case for real-world applications or you may create // this at a different time and/or in different order. let transport_options = - WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, })); let producer_transport = room .router() diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index a27d5a5ec1..d1940de235 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -3,6 +3,7 @@ #[cfg(test)] mod tests; +use mediasoup_sys::fbs::{common, rtp_packet, sctp_association, transport, web_rtc_transport}; use serde::de::{MapAccess, Visitor}; use serde::ser::SerializeStruct; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -44,18 +45,45 @@ impl AppData { } } -/// IP to listen on. +/// Listening protocol, IP and port for [`WebRtcServer`] to listen on. /// /// # Notes on usage /// If you use "0.0.0.0" or "::" as ip value, then you need to also provide `announced_ip`. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct ListenIp { +pub struct ListenInfo { + /// Network protocol. + pub protocol: Protocol, /// Listening IPv4 or IPv6. pub ip: IpAddr, /// Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with private IP). #[serde(skip_serializing_if = "Option::is_none")] pub announced_ip: Option, + /// Listening port. + #[serde(skip_serializing_if = "Option::is_none")] + pub port: Option, + /// Send buffer size (bytes). + #[serde(skip_serializing_if = "Option::is_none")] + pub send_buffer_size: Option, + /// Recv buffer size (bytes). + #[serde(skip_serializing_if = "Option::is_none")] + pub recv_buffer_size: Option, +} + +impl ListenInfo { + pub(crate) fn to_fbs(self) -> transport::ListenInfo { + transport::ListenInfo { + protocol: match self.protocol { + Protocol::Tcp => transport::Protocol::Tcp, + Protocol::Udp => transport::Protocol::Udp, + }, + ip: self.ip.to_string(), + announced_ip: self.announced_ip.map(|ip| ip.to_string()), + port: self.port.unwrap_or(0), + send_buffer_size: self.send_buffer_size.unwrap_or(0), + recv_buffer_size: self.recv_buffer_size.unwrap_or(0), + } + } } /// ICE role. @@ -68,6 +96,15 @@ pub enum IceRole { Controlling, } +impl IceRole { + pub(crate) fn from_fbs(role: web_rtc_transport::IceRole) -> Self { + match role { + web_rtc_transport::IceRole::Controlled => IceRole::Controlled, + web_rtc_transport::IceRole::Controlling => IceRole::Controlling, + } + } +} + /// ICE parameters. #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -80,6 +117,16 @@ pub struct IceParameters { pub ice_lite: Option, } +impl IceParameters { + pub(crate) fn from_fbs(parameters: web_rtc_transport::IceParameters) -> Self { + Self { + username_fragment: parameters.username_fragment.to_string(), + password: parameters.password.to_string(), + ice_lite: Some(parameters.ice_lite), + } + } +} + /// ICE candidate type. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -100,6 +147,14 @@ pub enum IceCandidateType { Relay, } +impl IceCandidateType { + pub(crate) fn from_fbs(candidate_type: web_rtc_transport::IceCandidateType) -> Self { + match candidate_type { + web_rtc_transport::IceCandidateType::Host => IceCandidateType::Host, + } + } +} + /// ICE candidate TCP type (always `Passive`). #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -108,6 +163,14 @@ pub enum IceCandidateTcpType { Passive, } +impl IceCandidateTcpType { + pub(crate) fn from_fbs(candidate_type: web_rtc_transport::IceCandidateTcpType) -> Self { + match candidate_type { + web_rtc_transport::IceCandidateTcpType::Passive => IceCandidateTcpType::Passive, + } + } +} + /// Transport protocol. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -118,6 +181,15 @@ pub enum Protocol { Udp, } +impl Protocol { + pub(crate) fn from_fbs(protocol: transport::Protocol) -> Self { + match protocol { + transport::Protocol::Tcp => Protocol::Tcp, + transport::Protocol::Udp => Protocol::Udp, + } + } +} + /// ICE candidate #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -140,6 +212,20 @@ pub struct IceCandidate { pub tcp_type: Option, } +impl IceCandidate { + pub(crate) fn from_fbs(candidate: &web_rtc_transport::IceCandidate) -> Self { + Self { + foundation: candidate.foundation.clone(), + priority: candidate.priority, + ip: candidate.ip.parse().expect("Error parsing IP address"), + protocol: Protocol::from_fbs(candidate.protocol), + port: candidate.port, + r#type: IceCandidateType::from_fbs(candidate.type_), + tcp_type: candidate.tcp_type.map(IceCandidateTcpType::from_fbs), + } + } +} + /// ICE state. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -155,8 +241,17 @@ pub enum IceState { /// ICE was `Connected` or `Completed` but it has suddenly failed (this can just happen if the /// selected tuple has `Tcp` protocol). Disconnected, - /// ICE state when the transport has been closed. - Closed, +} + +impl IceState { + pub(crate) fn from_fbs(state: web_rtc_transport::IceState) -> Self { + match state { + web_rtc_transport::IceState::New => IceState::New, + web_rtc_transport::IceState::Connected => IceState::Connected, + web_rtc_transport::IceState::Completed => IceState::Completed, + web_rtc_transport::IceState::Disconnected => IceState::Disconnected, + } + } } /// Tuple of local IP/port/protocol + optional remote IP/port. @@ -232,6 +327,28 @@ impl TransportTuple { None } } + + pub(crate) fn from_fbs(tuple: &transport::Tuple) -> TransportTuple { + match &tuple.remote_ip { + Some(_remote_ip) => TransportTuple::WithRemote { + local_ip: tuple.local_ip.parse().expect("Error parsing IP address"), + local_port: tuple.local_port, + remote_ip: tuple + .remote_ip + .as_ref() + .unwrap() + .parse() + .expect("Error parsing IP address"), + remote_port: tuple.remote_port, + protocol: Protocol::from_fbs(tuple.protocol), + }, + None => TransportTuple::LocalOnly { + local_ip: tuple.local_ip.parse().expect("Error parsing IP address"), + local_port: tuple.local_port, + protocol: Protocol::from_fbs(tuple.protocol), + }, + } + } } /// DTLS state. @@ -250,6 +367,18 @@ pub enum DtlsState { Closed, } +impl DtlsState { + pub(crate) fn from_fbs(state: web_rtc_transport::DtlsState) -> Self { + match state { + web_rtc_transport::DtlsState::New => DtlsState::New, + web_rtc_transport::DtlsState::Connecting => DtlsState::Connecting, + web_rtc_transport::DtlsState::Connected => DtlsState::Connected, + web_rtc_transport::DtlsState::Failed => DtlsState::Failed, + web_rtc_transport::DtlsState::Closed => DtlsState::Closed, + } + } +} + /// SCTP state. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -266,6 +395,18 @@ pub enum SctpState { Closed, } +impl SctpState { + pub(crate) fn from_fbs(state: &sctp_association::SctpState) -> Self { + match state { + sctp_association::SctpState::New => Self::New, + sctp_association::SctpState::Connecting => Self::Connecting, + sctp_association::SctpState::Connected => Self::Connected, + sctp_association::SctpState::Failed => Self::Failed, + sctp_association::SctpState::Closed => Self::Closed, + } + } +} + /// DTLS role. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -280,6 +421,24 @@ pub enum DtlsRole { Server, } +impl DtlsRole { + pub(crate) fn to_fbs(self) -> web_rtc_transport::DtlsRole { + match self { + DtlsRole::Auto => web_rtc_transport::DtlsRole::Auto, + DtlsRole::Client => web_rtc_transport::DtlsRole::Client, + DtlsRole::Server => web_rtc_transport::DtlsRole::Server, + } + } + + pub(crate) fn from_fbs(role: web_rtc_transport::DtlsRole) -> Self { + match role { + web_rtc_transport::DtlsRole::Auto => DtlsRole::Auto, + web_rtc_transport::DtlsRole::Client => DtlsRole::Client, + web_rtc_transport::DtlsRole::Server => DtlsRole::Server, + } + } +} + impl Default for DtlsRole { fn default() -> Self { Self::Auto @@ -318,6 +477,91 @@ pub enum DtlsFingerprint { }, } +fn hex_as_bytes(input: &str, output: &mut [u8]) { + for (i, o) in input.split(':').zip(&mut output.iter_mut()) { + *o = u8::from_str_radix(i, 16).unwrap_or_else(|error| { + panic!("Failed to parse value {i} as series of hex bytes: {error}") + }); + } +} + +impl DtlsFingerprint { + pub(crate) fn to_fbs(self) -> web_rtc_transport::Fingerprint { + match self { + DtlsFingerprint::Sha1 { .. } => web_rtc_transport::Fingerprint { + algorithm: web_rtc_transport::FingerprintAlgorithm::Sha1, + value: self.value_string(), + }, + DtlsFingerprint::Sha224 { .. } => web_rtc_transport::Fingerprint { + algorithm: web_rtc_transport::FingerprintAlgorithm::Sha224, + value: self.value_string(), + }, + DtlsFingerprint::Sha256 { .. } => web_rtc_transport::Fingerprint { + algorithm: web_rtc_transport::FingerprintAlgorithm::Sha256, + value: self.value_string(), + }, + DtlsFingerprint::Sha384 { .. } => web_rtc_transport::Fingerprint { + algorithm: web_rtc_transport::FingerprintAlgorithm::Sha384, + value: self.value_string(), + }, + DtlsFingerprint::Sha512 { .. } => web_rtc_transport::Fingerprint { + algorithm: web_rtc_transport::FingerprintAlgorithm::Sha512, + value: self.value_string(), + }, + } + } + + pub(crate) fn from_fbs(fingerprint: &web_rtc_transport::Fingerprint) -> DtlsFingerprint { + match fingerprint.algorithm { + web_rtc_transport::FingerprintAlgorithm::Sha1 => { + let mut value_result = [0_u8; 20]; + + hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + + DtlsFingerprint::Sha1 { + value: value_result, + } + } + web_rtc_transport::FingerprintAlgorithm::Sha224 => { + let mut value_result = [0_u8; 28]; + + hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + + DtlsFingerprint::Sha224 { + value: value_result, + } + } + web_rtc_transport::FingerprintAlgorithm::Sha256 => { + let mut value_result = [0_u8; 32]; + + hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + + DtlsFingerprint::Sha256 { + value: value_result, + } + } + web_rtc_transport::FingerprintAlgorithm::Sha384 => { + let mut value_result = [0_u8; 48]; + + hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + + DtlsFingerprint::Sha384 { + value: value_result, + } + } + web_rtc_transport::FingerprintAlgorithm::Sha512 => { + let mut value_result = [0_u8; 64]; + + hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + + DtlsFingerprint::Sha512 { + value: value_result, + } + } + } + } +} + impl fmt::Debug for DtlsFingerprint { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let name = match self { @@ -755,6 +999,30 @@ pub struct DtlsParameters { pub fingerprints: Vec, } +impl DtlsParameters { + pub(crate) fn to_fbs(&self) -> web_rtc_transport::DtlsParameters { + web_rtc_transport::DtlsParameters { + role: self.role.to_fbs(), + fingerprints: self + .fingerprints + .iter() + .map(|fingerprint| fingerprint.to_fbs()) + .collect(), + } + } + + pub(crate) fn from_fbs(parameters: web_rtc_transport::DtlsParameters) -> DtlsParameters { + DtlsParameters { + role: DtlsRole::from_fbs(parameters.role), + fingerprints: parameters + .fingerprints + .iter() + .map(DtlsFingerprint::from_fbs) + .collect(), + } + } +} + /// Trace event direction #[derive(Debug, Copy, Clone, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -765,6 +1033,15 @@ pub enum TraceEventDirection { Out, } +impl TraceEventDirection { + pub(crate) fn from_fbs(event_type: common::TraceDirection) -> Self { + match event_type { + common::TraceDirection::DirectionIn => TraceEventDirection::In, + common::TraceDirection::DirectionOut => TraceEventDirection::Out, + } + } +} + /// Container used for sending/receiving messages using `DirectTransport` data producers and data /// consumers. #[derive(Debug, Clone)] @@ -854,9 +1131,9 @@ pub struct RtpPacketTraceInfo { /// Whether packet contains a key frame. pub is_key_frame: bool, /// Packet size. - pub size: usize, + pub size: u64, /// Payload size. - pub payload_size: usize, + pub payload_size: u64, /// The spatial layer index (from 0 to N). pub spatial_layer: u8, /// The temporal layer index (from 0 to N). @@ -874,11 +1151,33 @@ pub struct RtpPacketTraceInfo { pub is_rtx: bool, } +impl RtpPacketTraceInfo { + pub(crate) fn from_fbs(rtp_packet: rtp_packet::Dump, is_rtx: bool) -> Self { + Self { + payload_type: rtp_packet.payload_type, + sequence_number: rtp_packet.sequence_number, + timestamp: rtp_packet.timestamp, + marker: rtp_packet.marker, + ssrc: rtp_packet.ssrc, + is_key_frame: rtp_packet.is_key_frame, + size: rtp_packet.size, + payload_size: rtp_packet.payload_size, + spatial_layer: rtp_packet.spatial_layer, + temporal_layer: rtp_packet.temporal_layer, + mid: rtp_packet.mid, + rid: rtp_packet.rid, + rrid: rtp_packet.rrid, + wide_sequence_number: rtp_packet.wide_sequence_number, + is_rtx, + } + } +} + /// SSRC info in trace event. #[derive(Debug, Copy, Clone, Deserialize, Serialize)] pub struct SsrcTraceInfo { /// RTP stream SSRC. - ssrc: u32, + pub ssrc: u32, } /// Bandwidth estimation type. @@ -892,6 +1191,15 @@ pub enum BweType { Remb, } +impl BweType { + pub(crate) fn from_fbs(info: transport::BweType) -> Self { + match info { + transport::BweType::TransportCc => BweType::TransportCc, + transport::BweType::Remb => BweType::Remb, + } + } +} + /// BWE info in trace event. #[derive(Debug, Copy, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -913,3 +1221,18 @@ pub struct BweTraceInfo { /// Available bitrate. available_bitrate: u32, } + +impl BweTraceInfo { + pub(crate) fn from_fbs(info: transport::BweTraceInfo) -> Self { + Self { + r#type: BweType::from_fbs(info.bwe_type), + desired_bitrate: info.desired_bitrate, + effective_desired_bitrate: info.effective_desired_bitrate, + min_bitrate: info.min_bitrate, + max_bitrate: info.max_bitrate, + start_bitrate: info.start_bitrate, + max_padding_bitrate: info.max_padding_bitrate, + available_bitrate: info.available_bitrate, + } + } +} diff --git a/rust/src/macros.rs b/rust/src/macros.rs index 5fd5d4d128..f331a0ba00 100644 --- a/rust/src/macros.rs +++ b/rust/src/macros.rs @@ -18,7 +18,7 @@ macro_rules! uuid_based_wrapper_type { Eq, PartialEq, )] - pub struct $struct_name(uuid::Uuid); + pub struct $struct_name(::uuid::Uuid); impl std::fmt::Display for $struct_name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -26,7 +26,15 @@ macro_rules! uuid_based_wrapper_type { } } - impl From<$struct_name> for uuid::Uuid { + impl ::std::str::FromStr for $struct_name { + type Err = ::uuid::Error; + + fn from_str(s: &str) -> Result { + ::uuid::Uuid::from_str(s).map(Self) + } + } + + impl From<$struct_name> for ::uuid::Uuid { fn from(id: $struct_name) -> Self { id.0 } @@ -34,7 +42,7 @@ macro_rules! uuid_based_wrapper_type { impl $struct_name { pub(super) fn new() -> Self { - $struct_name(uuid::Uuid::new_v4()) + $struct_name(::uuid::Uuid::new_v4()) } } diff --git a/rust/src/messages.rs b/rust/src/messages.rs index 865954b592..1d38d9d9f8 100644 --- a/rust/src/messages.rs +++ b/rust/src/messages.rs @@ -1,226 +1,554 @@ use crate::active_speaker_observer::ActiveSpeakerObserverOptions; use crate::audio_level_observer::AudioLevelObserverOptions; use crate::consumer::{ - ConsumerDump, ConsumerId, ConsumerLayers, ConsumerScore, ConsumerStats, ConsumerTraceEventType, - ConsumerType, + ConsumerId, ConsumerLayers, ConsumerScore, ConsumerTraceEventType, ConsumerType, }; -use crate::data_consumer::{DataConsumerDump, DataConsumerId, DataConsumerStat, DataConsumerType}; -use crate::data_producer::{DataProducerDump, DataProducerId, DataProducerStat, DataProducerType}; +use crate::data_consumer::{DataConsumerId, DataConsumerType}; +use crate::data_producer::{DataProducerId, DataProducerType}; use crate::data_structures::{ - DtlsParameters, DtlsRole, DtlsState, IceCandidate, IceParameters, IceRole, IceState, ListenIp, - SctpState, TransportTuple, + DtlsParameters, DtlsRole, DtlsState, IceCandidate, IceParameters, IceRole, IceState, + ListenInfo, SctpState, TransportTuple, }; use crate::direct_transport::DirectTransportOptions; use crate::ortc::RtpMapping; use crate::pipe_transport::PipeTransportOptions; use crate::plain_transport::PlainTransportOptions; -use crate::producer::{ - ProducerDump, ProducerId, ProducerStat, ProducerTraceEventType, ProducerType, -}; +use crate::producer::{ProducerId, ProducerTraceEventType, ProducerType}; +use crate::router::consumer::ConsumerDump; +use crate::router::producer::ProducerDump; use crate::router::{RouterDump, RouterId}; use crate::rtp_observer::RtpObserverId; use crate::rtp_parameters::{MediaKind, RtpEncodingParameters, RtpParameters}; use crate::sctp_parameters::{NumSctpStreams, SctpParameters, SctpStreamParameters}; use crate::srtp_parameters::{SrtpCryptoSuite, SrtpParameters}; use crate::transport::{TransportId, TransportTraceEventType}; -use crate::webrtc_server::{WebRtcServerDump, WebRtcServerId, WebRtcServerListenInfos}; -use crate::webrtc_transport::{TransportListenIps, WebRtcTransportListen, WebRtcTransportOptions}; -use crate::worker::{WorkerDump, WorkerUpdateSettings}; +use crate::webrtc_server::{ + WebRtcServerDump, WebRtcServerIceUsernameFragment, WebRtcServerId, WebRtcServerIpPort, + WebRtcServerListenInfos, WebRtcServerTupleHash, +}; +use crate::webrtc_transport::{ + WebRtcTransportListen, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; +use crate::worker::{ChannelMessageHandlers, WorkerDump, WorkerUpdateSettings}; +use mediasoup_sys::fbs::{ + active_speaker_observer, audio_level_observer, consumer, data_consumer, data_producer, + direct_transport, message, notification, pipe_transport, plain_transport, producer, request, + response, router, rtp_observer, transport, web_rtc_server, web_rtc_transport, worker, +}; use parking_lot::Mutex; -use serde::de::DeserializeOwned; +use planus::Builder; use serde::{Deserialize, Serialize}; -use serde_json::Value; +use std::error::Error; use std::fmt::{Debug, Display}; use std::net::IpAddr; use std::num::NonZeroU16; pub(crate) trait Request where - Self: Debug + Serialize, + Self: Debug, { + /// Request method to call on worker. + const METHOD: request::Method; type HandlerId: Display; - type Response: DeserializeOwned; + type Response; - /// Request method to call on worker. - fn as_method(&self) -> &'static str; + /// Get a serialized message out of this request. + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec; /// Default response to return in case of soft error, such as channel already closed, entity /// doesn't exist on worker during closing. fn default_for_soft_error() -> Option { None } + + /// Convert generic response into specific type of this request. + fn convert_response( + response: Option>, + ) -> Result>; } -pub(crate) trait Notification: Debug + Serialize { +pub(crate) trait Notification: Debug { + /// Notification event to call on worker. + const EVENT: notification::Event; type HandlerId: Display; - /// Request event to call on worker. - fn as_event(&self) -> &'static str; -} - -macro_rules! request_response { - ( - $handler_id_type: ty, - $method: literal, - $request_struct_name: ident { $( $(#[$request_field_name_attributes: meta])? $request_field_name: ident: $request_field_type: ty$(,)? )* }, - $existing_response_type: ty, - $default_for_soft_error: expr $(,)? - ) => { - #[derive(Debug, Serialize)] - #[serde(rename_all = "camelCase")] - pub(crate) struct $request_struct_name { - $( - $(#[$request_field_name_attributes])* - pub(crate) $request_field_name: $request_field_type, - )* - } + /// Get a serialized message out of this notification. + fn into_bytes(self, handler_id: Self::HandlerId) -> Vec; +} - impl Request for $request_struct_name { - type HandlerId = $handler_id_type; - type Response = $existing_response_type; +#[derive(Debug)] +pub(crate) struct WorkerCloseRequest {} - fn as_method(&self) -> &'static str { - $method - } +impl Request for WorkerCloseRequest { + const METHOD: request::Method = request::Method::WorkerClose; + type HandlerId = &'static str; + type Response = (); - fn default_for_soft_error() -> Option { - $default_for_soft_error - } - } - }; - // Call above macro with no default for soft error - ( - $handler_id_type: ty, - $method: literal, - $request_struct_name: ident $request_struct_impl: tt $(,)? - $existing_response_type: ty $(,)? - ) => { - request_response!( - $handler_id_type, - $method, - $request_struct_name $request_struct_impl, - $existing_response_type, - None, - ); - }; - // Call above macro with unit type as expected response - ( - $handler_id_type: ty, - $method: literal, - $request_struct_name: ident $request_struct_impl: tt $(,)? - ) => { - request_response!( - $handler_id_type, - $method, - $request_struct_name $request_struct_impl, - (), - None, - ); - }; - ( - $handler_id_type: ty, - $method: literal, - $request_struct_name: ident { $( $(#[$request_field_name_attributes: meta])? $request_field_name: ident: $request_field_type: ty$(,)? )* }, - $response_struct_name: ident { $( $response_field_name: ident: $response_field_type: ty$(,)? )* }, - ) => { - #[derive(Debug, Serialize)] - #[serde(rename_all = "camelCase")] - pub(crate) struct $request_struct_name { - $( - $(#[$request_field_name_attributes])* - pub(crate) $request_field_name: $request_field_type, - )* - } + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); - #[derive(Debug, Deserialize)] - #[serde(rename_all = "camelCase")] - pub(crate) struct $response_struct_name { - $( pub(crate) $response_field_name: $response_field_type, )* - } + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); - impl Request for $request_struct_name { - type HandlerId = $handler_id_type; - type Response = $response_struct_name; + builder.finish(message, None).to_vec() + } - fn as_method(&self) -> &'static str { - $method - } - } - }; + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } } -request_response!(&'static str, "worker.close", WorkerCloseRequest {}); +#[derive(Debug)] +pub(crate) struct WorkerDumpRequest {} -request_response!( - &'static str, - "worker.dump", - WorkerDumpRequest {}, - WorkerDump -); +impl Request for WorkerDumpRequest { + const METHOD: request::Method = request::Method::WorkerDump; + type HandlerId = &'static str; + type Response = WorkerDump; -request_response!( - &'static str, - "worker.updateSettings", - WorkerUpdateSettingsRequest { - #[serde(flatten)] - data: WorkerUpdateSettings, - }, -); + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); -request_response!( - &'static str, - "worker.createWebRtcServer", - WorkerCreateWebRtcServerRequest { - #[serde(rename = "webRtcServerId")] - webrtc_server_id: WebRtcServerId, - listen_infos: WebRtcServerListenInfos, - }, -); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); -request_response!( - &'static str, - "worker.closeWebRtcServer", - WebRtcServerCloseRequest { - #[serde(rename = "webRtcServerId")] - webrtc_server_id: WebRtcServerId, - }, - (), - Some(()), -); - -request_response!( - WebRtcServerId, - "webRtcServer.dump", - WebRtcServerDumpRequest {}, - WebRtcServerDump, -); - -request_response!( - &'static str, - "worker.createRouter", - WorkerCreateRouterRequest { - router_id: RouterId, - }, -); + builder.finish(message, None).to_vec() + } -request_response!( - &'static str, - "worker.closeRouter", - RouterCloseRequest { - router_id: RouterId, - }, - (), - Some(()), -); + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::WorkerDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = worker::DumpResponse::try_from(data)?; + + Ok(WorkerDump { + router_ids: data + .router_ids + .into_iter() + .map(|id| id.parse()) + .collect::>()?, + webrtc_server_ids: data + .web_rtc_server_ids + .into_iter() + .map(|id| id.parse()) + .collect::>()?, + channel_message_handlers: ChannelMessageHandlers { + channel_request_handlers: data + .channel_message_handlers + .channel_request_handlers + .into_iter() + .map(|id| id.parse()) + .collect::>()?, + channel_notification_handlers: data + .channel_message_handlers + .channel_notification_handlers + .into_iter() + .map(|id| id.parse()) + .collect::>()?, + }, + }) + } +} + +#[derive(Debug)] +pub(crate) struct WorkerUpdateSettingsRequest { + pub(crate) data: WorkerUpdateSettings, +} + +impl Request for WorkerUpdateSettingsRequest { + const METHOD: request::Method = request::Method::WorkerUpdateSettings; + type HandlerId = &'static str; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = worker::UpdateSettingsRequest::create( + &mut builder, + self.data + .log_level + .as_ref() + .map(|log_level| log_level.as_str()), + self.data.log_tags.as_ref().map(|log_tags| { + log_tags + .iter() + .map(|log_tag| log_tag.as_str()) + .collect::>() + }), + ); + let request_body = request::Body::create_worker_update_settings_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct WorkerCreateWebRtcServerRequest { + pub(crate) webrtc_server_id: WebRtcServerId, + pub(crate) listen_infos: WebRtcServerListenInfos, +} + +impl Request for WorkerCreateWebRtcServerRequest { + const METHOD: request::Method = request::Method::WorkerCreateWebrtcserver; + type HandlerId = &'static str; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = worker::CreateWebRtcServerRequest::create( + &mut builder, + self.webrtc_server_id.to_string(), + self.listen_infos.to_fbs(), + ); + let request_body = + request::Body::create_worker_create_web_rtc_server_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct WebRtcServerCloseRequest { + pub(crate) webrtc_server_id: WebRtcServerId, +} + +impl Request for WebRtcServerCloseRequest { + const METHOD: request::Method = request::Method::WorkerWebrtcserverClose; + type HandlerId = &'static str; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = worker::CloseWebRtcServerRequest::create( + &mut builder, + self.webrtc_server_id.to_string(), + ); + let request_body = + request::Body::create_worker_close_web_rtc_server_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct WebRtcServerDumpRequest {} + +impl Request for WebRtcServerDumpRequest { + const METHOD: request::Method = request::Method::WebrtcserverDump; + type HandlerId = WebRtcServerId; + type Response = WebRtcServerDump; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::WebRtcServerDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = web_rtc_server::DumpResponse::try_from(data)?; + + Ok(WebRtcServerDump { + id: data.id.parse()?, + udp_sockets: data + .udp_sockets + .into_iter() + .map(|ip_port| WebRtcServerIpPort { + ip: ip_port.ip.parse().unwrap(), + port: ip_port.port, + }) + .collect(), + tcp_servers: data + .tcp_servers + .into_iter() + .map(|ip_port| WebRtcServerIpPort { + ip: ip_port.ip.parse().unwrap(), + port: ip_port.port, + }) + .collect(), + webrtc_transport_ids: data + .web_rtc_transport_ids + .into_iter() + .map(|id| id.parse()) + .collect::>()?, + local_ice_username_fragments: data + .local_ice_username_fragments + .into_iter() + .map(|username_fragment| WebRtcServerIceUsernameFragment { + local_ice_username_fragment: username_fragment + .local_ice_username_fragment + .parse() + .unwrap(), + webrtc_transport_id: username_fragment.web_rtc_transport_id.parse().unwrap(), + }) + .collect(), + tuple_hashes: data + .tuple_hashes + .into_iter() + .map(|tuple_hash| WebRtcServerTupleHash { + tuple_hash: tuple_hash.tuple_hash, + webrtc_transport_id: tuple_hash.web_rtc_transport_id.parse().unwrap(), + }) + .collect(), + }) + } +} + +#[derive(Debug)] +pub(crate) struct WorkerCreateRouterRequest { + pub(crate) router_id: RouterId, +} + +impl Request for WorkerCreateRouterRequest { + const METHOD: request::Method = request::Method::WorkerCreateRouter; + type HandlerId = &'static str; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = worker::CreateRouterRequest::create(&mut builder, self.router_id.to_string()); + let request_body = request::Body::create_worker_create_router_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct RouterCloseRequest { + pub(crate) router_id: RouterId, +} + +impl Request for RouterCloseRequest { + const METHOD: request::Method = request::Method::WorkerCloseRouter; + type HandlerId = &'static str; + type Response = (); -request_response!(RouterId, "router.dump", RouterDumpRequest {}, RouterDump); + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = worker::CloseRouterRequest::create(&mut builder, self.router_id.to_string()); + let request_body = request::Body::create_worker_close_router_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct RouterDumpRequest {} + +impl Request for RouterDumpRequest { + const METHOD: request::Method = request::Method::RouterDump; + type HandlerId = RouterId; + type Response = RouterDump; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::RouterDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = router::DumpResponse::try_from(data)?; + + Ok(RouterDump { + id: data.id.parse()?, + map_consumer_id_producer_id: data + .map_consumer_id_producer_id + .into_iter() + .map(|key_value| Ok((key_value.key.parse()?, key_value.value.parse()?))) + .collect::>>()?, + map_data_consumer_id_data_producer_id: data + .map_data_consumer_id_data_producer_id + .into_iter() + .map(|key_value| Ok((key_value.key.parse()?, key_value.value.parse()?))) + .collect::>>()?, + map_data_producer_id_data_consumer_ids: data + .map_data_producer_id_data_consumer_ids + .into_iter() + .map(|key_values| { + Ok(( + key_values.key.parse()?, + key_values + .values + .into_iter() + .map(|value| value.parse()) + .collect::>()?, + )) + }) + .collect::>>()?, + map_producer_id_consumer_ids: data + .map_producer_id_consumer_ids + .into_iter() + .map(|key_values| { + Ok(( + key_values.key.parse()?, + key_values + .values + .into_iter() + .map(|value| value.parse()) + .collect::>()?, + )) + }) + .collect::>>()?, + map_producer_id_observer_ids: data + .map_producer_id_observer_ids + .into_iter() + .map(|key_values| { + Ok(( + key_values.key.parse()?, + key_values + .values + .into_iter() + .map(|value| value.parse()) + .collect::>()?, + )) + }) + .collect::>>()?, + rtp_observer_ids: data + .rtp_observer_ids + .into_iter() + .map(|id| id.parse()) + .collect::>()?, + transport_ids: data + .transport_ids + .into_iter() + .map(|id| id.parse()) + .collect::>()?, + }) + } +} #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub(crate) struct RouterCreateDirectTransportData { transport_id: TransportId, direct: bool, - max_message_size: usize, + max_message_size: u32, } impl RouterCreateDirectTransportData { @@ -234,26 +562,68 @@ impl RouterCreateDirectTransportData { max_message_size: direct_transport_options.max_message_size, } } + + pub(crate) fn to_fbs(&self) -> direct_transport::DirectTransportOptions { + direct_transport::DirectTransportOptions { + base: Box::new(transport::Options { + direct: true, + max_message_size: Some(self.max_message_size), + initial_available_outgoing_bitrate: None, + enable_sctp: false, + num_sctp_streams: None, + max_sctp_message_size: 0, + sctp_send_buffer_size: 0, + is_data_channel: false, + }), + } + } } -request_response!( - RouterId, - "router.createDirectTransport", - RouterCreateDirectTransportRequest { - #[serde(flatten)] - data: RouterCreateDirectTransportData, - }, - RouterCreateDirectTransportResponse {}, -); +#[derive(Debug)] +pub(crate) struct RouterCreateDirectTransportRequest { + pub(crate) data: RouterCreateDirectTransportData, +} + +impl Request for RouterCreateDirectTransportRequest { + const METHOD: request::Method = request::Method::RouterCreateDirecttransport; + type HandlerId = RouterId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = router::CreateDirectTransportRequest::create( + &mut builder, + self.data.transport_id.to_string(), + self.data.to_fbs(), + ); + let request_body = + request::Body::create_router_create_direct_transport_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} #[derive(Debug, Serialize)] #[serde(untagged)] enum RouterCreateWebrtcTransportListen { #[serde(rename_all = "camelCase")] Individual { - listen_ips: TransportListenIps, - #[serde(skip_serializing_if = "Option::is_none")] - port: Option, + listen_infos: WebRtcTransportListenInfos, }, Server { #[serde(rename = "webRtcServerId")] @@ -261,17 +631,39 @@ enum RouterCreateWebrtcTransportListen { }, } +impl RouterCreateWebrtcTransportListen { + pub(crate) fn to_fbs(&self) -> web_rtc_transport::Listen { + match self { + RouterCreateWebrtcTransportListen::Individual { listen_infos } => { + web_rtc_transport::Listen::ListenIndividual(Box::new( + web_rtc_transport::ListenIndividual { + listen_infos: listen_infos + .iter() + .map(|listen_info| listen_info.to_fbs()) + .collect(), + }, + )) + } + RouterCreateWebrtcTransportListen::Server { webrtc_server_id } => { + web_rtc_transport::Listen::ListenServer(Box::new(web_rtc_transport::ListenServer { + web_rtc_server_id: webrtc_server_id.to_string(), + })) + } + } + } +} + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] -pub(crate) struct RouterCreateWebrtcTransportRequest { +pub(crate) struct RouterCreateWebrtcTransportData { transport_id: TransportId, #[serde(flatten)] listen: RouterCreateWebrtcTransportListen, + initial_available_outgoing_bitrate: u32, enable_udp: bool, enable_tcp: bool, prefer_udp: bool, prefer_tcp: bool, - initial_available_outgoing_bitrate: u32, enable_sctp: bool, num_sctp_streams: NumSctpStreams, max_sctp_message_size: u32, @@ -279,7 +671,7 @@ pub(crate) struct RouterCreateWebrtcTransportRequest { is_data_channel: bool, } -impl RouterCreateWebrtcTransportRequest { +impl RouterCreateWebrtcTransportData { pub(crate) fn from_options( transport_id: TransportId, webrtc_transport_options: &WebRtcTransportOptions, @@ -287,10 +679,9 @@ impl RouterCreateWebrtcTransportRequest { Self { transport_id, listen: match &webrtc_transport_options.listen { - WebRtcTransportListen::Individual { listen_ips, port } => { + WebRtcTransportListen::Individual { listen_infos } => { RouterCreateWebrtcTransportListen::Individual { - listen_ips: listen_ips.clone(), - port: *port, + listen_infos: listen_infos.clone(), } } WebRtcTransportListen::Server { webrtc_server } => { @@ -299,12 +690,12 @@ impl RouterCreateWebrtcTransportRequest { } } }, + initial_available_outgoing_bitrate: webrtc_transport_options + .initial_available_outgoing_bitrate, enable_udp: webrtc_transport_options.enable_udp, enable_tcp: webrtc_transport_options.enable_tcp, prefer_udp: webrtc_transport_options.prefer_udp, prefer_tcp: webrtc_transport_options.prefer_tcp, - initial_available_outgoing_bitrate: webrtc_transport_options - .initial_available_outgoing_bitrate, enable_sctp: webrtc_transport_options.enable_sctp, num_sctp_streams: webrtc_transport_options.num_sctp_streams, max_sctp_message_size: webrtc_transport_options.max_sctp_message_size, @@ -312,6 +703,26 @@ impl RouterCreateWebrtcTransportRequest { is_data_channel: true, } } + + pub(crate) fn to_fbs(&self) -> web_rtc_transport::WebRtcTransportOptions { + web_rtc_transport::WebRtcTransportOptions { + base: Box::new(transport::Options { + direct: false, + max_message_size: None, + initial_available_outgoing_bitrate: Some(self.initial_available_outgoing_bitrate), + enable_sctp: self.enable_sctp, + num_sctp_streams: Some(Box::new(self.num_sctp_streams.to_fbs())), + max_sctp_message_size: self.max_sctp_message_size, + sctp_send_buffer_size: self.sctp_send_buffer_size, + is_data_channel: true, + }), + listen: self.listen.to_fbs(), + enable_udp: self.enable_udp, + enable_tcp: self.enable_tcp, + prefer_udp: self.prefer_udp, + prefer_tcp: self.prefer_tcp, + } + } } #[derive(Debug, Deserialize)] @@ -329,17 +740,155 @@ pub(crate) struct WebRtcTransportData { pub(crate) sctp_state: Mutex>, } -impl Request for RouterCreateWebrtcTransportRequest { +#[derive(Debug)] +pub(crate) struct RouterCreateWebRtcTransportRequest { + pub(crate) data: RouterCreateWebrtcTransportData, +} + +impl Request for RouterCreateWebRtcTransportRequest { + const METHOD: request::Method = request::Method::RouterCreateWebrtctransport; type HandlerId = RouterId; type Response = WebRtcTransportData; - fn as_method(&self) -> &'static str { - match &self.listen { - RouterCreateWebrtcTransportListen::Individual { .. } => "router.createWebRtcTransport", - RouterCreateWebrtcTransportListen::Server { .. } => { - "router.createWebRtcTransportWithServer" - } - } + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let RouterCreateWebrtcTransportListen::Individual { listen_infos: _ } = self.data.listen + else { + panic!("RouterCreateWebrtcTransportListen variant must be Individual"); + }; + + let mut builder = Builder::new(); + let data = router::CreateWebRtcTransportRequest::create( + &mut builder, + self.data.transport_id.to_string(), + self.data.to_fbs(), + ); + let request_body = + request::Body::create_router_create_web_rtc_transport_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::WebRtcTransportDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = web_rtc_transport::DumpResponse::try_from(data)?; + + Ok(WebRtcTransportData { + ice_role: IceRole::from_fbs(data.ice_role), + ice_parameters: IceParameters::from_fbs(*data.ice_parameters), + ice_candidates: data + .ice_candidates + .iter() + .map(IceCandidate::from_fbs) + .collect(), + ice_state: Mutex::new(IceState::from_fbs(data.ice_state)), + ice_selected_tuple: Mutex::new( + data.ice_selected_tuple + .map(|tuple| TransportTuple::from_fbs(tuple.as_ref())), + ), + dtls_parameters: Mutex::new(DtlsParameters::from_fbs(*data.dtls_parameters)), + dtls_state: Mutex::new(DtlsState::from_fbs(data.dtls_state)), + dtls_remote_cert: Mutex::new(None), + sctp_parameters: data + .base + .sctp_parameters + .map(|parameters| SctpParameters::from_fbs(parameters.as_ref())), + sctp_state: Mutex::new( + data.base + .sctp_state + .map(|state| SctpState::from_fbs(&state)), + ), + }) + } +} + +#[derive(Debug)] +pub(crate) struct RouterCreateWebRtcTransportWithServerRequest { + pub(crate) data: RouterCreateWebrtcTransportData, +} + +impl Request for RouterCreateWebRtcTransportWithServerRequest { + const METHOD: request::Method = request::Method::RouterCreateWebrtctransportWithServer; + type HandlerId = RouterId; + type Response = WebRtcTransportData; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let RouterCreateWebrtcTransportListen::Server { + webrtc_server_id: _, + } = self.data.listen + else { + panic!("RouterCreateWebrtcTransportListen variant must be Server"); + }; + + let mut builder = Builder::new(); + let data = router::CreateWebRtcTransportRequest::create( + &mut builder, + self.data.transport_id.to_string(), + self.data.to_fbs(), + ); + let request_body = + request::Body::create_router_create_web_rtc_transport_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::WebRtcTransportDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = web_rtc_transport::DumpResponse::try_from(data)?; + + Ok(WebRtcTransportData { + ice_role: IceRole::from_fbs(data.ice_role), + ice_parameters: IceParameters::from_fbs(*data.ice_parameters), + ice_candidates: data + .ice_candidates + .iter() + .map(IceCandidate::from_fbs) + .collect(), + ice_state: Mutex::new(IceState::from_fbs(data.ice_state)), + ice_selected_tuple: Mutex::new( + data.ice_selected_tuple + .map(|tuple| TransportTuple::from_fbs(tuple.as_ref())), + ), + dtls_parameters: Mutex::new(DtlsParameters::from_fbs(*data.dtls_parameters)), + dtls_state: Mutex::new(DtlsState::from_fbs(data.dtls_state)), + dtls_remote_cert: Mutex::new(None), + sctp_parameters: data + .base + .sctp_parameters + .map(|parameters| SctpParameters::from_fbs(parameters.as_ref())), + sctp_state: Mutex::new( + data.base + .sctp_state + .map(|state| SctpState::from_fbs(&state)), + ), + }) } } @@ -347,9 +896,8 @@ impl Request for RouterCreateWebrtcTransportRequest { #[serde(rename_all = "camelCase")] pub(crate) struct RouterCreatePlainTransportData { transport_id: TransportId, - listen_ip: ListenIp, - #[serde(skip_serializing_if = "Option::is_none")] - port: Option, + listen_info: ListenInfo, + rtcp_listen_info: Option, rtcp_mux: bool, comedia: bool, enable_sctp: bool, @@ -368,8 +916,8 @@ impl RouterCreatePlainTransportData { ) -> Self { Self { transport_id, - listen_ip: plain_transport_options.listen_ip, - port: plain_transport_options.port, + listen_info: plain_transport_options.listen_info, + rtcp_listen_info: plain_transport_options.rtcp_listen_info, rtcp_mux: plain_transport_options.rtcp_mux, comedia: plain_transport_options.comedia, enable_sctp: plain_transport_options.enable_sctp, @@ -381,34 +929,111 @@ impl RouterCreatePlainTransportData { is_data_channel: false, } } + + pub(crate) fn to_fbs(&self) -> plain_transport::PlainTransportOptions { + plain_transport::PlainTransportOptions { + base: Box::new(transport::Options { + direct: false, + max_message_size: None, + initial_available_outgoing_bitrate: None, + enable_sctp: self.enable_sctp, + num_sctp_streams: Some(Box::new(self.num_sctp_streams.to_fbs())), + max_sctp_message_size: self.max_sctp_message_size, + sctp_send_buffer_size: self.sctp_send_buffer_size, + is_data_channel: self.is_data_channel, + }), + listen_info: Box::new(self.listen_info.to_fbs()), + rtcp_listen_info: self + .rtcp_listen_info + .map(|listen_info| Box::new(listen_info.to_fbs())), + rtcp_mux: self.rtcp_mux, + comedia: self.comedia, + enable_srtp: self.enable_srtp, + srtp_crypto_suite: Some(SrtpCryptoSuite::to_fbs(self.srtp_crypto_suite)), + } + } } -request_response!( - RouterId, - "router.createPlainTransport", - RouterCreatePlainTransportRequest { - #[serde(flatten)] - data: RouterCreatePlainTransportData, - }, - PlainTransportData { - // The following fields are present, but unused - // rtcp_mux: bool, - // comedia: bool, - tuple: Mutex, - rtcp_tuple: Mutex>, - sctp_parameters: Option, - sctp_state: Mutex>, - srtp_parameters: Mutex>, - }, -); +#[derive(Debug)] +pub(crate) struct RouterCreatePlainTransportRequest { + pub(crate) data: RouterCreatePlainTransportData, +} + +impl Request for RouterCreatePlainTransportRequest { + const METHOD: request::Method = request::Method::RouterCreatePlaintransport; + type HandlerId = RouterId; + type Response = PlainTransportData; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = router::CreatePlainTransportRequest::create( + &mut builder, + self.data.transport_id.to_string(), + self.data.to_fbs(), + ); + let request_body = + request::Body::create_router_create_plain_transport_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::PlainTransportDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = plain_transport::DumpResponse::try_from(data)?; + + Ok(PlainTransportData { + tuple: Mutex::new(TransportTuple::from_fbs(data.tuple.as_ref())), + rtcp_tuple: Mutex::new( + data.rtcp_tuple + .map(|tuple| TransportTuple::from_fbs(tuple.as_ref())), + ), + sctp_parameters: data + .base + .sctp_parameters + .map(|parameters| SctpParameters::from_fbs(parameters.as_ref())), + sctp_state: Mutex::new( + data.base + .sctp_state + .map(|state| SctpState::from_fbs(&state)), + ), + srtp_parameters: Mutex::new( + data.srtp_parameters + .map(|parameters| SrtpParameters::from_fbs(parameters.as_ref())), + ), + }) + } +} + +pub(crate) struct PlainTransportData { + // The following fields are present, but unused + // rtcp_mux: bool, + // comedia: bool, + pub(crate) tuple: Mutex, + pub(crate) rtcp_tuple: Mutex>, + pub(crate) sctp_parameters: Option, + pub(crate) sctp_state: Mutex>, + pub(crate) srtp_parameters: Mutex>, +} #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub(crate) struct RouterCreatePipeTransportData { transport_id: TransportId, - listen_ip: ListenIp, - #[serde(skip_serializing_if = "Option::is_none")] - port: Option, + listen_info: ListenInfo, enable_sctp: bool, num_sctp_streams: NumSctpStreams, max_sctp_message_size: u32, @@ -425,8 +1050,7 @@ impl RouterCreatePipeTransportData { ) -> Self { Self { transport_id, - listen_ip: pipe_transport_options.listen_ip, - port: pipe_transport_options.port, + listen_info: pipe_transport_options.listen_info, enable_sctp: pipe_transport_options.enable_sctp, num_sctp_streams: pipe_transport_options.num_sctp_streams, max_sctp_message_size: pipe_transport_options.max_sctp_message_size, @@ -436,23 +1060,100 @@ impl RouterCreatePipeTransportData { is_data_channel: false, } } + + pub(crate) fn to_fbs(&self) -> pipe_transport::PipeTransportOptions { + pipe_transport::PipeTransportOptions { + base: Box::new(transport::Options { + direct: false, + max_message_size: None, + initial_available_outgoing_bitrate: None, + enable_sctp: self.enable_sctp, + num_sctp_streams: Some(Box::new(self.num_sctp_streams.to_fbs())), + max_sctp_message_size: self.max_sctp_message_size, + sctp_send_buffer_size: self.sctp_send_buffer_size, + is_data_channel: self.is_data_channel, + }), + listen_info: Box::new(self.listen_info.to_fbs()), + enable_rtx: self.enable_rtx, + enable_srtp: self.enable_srtp, + } + } } -request_response!( - RouterId, - "router.createPipeTransport", - RouterCreatePipeTransportRequest { - #[serde(flatten)] - data: RouterCreatePipeTransportData, - }, - PipeTransportData { - tuple: Mutex, - sctp_parameters: Option, - sctp_state: Mutex>, - rtx: bool, - srtp_parameters: Mutex>, - }, -); +#[derive(Debug)] +pub(crate) struct RouterCreatePipeTransportRequest { + pub(crate) data: RouterCreatePipeTransportData, +} + +impl Request for RouterCreatePipeTransportRequest { + const METHOD: request::Method = request::Method::RouterCreatePipetransport; + type HandlerId = RouterId; + type Response = PipeTransportData; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = router::CreatePipeTransportRequest::create( + &mut builder, + self.data.transport_id.to_string(), + self.data.to_fbs(), + ); + let request_body = + request::Body::create_router_create_pipe_transport_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::PipeTransportDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = pipe_transport::DumpResponse::try_from(data)?; + + Ok(PipeTransportData { + tuple: Mutex::new(TransportTuple::from_fbs(data.tuple.as_ref())), + sctp_parameters: data + .base + .sctp_parameters + .map(|parameters| SctpParameters::from_fbs(parameters.as_ref())), + sctp_state: Mutex::new( + data.base + .sctp_state + .map(|state| SctpState::from_fbs(&state)), + ), + rtx: data.rtx, + srtp_parameters: Mutex::new( + data.srtp_parameters + .map(|parameters| SrtpParameters::from_fbs(parameters.as_ref())), + ), + }) + } +} + +pub(crate) struct PipeTransportData { + pub(crate) tuple: Mutex, + pub(crate) sctp_parameters: Option, + pub(crate) sctp_state: Mutex>, + pub(crate) rtx: bool, + pub(crate) srtp_parameters: Mutex>, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct RouterCreateAudioLevelObserverRequest { + pub(crate) data: RouterCreateAudioLevelObserverData, +} #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] @@ -477,14 +1178,53 @@ impl RouterCreateAudioLevelObserverData { } } -request_response!( - RouterId, - "router.createAudioLevelObserver", - RouterCreateAudioLevelObserverRequest { - #[serde(flatten)] - data: RouterCreateAudioLevelObserverData, - }, -); +impl Request for RouterCreateAudioLevelObserverRequest { + const METHOD: request::Method = request::Method::RouterCreateAudiolevelobserver; + type HandlerId = RouterId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let options = audio_level_observer::AudioLevelObserverOptions::create( + &mut builder, + u16::from(self.data.max_entries), + self.data.threshold, + self.data.interval, + ); + let data = router::CreateAudioLevelObserverRequest::create( + &mut builder, + self.data.rtp_observer_id.to_string(), + options, + ); + let request_body = + request::Body::create_router_create_audio_level_observer_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct RouterCreateActiveSpeakerObserverRequest { + pub(crate) data: RouterCreateActiveSpeakerObserverData, +} #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] @@ -505,411 +1245,1957 @@ impl RouterCreateActiveSpeakerObserverData { } } -request_response!( - RouterId, - "router.createActiveSpeakerObserver", - RouterCreateActiveSpeakerObserverRequest { - #[serde(flatten)] - data: RouterCreateActiveSpeakerObserverData, - }, -); - -request_response!( - RouterId, - "router.closeTransport", - TransportCloseRequest { - transport_id: TransportId, - }, - (), - Some(()), -); - -request_response!( - TransportId, - "transport.dump", - TransportDumpRequest {}, - Value, -); - -request_response!( - TransportId, - "transport.getStats", - TransportGetStatsRequest {}, - Value, -); - -request_response!( - TransportId, - "transport.connect", - TransportConnectWebRtcRequest { - dtls_parameters: DtlsParameters, - }, - TransportConnectResponseWebRtc { - dtls_local_role: DtlsRole, - }, -); - -request_response!( - TransportId, - "transport.connect", - TransportConnectPipeRequest { - ip: IpAddr, - port: u16, - #[serde(skip_serializing_if = "Option::is_none")] - srtp_parameters: Option, - }, - TransportConnectResponsePipe { - tuple: TransportTuple, - }, -); - -request_response!( - TransportId, - "transport.connect", - TransportConnectPlainRequest { - #[serde(skip_serializing_if = "Option::is_none")] - ip: Option, - #[serde(skip_serializing_if = "Option::is_none")] - port: Option, - #[serde(skip_serializing_if = "Option::is_none")] - rtcp_port: Option, - #[serde(skip_serializing_if = "Option::is_none")] - srtp_parameters: Option, - }, - TransportConnectResponsePlain { - tuple: Option, - rtcp_tuple: Option, - srtp_parameters: Option, - }, -); - -request_response!( - TransportId, - "transport.setMaxIncomingBitrate", - TransportSetMaxIncomingBitrateRequest { bitrate: u32 }, -); - -request_response!( - TransportId, - "transport.setMaxOutgoingBitrate", - TransportSetMaxOutgoingBitrateRequest { bitrate: u32 }, -); - -request_response!( - TransportId, - "transport.setMinOutgoingBitrate", - TransportSetMinOutgoingBitrateRequest { bitrate: u32 }, -); - -request_response!( - TransportId, - "transport.restartIce", - TransportRestartIceRequest {}, - TransportRestartIceResponse { - ice_parameters: IceParameters, - }, -); - -request_response!( - TransportId, - "transport.produce", - TransportProduceRequest { - producer_id: ProducerId, - kind: MediaKind, - rtp_parameters: RtpParameters, - rtp_mapping: RtpMapping, - key_frame_request_delay: u32, - paused: bool, - }, - TransportProduceResponse { - r#type: ProducerType, - }, -); - -request_response!( - TransportId, - "transport.consume", - TransportConsumeRequest { - consumer_id: ConsumerId, - producer_id: ProducerId, - kind: MediaKind, - rtp_parameters: RtpParameters, - r#type: ConsumerType, - consumable_rtp_encodings: Vec, - paused: bool, - preferred_layers: Option, - ignore_dtx: bool, - }, - TransportConsumeResponse { - paused: bool, - producer_paused: bool, - score: ConsumerScore, - preferred_layers: Option, - }, -); - -request_response!( - TransportId, - "transport.produceData", - TransportProduceDataRequest { - data_producer_id: DataProducerId, - r#type: DataProducerType, - #[serde(skip_serializing_if = "Option::is_none")] - sctp_stream_parameters: Option, - label: String, - protocol: String, - }, - TransportProduceDataResponse { - r#type: DataProducerType, - sctp_stream_parameters: Option, - label: String, - protocol: String, - }, -); - -request_response!( - TransportId, - "transport.consumeData", - TransportConsumeDataRequest { - data_consumer_id: DataConsumerId, - data_producer_id: DataProducerId, - r#type: DataConsumerType, - #[serde(skip_serializing_if = "Option::is_none")] - sctp_stream_parameters: Option, - label: String, - protocol: String, - }, - TransportConsumeDataResponse { - r#type: DataConsumerType, - sctp_stream_parameters: Option, - label: String, - protocol: String, - }, -); +impl Request for RouterCreateActiveSpeakerObserverRequest { + const METHOD: request::Method = request::Method::RouterCreateActivespeakerobserver; + type HandlerId = RouterId; + type Response = (); -request_response!( - TransportId, - "transport.enableTraceEvent", - TransportEnableTraceEventRequest { - types: Vec, - }, -); + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct TransportSendRtcpNotification {} + let options = active_speaker_observer::ActiveSpeakerObserverOptions::create( + &mut builder, + self.data.interval, + ); + let data = router::CreateActiveSpeakerObserverRequest::create( + &mut builder, + self.data.rtp_observer_id.to_string(), + options, + ); + let request_body = + request::Body::create_router_create_active_speaker_observer_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); -impl Notification for TransportSendRtcpNotification { - type HandlerId = TransportId; + builder.finish(message, None).to_vec() + } - fn as_event(&self) -> &'static str { - "transport.sendRtcp" + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) } } -request_response!( - TransportId, - "transport.closeProducer", - ProducerCloseRequest { - producer_id: ProducerId, - }, - (), - Some(()), -); - -request_response!( - ProducerId, - "producer.dump", - ProducerDumpRequest {}, - ProducerDump -); - -request_response!( - ProducerId, - "producer.getStats", - ProducerGetStatsRequest {}, - Vec, -); - -request_response!(ProducerId, "producer.pause", ProducerPauseRequest {}); - -request_response!(ProducerId, "producer.resume", ProducerResumeRequest {}); - -request_response!( - ProducerId, - "producer.enableTraceEvent", - ProducerEnableTraceEventRequest { - types: Vec, - }, -); +#[derive(Debug)] +pub(crate) struct TransportDumpRequest {} + +impl Request for TransportDumpRequest { + const METHOD: request::Method = request::Method::TransportDump; + type HandlerId = TransportId; + type Response = response::Body; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + match response { + Some(data) => Ok(data.try_into().unwrap()), + _ => { + panic!("Wrong message from worker: {response:?}"); + } + } + } +} +#[derive(Debug)] +pub(crate) struct TransportGetStatsRequest {} + +impl Request for TransportGetStatsRequest { + const METHOD: request::Method = request::Method::TransportGetStats; + type HandlerId = TransportId; + type Response = response::Body; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + match response { + Some(data) => Ok(data.try_into().unwrap()), + _ => { + panic!("Wrong message from worker: {response:?}"); + } + } + } +} + +#[derive(Debug)] +pub(crate) struct TransportCloseRequest { + pub(crate) transport_id: TransportId, +} + +impl Request for TransportCloseRequest { + const METHOD: request::Method = request::Method::RouterCloseTransport; + type HandlerId = RouterId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = + router::CloseTransportRequest::create(&mut builder, self.transport_id.to_string()); + let request_body = request::Body::create_router_close_transport_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct WebRtcTransportConnectResponse { + pub(crate) dtls_local_role: DtlsRole, +} + +#[derive(Debug)] +pub(crate) struct WebRtcTransportConnectRequest { + pub(crate) dtls_parameters: DtlsParameters, +} + +impl Request for WebRtcTransportConnectRequest { + const METHOD: request::Method = request::Method::WebrtctransportConnect; + type HandlerId = TransportId; + type Response = WebRtcTransportConnectResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = + web_rtc_transport::ConnectRequest::create(&mut builder, self.dtls_parameters.to_fbs()); + let request_body = + request::Body::create_web_rtc_transport_connect_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::WebRtcTransportConnectResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = web_rtc_transport::ConnectResponse::try_from(data)?; + + Ok(WebRtcTransportConnectResponse { + dtls_local_role: DtlsRole::from_fbs(data.dtls_local_role), + }) + } +} + +#[derive(Debug)] +pub(crate) struct PipeTransportConnectResponse { + pub(crate) tuple: TransportTuple, +} + +#[derive(Debug)] +pub(crate) struct PipeTransportConnectRequest { + pub(crate) ip: IpAddr, + pub(crate) port: u16, + pub(crate) srtp_parameters: Option, +} + +impl Request for PipeTransportConnectRequest { + const METHOD: request::Method = request::Method::PipetransportConnect; + type HandlerId = TransportId; + type Response = PipeTransportConnectResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = pipe_transport::ConnectRequest::create( + &mut builder, + self.ip.to_string(), + self.port, + self.srtp_parameters.map(|parameters| parameters.to_fbs()), + ); + let request_body = request::Body::create_pipe_transport_connect_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::PipeTransportConnectResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = pipe_transport::ConnectResponse::try_from(data)?; + + Ok(PipeTransportConnectResponse { + tuple: TransportTuple::from_fbs(data.tuple.as_ref()), + }) + } +} + +#[derive(Debug)] +pub(crate) struct PlainTransportConnectResponse { + pub(crate) tuple: TransportTuple, + pub(crate) rtcp_tuple: Option, + pub(crate) srtp_parameters: Option, +} + +#[derive(Debug)] +pub(crate) struct TransportConnectPlainRequest { + pub(crate) ip: Option, + pub(crate) port: Option, + pub(crate) rtcp_port: Option, + pub(crate) srtp_parameters: Option, +} + +impl Request for TransportConnectPlainRequest { + const METHOD: request::Method = request::Method::PlaintransportConnect; + type HandlerId = TransportId; + type Response = PlainTransportConnectResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = plain_transport::ConnectRequest::create( + &mut builder, + self.ip.map(|ip| ip.to_string()), + self.port, + self.rtcp_port, + self.srtp_parameters.map(|parameters| parameters.to_fbs()), + ); + let request_body = + request::Body::create_plain_transport_connect_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::PlainTransportConnectResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = plain_transport::ConnectResponse::try_from(data)?; + + Ok(PlainTransportConnectResponse { + tuple: TransportTuple::from_fbs(data.tuple.as_ref()), + rtcp_tuple: data + .rtcp_tuple + .map(|tuple| TransportTuple::from_fbs(tuple.as_ref())), + srtp_parameters: data + .srtp_parameters + .map(|parameters| SrtpParameters::from_fbs(parameters.as_ref())), + }) + } +} + +#[derive(Debug)] +pub(crate) struct TransportSetMaxIncomingBitrateRequest { + pub(crate) bitrate: u32, +} + +impl Request for TransportSetMaxIncomingBitrateRequest { + const METHOD: request::Method = request::Method::TransportSetMaxIncomingBitrate; + type HandlerId = TransportId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = transport::SetMaxIncomingBitrateRequest::create(&mut builder, self.bitrate); + let request_body = + request::Body::create_transport_set_max_incoming_bitrate_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct TransportSetMaxOutgoingBitrateRequest { + pub(crate) bitrate: u32, +} + +impl Request for TransportSetMaxOutgoingBitrateRequest { + const METHOD: request::Method = request::Method::TransportSetMaxOutgoingBitrate; + type HandlerId = TransportId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = transport::SetMaxOutgoingBitrateRequest::create(&mut builder, self.bitrate); + let request_body = + request::Body::create_transport_set_max_outgoing_bitrate_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct TransportSetMinOutgoingBitrateRequest { + pub(crate) bitrate: u32, +} + +impl Request for TransportSetMinOutgoingBitrateRequest { + const METHOD: request::Method = request::Method::TransportSetMinOutgoingBitrate; + type HandlerId = TransportId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = transport::SetMinOutgoingBitrateRequest::create(&mut builder, self.bitrate); + let request_body = + request::Body::create_transport_set_min_outgoing_bitrate_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct TransportRestartIceRequest {} + +impl Request for TransportRestartIceRequest { + const METHOD: request::Method = request::Method::TransportRestartIce; + type HandlerId = TransportId; + type Response = IceParameters; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::TransportRestartIceResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = transport::RestartIceResponse::try_from(data)?; + + Ok(IceParameters::from_fbs(web_rtc_transport::IceParameters { + username_fragment: data.username_fragment, + password: data.password, + ice_lite: data.ice_lite, + })) + } +} + +#[derive(Debug)] +pub(crate) struct TransportProduceRequest { + pub(crate) producer_id: ProducerId, + pub(crate) kind: MediaKind, + pub(crate) rtp_parameters: RtpParameters, + pub(crate) rtp_mapping: RtpMapping, + pub(crate) key_frame_request_delay: u32, + pub(crate) paused: bool, +} + +#[derive(Debug)] +pub(crate) struct TransportProduceResponse { + pub(crate) r#type: ProducerType, +} + +impl Request for TransportProduceRequest { + const METHOD: request::Method = request::Method::TransportProduce; + type HandlerId = TransportId; + type Response = TransportProduceResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = transport::ProduceRequest::create( + &mut builder, + self.producer_id.to_string(), + self.kind.to_fbs(), + Box::new(self.rtp_parameters.into_fbs()), + Box::new(self.rtp_mapping.to_fbs()), + self.key_frame_request_delay, + self.paused, + ); + let request_body = request::Body::create_transport_produce_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::TransportProduceResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = transport::ProduceResponse::try_from(data)?; + + Ok(TransportProduceResponse { + r#type: ProducerType::from_fbs(data.type_), + }) + } +} + +#[derive(Debug)] +pub(crate) struct TransportConsumeRequest { + pub(crate) consumer_id: ConsumerId, + pub(crate) producer_id: ProducerId, + pub(crate) kind: MediaKind, + pub(crate) rtp_parameters: RtpParameters, + pub(crate) r#type: ConsumerType, + pub(crate) consumable_rtp_encodings: Vec, + pub(crate) paused: bool, + pub(crate) preferred_layers: Option, + pub(crate) ignore_dtx: bool, +} + +#[derive(Debug)] +pub(crate) struct TransportConsumeResponse { + pub(crate) paused: bool, + pub(crate) producer_paused: bool, + pub(crate) score: ConsumerScore, + pub(crate) preferred_layers: Option, +} + +impl Request for TransportConsumeRequest { + const METHOD: request::Method = request::Method::TransportConsume; + type HandlerId = TransportId; + type Response = TransportConsumeResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = transport::ConsumeRequest::create( + &mut builder, + self.consumer_id.to_string(), + self.producer_id.to_string(), + self.kind.to_fbs(), + Box::new(self.rtp_parameters.into_fbs()), + self.r#type.to_fbs(), + self.consumable_rtp_encodings + .iter() + .map(RtpEncodingParameters::to_fbs) + .collect::>(), + self.paused, + self.preferred_layers.map(ConsumerLayers::to_fbs), + self.ignore_dtx, + ); + let request_body = request::Body::create_transport_consume_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::TransportConsumeResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = transport::ConsumeResponse::try_from(data)?; + + Ok(TransportConsumeResponse { + paused: data.paused, + producer_paused: data.producer_paused, + score: ConsumerScore::from_fbs(*data.score), + preferred_layers: data + .preferred_layers + .map(|preferred_layers| ConsumerLayers::from_fbs(*preferred_layers)), + }) + } +} + +#[derive(Debug)] +pub(crate) struct TransportProduceDataRequest { + pub(crate) data_producer_id: DataProducerId, + pub(crate) r#type: DataProducerType, + // #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) sctp_stream_parameters: Option, + pub(crate) label: String, + pub(crate) protocol: String, + pub(crate) paused: bool, +} + +#[derive(Debug)] +pub(crate) struct TransportProduceDataResponse { + pub(crate) r#type: DataProducerType, + pub(crate) sctp_stream_parameters: Option, + pub(crate) label: String, + pub(crate) protocol: String, + pub(crate) paused: bool, +} + +impl Request for TransportProduceDataRequest { + const METHOD: request::Method = request::Method::TransportProduceData; + type HandlerId = TransportId; + type Response = TransportProduceDataResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = transport::ProduceDataRequest::create( + &mut builder, + self.data_producer_id.to_string(), + match self.r#type { + DataProducerType::Sctp => data_producer::Type::Sctp, + DataProducerType::Direct => data_producer::Type::Direct, + }, + self.sctp_stream_parameters + .map(SctpStreamParameters::to_fbs), + if self.label.is_empty() { + None + } else { + Some(self.label) + }, + if self.protocol.is_empty() { + None + } else { + Some(self.protocol) + }, + self.paused, + ); + let request_body = request::Body::create_transport_produce_data_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::DataProducerDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = data_producer::DumpResponse::try_from(data)?; + + Ok(TransportProduceDataResponse { + r#type: match data.type_ { + data_producer::Type::Sctp => DataProducerType::Sctp, + data_producer::Type::Direct => DataProducerType::Direct, + }, + sctp_stream_parameters: data + .sctp_stream_parameters + .map(|stream_parameters| SctpStreamParameters::from_fbs(*stream_parameters)), + label: data.label.to_string(), + protocol: data.protocol.to_string(), + paused: data.paused, + }) + } +} + +#[derive(Debug)] +pub(crate) struct TransportConsumeDataRequest { + pub(crate) data_consumer_id: DataConsumerId, + pub(crate) data_producer_id: DataProducerId, + pub(crate) r#type: DataConsumerType, + pub(crate) sctp_stream_parameters: Option, + pub(crate) label: String, + pub(crate) protocol: String, + pub(crate) paused: bool, + pub(crate) subchannels: Option>, +} + +#[derive(Debug)] +pub(crate) struct TransportConsumeDataResponse { + pub(crate) r#type: DataConsumerType, + pub(crate) sctp_stream_parameters: Option, + pub(crate) label: String, + pub(crate) protocol: String, + pub(crate) paused: bool, + pub(crate) data_producer_paused: bool, + pub(crate) subchannels: Vec, +} + +impl Request for TransportConsumeDataRequest { + const METHOD: request::Method = request::Method::TransportConsumeData; + type HandlerId = TransportId; + type Response = TransportConsumeDataResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = transport::ConsumeDataRequest::create( + &mut builder, + self.data_consumer_id.to_string(), + self.data_producer_id.to_string(), + match self.r#type { + DataConsumerType::Sctp => data_producer::Type::Sctp, + DataConsumerType::Direct => data_producer::Type::Direct, + }, + self.sctp_stream_parameters + .map(SctpStreamParameters::to_fbs), + if self.label.is_empty() { + None + } else { + Some(self.label) + }, + if self.protocol.is_empty() { + None + } else { + Some(self.protocol) + }, + self.paused, + self.subchannels, + ); + let request_body = request::Body::create_transport_consume_data_request(&mut builder, data); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::DataConsumerDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = data_consumer::DumpResponse::try_from(data)?; + + Ok(TransportConsumeDataResponse { + r#type: match data.type_ { + data_producer::Type::Sctp => DataConsumerType::Sctp, + data_producer::Type::Direct => DataConsumerType::Direct, + }, + sctp_stream_parameters: data + .sctp_stream_parameters + .map(|stream_parameters| SctpStreamParameters::from_fbs(*stream_parameters)), + label: data.label.to_string(), + protocol: data.protocol.to_string(), + paused: data.paused, + data_producer_paused: data.data_producer_paused, + subchannels: data.subchannels, + }) + } +} + +#[derive(Debug)] +pub(crate) struct TransportEnableTraceEventRequest { + pub(crate) types: Vec, +} + +impl Request for TransportEnableTraceEventRequest { + const METHOD: request::Method = request::Method::TransportEnableTraceEvent; + type HandlerId = TransportId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = transport::EnableTraceEventRequest { + events: self + .types + .into_iter() + .map(TransportTraceEventType::to_fbs) + .collect(), + }; + + let request_body = request::Body::TransportEnableTraceEventRequest(Box::new(data)); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } + + fn default_for_soft_error() -> Option { + None + } +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct TransportSendRtcpNotification { + pub(crate) rtcp_packet: Vec, +} + +impl Notification for TransportSendRtcpNotification { + const EVENT: notification::Event = notification::Event::TransportSendRtcp; + type HandlerId = TransportId; + + fn into_bytes(self, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = transport::SendRtcpNotification::create(&mut builder, self.rtcp_packet); + let notification_body = + notification::Body::create_transport_send_rtcp_notification(&mut builder, data); + + let notification = notification::Notification::create( + &mut builder, + handler_id.to_string(), + Self::EVENT, + Some(notification_body), + ); + let message_body = message::Body::create_notification(&mut builder, notification); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } +} + +#[derive(Debug)] +pub(crate) struct ProducerCloseRequest { + pub(crate) producer_id: ProducerId, +} + +impl Request for ProducerCloseRequest { + const METHOD: request::Method = request::Method::TransportCloseProducer; + type HandlerId = TransportId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = + transport::CloseProducerRequest::create(&mut builder, self.producer_id.to_string()); + let request_body = + request::Body::create_transport_close_producer_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct ProducerDumpRequest {} + +impl Request for ProducerDumpRequest { + const METHOD: request::Method = request::Method::ProducerDump; + type HandlerId = ProducerId; + type Response = ProducerDump; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::ProducerDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + ProducerDump::from_fbs_ref(data) + } +} + +#[derive(Debug)] +pub(crate) struct ProducerGetStatsRequest {} + +impl Request for ProducerGetStatsRequest { + const METHOD: request::Method = request::Method::ProducerGetStats; + type HandlerId = ProducerId; + type Response = response::Body; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + match response { + Some(data) => Ok(data.try_into().unwrap()), + _ => { + panic!("Wrong message from worker: {response:?}"); + } + } + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct ProducerPauseRequest {} + +impl Request for ProducerPauseRequest { + const METHOD: request::Method = request::Method::ProducerPause; + type HandlerId = ProducerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct ProducerResumeRequest {} + +impl Request for ProducerResumeRequest { + const METHOD: request::Method = request::Method::ProducerResume; + type HandlerId = ProducerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct ProducerEnableTraceEventRequest { + pub(crate) types: Vec, +} + +impl Request for ProducerEnableTraceEventRequest { + const METHOD: request::Method = request::Method::ProducerEnableTraceEvent; + type HandlerId = ProducerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = producer::EnableTraceEventRequest { + events: self + .types + .into_iter() + .map(ProducerTraceEventType::to_fbs) + .collect(), + }; + + let request_body = request::Body::ProducerEnableTraceEventRequest(Box::new(data)); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } + + fn default_for_soft_error() -> Option { + None + } +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct ProducerSendNotification { + pub(crate) rtp_packet: Vec, +} + +impl Notification for ProducerSendNotification { + const EVENT: notification::Event = notification::Event::ProducerSend; + type HandlerId = ProducerId; + + fn into_bytes(self, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = producer::SendNotification::create(&mut builder, self.rtp_packet); + let notification_body = + notification::Body::create_producer_send_notification(&mut builder, data); + + let notification = notification::Notification::create( + &mut builder, + handler_id.to_string(), + Self::EVENT, + Some(notification_body), + ); + let message_body = message::Body::create_notification(&mut builder, notification); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } +} + +#[derive(Debug)] +pub(crate) struct ConsumerCloseRequest { + pub(crate) consumer_id: ConsumerId, +} + +impl Request for ConsumerCloseRequest { + const METHOD: request::Method = request::Method::TransportCloseConsumer; + type HandlerId = TransportId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = + transport::CloseConsumerRequest::create(&mut builder, self.consumer_id.to_string()); + let request_body = + request::Body::create_transport_close_consumer_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct ConsumerDumpRequest {} + +impl Request for ConsumerDumpRequest { + const METHOD: request::Method = request::Method::ConsumerDump; + type HandlerId = ConsumerId; + type Response = ConsumerDump; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::ConsumerDumpResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + ConsumerDump::from_fbs_ref(data) + } +} + +#[derive(Debug)] +pub(crate) struct ConsumerGetStatsRequest {} + +impl Request for ConsumerGetStatsRequest { + const METHOD: request::Method = request::Method::ConsumerGetStats; + type HandlerId = ConsumerId; + type Response = response::Body; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + match response { + Some(data) => Ok(data.try_into().unwrap()), + _ => { + panic!("Wrong message from worker: {response:?}"); + } + } + } +} + +#[derive(Debug)] +pub(crate) struct ConsumerPauseRequest {} + +impl Request for ConsumerPauseRequest { + const METHOD: request::Method = request::Method::ConsumerPause; + type HandlerId = ConsumerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct ConsumerResumeRequest {} + +impl Request for ConsumerResumeRequest { + const METHOD: request::Method = request::Method::ConsumerResume; + type HandlerId = ConsumerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct ConsumerSetPreferredLayersRequest { + pub(crate) data: ConsumerLayers, +} + +impl Request for ConsumerSetPreferredLayersRequest { + const METHOD: request::Method = request::Method::ConsumerSetPreferredLayers; + type HandlerId = ConsumerId; + type Response = Option; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = consumer::SetPreferredLayersRequest::create( + &mut builder, + ConsumerLayers::to_fbs(self.data), + ); + let request_body = + request::Body::create_consumer_set_preferred_layers_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::ConsumerSetPreferredLayersResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = consumer::SetPreferredLayersResponse::try_from(data)?; + + match data.preferred_layers { + Some(preferred_layers) => Ok(Some(ConsumerLayers::from_fbs(*preferred_layers))), + None => Ok(None), + } + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct ConsumerSetPriorityRequest { + pub(crate) priority: u8, +} + +#[derive(Debug, Serialize)] +pub(crate) struct ConsumerSetPriorityResponse { + pub(crate) priority: u8, +} + +impl Request for ConsumerSetPriorityRequest { + const METHOD: request::Method = request::Method::ConsumerSetPriority; + type HandlerId = ConsumerId; + type Response = ConsumerSetPriorityResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = consumer::SetPriorityRequest::create(&mut builder, self.priority); + let request_body = request::Body::create_consumer_set_priority_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::ConsumerSetPriorityResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = consumer::SetPriorityResponse::try_from(data)?; + + Ok(ConsumerSetPriorityResponse { + priority: data.priority, + }) + } +} + +#[derive(Debug)] +pub(crate) struct ConsumerRequestKeyFrameRequest {} + +impl Request for ConsumerRequestKeyFrameRequest { + const METHOD: request::Method = request::Method::ConsumerRequestKeyFrame; + type HandlerId = ConsumerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct ConsumerEnableTraceEventRequest { + pub(crate) types: Vec, +} + +impl Request for ConsumerEnableTraceEventRequest { + const METHOD: request::Method = request::Method::ConsumerEnableTraceEvent; + type HandlerId = ConsumerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = consumer::EnableTraceEventRequest { + events: self + .types + .into_iter() + .map(ConsumerTraceEventType::to_fbs) + .collect(), + }; + + let request_body = request::Body::ConsumerEnableTraceEventRequest(Box::new(data)); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } + + fn default_for_soft_error() -> Option { + None + } +} + +#[derive(Debug)] +pub(crate) struct DataProducerCloseRequest { + pub(crate) data_producer_id: DataProducerId, +} + +impl Request for DataProducerCloseRequest { + const METHOD: request::Method = request::Method::TransportCloseDataproducer; + type HandlerId = TransportId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = transport::CloseDataProducerRequest::create( + &mut builder, + self.data_producer_id.to_string(), + ); + let request_body = + request::Body::create_transport_close_data_producer_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct DataProducerDumpRequest {} + +impl Request for DataProducerDumpRequest { + const METHOD: request::Method = request::Method::DataproducerDump; + type HandlerId = DataProducerId; + type Response = response::Body; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + match response { + Some(data) => Ok(data.try_into().unwrap()), + _ => { + panic!("Wrong message from worker: {response:?}"); + } + } + } +} + +#[derive(Debug)] +pub(crate) struct DataProducerGetStatsRequest {} + +impl Request for DataProducerGetStatsRequest { + const METHOD: request::Method = request::Method::DataproducerGetStats; + type HandlerId = DataProducerId; + type Response = response::Body; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + match response { + Some(data) => Ok(data.try_into().unwrap()), + _ => { + panic!("Wrong message from worker: {response:?}"); + } + } + } +} #[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct ProducerSendNotification {} +pub(crate) struct DataProducerPauseRequest {} -impl Notification for ProducerSendNotification { - type HandlerId = ProducerId; +impl Request for DataProducerPauseRequest { + const METHOD: request::Method = request::Method::DataproducerPause; + type HandlerId = DataProducerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } - fn as_event(&self) -> &'static str { - "producer.send" + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) } } -request_response!( - TransportId, - "transport.closeConsumer", - ConsumerCloseRequest { - consumer_id: ConsumerId, - }, - (), - Some(()), -); - -request_response!( - ConsumerId, - "consumer.dump", - ConsumerDumpRequest {}, - ConsumerDump, -); - -request_response!( - ConsumerId, - "consumer.getStats", - ConsumerGetStatsRequest {}, - ConsumerStats, -); - -request_response!(ConsumerId, "consumer.pause", ConsumerPauseRequest {},); - -request_response!(ConsumerId, "consumer.resume", ConsumerResumeRequest {},); - -request_response!( - ConsumerId, - "consumer.setPreferredLayers", - ConsumerSetPreferredLayersRequest { - #[serde(flatten)] - data: ConsumerLayers, - }, - Option, -); - -request_response!( - ConsumerId, - "consumer.setPriority", - ConsumerSetPriorityRequest { priority: u8 }, - ConsumerSetPriorityResponse { priority: u8 }, -); - -request_response!( - ConsumerId, - "consumer.requestKeyFrame", - ConsumerRequestKeyFrameRequest {}, -); - -request_response!( - ConsumerId, - "consumer.enableTraceEvent", - ConsumerEnableTraceEventRequest { - types: Vec, - }, -); +#[derive(Debug, Serialize)] +pub(crate) struct DataProducerResumeRequest {} -request_response!( - TransportId, - "transport.closeDataProducer", - DataProducerCloseRequest { - data_producer_id: DataProducerId, - }, - (), - Some(()), -); - -request_response!( - DataProducerId, - "dataProducer.dump", - DataProducerDumpRequest {}, - DataProducerDump, -); - -request_response!( - DataProducerId, - "dataProducer.getStats", - DataProducerGetStatsRequest {}, - Vec, -); - -#[derive(Debug, Copy, Clone, Serialize)] -#[serde(into = "u32")] +impl Request for DataProducerResumeRequest { + const METHOD: request::Method = request::Method::DataproducerResume; + type HandlerId = DataProducerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] pub(crate) struct DataProducerSendNotification { - #[serde(flatten)] pub(crate) ppid: u32, + pub(crate) payload: Vec, + pub(crate) subchannels: Option>, + pub(crate) required_subchannel: Option, } -impl From for u32 { - fn from(notification: DataProducerSendNotification) -> Self { - notification.ppid +impl Notification for DataProducerSendNotification { + const EVENT: notification::Event = notification::Event::DataproducerSend; + type HandlerId = DataProducerId; + + fn into_bytes(self, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = data_producer::SendNotification::create( + &mut builder, + self.ppid, + self.payload, + self.subchannels, + self.required_subchannel, + ); + let notification_body = + notification::Body::create_data_producer_send_notification(&mut builder, data); + + let notification = notification::Notification::create( + &mut builder, + handler_id.to_string(), + Self::EVENT, + Some(notification_body), + ); + let message_body = message::Body::create_notification(&mut builder, notification); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() } } -impl Notification for DataProducerSendNotification { - type HandlerId = DataProducerId; +#[derive(Debug)] +pub(crate) struct DataConsumerCloseRequest { + pub(crate) data_consumer_id: DataConsumerId, +} + +impl Request for DataConsumerCloseRequest { + const METHOD: request::Method = request::Method::TransportCloseDataconsumer; + type HandlerId = TransportId; + type Response = (); - fn as_event(&self) -> &'static str { - "dataProducer.send" + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = transport::CloseDataConsumerRequest::create( + &mut builder, + self.data_consumer_id.to_string(), + ); + let request_body = + request::Body::create_transport_close_data_consumer_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) } } -request_response!( - TransportId, - "transport.closeDataConsumer", - DataConsumerCloseRequest { - data_consumer_id: DataConsumerId, - }, - (), - Some(()), -); - -request_response!( - DataConsumerId, - "dataConsumer.dump", - DataConsumerDumpRequest {}, - DataConsumerDump, -); - -request_response!( - DataConsumerId, - "dataConsumer.getStats", - DataConsumerGetStatsRequest {}, - Vec, -); - -request_response!( - DataConsumerId, - "dataConsumer.getBufferedAmount", - DataConsumerGetBufferedAmountRequest {}, - DataConsumerGetBufferedAmountResponse { - buffered_amount: u32, - }, -); +#[derive(Debug)] +pub(crate) struct DataConsumerDumpRequest {} + +impl Request for DataConsumerDumpRequest { + const METHOD: request::Method = request::Method::DataconsumerDump; + type HandlerId = DataConsumerId; + type Response = response::Body; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + match response { + Some(data) => Ok(data.try_into().unwrap()), + _ => { + panic!("Wrong message from worker: {response:?}"); + } + } + } +} + +#[derive(Debug)] +pub(crate) struct DataConsumerGetStatsRequest {} + +impl Request for DataConsumerGetStatsRequest { + const METHOD: request::Method = request::Method::DataconsumerGetStats; + type HandlerId = DataConsumerId; + type Response = response::Body; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + match response { + Some(data) => Ok(data.try_into().unwrap()), + _ => { + panic!("Wrong message from worker: {response:?}"); + } + } + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct DataConsumerPauseRequest {} + +impl Request for DataConsumerPauseRequest { + const METHOD: request::Method = request::Method::DataconsumerPause; + type HandlerId = DataConsumerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct DataConsumerResumeRequest {} + +impl Request for DataConsumerResumeRequest { + const METHOD: request::Method = request::Method::DataconsumerResume; + type HandlerId = DataConsumerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct DataConsumerGetBufferedAmountRequest {} + +#[derive(Debug, Serialize)] +pub(crate) struct DataConsumerGetBufferedAmountResponse { + pub(crate) buffered_amount: u32, +} + +impl Request for DataConsumerGetBufferedAmountRequest { + const METHOD: request::Method = request::Method::DataconsumerGetBufferedAmount; + type HandlerId = DataConsumerId; + type Response = DataConsumerGetBufferedAmountResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::DataConsumerGetBufferedAmountResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = data_consumer::GetBufferedAmountResponse::try_from(data)?; + + Ok(DataConsumerGetBufferedAmountResponse { + buffered_amount: data.buffered_amount, + }) + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct DataConsumerSetBufferedAmountLowThresholdRequest { + pub(crate) threshold: u32, +} + +impl Request for DataConsumerSetBufferedAmountLowThresholdRequest { + const METHOD: request::Method = request::Method::DataconsumerSetBufferedAmountLowThreshold; + type HandlerId = DataConsumerId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = data_consumer::SetBufferedAmountLowThresholdRequest::create( + &mut builder, + self.threshold, + ); + let request_body = + request::Body::create_data_consumer_set_buffered_amount_low_threshold_request( + &mut builder, + data, + ); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } -request_response!( - DataConsumerId, - "dataConsumer.setBufferedAmountLowThreshold", - DataConsumerSetBufferedAmountLowThresholdRequest { threshold: u32 }, -); + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} -#[derive(Debug, Copy, Clone, Serialize)] +#[derive(Debug, Clone, Serialize)] #[serde(into = "u32")] pub(crate) struct DataConsumerSendRequest { pub(crate) ppid: u32, + pub(crate) payload: Vec, } impl Request for DataConsumerSendRequest { + const METHOD: request::Method = request::Method::DataconsumerSend; type HandlerId = DataConsumerId; type Response = (); - fn as_method(&self) -> &'static str { - "dataConsumer.send" + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = data_consumer::SendRequest::create(&mut builder, self.ppid, self.payload); + let request_body = request::Body::create_data_consumer_send_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) } } @@ -919,40 +3205,227 @@ impl From for u32 { } } -request_response!( - RouterId, - "router.closeRtpObserver", - RtpObserverCloseRequest { - rtp_observer_id: RtpObserverId, - }, - (), - Some(()), -); - -request_response!( - RtpObserverId, - "rtpObserver.pause", - RtpObserverPauseRequest {}, -); - -request_response!( - RtpObserverId, - "rtpObserver.resume", - RtpObserverResumeRequest {}, -); - -request_response!( - RtpObserverId, - "rtpObserver.addProducer", - RtpObserverAddProducerRequest { - producer_id: ProducerId, - }, -); +#[derive(Debug, Clone, Serialize)] +pub(crate) struct DataConsumerSetSubchannelsRequest { + pub(crate) subchannels: Vec, +} -request_response!( - RtpObserverId, - "rtpObserver.removeProducer", - RtpObserverRemoveProducerRequest { - producer_id: ProducerId, - }, -); +#[derive(Debug, Clone, Serialize)] +pub(crate) struct DataConsumerSetSubchannelsResponse { + pub(crate) subchannels: Vec, +} + +impl Request for DataConsumerSetSubchannelsRequest { + const METHOD: request::Method = request::Method::DataconsumerSetSubchannels; + type HandlerId = DataConsumerId; + type Response = DataConsumerSetSubchannelsResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = data_consumer::SetSubchannelsRequest::create(&mut builder, self.subchannels); + let request_body = + request::Body::create_data_consumer_set_subchannels_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::DataConsumerSetSubchannelsResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = data_consumer::SetSubchannelsResponse::try_from(data)?; + + Ok(DataConsumerSetSubchannelsResponse { + subchannels: data.subchannels, + }) + } +} + +#[derive(Debug)] +pub(crate) struct RtpObserverCloseRequest { + pub(crate) rtp_observer_id: RtpObserverId, +} + +impl Request for RtpObserverCloseRequest { + const METHOD: request::Method = request::Method::RouterCloseRtpobserver; + type HandlerId = RouterId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let data = + router::CloseRtpObserverRequest::create(&mut builder, self.rtp_observer_id.to_string()); + let request_body = + request::Body::create_router_close_rtp_observer_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct RtpObserverPauseRequest {} + +impl Request for RtpObserverPauseRequest { + const METHOD: request::Method = request::Method::RtpobserverPause; + type HandlerId = RtpObserverId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug)] +pub(crate) struct RtpObserverResumeRequest {} + +impl Request for RtpObserverResumeRequest { + const METHOD: request::Method = request::Method::RtpobserverResume; + type HandlerId = RtpObserverId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + None::, + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct RtpObserverAddProducerRequest { + pub(crate) producer_id: ProducerId, +} + +impl Request for RtpObserverAddProducerRequest { + const METHOD: request::Method = request::Method::RtpobserverAddProducer; + type HandlerId = RtpObserverId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = + rtp_observer::AddProducerRequest::create(&mut builder, self.producer_id.to_string()); + let request_body = + request::Body::create_rtp_observer_add_producer_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct RtpObserverRemoveProducerRequest { + pub(crate) producer_id: ProducerId, +} + +impl Request for RtpObserverRemoveProducerRequest { + const METHOD: request::Method = request::Method::RtpobserverRemoveProducer; + type HandlerId = RtpObserverId; + type Response = (); + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = + rtp_observer::RemoveProducerRequest::create(&mut builder, self.producer_id.to_string()); + let request_body = + request::Body::create_rtp_observer_remove_producer_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + _response: Option>, + ) -> Result> { + Ok(()) + } +} diff --git a/rust/src/ortc.rs b/rust/src/ortc.rs index 74a5ec8038..88acf21650 100644 --- a/rust/src/ortc.rs +++ b/rust/src/ortc.rs @@ -7,10 +7,12 @@ use crate::rtp_parameters::{ }; use crate::scalability_modes::ScalabilityMode; use crate::supported_rtp_capabilities; +use mediasoup_sys::fbs::rtp_parameters; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::collections::BTreeMap; use std::convert::TryFrom; +use std::error::Error; use std::mem; use std::num::{NonZeroU32, NonZeroU8}; use std::ops::Deref; @@ -52,6 +54,64 @@ pub struct RtpMapping { pub encodings: Vec, } +impl RtpMapping { + pub(crate) fn to_fbs(&self) -> rtp_parameters::RtpMapping { + rtp_parameters::RtpMapping { + codecs: self + .codecs + .iter() + .map(|mapping| rtp_parameters::CodecMapping { + payload_type: mapping.payload_type, + mapped_payload_type: mapping.mapped_payload_type, + }) + .collect(), + encodings: self + .encodings + .iter() + .map(|mapping| rtp_parameters::EncodingMapping { + rid: mapping.rid.clone().map(|rid| rid.to_string()), + ssrc: mapping.ssrc, + scalability_mode: Some(mapping.scalability_mode.to_string()), + mapped_ssrc: mapping.mapped_ssrc, + }) + .collect(), + } + } + + pub(crate) fn from_fbs_ref( + mapping: rtp_parameters::RtpMappingRef<'_>, + ) -> Result> { + Ok(Self { + codecs: mapping + .codecs()? + .iter() + .map(|mapping| { + Ok(RtpMappingCodec { + payload_type: mapping?.payload_type()?, + mapped_payload_type: mapping?.mapped_payload_type()?, + }) + }) + .collect::, Box>>()?, + encodings: mapping + .encodings()? + .iter() + .map(|mapping| { + Ok(RtpMappingEncoding { + rid: mapping?.rid()?.map(|rid| rid.to_string()), + ssrc: mapping?.ssrc()?, + scalability_mode: mapping? + .scalability_mode()? + .map(|maybe_scalability_mode| maybe_scalability_mode.parse()) + .transpose()? + .unwrap_or_default(), + mapped_ssrc: mapping?.mapped_ssrc()?, + }) + }) + .collect::, Box>>()?, + }) + } +} + /// Error caused by invalid RTP parameters. #[derive(Debug, Error, Eq, PartialEq)] pub enum RtpParametersError { @@ -603,7 +663,6 @@ pub(crate) fn get_consumable_rtp_parameters( consumable_params.rtcp = RtcpParameters { cname: params.rtcp.cname.clone(), reduced_size: true, - mux: Some(true), }; consumable_params diff --git a/rust/src/ortc/tests.rs b/rust/src/ortc/tests.rs index c2be87d012..564980aa5f 100644 --- a/rust/src/ortc/tests.rs +++ b/rust/src/ortc/tests.rs @@ -368,7 +368,6 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume RtcpParameters { cname: rtp_parameters.rtcp.cname.clone(), reduced_size: true, - mux: Some(true), } ); @@ -543,7 +542,6 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume RtcpParameters { cname: rtp_parameters.rtcp.cname.clone(), reduced_size: true, - mux: Some(true), }, ); @@ -650,7 +648,6 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume RtcpParameters { cname: rtp_parameters.rtcp.cname, reduced_size: true, - mux: Some(true), }, ); } diff --git a/rust/src/prelude.rs b/rust/src/prelude.rs index f23ce3e364..63a010fd5c 100644 --- a/rust/src/prelude.rs +++ b/rust/src/prelude.rs @@ -20,8 +20,7 @@ pub use crate::router::{ }; pub use crate::webrtc_server::{ - WebRtcServer, WebRtcServerId, WebRtcServerListenInfo, WebRtcServerListenInfos, - WebRtcServerOptions, + WebRtcServer, WebRtcServerId, WebRtcServerListenInfos, WebRtcServerOptions, }; pub use crate::direct_transport::{DirectTransport, DirectTransportOptions, WeakDirectTransport}; @@ -36,7 +35,8 @@ pub use crate::transport::{ TransportId, }; pub use crate::webrtc_transport::{ - TransportListenIps, WebRtcTransport, WebRtcTransportOptions, WebRtcTransportRemoteParameters, + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, + WebRtcTransportRemoteParameters, }; pub use crate::active_speaker_observer::{ @@ -60,11 +60,13 @@ pub use crate::data_producer::{ pub use crate::producer::{Producer, ProducerId, ProducerOptions, WeakProducer}; pub use crate::data_structures::{ - AppData, DtlsParameters, IceCandidate, IceParameters, ListenIp, WebRtcMessage, + AppData, DtlsParameters, IceCandidate, IceParameters, ListenInfo, Protocol, WebRtcMessage, }; pub use crate::rtp_parameters::{ - MediaKind, MimeTypeAudio, MimeTypeVideo, RtcpFeedback, RtpCapabilities, - RtpCapabilitiesFinalized, RtpCodecCapability, RtpCodecParametersParameters, RtpParameters, + MediaKind, MimeTypeAudio, MimeTypeVideo, RtcpFeedback, RtcpParameters, RtpCapabilities, + RtpCapabilitiesFinalized, RtpCodecCapability, RtpCodecParameters, RtpCodecParametersParameters, + RtpEncodingParameters, RtpEncodingParametersRtx, RtpHeaderExtensionParameters, + RtpHeaderExtensionUri, RtpParameters, }; pub use crate::sctp_parameters::SctpStreamParameters; pub use crate::srtp_parameters::SrtpCryptoSuite; diff --git a/rust/src/router.rs b/rust/src/router.rs index 4ee29355da..c2d09a0228 100644 --- a/rust/src/router.rs +++ b/rust/src/router.rs @@ -28,7 +28,7 @@ use crate::data_consumer::{DataConsumer, DataConsumerId, DataConsumerOptions}; use crate::data_producer::{ DataProducer, DataProducerId, DataProducerOptions, NonClosingDataProducer, WeakDataProducer, }; -use crate::data_structures::{AppData, ListenIp}; +use crate::data_structures::{AppData, ListenInfo, Protocol}; use crate::direct_transport::{DirectTransport, DirectTransportOptions}; use crate::messages::{ RouterCloseRequest, RouterCreateActiveSpeakerObserverData, @@ -36,7 +36,9 @@ use crate::messages::{ RouterCreateAudioLevelObserverRequest, RouterCreateDirectTransportData, RouterCreateDirectTransportRequest, RouterCreatePipeTransportData, RouterCreatePipeTransportRequest, RouterCreatePlainTransportData, - RouterCreatePlainTransportRequest, RouterCreateWebrtcTransportRequest, RouterDumpRequest, + RouterCreatePlainTransportRequest, RouterCreateWebRtcTransportRequest, + RouterCreateWebRtcTransportWithServerRequest, RouterCreateWebrtcTransportData, + RouterDumpRequest, }; use crate::pipe_transport::{ PipeTransport, PipeTransportOptions, PipeTransportRemoteParameters, WeakPipeTransport, @@ -51,7 +53,7 @@ use crate::transport::{ TransportId, }; use crate::webrtc_transport::{WebRtcTransport, WebRtcTransportListen, WebRtcTransportOptions}; -use crate::worker::{Channel, PayloadChannel, RequestError, Worker}; +use crate::worker::{Channel, RequestError, Worker}; use crate::{ortc, uuid_based_wrapper_type}; use async_executor::Executor; use async_lock::Mutex as AsyncMutex; @@ -116,8 +118,8 @@ pub struct PipeToRouterOptions { pub router: Router, /// IP used in the PipeTransport pair. /// - /// Default `127.0.0.1`. - listen_ip: ListenIp, + /// Default `{ protocol: 'udp', ip: '127.0.0.1' }`. + listen_info: ListenInfo, /// Create a SCTP association. /// /// Default `true`. @@ -140,9 +142,13 @@ impl PipeToRouterOptions { pub fn new(router: Router) -> Self { Self { router, - listen_ip: ListenIp { + listen_info: ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }, enable_sctp: true, num_sctp_streams: NumSctpStreams::default(), @@ -170,7 +176,7 @@ pub struct PipeProducerToRouterPair { } /// Error that caused [`Router::pipe_producer_to_router()`] to fail. -#[derive(Debug, Error, Eq, PartialEq)] +#[derive(Debug, Error)] pub enum PipeProducerToRouterError { /// Destination router must be different #[error("Destination router must be different")] @@ -367,7 +373,6 @@ struct Inner { executor: Arc>, rtp_capabilities: RtpCapabilitiesFinalized, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, producers: Arc>>, @@ -441,7 +446,6 @@ impl Router { id: RouterId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, rtp_capabilities: RtpCapabilitiesFinalized, app_data: AppData, worker: Worker, @@ -473,7 +477,6 @@ impl Router { executor, rtp_capabilities, channel, - payload_channel, handlers, producers, data_producers, @@ -576,7 +579,6 @@ impl Router { transport_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), direct_transport_options.app_data, self.clone(), ); @@ -601,10 +603,14 @@ impl Router { /// /// # async fn f(router: Router) -> Result<(), Box> { /// let transport = router - /// .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - /// ListenIp { + /// .create_webrtc_transport(WebRtcTransportOptions::new(WebRtcTransportListenInfos::new( + /// ListenInfo { + /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// port: None, + /// send_buffer_size: None, + /// recv_buffer_size: None, /// }, /// ))) /// .await?; @@ -621,23 +627,41 @@ impl Router { let _buffer_guard = self.inner.channel.buffer_messages_for(transport_id.into()); - let data = self - .inner - .channel - .request( - self.inner.id, - RouterCreateWebrtcTransportRequest::from_options( - transport_id, - &webrtc_transport_options, - ), - ) - .await?; + let data = match webrtc_transport_options.listen { + WebRtcTransportListen::Individual { listen_infos: _ } => { + self.inner + .channel + .request( + self.inner.id, + RouterCreateWebRtcTransportRequest { + data: RouterCreateWebrtcTransportData::from_options( + transport_id, + &webrtc_transport_options, + ), + }, + ) + .await? + } + WebRtcTransportListen::Server { webrtc_server: _ } => { + self.inner + .channel + .request( + self.inner.id, + RouterCreateWebRtcTransportWithServerRequest { + data: RouterCreateWebrtcTransportData::from_options( + transport_id, + &webrtc_transport_options, + ), + }, + ) + .await? + } + }; let transport = WebRtcTransport::new( transport_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), data, webrtc_transport_options.app_data, self.clone(), @@ -667,9 +691,13 @@ impl Router { /// /// # async fn f(router: Router) -> Result<(), Box> { /// let transport = router - /// .create_pipe_transport(PipeTransportOptions::new(ListenIp { + /// .create_pipe_transport(PipeTransportOptions::new(ListenInfo { + /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// port: None, + /// send_buffer_size: None, + /// recv_buffer_size: None, /// })) /// .await?; /// # Ok(()) @@ -703,7 +731,6 @@ impl Router { transport_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), data, pipe_transport_options.app_data, self.clone(), @@ -729,9 +756,13 @@ impl Router { /// /// # async fn f(router: Router) -> Result<(), Box> { /// let transport = router - /// .create_plain_transport(PlainTransportOptions::new(ListenIp { + /// .create_plain_transport(PlainTransportOptions::new(ListenInfo { + /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// port: None, + /// send_buffer_size: None, + /// recv_buffer_size: None, /// })) /// .await?; /// # Ok(()) @@ -765,7 +796,6 @@ impl Router { transport_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), data, plain_transport_options.app_data, self.clone(), @@ -935,10 +965,14 @@ impl Router { /// /// // Produce in router1. /// let transport1 = router1 - /// .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - /// ListenIp { + /// .create_webrtc_transport(WebRtcTransportOptions::new(WebRtcTransportListenInfos::new( + /// ListenInfo { + /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// port: None, + /// send_buffer_size: None, + /// recv_buffer_size: None, /// }, /// ))) /// .await?; @@ -973,10 +1007,14 @@ impl Router { /// /// // Consume producer1 from router2. /// let transport2 = router2 - /// .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - /// ListenIp { + /// .create_webrtc_transport(WebRtcTransportOptions::new(WebRtcTransportListenInfos::new( + /// ListenInfo { + /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// port: None, + /// send_buffer_size: None, + /// recv_buffer_size: None, /// }, /// ))) /// .await?; @@ -1154,10 +1192,14 @@ impl Router { /// // Produce in router1. /// let transport1 = router1 /// .create_webrtc_transport({ - /// let mut options = WebRtcTransportOptions::new(TransportListenIps::new( - /// ListenIp { + /// let mut options = WebRtcTransportOptions::new(WebRtcTransportListenInfos::new( + /// ListenInfo { + /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// port: None, + /// send_buffer_size: None, + /// recv_buffer_size: None, /// }, /// )); /// options.enable_sctp = true; @@ -1181,10 +1223,14 @@ impl Router { /// // Consume data_producer1 from router2. /// let transport2 = router2 /// .create_webrtc_transport({ - /// let mut options = WebRtcTransportOptions::new(TransportListenIps::new( - /// ListenIp { + /// let mut options = WebRtcTransportOptions::new(WebRtcTransportListenInfos::new( + /// ListenInfo { + /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// port: None, + /// send_buffer_size: None, + /// recv_buffer_size: None, /// }, /// )); /// options.enable_sctp = true; @@ -1400,7 +1446,7 @@ impl Router { ) -> Result { let PipeToRouterOptions { router, - listen_ip, + listen_info, enable_sctp, num_sctp_streams, enable_rtx, @@ -1415,7 +1461,7 @@ impl Router { enable_rtx, enable_srtp, app_data: AppData::default(), - ..PipeTransportOptions::new(listen_ip) + ..PipeTransportOptions::new(listen_info) }; let local_pipe_transport_fut = self.create_pipe_transport(transport_options.clone()); diff --git a/rust/src/router/active_speaker_observer.rs b/rust/src/router/active_speaker_observer.rs index 5999f04526..3707ea9ba0 100644 --- a/rust/src/router/active_speaker_observer.rs +++ b/rust/src/router/active_speaker_observer.rs @@ -9,11 +9,12 @@ use crate::messages::{ use crate::producer::{Producer, ProducerId}; use crate::router::Router; use crate::rtp_observer::{RtpObserver, RtpObserverAddProducerOptions, RtpObserverId}; -use crate::worker::{Channel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, NotificationParseError, RequestError, SubscriptionHandler}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; +use mediasoup_sys::fbs::notification; use parking_lot::Mutex; use serde::Deserialize; use std::fmt; @@ -74,6 +75,29 @@ enum Notification { DominantSpeaker(DominantSpeakerNotification), } +impl Notification { + pub(crate) fn from_fbs( + notification: notification::NotificationRef<'_>, + ) -> Result { + match notification.event().unwrap() { + notification::Event::ActivespeakerobserverDominantSpeaker => { + let Ok(Some( + notification::BodyRef::ActiveSpeakerObserverDominantSpeakerNotification(body), + )) = notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let dominant_speaker_notification = DominantSpeakerNotification { + producer_id: body.producer_id().unwrap().parse().unwrap(), + }; + Ok(Notification::DominantSpeaker(dominant_speaker_notification)) + } + _ => Err(NotificationParseError::InvalidEvent), + } + } +} + struct Inner { id: RtpObserverId, executor: Arc>, @@ -294,7 +318,7 @@ impl ActiveSpeakerObserver { let handlers = Arc::clone(&handlers); channel.subscribe_to_notifications(id.into(), move |notification| { - match serde_json::from_slice::(notification) { + match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::DominantSpeaker(dominant_speaker) => { let DominantSpeakerNotification { producer_id } = dominant_speaker; diff --git a/rust/src/router/audio_level_observer.rs b/rust/src/router/audio_level_observer.rs index cd55b6adff..e696d4c715 100644 --- a/rust/src/router/audio_level_observer.rs +++ b/rust/src/router/audio_level_observer.rs @@ -9,11 +9,12 @@ use crate::messages::{ use crate::producer::{Producer, ProducerId}; use crate::router::Router; use crate::rtp_observer::{RtpObserver, RtpObserverAddProducerOptions, RtpObserverId}; -use crate::worker::{Channel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, NotificationParseError, RequestError, SubscriptionHandler}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; +use mediasoup_sys::fbs::{audio_level_observer, notification}; use parking_lot::Mutex; use serde::Deserialize; use std::fmt; @@ -85,6 +86,40 @@ enum Notification { Silence, } +impl Notification { + pub(crate) fn from_fbs( + notification: notification::NotificationRef<'_>, + ) -> Result { + match notification.event().unwrap() { + notification::Event::AudiolevelobserverVolumes => { + let Ok(Some(notification::BodyRef::AudioLevelObserverVolumesNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let volumes_fbs: Vec<_> = body + .volumes() + .unwrap() + .iter() + .map(|volume| audio_level_observer::Volume::try_from(volume.unwrap()).unwrap()) + .collect(); + let volumes = volumes_fbs + .iter() + .map(|volume| VolumeNotification { + producer_id: volume.producer_id.parse().unwrap(), + volume: volume.volume, + }) + .collect(); + + Ok(Notification::Volumes(volumes)) + } + notification::Event::AudiolevelobserverSilence => Ok(Notification::Silence), + _ => Err(NotificationParseError::InvalidEvent), + } + } +} + struct Inner { id: RtpObserverId, executor: Arc>, @@ -305,7 +340,7 @@ impl AudioLevelObserver { let handlers = Arc::clone(&handlers); channel.subscribe_to_notifications(id.into(), move |notification| { - match serde_json::from_slice::(notification) { + match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::Volumes(volumes) => { let volumes = volumes diff --git a/rust/src/router/consumer.rs b/rust/src/router/consumer.rs index 7cc9e6b223..cfc6e0697d 100644 --- a/rust/src/router/consumer.rs +++ b/rust/src/router/consumer.rs @@ -8,16 +8,21 @@ use crate::messages::{ ConsumerResumeRequest, ConsumerSetPreferredLayersRequest, ConsumerSetPriorityRequest, }; use crate::producer::{Producer, ProducerId, ProducerStat, ProducerType, WeakProducer}; -use crate::rtp_parameters::{MediaKind, MimeType, RtpCapabilities, RtpParameters}; -use crate::scalability_modes::ScalabilityMode; +use crate::rtp_parameters::{ + MediaKind, MimeType, RtpCapabilities, RtpEncodingParameters, RtpParameters, +}; use crate::transport::Transport; use crate::uuid_based_wrapper_type; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, NotificationParseError, RequestError, SubscriptionHandler}; use async_executor::Executor; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; +use mediasoup_sys::fbs::{ + consumer, notification, response, rtp_parameters, rtp_stream, rtx_stream, +}; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; +use std::error::Error; use std::fmt; use std::fmt::Debug; use std::sync::atomic::{AtomicBool, Ordering}; @@ -38,6 +43,22 @@ pub struct ConsumerLayers { pub temporal_layer: Option, } +impl ConsumerLayers { + pub(crate) fn to_fbs(self) -> consumer::ConsumerLayers { + consumer::ConsumerLayers { + spatial_layer: self.spatial_layer, + temporal_layer: self.temporal_layer, + } + } + + pub(crate) fn from_fbs(consumer_layers: consumer::ConsumerLayers) -> Self { + Self { + spatial_layer: consumer_layers.spatial_layer, + temporal_layer: consumer_layers.temporal_layer, + } + } +} + /// Score of consumer and corresponding producer. #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -53,6 +74,16 @@ pub struct ConsumerScore { pub producer_scores: Vec, } +impl ConsumerScore { + pub(crate) fn from_fbs(consumer_score: consumer::ConsumerScore) -> Self { + Self { + score: consumer_score.score, + producer_score: consumer_score.producer_score, + producer_scores: consumer_score.producer_scores.into_iter().collect(), + } + } +} + /// [`Consumer`] options. #[derive(Debug, Clone)] #[non_exhaustive] @@ -116,7 +147,7 @@ impl ConsumerOptions { pub struct RtpStreamParams { pub clock_rate: u32, pub cname: String, - pub encoding_idx: usize, + pub encoding_idx: u32, pub mime_type: MimeType, pub payload_type: u8, pub spatial_layers: u8, @@ -127,41 +158,79 @@ pub struct RtpStreamParams { pub use_nack: bool, pub use_pli: bool, pub rid: Option, - pub rtc_ssrc: Option, - pub rtc_payload_type: Option, + pub rtx_ssrc: Option, + pub rtx_payload_type: Option, +} + +impl RtpStreamParams { + pub(crate) fn from_fbs_ref(params: rtp_stream::ParamsRef<'_>) -> Result> { + Ok(Self { + clock_rate: params.clock_rate()?, + cname: params.cname()?.to_string(), + encoding_idx: params.encoding_idx()?, + mime_type: params.mime_type()?.parse()?, + payload_type: params.payload_type()?, + spatial_layers: params.spatial_layers()?, + ssrc: params.ssrc()?, + temporal_layers: params.temporal_layers()?, + use_dtx: params.use_dtx()?, + use_in_band_fec: params.use_in_band_fec()?, + use_nack: params.use_nack()?, + use_pli: params.use_pli()?, + rid: params.rid()?.map(|rid| rid.to_string()), + rtx_ssrc: params.rtx_ssrc()?, + rtx_payload_type: params.rtx_payload_type()?, + }) + } } #[derive(Debug, Clone, PartialOrd, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] #[doc(hidden)] -pub struct RtpStream { - pub params: RtpStreamParams, - pub score: u8, +pub struct RtxStreamParams { + pub clock_rate: u32, + pub cname: String, + pub mime_type: MimeType, + pub payload_type: u8, + pub ssrc: u32, + pub rrid: Option, +} + +impl RtxStreamParams { + pub(crate) fn from_fbs_ref(params: rtx_stream::ParamsRef<'_>) -> Result> { + Ok(Self { + clock_rate: params.clock_rate()?, + cname: params.cname()?.to_string(), + mime_type: params.mime_type()?.parse()?, + payload_type: params.payload_type()?, + ssrc: params.ssrc()?, + rrid: params.rrid()?.map(|rrid| rrid.to_string()), + }) + } } #[derive(Debug, Clone, PartialOrd, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] #[doc(hidden)] -pub struct RtpRtxParameters { - pub ssrc: Option, +pub struct RtpStream { + pub params: RtpStreamParams, + pub score: u8, +} + +impl RtpStream { + pub(crate) fn from_fbs_ref(dump: rtp_stream::DumpRef<'_>) -> Result> { + Ok(Self { + params: RtpStreamParams::from_fbs_ref(dump.params()?)?, + score: dump.score()?, + }) + } } -#[derive(Debug, Clone, PartialOrd, PartialEq, Deserialize, Serialize)] +#[derive(Debug, Clone, PartialOrd, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] #[doc(hidden)] -pub struct ConsumableRtpEncoding { +pub struct RtpRtxParameters { pub ssrc: Option, - pub rid: Option, - pub codec_payload_type: Option, - pub rtx: Option, - pub max_bitrate: Option, - pub max_framerate: Option, - pub dtx: Option, - #[serde(default, skip_serializing_if = "ScalabilityMode::is_none")] - pub scalability_mode: ScalabilityMode, - pub spatial_layers: Option, - pub temporal_layers: Option, - pub ksvc: Option, } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -177,10 +246,10 @@ pub struct ConsumerDump { pub producer_paused: bool, pub rtp_parameters: RtpParameters, pub supported_codec_payload_types: Vec, - pub trace_event_types: String, + pub trace_event_types: Vec, pub r#type: ConsumerType, - pub consumable_rtp_encodings: Vec, - pub rtp_stream: RtpStream, + pub consumable_rtp_encodings: Vec, + pub rtp_streams: Vec, /// Essentially `Option` or `Option<-1>` pub preferred_spatial_layer: Option, /// Essentially `Option` or `Option<-1>` @@ -195,6 +264,53 @@ pub struct ConsumerDump { pub current_temporal_layer: Option, } +impl ConsumerDump { + pub(crate) fn from_fbs_ref( + dump: consumer::DumpResponseRef<'_>, + ) -> Result> { + let dump = dump.data(); + + Ok(Self { + id: dump?.base()?.id()?.parse()?, + kind: MediaKind::from_fbs(dump?.base()?.kind()?), + paused: dump?.base()?.paused()?, + priority: dump?.base()?.priority()?, + producer_id: dump?.base()?.producer_id()?.parse()?, + producer_paused: dump?.base()?.producer_paused()?, + rtp_parameters: RtpParameters::from_fbs_ref(dump?.base()?.rtp_parameters()?)?, + supported_codec_payload_types: Vec::from( + dump?.base()?.supported_codec_payload_types()?, + ), + trace_event_types: dump? + .base()? + .trace_event_types()? + .iter() + .map(|trace_event_type| Ok(ConsumerTraceEventType::from_fbs(trace_event_type?))) + .collect::>>()?, + r#type: ConsumerType::from_fbs(dump?.base()?.type_()?), + consumable_rtp_encodings: dump? + .base()? + .consumable_rtp_encodings()? + .iter() + .map(|encoding_parameters| { + RtpEncodingParameters::from_fbs_ref(encoding_parameters?) + }) + .collect::>>()?, + rtp_streams: dump? + .rtp_streams()? + .iter() + .map(|stream| RtpStream::from_fbs_ref(stream?)) + .collect::>>()?, + preferred_spatial_layer: dump?.preferred_spatial_layer()?, + target_spatial_layer: dump?.target_spatial_layer()?, + current_spatial_layer: dump?.current_spatial_layer()?, + preferred_temporal_layer: dump?.preferred_temporal_layer()?, + target_temporal_layer: dump?.target_temporal_layer()?, + current_temporal_layer: dump?.current_temporal_layer()?, + }) + } +} + /// Consumer type. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -220,6 +336,26 @@ impl From for ConsumerType { } } +impl ConsumerType { + pub(crate) fn to_fbs(self) -> rtp_parameters::Type { + match self { + ConsumerType::Simple => rtp_parameters::Type::Simple, + ConsumerType::Simulcast => rtp_parameters::Type::Simulcast, + ConsumerType::Svc => rtp_parameters::Type::Svc, + ConsumerType::Pipe => rtp_parameters::Type::Pipe, + } + } + + pub(crate) fn from_fbs(r#type: rtp_parameters::Type) -> ConsumerType { + match r#type { + rtp_parameters::Type::Simple => ConsumerType::Simple, + rtp_parameters::Type::Simulcast => ConsumerType::Simulcast, + rtp_parameters::Type::Svc => ConsumerType::Svc, + rtp_parameters::Type::Pipe => ConsumerType::Pipe, + } + } +} + /// RTC statistics of the consumer alone. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -233,22 +369,56 @@ pub struct ConsumerStat { pub rtx_ssrc: Option, pub kind: MediaKind, pub mime_type: MimeType, - pub packets_lost: u32, + pub packets_lost: u64, pub fraction_lost: u8, - pub packets_discarded: usize, - pub packets_retransmitted: usize, - pub packets_repaired: usize, - pub nack_count: usize, - pub nack_packet_count: usize, - pub pli_count: usize, - pub fir_count: usize, + pub packets_discarded: u64, + pub packets_retransmitted: u64, + pub packets_repaired: u64, + pub nack_count: u64, + pub nack_packet_count: u64, + pub pli_count: u64, + pub fir_count: u64, pub score: u8, - pub packet_count: usize, - pub byte_count: usize, + pub packet_count: u64, + pub byte_count: u64, pub bitrate: u32, pub round_trip_time: Option, } +impl ConsumerStat { + pub(crate) fn from_fbs(stats: &rtp_stream::Stats) -> Self { + let rtp_stream::StatsData::SendStats(ref stats) = stats.data else { + panic!("Wrong message from worker"); + }; + + let rtp_stream::StatsData::BaseStats(ref base) = stats.base.data else { + panic!("Wrong message from worker"); + }; + + Self { + timestamp: base.timestamp, + ssrc: base.ssrc, + rtx_ssrc: base.rtx_ssrc, + kind: MediaKind::from_fbs(base.kind), + mime_type: base.mime_type.to_string().parse().unwrap(), + packets_lost: base.packets_lost, + fraction_lost: base.fraction_lost, + packets_discarded: base.packets_discarded, + packets_retransmitted: base.packets_retransmitted, + packets_repaired: base.packets_repaired, + nack_count: base.nack_count, + nack_packet_count: base.nack_packet_count, + pli_count: base.pli_count, + fir_count: base.fir_count, + score: base.score, + packet_count: stats.packet_count, + byte_count: stats.byte_count, + bitrate: stats.bitrate, + round_trip_time: Some(base.round_trip_time), + } + } +} + /// RTC statistics of the consumer, may or may not include producer statistics. #[allow(clippy::large_enum_variant)] #[derive(Debug, Deserialize, Serialize)] @@ -319,6 +489,61 @@ pub enum ConsumerTraceEventData { }, } +impl ConsumerTraceEventData { + pub(crate) fn from_fbs(data: consumer::TraceNotification) -> Self { + match data.type_ { + consumer::TraceEventType::Rtp => ConsumerTraceEventData::Rtp { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(consumer::TraceInfo::RtpTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + RtpPacketTraceInfo::from_fbs(*info.rtp_packet, info.is_rtx) + }, + }, + consumer::TraceEventType::Keyframe => ConsumerTraceEventData::KeyFrame { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(consumer::TraceInfo::KeyFrameTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + RtpPacketTraceInfo::from_fbs(*info.rtp_packet, info.is_rtx) + }, + }, + consumer::TraceEventType::Nack => ConsumerTraceEventData::Nack { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + }, + consumer::TraceEventType::Pli => ConsumerTraceEventData::Pli { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(consumer::TraceInfo::PliTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + SsrcTraceInfo { ssrc: info.ssrc } + }, + }, + consumer::TraceEventType::Fir => ConsumerTraceEventData::Fir { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(consumer::TraceInfo::FirTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + SsrcTraceInfo { ssrc: info.ssrc } + }, + }, + } + } +} + /// Types of consumer trace events. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -335,21 +560,88 @@ pub enum ConsumerTraceEventType { Fir, } +impl ConsumerTraceEventType { + pub(crate) fn to_fbs(self) -> consumer::TraceEventType { + match self { + ConsumerTraceEventType::Rtp => consumer::TraceEventType::Rtp, + ConsumerTraceEventType::KeyFrame => consumer::TraceEventType::Keyframe, + ConsumerTraceEventType::Nack => consumer::TraceEventType::Nack, + ConsumerTraceEventType::Pli => consumer::TraceEventType::Pli, + ConsumerTraceEventType::Fir => consumer::TraceEventType::Fir, + } + } + + pub(crate) fn from_fbs(event_type: consumer::TraceEventType) -> Self { + match event_type { + consumer::TraceEventType::Rtp => ConsumerTraceEventType::Rtp, + consumer::TraceEventType::Keyframe => ConsumerTraceEventType::KeyFrame, + consumer::TraceEventType::Nack => ConsumerTraceEventType::Nack, + consumer::TraceEventType::Pli => ConsumerTraceEventType::Pli, + consumer::TraceEventType::Fir => ConsumerTraceEventType::Fir, + } + } +} #[derive(Debug, Deserialize)] #[serde(tag = "event", rename_all = "lowercase", content = "data")] enum Notification { ProducerClose, ProducerPause, ProducerResume, + // TODO. + // Rtp, Score(ConsumerScore), LayersChange(Option), Trace(ConsumerTraceEventData), } -#[derive(Debug, Deserialize)] -#[serde(tag = "event", rename_all = "lowercase", content = "data")] -enum PayloadNotification { - Rtp, +impl Notification { + pub(crate) fn from_fbs( + notification: notification::NotificationRef<'_>, + ) -> Result { + match notification.event().unwrap() { + notification::Event::ConsumerProducerClose => Ok(Notification::ProducerClose), + notification::Event::ConsumerProducerPause => Ok(Notification::ProducerPause), + notification::Event::ConsumerProducerResume => Ok(Notification::ProducerResume), + notification::Event::ConsumerScore => { + let Ok(Some(notification::BodyRef::ConsumerScoreNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let score_fbs = consumer::ConsumerScore::try_from(body.score().unwrap()).unwrap(); + let score = ConsumerScore::from_fbs(score_fbs); + + Ok(Notification::Score(score)) + } + notification::Event::ConsumerLayersChange => { + let Ok(Some(notification::BodyRef::ConsumerLayersChangeNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let layers_fbs = + consumer::ConsumerLayers::try_from(body.layers().unwrap()).unwrap(); + let layers = ConsumerLayers::from_fbs(layers_fbs); + + Ok(Notification::LayersChange(Some(layers))) + } + notification::Event::ConsumerTrace => { + let Ok(Some(notification::BodyRef::ConsumerTraceNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let trace_notification_fbs = consumer::TraceNotification::try_from(body).unwrap(); + let trace_notification = ConsumerTraceEventData::from_fbs(trace_notification_fbs); + + Ok(Notification::Trace(trace_notification)) + } + _ => Err(NotificationParseError::InvalidEvent), + } + } } #[derive(Default)] @@ -468,7 +760,6 @@ impl Consumer { paused: bool, executor: Arc>, channel: Channel, - payload_channel: &PayloadChannel, producer_paused: bool, score: ConsumerScore, preferred_layers: Option, @@ -497,7 +788,7 @@ impl Consumer { let inner_weak = Arc::clone(&inner_weak); channel.subscribe_to_notifications(id.into(), move |notification| { - match serde_json::from_slice::(notification) { + match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::ProducerClose => { if !closed.load(Ordering::SeqCst) { @@ -541,6 +832,14 @@ impl Consumer { handlers.resume.call_simple(); } } + /* + * TODO. + Notification::Rtp => { + handlers.rtp.call(|callback| { + callback(notification); + }); + } + */ Notification::Score(consumer_score) => { *score.lock() = consumer_score.clone(); handlers.score.call_simple(&consumer_score); @@ -560,25 +859,6 @@ impl Consumer { }) }; - let payload_subscription_handler = { - let handlers = Arc::clone(&handlers); - - payload_channel.subscribe_to_notifications(id.into(), move |message, payload| { - match serde_json::from_slice::(message) { - Ok(notification) => match notification { - PayloadNotification::Rtp => { - handlers.rtp.call(|callback| { - callback(payload); - }); - } - }, - Err(error) => { - error!("Failed to parse payload notification: {}", error); - } - } - }) - }; - let on_transport_close_handler = transport.on_close({ let inner_weak = Arc::clone(&inner_weak); @@ -609,10 +889,7 @@ impl Consumer { transport, weak_producer: producer.downgrade(), closed, - _subscription_handlers: Mutex::new(vec![ - subscription_handler, - payload_subscription_handler, - ]), + _subscription_handlers: Mutex::new(vec![subscription_handler]), _on_transport_close_handler: Mutex::new(on_transport_close_handler), }); @@ -730,10 +1007,30 @@ impl Consumer { pub async fn get_stats(&self) -> Result { debug!("get_stats()"); - self.inner + let response = self + .inner .channel .request(self.id(), ConsumerGetStatsRequest {}) - .await + .await; + + if let Ok(response::Body::ConsumerGetStatsResponse(data)) = response { + match data.stats.len() { + 0 => panic!("Empty stats response from worker"), + 1 => { + let consumer_stat = ConsumerStat::from_fbs(&data.stats[0]); + + Ok(ConsumerStats::JustConsumer((consumer_stat,))) + } + _ => { + let consumer_stat = ConsumerStat::from_fbs(&data.stats[0]); + let producer_stat = ProducerStat::from_fbs(&data.stats[1]); + + Ok(ConsumerStats::WithProducer((consumer_stat, producer_stat))) + } + } + } else { + panic!("Wrong message from worker"); + } } /// Pauses the consumer (no RTP is sent to the consuming endpoint). diff --git a/rust/src/router/consumer/tests.rs b/rust/src/router/consumer/tests.rs index 62d7a69b4c..8f4fe2a74a 100644 --- a/rust/src/router/consumer/tests.rs +++ b/rust/src/router/consumer/tests.rs @@ -1,5 +1,5 @@ use crate::consumer::ConsumerOptions; -use crate::data_structures::ListenIp; +use crate::data_structures::{ListenInfo, Protocol}; use crate::producer::ProducerOptions; use crate::router::{Router, RouterOptions}; use crate::rtp_parameters::{ @@ -7,7 +7,9 @@ use crate::rtp_parameters::{ RtpCodecParametersParameters, RtpParameters, }; use crate::transport::Transport; -use crate::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use crate::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use crate::worker::WorkerSettings; use crate::worker_manager::WorkerManager; use futures_lite::future; @@ -79,10 +81,15 @@ async fn init() -> (Router, WebRtcTransport, WebRtcTransport) { .await .expect("Failed to create router"); - let transport_options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); let transport_1 = router .create_webrtc_transport(transport_options.clone()) diff --git a/rust/src/router/data_consumer.rs b/rust/src/router/data_consumer.rs index 5477e31400..2b7fe52e5b 100644 --- a/rust/src/router/data_consumer.rs +++ b/rust/src/router/data_consumer.rs @@ -5,19 +5,24 @@ use crate::data_producer::{DataProducer, DataProducerId, WeakDataProducer}; use crate::data_structures::{AppData, WebRtcMessage}; use crate::messages::{ DataConsumerCloseRequest, DataConsumerDumpRequest, DataConsumerGetBufferedAmountRequest, - DataConsumerGetStatsRequest, DataConsumerSendRequest, - DataConsumerSetBufferedAmountLowThresholdRequest, + DataConsumerGetStatsRequest, DataConsumerPauseRequest, DataConsumerResumeRequest, + DataConsumerSendRequest, DataConsumerSetBufferedAmountLowThresholdRequest, + DataConsumerSetSubchannelsRequest, }; use crate::sctp_parameters::SctpStreamParameters; use crate::transport::Transport; use crate::uuid_based_wrapper_type; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, NotificationParseError, RequestError, SubscriptionHandler}; use async_executor::Executor; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; +use mediasoup_sys::fbs::{data_consumer, data_producer, notification, response}; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; use std::borrow::Cow; +use std::error::Error; +// TODO. +// use std::borrow::Cow; use std::fmt; use std::fmt::Debug; use std::sync::atomic::{AtomicBool, Ordering}; @@ -50,6 +55,12 @@ pub struct DataConsumerOptions { /// Defaults to the value in the [`DataProducer`](crate::data_producer::DataProducer) if it /// has type `Sctp` or unset if it has type `Direct`. pub(super) max_retransmits: Option, + /// Whether the DataConsumer must start in paused mode. Default false. + pub paused: bool, + /// Subchannels this DataConsumer initially subscribes to. + /// Only used in case this DataConsumer receives messages from a local DataProducer + /// that specifies subchannel(s) when calling send(). + pub subchannels: Option>, /// Custom application data. pub app_data: AppData, } @@ -64,18 +75,22 @@ impl DataConsumerOptions { ordered: None, max_packet_life_time: None, max_retransmits: None, + subchannels: None, + paused: false, app_data: AppData::default(), } } /// For [`DirectTransport`](crate::direct_transport::DirectTransport). #[must_use] - pub fn new_direct(data_producer_id: DataProducerId) -> Self { + pub fn new_direct(data_producer_id: DataProducerId, subchannels: Option>) -> Self { Self { data_producer_id, ordered: Some(true), max_packet_life_time: None, max_retransmits: None, + paused: false, + subchannels, app_data: AppData::default(), } } @@ -88,6 +103,8 @@ impl DataConsumerOptions { ordered: None, max_packet_life_time: None, max_retransmits: None, + paused: false, + subchannels: None, app_data: AppData::default(), } } @@ -104,6 +121,8 @@ impl DataConsumerOptions { ordered: None, max_packet_life_time: Some(max_packet_life_time), max_retransmits: None, + paused: false, + subchannels: None, app_data: AppData::default(), } } @@ -119,6 +138,8 @@ impl DataConsumerOptions { ordered: None, max_packet_life_time: None, max_retransmits: Some(max_retransmits), + paused: false, + subchannels: None, app_data: AppData::default(), } } @@ -136,6 +157,32 @@ pub struct DataConsumerDump { pub protocol: String, pub sctp_stream_parameters: Option, pub buffered_amount_low_threshold: u32, + pub paused: bool, + pub subchannels: Vec, + pub data_producer_paused: bool, +} + +impl DataConsumerDump { + pub(crate) fn from_fbs(dump: data_consumer::DumpResponse) -> Result> { + Ok(Self { + id: dump.id.parse()?, + data_producer_id: dump.data_producer_id.parse()?, + r#type: if dump.type_ == data_producer::Type::Sctp { + DataConsumerType::Sctp + } else { + DataConsumerType::Direct + }, + label: dump.label, + protocol: dump.protocol, + sctp_stream_parameters: dump + .sctp_stream_parameters + .map(|parameters| SctpStreamParameters::from_fbs(*parameters)), + buffered_amount_low_threshold: dump.buffered_amount_low_threshold, + paused: dump.paused, + subchannels: dump.subchannels, + data_producer_paused: dump.data_producer_paused, + }) + } } /// RTC statistics of the data consumer. @@ -148,11 +195,24 @@ pub struct DataConsumerStat { pub timestamp: u64, pub label: String, pub protocol: String, - pub messages_sent: usize, - pub bytes_sent: usize, + pub messages_sent: u64, + pub bytes_sent: u64, pub buffered_amount: u32, } +impl DataConsumerStat { + pub(crate) fn from_fbs(stats: &data_consumer::GetStatsResponse) -> Self { + Self { + timestamp: stats.timestamp, + label: stats.label.to_string(), + protocol: stats.protocol.to_string(), + messages_sent: stats.messages_sent, + bytes_sent: stats.bytes_sent, + buffered_amount: stats.buffered_amount, + } + } +} + /// Data consumer type. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -167,17 +227,63 @@ pub enum DataConsumerType { #[serde(tag = "event", rename_all = "lowercase", content = "data")] enum Notification { DataProducerClose, + DataProducerPause, + DataProducerResume, SctpSendBufferFull, + Message { + ppid: u32, + data: Vec, + }, #[serde(rename_all = "camelCase")] BufferedAmountLow { buffered_amount: u32, }, } -#[derive(Debug, Deserialize)] -#[serde(tag = "event", rename_all = "lowercase", content = "data")] -enum PayloadNotification { - Message { ppid: u32 }, +impl Notification { + pub(crate) fn from_fbs( + notification: notification::NotificationRef<'_>, + ) -> Result { + match notification.event().unwrap() { + notification::Event::DataconsumerDataproducerClose => { + Ok(Notification::DataProducerClose) + } + notification::Event::DataconsumerDataproducerPause => { + Ok(Notification::DataProducerPause) + } + notification::Event::DataconsumerDataproducerResume => { + Ok(Notification::DataProducerResume) + } + notification::Event::DataconsumerSctpSendbufferFull => { + Ok(Notification::SctpSendBufferFull) + } + notification::Event::DataconsumerMessage => { + let Ok(Some(notification::BodyRef::DataConsumerMessageNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + Ok(Notification::Message { + ppid: body.ppid().unwrap(), + data: body.data().unwrap().into(), + }) + } + notification::Event::DataconsumerBufferedAmountLow => { + let Ok(Some(notification::BodyRef::DataConsumerBufferedAmountLowNotification( + body, + ))) = notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + Ok(Notification::BufferedAmountLow { + buffered_amount: body.buffered_amount().unwrap(), + }) + } + _ => Err(NotificationParseError::InvalidEvent), + } + } } #[derive(Default)] @@ -187,6 +293,10 @@ struct Handlers { sctp_send_buffer_full: Bag>, buffered_amount_low: Bag>, data_producer_close: BagOnce>, + pause: Bag>, + resume: Bag>, + data_producer_pause: Bag>, + data_producer_resume: Bag>, transport_close: BagOnce>, close: BagOnce>, } @@ -199,9 +309,11 @@ struct Inner { protocol: String, data_producer_id: DataProducerId, direct: bool, + paused: Arc>, + subchannels: Arc>>, + data_producer_paused: Arc>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, transport: Arc, @@ -267,6 +379,8 @@ impl fmt::Debug for RegularDataConsumer { .field("label", &self.inner.label) .field("protocol", &self.inner.protocol) .field("data_producer_id", &self.inner.data_producer_id) + .field("paused", &self.inner.paused) + .field("data_producer_paused", &self.inner.data_producer_paused) .field("transport", &self.inner.transport) .field("closed", &self.inner.closed) .finish() @@ -295,6 +409,8 @@ impl fmt::Debug for DirectDataConsumer { .field("label", &self.inner.label) .field("protocol", &self.inner.protocol) .field("data_producer_id", &self.inner.data_producer_id) + .field("paused", &self.inner.paused) + .field("data_producer_paused", &self.inner.data_producer_paused) .field("transport", &self.inner.transport) .field("closed", &self.inner.closed) .finish() @@ -342,10 +458,12 @@ impl DataConsumer { sctp_stream_parameters: Option, label: String, protocol: String, + paused: bool, data_producer: DataProducer, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, + data_producer_paused: bool, + subchannels: Vec, app_data: AppData, transport: Arc, direct: bool, @@ -354,15 +472,21 @@ impl DataConsumer { let handlers = Arc::::default(); let closed = Arc::new(AtomicBool::new(false)); + let paused = Arc::new(Mutex::new(paused)); + #[allow(clippy::mutex_atomic)] + let data_producer_paused = Arc::new(Mutex::new(data_producer_paused)); + let subchannels = Arc::new(Mutex::new(subchannels)); let inner_weak = Arc::>>>::default(); let subscription_handler = { let handlers = Arc::clone(&handlers); let closed = Arc::clone(&closed); + let paused = Arc::clone(&paused); + let data_producer_paused = Arc::clone(&data_producer_paused); let inner_weak = Arc::clone(&inner_weak); channel.subscribe_to_notifications(id.into(), move |notification| { - match serde_json::from_slice::(notification) { + match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::DataProducerClose => { if !closed.load(Ordering::SeqCst) { @@ -383,30 +507,34 @@ impl DataConsumer { } } } - Notification::SctpSendBufferFull => { - handlers.sctp_send_buffer_full.call_simple(); - } - Notification::BufferedAmountLow { buffered_amount } => { - handlers.buffered_amount_low.call(|callback| { - callback(buffered_amount); - }); + Notification::DataProducerPause => { + let mut data_producer_paused = data_producer_paused.lock(); + let was_paused = *paused.lock() || *data_producer_paused; + *data_producer_paused = true; + + handlers.data_producer_pause.call_simple(); + + if !was_paused { + handlers.pause.call_simple(); + } } - }, - Err(error) => { - error!("Failed to parse notification: {}", error); - } - } - }) - }; + Notification::DataProducerResume => { + let mut data_producer_paused = data_producer_paused.lock(); + let paused = *paused.lock(); + let was_paused = paused || *data_producer_paused; + *data_producer_paused = false; - let payload_subscription_handler = { - let handlers = Arc::clone(&handlers); + handlers.data_producer_resume.call_simple(); - payload_channel.subscribe_to_notifications(id.into(), move |message, payload| { - match serde_json::from_slice::(message) { - Ok(notification) => match notification { - PayloadNotification::Message { ppid } => { - match WebRtcMessage::new(ppid, Cow::from(payload)) { + if was_paused && !paused { + handlers.resume.call_simple(); + } + } + Notification::SctpSendBufferFull => { + handlers.sctp_send_buffer_full.call_simple(); + } + Notification::Message { ppid, data } => { + match WebRtcMessage::new(ppid, Cow::from(data)) { Ok(message) => { handlers.message.call(|callback| { callback(&message); @@ -417,9 +545,14 @@ impl DataConsumer { } } } + Notification::BufferedAmountLow { buffered_amount } => { + handlers.buffered_amount_low.call(|callback| { + callback(buffered_amount); + }); + } }, Err(error) => { - error!("Failed to parse payload notification: {}", error); + error!("Failed to parse notification: {}", error); } } }) @@ -443,19 +576,18 @@ impl DataConsumer { label, protocol, data_producer_id: data_producer.id(), + paused, + data_producer_paused, direct, executor, channel, - payload_channel, handlers, + subchannels, app_data, transport, weak_data_producer: data_producer.downgrade(), closed, - _subscription_handlers: Mutex::new(vec![ - subscription_handler, - payload_subscription_handler, - ]), + _subscription_handlers: Mutex::new(vec![subscription_handler]), _on_transport_close_handler: Mutex::new(on_transport_close_handler), }); @@ -491,6 +623,19 @@ impl DataConsumer { self.inner().r#type } + /// Whether the data consumer is paused. It does not take into account whether the + /// associated data producer is paused. + #[must_use] + pub fn paused(&self) -> bool { + *self.inner().paused.lock() + } + + /// Whether the associate data producer is paused. + #[must_use] + pub fn producer_paused(&self) -> bool { + *self.inner().data_producer_paused.lock() + } + /// The SCTP stream parameters (just if the data consumer type is `Sctp`). #[must_use] pub fn sctp_stream_parameters(&self) -> Option { @@ -509,6 +654,12 @@ impl DataConsumer { &self.inner().protocol } + /// The data consumer subchannels. + #[must_use] + pub fn subchannels(&self) -> Vec { + self.inner().subchannels.lock().clone() + } + /// Custom application data. #[must_use] pub fn app_data(&self) -> &AppData { @@ -526,10 +677,17 @@ impl DataConsumer { pub async fn dump(&self) -> Result { debug!("dump()"); - self.inner() + let response = self + .inner() .channel .request(self.id(), DataConsumerDumpRequest {}) - .await + .await?; + + if let response::Body::DataConsumerDumpResponse(data) = response { + Ok(DataConsumerDump::from_fbs(*data).expect("Error parsing dump response")) + } else { + panic!("Wrong message from worker"); + } } /// Returns current statistics of the data consumer. @@ -539,10 +697,57 @@ impl DataConsumer { pub async fn get_stats(&self) -> Result, RequestError> { debug!("get_stats()"); - self.inner() + let response = self + .inner() .channel .request(self.id(), DataConsumerGetStatsRequest {}) - .await + .await?; + + if let response::Body::DataConsumerGetStatsResponse(data) = response { + Ok(vec![DataConsumerStat::from_fbs(&data)]) + } else { + panic!("Wrong message from worker"); + } + } + + /// Pauses the data consumer (no mossage is sent to the consuming endpoint). + pub async fn pause(&self) -> Result<(), RequestError> { + debug!("pause()"); + + self.inner() + .channel + .request(self.id(), DataConsumerPauseRequest {}) + .await?; + + let mut paused = self.inner().paused.lock(); + let was_paused = *paused || *self.inner().data_producer_paused.lock(); + *paused = true; + + if !was_paused { + self.inner().handlers.pause.call_simple(); + } + + Ok(()) + } + + /// Resumes the data consumer (messages are sent again to the consuming endpoint). + pub async fn resume(&self) -> Result<(), RequestError> { + debug!("resume()"); + + self.inner() + .channel + .request(self.id(), DataConsumerResumeRequest {}) + .await?; + + let mut paused = self.inner().paused.lock(); + let was_paused = *paused || *self.inner().data_producer_paused.lock(); + *paused = false; + + if was_paused { + self.inner().handlers.resume.call_simple(); + } + + Ok(()) } /// Returns the number of bytes of data currently buffered to be sent over the underlying SCTP @@ -631,6 +836,37 @@ impl DataConsumer { .add(Box::new(callback)) } + /// Callback is called when the data consumer or its associated data producer is + /// paused and, as result, the data consumer becomes paused. + pub fn on_pause(&self, callback: F) -> HandlerId { + self.inner().handlers.pause.add(Arc::new(callback)) + } + + /// Callback is called when the data consumer or its associated data producer is + /// resumed and, as result, the data consumer is no longer paused. + pub fn on_resume(&self, callback: F) -> HandlerId { + self.inner().handlers.resume.add(Arc::new(callback)) + } + + /// Callback is called when the associated data producer is paused. + pub fn on_data_producer_pause( + &self, + callback: F, + ) -> HandlerId { + self.inner() + .handlers + .data_producer_pause + .add(Arc::new(callback)) + } + + /// Callback is called when the associated data producer is resumed. + pub fn on_producer_resume(&self, callback: F) -> HandlerId { + self.inner() + .handlers + .data_producer_resume + .add(Arc::new(callback)) + } + /// Callback is called when the transport this data consumer belongs to is closed for whatever /// reason. The data consumer itself is also closed. pub fn on_transport_close(&self, callback: F) -> HandlerId { @@ -670,17 +906,35 @@ impl DataConsumer { impl DirectDataConsumer { /// Sends direct messages from the Rust process. pub async fn send(&self, message: WebRtcMessage<'_>) -> Result<(), RequestError> { - let (ppid, payload) = message.into_ppid_and_payload(); + let (ppid, _payload) = message.into_ppid_and_payload(); self.inner - .payload_channel + .channel .request( self.inner.id, - DataConsumerSendRequest { ppid }, - payload.into_owned(), + DataConsumerSendRequest { + ppid, + payload: _payload.into_owned(), + }, ) .await } + + /// Sets subchannels to the worker DataConsumer. + pub async fn set_subchannels(&self, subchannels: Vec) -> Result<(), RequestError> { + let response = self + .inner + .channel + .request( + self.inner.id, + DataConsumerSetSubchannelsRequest { subchannels }, + ) + .await?; + + *self.inner.subchannels.lock() = response.subchannels; + + Ok(()) + } } /// [`WeakDataConsumer`] doesn't own data consumer instance on mediasoup-worker and will not prevent diff --git a/rust/src/router/data_consumer/tests.rs b/rust/src/router/data_consumer/tests.rs index d12a876eb7..7ef9a80588 100644 --- a/rust/src/router/data_consumer/tests.rs +++ b/rust/src/router/data_consumer/tests.rs @@ -1,11 +1,11 @@ use crate::data_consumer::DataConsumerOptions; use crate::data_producer::{DataProducer, DataProducerOptions}; -use crate::data_structures::ListenIp; +use crate::data_structures::{ListenInfo, Protocol}; use crate::plain_transport::PlainTransportOptions; use crate::router::{Router, RouterOptions}; use crate::sctp_parameters::SctpStreamParameters; use crate::transport::Transport; -use crate::webrtc_transport::{TransportListenIps, WebRtcTransportOptions}; +use crate::webrtc_transport::{WebRtcTransportListenInfos, WebRtcTransportOptions}; use crate::worker::WorkerSettings; use crate::worker_manager::WorkerManager; use futures_lite::future; @@ -36,9 +36,13 @@ async fn init() -> (Router, DataProducer) { let transport = router .create_webrtc_transport({ let mut transport_options = - WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, })); transport_options.enable_sctp = true; @@ -65,9 +69,13 @@ fn data_producer_close_event() { let transport2 = router .create_plain_transport({ - let mut transport_options = PlainTransportOptions::new(ListenIp { + let mut transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); transport_options.enable_sctp = true; @@ -114,9 +122,13 @@ fn transport_close_event() { let transport2 = router .create_plain_transport({ - let mut transport_options = PlainTransportOptions::new(ListenIp { + let mut transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); transport_options.enable_sctp = true; diff --git a/rust/src/router/data_producer.rs b/rust/src/router/data_producer.rs index 64e9f2ad55..8660a89c92 100644 --- a/rust/src/router/data_producer.rs +++ b/rust/src/router/data_producer.rs @@ -4,17 +4,19 @@ mod tests; use crate::data_structures::{AppData, WebRtcMessage}; use crate::messages::{ DataProducerCloseRequest, DataProducerDumpRequest, DataProducerGetStatsRequest, - DataProducerSendNotification, + DataProducerPauseRequest, DataProducerResumeRequest, DataProducerSendNotification, }; use crate::sctp_parameters::SctpStreamParameters; use crate::transport::Transport; use crate::uuid_based_wrapper_type; -use crate::worker::{Channel, NotificationError, PayloadChannel, RequestError}; +use crate::worker::{Channel, NotificationError, RequestError}; use async_executor::Executor; -use event_listener_primitives::{BagOnce, HandlerId}; +use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; +use mediasoup_sys::fbs::{data_producer, response}; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; +use std::error::Error; use std::fmt; use std::fmt::Debug; use std::sync::atomic::{AtomicBool, Ordering}; @@ -41,6 +43,8 @@ pub struct DataProducerOptions { pub label: String, /// Name of the sub-protocol used by this DataChannel. pub protocol: String, + /// Whether the data producer must start in paused mode. Default false. + pub paused: bool, /// Custom application data. pub app_data: AppData, } @@ -56,6 +60,7 @@ impl DataProducerOptions { sctp_stream_parameters: Some(sctp_stream_parameters), label: "".to_string(), protocol: "".to_string(), + paused: false, app_data: AppData::default(), } } @@ -68,6 +73,7 @@ impl DataProducerOptions { sctp_stream_parameters: Some(sctp_stream_parameters), label: "".to_string(), protocol: "".to_string(), + paused: false, app_data: AppData::default(), } } @@ -80,6 +86,7 @@ impl DataProducerOptions { sctp_stream_parameters: None, label: "".to_string(), protocol: "".to_string(), + paused: false, app_data: AppData::default(), } } @@ -105,6 +112,26 @@ pub struct DataProducerDump { pub label: String, pub protocol: String, pub sctp_stream_parameters: Option, + pub paused: bool, +} + +impl DataProducerDump { + pub(crate) fn from_fbs(dump: data_producer::DumpResponse) -> Result> { + Ok(Self { + id: dump.id.parse()?, + r#type: if dump.type_ == data_producer::Type::Sctp { + DataProducerType::Sctp + } else { + DataProducerType::Direct + }, + label: dump.label, + protocol: dump.protocol, + sctp_stream_parameters: dump + .sctp_stream_parameters + .map(|parameters| SctpStreamParameters::from_fbs(*parameters)), + paused: dump.paused, + }) + } } /// RTC statistics of the data producer. @@ -117,13 +144,27 @@ pub struct DataProducerStat { pub timestamp: u64, pub label: String, pub protocol: String, - pub messages_received: usize, - pub bytes_received: usize, + pub messages_received: u64, + pub bytes_received: u64, +} + +impl DataProducerStat { + pub(crate) fn from_fbs(stats: &data_producer::GetStatsResponse) -> Self { + Self { + timestamp: stats.timestamp, + label: stats.label.to_string(), + protocol: stats.protocol.to_string(), + messages_received: stats.messages_received, + bytes_received: stats.bytes_received, + } + } } #[derive(Default)] #[allow(clippy::type_complexity)] struct Handlers { + pause: Bag>, + resume: Bag>, transport_close: BagOnce>, close: BagOnce>, } @@ -134,10 +175,10 @@ struct Inner { sctp_stream_parameters: Option, label: String, protocol: String, + paused: AtomicBool, direct: bool, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, transport: Arc, @@ -194,6 +235,7 @@ impl fmt::Debug for RegularDataProducer { .field("sctp_stream_parameters", &self.inner.sctp_stream_parameters) .field("label", &self.inner.label) .field("protocol", &self.inner.protocol) + .field("paused", &self.inner.paused) .field("transport", &self.inner.transport) .field("closed", &self.inner.closed) .finish() @@ -221,6 +263,7 @@ impl fmt::Debug for DirectDataProducer { .field("sctp_stream_parameters", &self.inner.sctp_stream_parameters) .field("label", &self.inner.label) .field("protocol", &self.inner.protocol) + .field("paused", &self.inner.paused) .field("transport", &self.inner.transport) .field("closed", &self.inner.closed) .finish() @@ -267,9 +310,9 @@ impl DataProducer { sctp_stream_parameters: Option, label: String, protocol: String, + paused: bool, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, app_data: AppData, transport: Arc, direct: bool, @@ -296,10 +339,10 @@ impl DataProducer { sctp_stream_parameters, label, protocol, + paused: AtomicBool::new(paused), direct, executor, channel, - payload_channel, handlers, app_data, transport, @@ -339,6 +382,12 @@ impl DataProducer { self.inner().sctp_stream_parameters } + /// Whether the DataProducer is paused. + #[must_use] + pub fn paused(&self) -> bool { + self.inner().paused.load(Ordering::SeqCst) + } + /// The data producer label. #[must_use] pub fn label(&self) -> &String { @@ -368,10 +417,17 @@ impl DataProducer { pub async fn dump(&self) -> Result { debug!("dump()"); - self.inner() + let response = self + .inner() .channel .request(self.id(), DataProducerDumpRequest {}) - .await + .await?; + + if let response::Body::DataProducerDumpResponse(data) = response { + Ok(DataProducerDump::from_fbs(*data).expect("Error parsing dump response")) + } else { + panic!("Wrong message from worker"); + } } /// Returns current statistics of the data producer. @@ -381,10 +437,57 @@ impl DataProducer { pub async fn get_stats(&self) -> Result, RequestError> { debug!("get_stats()"); - self.inner() + let response = self + .inner() .channel .request(self.id(), DataProducerGetStatsRequest {}) - .await + .await?; + + if let response::Body::DataProducerGetStatsResponse(data) = response { + Ok(vec![DataProducerStat::from_fbs(&data)]) + } else { + panic!("Wrong message from worker"); + } + } + + /// Pauses the data producer (no message is sent to its associated data consumers). + /// Calls [`DataConsumer::on_data_producer_pause`](crate::data_consumer::DataConsumer::on_data_producer_pause) + /// callback on all its associated data consumers. + pub async fn pause(&self) -> Result<(), RequestError> { + debug!("pause()"); + + self.inner() + .channel + .request(self.id(), DataProducerPauseRequest {}) + .await?; + + let was_paused = self.inner().paused.swap(true, Ordering::SeqCst); + + if !was_paused { + self.inner().handlers.pause.call_simple(); + } + + Ok(()) + } + + /// Resumes the data producer (messages are sent to its associated data consumers). + /// Calls [`DataConsumer::on_data_producer_resume`](crate::data_consumer::DataConsumer::on_data_producer_resume) + /// callback on all its associated data consumers. + pub async fn resume(&self) -> Result<(), RequestError> { + debug!("resume()"); + + self.inner() + .channel + .request(self.id(), DataProducerResumeRequest {}) + .await?; + + let was_paused = self.inner().paused.swap(false, Ordering::SeqCst); + + if was_paused { + self.inner().handlers.resume.call_simple(); + } + + Ok(()) } /// Callback is called when the transport this data producer belongs to is closed for whatever @@ -397,6 +500,16 @@ impl DataProducer { .add(Box::new(callback)) } + /// Callback is called when the data producer is paused. + pub fn on_pause(&self, callback: F) -> HandlerId { + self.inner().handlers.pause.add(Arc::new(callback)) + } + + /// Callback is called when the data producer is resumed. + pub fn on_resume(&self, callback: F) -> HandlerId { + self.inner().handlers.resume.add(Arc::new(callback)) + } + /// Callback is called when the producer is closed for whatever reason. /// /// NOTE: Callback will be called in place if data producer is already closed. @@ -430,13 +543,22 @@ impl DataProducer { impl DirectDataProducer { /// Sends direct messages from the Rust to the worker. - pub fn send(&self, message: WebRtcMessage<'_>) -> Result<(), NotificationError> { - let (ppid, payload) = message.into_ppid_and_payload(); - - self.inner.payload_channel.notify( + pub fn send( + &self, + message: WebRtcMessage<'_>, + subchannels: Option>, + required_subchannel: Option, + ) -> Result<(), NotificationError> { + let (ppid, _payload) = message.into_ppid_and_payload(); + + self.inner.channel.notify( self.inner.id, - DataProducerSendNotification { ppid }, - payload.into_owned(), + DataProducerSendNotification { + ppid, + payload: _payload.into_owned(), + subchannels, + required_subchannel, + }, ) } } diff --git a/rust/src/router/data_producer/tests.rs b/rust/src/router/data_producer/tests.rs index a98116529d..3bbb34db02 100644 --- a/rust/src/router/data_producer/tests.rs +++ b/rust/src/router/data_producer/tests.rs @@ -1,9 +1,11 @@ use crate::data_producer::DataProducerOptions; -use crate::data_structures::ListenIp; +use crate::data_structures::{ListenInfo, Protocol}; use crate::router::{Router, RouterOptions}; use crate::sctp_parameters::SctpStreamParameters; use crate::transport::Transport; -use crate::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use crate::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use crate::worker::WorkerSettings; use crate::worker_manager::WorkerManager; use futures_lite::future; @@ -34,9 +36,13 @@ async fn init() -> (Router, WebRtcTransport) { let transport1 = router .create_webrtc_transport({ let mut transport_options = - WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, })); transport_options.enable_sctp = true; diff --git a/rust/src/router/direct_transport.rs b/rust/src/router/direct_transport.rs index 4658bb0564..817a37cd1a 100644 --- a/rust/src/router/direct_transport.rs +++ b/rust/src/router/direct_transport.rs @@ -16,15 +16,17 @@ use crate::transport::{ TransportTraceEventType, }; use crate::worker::{ - Channel, NotificationError, PayloadChannel, RequestError, SubscriptionHandler, + Channel, NotificationError, NotificationParseError, RequestError, SubscriptionHandler, }; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; +use mediasoup_sys::fbs::{direct_transport, notification, response, transport}; use nohash_hasher::IntMap; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; +use std::error::Error; use std::fmt; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::{Arc, Weak}; @@ -35,7 +37,7 @@ use std::sync::{Arc, Weak}; pub struct DirectTransportOptions { /// Maximum allowed size for direct messages sent from DataProducers. /// Default 262_144. - pub max_message_size: usize, + pub max_message_size: u32, /// Custom application data. pub app_data: AppData, } @@ -59,17 +61,85 @@ pub struct DirectTransportDump { pub direct: bool, pub producer_ids: Vec, pub consumer_ids: Vec, - pub map_ssrc_consumer_id: IntMap, - pub map_rtx_ssrc_consumer_id: IntMap, + pub map_ssrc_consumer_id: Vec<(u32, ConsumerId)>, + pub map_rtx_ssrc_consumer_id: Vec<(u32, ConsumerId)>, pub data_producer_ids: Vec, pub data_consumer_ids: Vec, pub recv_rtp_header_extensions: RecvRtpHeaderExtensions, pub rtp_listener: RtpListener, - pub max_message_size: usize, + pub max_message_size: u32, pub sctp_parameters: Option, pub sctp_state: Option, pub sctp_listener: Option, - pub trace_event_types: String, + pub trace_event_types: Vec, +} + +impl DirectTransportDump { + pub(crate) fn from_fbs(dump: direct_transport::DumpResponse) -> Result> { + Ok(Self { + id: dump.base.id.parse()?, + direct: true, + producer_ids: dump + .base + .producer_ids + .iter() + .map(|producer_id| Ok(producer_id.parse()?)) + .collect::>>()?, + consumer_ids: dump + .base + .consumer_ids + .iter() + .map(|consumer_id| Ok(consumer_id.parse()?)) + .collect::>>()?, + map_ssrc_consumer_id: dump + .base + .map_ssrc_consumer_id + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + map_rtx_ssrc_consumer_id: dump + .base + .map_rtx_ssrc_consumer_id + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + data_producer_ids: dump + .base + .data_producer_ids + .iter() + .map(|data_producer_id| Ok(data_producer_id.parse()?)) + .collect::>>()?, + data_consumer_ids: dump + .base + .data_consumer_ids + .iter() + .map(|data_consumer_id| Ok(data_consumer_id.parse()?)) + .collect::>>()?, + recv_rtp_header_extensions: RecvRtpHeaderExtensions::from_fbs( + dump.base.recv_rtp_header_extensions.as_ref(), + ), + rtp_listener: RtpListener::from_fbs(dump.base.rtp_listener.as_ref())?, + max_message_size: dump.base.max_message_size, + sctp_parameters: dump + .base + .sctp_parameters + .as_ref() + .map(|parameters| SctpParameters::from_fbs(parameters.as_ref())), + sctp_state: dump + .base + .sctp_state + .map(|state| SctpState::from_fbs(&state)), + sctp_listener: dump.base.sctp_listener.as_ref().map(|listener| { + SctpListener::from_fbs(listener.as_ref()).expect("Error parsing SctpListner") + }), + trace_event_types: dump + .base + .trace_event_types + .iter() + .map(TransportTraceEventType::from_fbs) + .collect(), + }) + } } /// RTC statistics of the direct transport. @@ -79,36 +149,69 @@ pub struct DirectTransportDump { #[allow(missing_docs)] pub struct DirectTransportStat { // Common to all Transports. - // `type` field is present in worker, but ignored here pub transport_id: TransportId, pub timestamp: u64, pub sctp_state: Option, - pub bytes_received: usize, + pub bytes_received: u64, pub recv_bitrate: u32, - pub bytes_sent: usize, + pub bytes_sent: u64, pub send_bitrate: u32, - pub rtp_bytes_received: usize, + pub rtp_bytes_received: u64, pub rtp_recv_bitrate: u32, - pub rtp_bytes_sent: usize, + pub rtp_bytes_sent: u64, pub rtp_send_bitrate: u32, - pub rtx_bytes_received: usize, + pub rtx_bytes_received: u64, pub rtx_recv_bitrate: u32, - pub rtx_bytes_sent: usize, + pub rtx_bytes_sent: u64, pub rtx_send_bitrate: u32, - pub probation_bytes_sent: usize, + pub probation_bytes_sent: u64, pub probation_send_bitrate: u32, #[serde(skip_serializing_if = "Option::is_none")] pub available_outgoing_bitrate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub available_incoming_bitrate: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub max_incoming_bitrate: Option, + pub max_outgoing_bitrate: Option, + pub min_outgoing_bitrate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub rtp_packet_loss_received: Option, #[serde(skip_serializing_if = "Option::is_none")] pub rtp_packet_loss_sent: Option, } +impl DirectTransportStat { + pub(crate) fn from_fbs( + stats: direct_transport::GetStatsResponse, + ) -> Result> { + Ok(Self { + transport_id: stats.base.transport_id.parse()?, + timestamp: stats.base.timestamp, + sctp_state: stats.base.sctp_state.as_ref().map(SctpState::from_fbs), + bytes_received: stats.base.bytes_received, + recv_bitrate: stats.base.recv_bitrate, + bytes_sent: stats.base.bytes_sent, + send_bitrate: stats.base.send_bitrate, + rtp_bytes_received: stats.base.rtp_bytes_received, + rtp_recv_bitrate: stats.base.rtp_recv_bitrate, + rtp_bytes_sent: stats.base.rtp_bytes_sent, + rtp_send_bitrate: stats.base.rtp_send_bitrate, + rtx_bytes_received: stats.base.rtx_bytes_received, + rtx_recv_bitrate: stats.base.rtx_recv_bitrate, + rtx_bytes_sent: stats.base.rtx_bytes_sent, + rtx_send_bitrate: stats.base.rtx_send_bitrate, + probation_bytes_sent: stats.base.probation_bytes_sent, + probation_send_bitrate: stats.base.probation_send_bitrate, + available_outgoing_bitrate: stats.base.available_outgoing_bitrate, + available_incoming_bitrate: stats.base.available_incoming_bitrate, + max_incoming_bitrate: stats.base.max_incoming_bitrate, + max_outgoing_bitrate: stats.base.max_outgoing_bitrate, + min_outgoing_bitrate: stats.base.min_outgoing_bitrate, + rtp_packet_loss_received: stats.base.rtp_packet_loss_received, + rtp_packet_loss_sent: stats.base.rtp_packet_loss_sent, + }) + } +} + #[derive(Default)] #[allow(clippy::type_complexity)] struct Handlers { @@ -126,12 +229,41 @@ struct Handlers { #[serde(tag = "event", rename_all = "lowercase", content = "data")] enum Notification { Trace(TransportTraceEventData), + // TODO. + // Rtcp, } -#[derive(Debug, Deserialize)] -#[serde(tag = "event", rename_all = "lowercase", content = "data")] -enum PayloadNotification { - Rtcp, +impl Notification { + pub(crate) fn from_fbs( + notification: notification::NotificationRef<'_>, + ) -> Result { + match notification.event().unwrap() { + notification::Event::TransportTrace => { + let Ok(Some(notification::BodyRef::TransportTraceNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let trace_notification_fbs = transport::TraceNotification::try_from(body).unwrap(); + let trace_notification = TransportTraceEventData::from_fbs(trace_notification_fbs); + + Ok(Notification::Trace(trace_notification)) + } + /* + * TODO. + notification::Event::DirecttransportRtcp => { + let Ok(Some(notification::BodyRef::RtcpNotification(_body))) = notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + Ok(Notification::Rtcp) + } + */ + _ => Err(NotificationParseError::InvalidEvent), + } + } } struct Inner { @@ -141,7 +273,6 @@ struct Inner { cname_for_producers: Mutex>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, // Make sure router is not dropped until this transport is not dropped @@ -374,11 +505,11 @@ impl TransportGeneric for DirectTransport { async fn dump(&self) -> Result { debug!("dump()"); - serde_json::from_value(self.dump_impl().await?).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) + if let response::Body::DirectTransportDumpResponse(data) = self.dump_impl().await? { + Ok(DirectTransportDump::from_fbs(*data).expect("Error parsing dump response")) + } else { + panic!("Wrong message from worker"); + } } /// Returns current RTC statistics of the transport. @@ -388,11 +519,14 @@ impl TransportGeneric for DirectTransport { async fn get_stats(&self) -> Result, RequestError> { debug!("get_stats()"); - serde_json::from_value(self.get_stats_impl().await?).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) + if let response::Body::DirectTransportGetStatsResponse(data) = self.get_stats_impl().await? + { + Ok(vec![ + DirectTransportStat::from_fbs(*data).expect("Error parsing dump response") + ]) + } else { + panic!("Wrong message from worker"); + } } } @@ -401,10 +535,6 @@ impl TransportImpl for DirectTransport { &self.inner.channel } - fn payload_channel(&self) -> &PayloadChannel { - &self.inner.payload_channel - } - fn executor(&self) -> &Arc> { &self.inner.executor } @@ -427,7 +557,6 @@ impl DirectTransport { id: TransportId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, app_data: AppData, router: Router, ) -> Self { @@ -439,11 +568,18 @@ impl DirectTransport { let handlers = Arc::clone(&handlers); channel.subscribe_to_notifications(id.into(), move |notification| { - match serde_json::from_slice::(notification) { + match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::Trace(trace_event_data) => { handlers.trace.call_simple(&trace_event_data); - } + } /* + * TODO. + Notification::Rtcp => { + handlers.rtcp.call(|callback| { + callback(notification); + }); + } + */ }, Err(error) => { error!("Failed to parse notification: {}", error); @@ -452,25 +588,6 @@ impl DirectTransport { }) }; - let payload_subscription_handler = { - let handlers = Arc::clone(&handlers); - - payload_channel.subscribe_to_notifications(id.into(), move |message, payload| { - match serde_json::from_slice::(message) { - Ok(notification) => match notification { - PayloadNotification::Rtcp => { - handlers.rtcp.call(|callback| { - callback(payload); - }); - } - }, - Err(error) => { - error!("Failed to parse payload notification: {}", error); - } - } - }) - }; - let next_mid_for_consumers = AtomicUsize::default(); let used_sctp_stream_ids = Mutex::new(IntMap::default()); let cname_for_producers = Mutex::new(None); @@ -493,15 +610,11 @@ impl DirectTransport { cname_for_producers, executor, channel, - payload_channel, handlers, app_data, router, closed: AtomicBool::new(false), - _subscription_handlers: Mutex::new(vec![ - subscription_handler, - payload_subscription_handler, - ]), + _subscription_handlers: Mutex::new(vec![subscription_handler]), _on_router_close_handler: Mutex::new(on_router_close_handler), }); @@ -515,8 +628,8 @@ impl DirectTransport { /// * `rtcp_packet` - Bytes containing a valid RTCP packet (can be a compound packet). pub fn send_rtcp(&self, rtcp_packet: Vec) -> Result<(), NotificationError> { self.inner - .payload_channel - .notify(self.id(), TransportSendRtcpNotification {}, rtcp_packet) + .channel + .notify(self.id(), TransportSendRtcpNotification { rtcp_packet }) } /// Callback is called when the direct transport receives a RTCP packet from its router. diff --git a/rust/src/router/pipe_transport.rs b/rust/src/router/pipe_transport.rs index 187811d494..e69ee992da 100644 --- a/rust/src/router/pipe_transport.rs +++ b/rust/src/router/pipe_transport.rs @@ -4,8 +4,8 @@ mod tests; use crate::consumer::{Consumer, ConsumerId, ConsumerOptions}; use crate::data_consumer::{DataConsumer, DataConsumerId, DataConsumerOptions, DataConsumerType}; use crate::data_producer::{DataProducer, DataProducerId, DataProducerOptions, DataProducerType}; -use crate::data_structures::{AppData, ListenIp, SctpState, TransportTuple}; -use crate::messages::{PipeTransportData, TransportCloseRequest, TransportConnectPipeRequest}; +use crate::data_structures::{AppData, ListenInfo, SctpState, TransportTuple}; +use crate::messages::{PipeTransportConnectRequest, PipeTransportData, TransportCloseRequest}; use crate::producer::{Producer, ProducerId, ProducerOptions}; use crate::router::transport::{TransportImpl, TransportType}; use crate::router::Router; @@ -16,14 +16,16 @@ use crate::transport::{ RtpListener, SctpListener, Transport, TransportGeneric, TransportId, TransportTraceEventData, TransportTraceEventType, }; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, NotificationParseError, RequestError, SubscriptionHandler}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; +use mediasoup_sys::fbs::{notification, pipe_transport, response, transport}; use nohash_hasher::IntMap; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; +use std::error::Error; use std::fmt; use std::net::IpAddr; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; @@ -33,10 +35,8 @@ use std::sync::{Arc, Weak}; #[derive(Debug, Clone)] #[non_exhaustive] pub struct PipeTransportOptions { - /// Listening IP address. - pub listen_ip: ListenIp, - /// Fixed port to listen on instead of selecting automatically from Worker's port range. - pub port: Option, + /// Listening info. + pub listen_info: ListenInfo, /// Create a SCTP association. /// Default false. pub enable_sctp: bool, @@ -64,10 +64,9 @@ pub struct PipeTransportOptions { impl PipeTransportOptions { /// Create Pipe transport options with given listen IP. #[must_use] - pub fn new(listen_ip: ListenIp) -> Self { + pub fn new(listen_info: ListenInfo) -> Self { Self { - listen_ip, - port: None, + listen_info, enable_sctp: false, num_sctp_streams: NumSctpStreams::default(), max_sctp_message_size: 268_435_456, @@ -95,17 +94,92 @@ pub struct PipeTransportDump { pub data_consumer_ids: Vec, pub recv_rtp_header_extensions: RecvRtpHeaderExtensions, pub rtp_listener: RtpListener, - pub max_message_size: usize, + pub max_message_size: u32, pub sctp_parameters: Option, pub sctp_state: Option, pub sctp_listener: Option, - pub trace_event_types: String, + pub trace_event_types: Vec, // PipeTransport specific. - pub tuple: Option, + pub tuple: TransportTuple, pub rtx: bool, pub srtp_parameters: Option, } +impl PipeTransportDump { + pub(crate) fn from_fbs(dump: pipe_transport::DumpResponse) -> Result> { + Ok(Self { + // Common to all Transports. + id: dump.base.id.parse()?, + direct: false, + producer_ids: dump + .base + .producer_ids + .iter() + .map(|producer_id| Ok(producer_id.parse()?)) + .collect::>>()?, + consumer_ids: dump + .base + .consumer_ids + .iter() + .map(|consumer_id| Ok(consumer_id.parse()?)) + .collect::>>()?, + map_ssrc_consumer_id: dump + .base + .map_ssrc_consumer_id + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + map_rtx_ssrc_consumer_id: dump + .base + .map_rtx_ssrc_consumer_id + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + data_producer_ids: dump + .base + .data_producer_ids + .iter() + .map(|data_producer_id| Ok(data_producer_id.parse()?)) + .collect::>>()?, + data_consumer_ids: dump + .base + .data_consumer_ids + .iter() + .map(|data_consumer_id| Ok(data_consumer_id.parse()?)) + .collect::>>()?, + recv_rtp_header_extensions: RecvRtpHeaderExtensions::from_fbs( + dump.base.recv_rtp_header_extensions.as_ref(), + ), + rtp_listener: RtpListener::from_fbs(dump.base.rtp_listener.as_ref())?, + max_message_size: dump.base.max_message_size, + sctp_parameters: dump + .base + .sctp_parameters + .as_ref() + .map(|parameters| SctpParameters::from_fbs(parameters.as_ref())), + sctp_state: dump + .base + .sctp_state + .map(|state| SctpState::from_fbs(&state)), + sctp_listener: dump.base.sctp_listener.as_ref().map(|listener| { + SctpListener::from_fbs(listener.as_ref()).expect("Error parsing SctpListner") + }), + trace_event_types: dump + .base + .trace_event_types + .iter() + .map(TransportTraceEventType::from_fbs) + .collect(), + // PipeTransport specific. + tuple: TransportTuple::from_fbs(dump.tuple.as_ref()), + rtx: dump.rtx, + srtp_parameters: dump + .srtp_parameters + .map(|parameters| SrtpParameters::from_fbs(parameters.as_ref())), + }) + } +} + /// RTC statistics of the pipe transport. #[derive(Debug, Clone, PartialOrd, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -117,32 +191,68 @@ pub struct PipeTransportStat { pub transport_id: TransportId, pub timestamp: u64, pub sctp_state: Option, - pub bytes_received: usize, + pub bytes_received: u64, pub recv_bitrate: u32, - pub bytes_sent: usize, + pub bytes_sent: u64, pub send_bitrate: u32, - pub rtp_bytes_received: usize, + pub rtp_bytes_received: u64, pub rtp_recv_bitrate: u32, - pub rtp_bytes_sent: usize, + pub rtp_bytes_sent: u64, pub rtp_send_bitrate: u32, - pub rtx_bytes_received: usize, + pub rtx_bytes_received: u64, pub rtx_recv_bitrate: u32, - pub rtx_bytes_sent: usize, + pub rtx_bytes_sent: u64, pub rtx_send_bitrate: u32, - pub probation_bytes_sent: usize, + pub probation_bytes_sent: u64, pub probation_send_bitrate: u32, #[serde(skip_serializing_if = "Option::is_none")] pub available_outgoing_bitrate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub available_incoming_bitrate: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub max_incoming_bitrate: Option, + pub max_outgoing_bitrate: Option, + pub min_outgoing_bitrate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub rtp_packet_loss_received: Option, #[serde(skip_serializing_if = "Option::is_none")] pub rtp_packet_loss_sent: Option, // PipeTransport specific. - pub tuple: Option, + pub tuple: TransportTuple, +} + +impl PipeTransportStat { + pub(crate) fn from_fbs( + stats: pipe_transport::GetStatsResponse, + ) -> Result> { + Ok(Self { + transport_id: stats.base.transport_id.parse()?, + timestamp: stats.base.timestamp, + sctp_state: stats.base.sctp_state.as_ref().map(SctpState::from_fbs), + bytes_received: stats.base.bytes_received, + recv_bitrate: stats.base.recv_bitrate, + bytes_sent: stats.base.bytes_sent, + send_bitrate: stats.base.send_bitrate, + rtp_bytes_received: stats.base.rtp_bytes_received, + rtp_recv_bitrate: stats.base.rtp_recv_bitrate, + rtp_bytes_sent: stats.base.rtp_bytes_sent, + rtp_send_bitrate: stats.base.rtp_send_bitrate, + rtx_bytes_received: stats.base.rtx_bytes_received, + rtx_recv_bitrate: stats.base.rtx_recv_bitrate, + rtx_bytes_sent: stats.base.rtx_bytes_sent, + rtx_send_bitrate: stats.base.rtx_send_bitrate, + probation_bytes_sent: stats.base.probation_bytes_sent, + probation_send_bitrate: stats.base.probation_send_bitrate, + available_outgoing_bitrate: stats.base.available_outgoing_bitrate, + available_incoming_bitrate: stats.base.available_incoming_bitrate, + max_incoming_bitrate: stats.base.max_incoming_bitrate, + max_outgoing_bitrate: stats.base.max_outgoing_bitrate, + min_outgoing_bitrate: stats.base.min_outgoing_bitrate, + rtp_packet_loss_received: stats.base.rtp_packet_loss_received, + rtp_packet_loss_sent: stats.base.rtp_packet_loss_sent, + // PlainTransport specific. + tuple: TransportTuple::from_fbs(stats.tuple.as_ref()), + }) + } } /// Remote parameters for pipe transport. @@ -181,6 +291,39 @@ enum Notification { Trace(TransportTraceEventData), } +impl Notification { + pub(crate) fn from_fbs( + notification: notification::NotificationRef<'_>, + ) -> Result { + match notification.event().unwrap() { + notification::Event::TransportSctpStateChange => { + let Ok(Some(notification::BodyRef::TransportSctpStateChangeNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let sctp_state = SctpState::from_fbs(&body.sctp_state().unwrap()); + + Ok(Notification::SctpStateChange { sctp_state }) + } + notification::Event::TransportTrace => { + let Ok(Some(notification::BodyRef::TransportTraceNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let trace_notification_fbs = transport::TraceNotification::try_from(body).unwrap(); + let trace_notification = TransportTraceEventData::from_fbs(trace_notification_fbs); + + Ok(Notification::Trace(trace_notification)) + } + _ => Err(NotificationParseError::InvalidEvent), + } + } +} + struct Inner { id: TransportId, next_mid_for_consumers: AtomicUsize, @@ -188,7 +331,6 @@ struct Inner { cname_for_producers: Mutex>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, data: Arc, app_data: AppData, @@ -414,21 +556,23 @@ impl TransportGeneric for PipeTransport { async fn dump(&self) -> Result { debug!("dump()"); - serde_json::from_value(self.dump_impl().await?).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) + if let response::Body::PipeTransportDumpResponse(data) = self.dump_impl().await? { + Ok(PipeTransportDump::from_fbs(*data).expect("Error parsing dump response")) + } else { + panic!("Wrong message from worker"); + } } async fn get_stats(&self) -> Result, RequestError> { debug!("get_stats()"); - serde_json::from_value(self.get_stats_impl().await?).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) + if let response::Body::PipeTransportGetStatsResponse(data) = self.get_stats_impl().await? { + Ok(vec![ + PipeTransportStat::from_fbs(*data).expect("Error parsing dump response") + ]) + } else { + panic!("Wrong message from worker"); + } } } @@ -437,10 +581,6 @@ impl TransportImpl for PipeTransport { &self.inner.channel } - fn payload_channel(&self) -> &PayloadChannel { - &self.inner.payload_channel - } - fn executor(&self) -> &Arc> { &self.inner.executor } @@ -463,7 +603,6 @@ impl PipeTransport { id: TransportId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, data: PipeTransportData, app_data: AppData, router: Router, @@ -478,7 +617,7 @@ impl PipeTransport { let data = Arc::clone(&data); channel.subscribe_to_notifications(id.into(), move |notification| { - match serde_json::from_slice::(notification) { + match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::SctpStateChange { sctp_state } => { data.sctp_state.lock().replace(sctp_state); @@ -528,7 +667,6 @@ impl PipeTransport { cname_for_producers, executor, channel, - payload_channel, handlers, data, app_data, @@ -555,7 +693,7 @@ impl PipeTransport { .channel .request( self.id(), - TransportConnectPipeRequest { + PipeTransportConnectRequest { ip: remote_parameters.ip, port: remote_parameters.port, srtp_parameters: remote_parameters.srtp_parameters, diff --git a/rust/src/router/pipe_transport/tests.rs b/rust/src/router/pipe_transport/tests.rs index 67862e5bc2..54a1f22a48 100644 --- a/rust/src/router/pipe_transport/tests.rs +++ b/rust/src/router/pipe_transport/tests.rs @@ -1,7 +1,7 @@ use crate::consumer::ConsumerOptions; use crate::data_consumer::DataConsumerOptions; use crate::data_producer::DataProducerOptions; -use crate::data_structures::ListenIp; +use crate::data_structures::{ListenInfo, Protocol}; use crate::producer::ProducerOptions; use crate::router::{PipeToRouterOptions, Router, RouterOptions}; use crate::rtp_parameters::{ @@ -10,7 +10,9 @@ use crate::rtp_parameters::{ }; use crate::sctp_parameters::SctpStreamParameters; use crate::transport::Transport; -use crate::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use crate::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use crate::worker::WorkerSettings; use crate::worker_manager::WorkerManager; use futures_lite::future; @@ -95,10 +97,15 @@ async fn init() -> (Router, Router, WebRtcTransport, WebRtcTransport) { .await .expect("Failed to create router"); - let mut transport_options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let mut transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); transport_options.enable_sctp = true; let transport_1 = router1 diff --git a/rust/src/router/plain_transport.rs b/rust/src/router/plain_transport.rs index ee15cb195d..8988b6d37b 100644 --- a/rust/src/router/plain_transport.rs +++ b/rust/src/router/plain_transport.rs @@ -4,7 +4,7 @@ mod tests; use crate::consumer::{Consumer, ConsumerId, ConsumerOptions}; use crate::data_consumer::{DataConsumer, DataConsumerId, DataConsumerOptions, DataConsumerType}; use crate::data_producer::{DataProducer, DataProducerId, DataProducerOptions, DataProducerType}; -use crate::data_structures::{AppData, ListenIp, SctpState, TransportTuple}; +use crate::data_structures::{AppData, ListenInfo, SctpState, TransportTuple}; use crate::messages::{PlainTransportData, TransportCloseRequest, TransportConnectPlainRequest}; use crate::producer::{Producer, ProducerId, ProducerOptions}; use crate::router::transport::{TransportImpl, TransportType}; @@ -16,14 +16,16 @@ use crate::transport::{ RtpListener, SctpListener, Transport, TransportGeneric, TransportId, TransportTraceEventData, TransportTraceEventType, }; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, NotificationParseError, RequestError, SubscriptionHandler}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; +use mediasoup_sys::fbs::{notification, plain_transport, response, transport}; use nohash_hasher::IntMap; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; +use std::error::Error; use std::fmt; use std::net::IpAddr; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; @@ -42,10 +44,10 @@ use std::sync::{Arc, Weak}; #[derive(Debug, Clone)] #[non_exhaustive] pub struct PlainTransportOptions { - /// Listening IP address. - pub listen_ip: ListenIp, - /// Fixed port to listen on instead of selecting automatically from Worker's port range. - pub port: Option, + /// Listening info. + pub listen_info: ListenInfo, + /// Optional listening info for RTCP. + pub rtcp_listen_info: Option, /// Use RTCP-mux (RTP and RTCP in the same port). /// Default true. pub rtcp_mux: bool, @@ -78,10 +80,10 @@ pub struct PlainTransportOptions { impl PlainTransportOptions { /// Create Plain transport options with given listen IP. #[must_use] - pub fn new(listen_ip: ListenIp) -> Self { + pub fn new(listen_info: ListenInfo) -> Self { Self { - listen_ip, - port: None, + listen_info, + rtcp_listen_info: None, rtcp_mux: true, comedia: false, enable_sctp: false, @@ -111,11 +113,11 @@ pub struct PlainTransportDump { pub data_consumer_ids: Vec, pub recv_rtp_header_extensions: RecvRtpHeaderExtensions, pub rtp_listener: RtpListener, - pub max_message_size: usize, + pub max_message_size: u32, pub sctp_parameters: Option, pub sctp_state: Option, pub sctp_listener: Option, - pub trace_event_types: String, + pub trace_event_types: Vec, // PlainTransport specific. pub rtcp_mux: bool, pub comedia: bool, @@ -124,6 +126,85 @@ pub struct PlainTransportDump { pub srtp_parameters: Option, } +impl PlainTransportDump { + pub(crate) fn from_fbs(dump: plain_transport::DumpResponse) -> Result> { + Ok(Self { + // Common to all Transports. + id: dump.base.id.parse()?, + direct: false, + producer_ids: dump + .base + .producer_ids + .iter() + .map(|producer_id| Ok(producer_id.parse()?)) + .collect::>>()?, + consumer_ids: dump + .base + .consumer_ids + .iter() + .map(|consumer_id| Ok(consumer_id.parse()?)) + .collect::>>()?, + map_ssrc_consumer_id: dump + .base + .map_ssrc_consumer_id + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + map_rtx_ssrc_consumer_id: dump + .base + .map_rtx_ssrc_consumer_id + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + data_producer_ids: dump + .base + .data_producer_ids + .iter() + .map(|data_producer_id| Ok(data_producer_id.parse()?)) + .collect::>>()?, + data_consumer_ids: dump + .base + .data_consumer_ids + .iter() + .map(|data_consumer_id| Ok(data_consumer_id.parse()?)) + .collect::>>()?, + recv_rtp_header_extensions: RecvRtpHeaderExtensions::from_fbs( + dump.base.recv_rtp_header_extensions.as_ref(), + ), + rtp_listener: RtpListener::from_fbs(dump.base.rtp_listener.as_ref())?, + max_message_size: dump.base.max_message_size, + sctp_parameters: dump + .base + .sctp_parameters + .as_ref() + .map(|parameters| SctpParameters::from_fbs(parameters.as_ref())), + sctp_state: dump + .base + .sctp_state + .map(|state| SctpState::from_fbs(&state)), + sctp_listener: dump.base.sctp_listener.as_ref().map(|listener| { + SctpListener::from_fbs(listener.as_ref()).expect("Error parsing SctpListner") + }), + trace_event_types: dump + .base + .trace_event_types + .iter() + .map(TransportTraceEventType::from_fbs) + .collect(), + // PlainTransport specific. + rtcp_mux: dump.rtcp_mux, + comedia: dump.comedia, + tuple: TransportTuple::from_fbs(dump.tuple.as_ref()), + rtcp_tuple: dump + .rtcp_tuple + .map(|tuple| TransportTuple::from_fbs(tuple.as_ref())), + srtp_parameters: dump + .srtp_parameters + .map(|parameters| SrtpParameters::from_fbs(parameters.as_ref())), + }) + } +} + /// RTC statistics of the plain transport. #[derive(Debug, Clone, PartialOrd, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -135,26 +216,27 @@ pub struct PlainTransportStat { pub transport_id: TransportId, pub timestamp: u64, pub sctp_state: Option, - pub bytes_received: usize, + pub bytes_received: u64, pub recv_bitrate: u32, - pub bytes_sent: usize, + pub bytes_sent: u64, pub send_bitrate: u32, - pub rtp_bytes_received: usize, + pub rtp_bytes_received: u64, pub rtp_recv_bitrate: u32, - pub rtp_bytes_sent: usize, + pub rtp_bytes_sent: u64, pub rtp_send_bitrate: u32, - pub rtx_bytes_received: usize, + pub rtx_bytes_received: u64, pub rtx_recv_bitrate: u32, - pub rtx_bytes_sent: usize, + pub rtx_bytes_sent: u64, pub rtx_send_bitrate: u32, - pub probation_bytes_sent: usize, + pub probation_bytes_sent: u64, pub probation_send_bitrate: u32, #[serde(skip_serializing_if = "Option::is_none")] pub available_outgoing_bitrate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub available_incoming_bitrate: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub max_incoming_bitrate: Option, + pub max_outgoing_bitrate: Option, + pub min_outgoing_bitrate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub rtp_packet_loss_received: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -162,10 +244,50 @@ pub struct PlainTransportStat { // PlainTransport specific. pub rtcp_mux: bool, pub comedia: bool, - pub tuple: Option, + pub tuple: TransportTuple, pub rtcp_tuple: Option, } +impl PlainTransportStat { + pub(crate) fn from_fbs( + stats: plain_transport::GetStatsResponse, + ) -> Result> { + Ok(Self { + transport_id: stats.base.transport_id.parse()?, + timestamp: stats.base.timestamp, + sctp_state: stats.base.sctp_state.as_ref().map(SctpState::from_fbs), + bytes_received: stats.base.bytes_received, + recv_bitrate: stats.base.recv_bitrate, + bytes_sent: stats.base.bytes_sent, + send_bitrate: stats.base.send_bitrate, + rtp_bytes_received: stats.base.rtp_bytes_received, + rtp_recv_bitrate: stats.base.rtp_recv_bitrate, + rtp_bytes_sent: stats.base.rtp_bytes_sent, + rtp_send_bitrate: stats.base.rtp_send_bitrate, + rtx_bytes_received: stats.base.rtx_bytes_received, + rtx_recv_bitrate: stats.base.rtx_recv_bitrate, + rtx_bytes_sent: stats.base.rtx_bytes_sent, + rtx_send_bitrate: stats.base.rtx_send_bitrate, + probation_bytes_sent: stats.base.probation_bytes_sent, + probation_send_bitrate: stats.base.probation_send_bitrate, + available_outgoing_bitrate: stats.base.available_outgoing_bitrate, + available_incoming_bitrate: stats.base.available_incoming_bitrate, + max_incoming_bitrate: stats.base.max_incoming_bitrate, + max_outgoing_bitrate: stats.base.max_outgoing_bitrate, + min_outgoing_bitrate: stats.base.min_outgoing_bitrate, + rtp_packet_loss_received: stats.base.rtp_packet_loss_received, + rtp_packet_loss_sent: stats.base.rtp_packet_loss_sent, + // PlainTransport specific. + rtcp_mux: stats.rtcp_mux, + comedia: stats.comedia, + tuple: TransportTuple::from_fbs(stats.tuple.as_ref()), + rtcp_tuple: stats + .rtcp_tuple + .map(|tuple| TransportTuple::from_fbs(tuple.as_ref())), + }) + } +} + /// Remote parameters for plain transport. #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -218,6 +340,63 @@ enum Notification { Trace(TransportTraceEventData), } +impl Notification { + pub(crate) fn from_fbs( + notification: notification::NotificationRef<'_>, + ) -> Result { + match notification.event().unwrap() { + notification::Event::PlaintransportTuple => { + let Ok(Some(notification::BodyRef::PlainTransportTupleNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let tuple_fbs = transport::Tuple::try_from(body.tuple().unwrap()).unwrap(); + let tuple = TransportTuple::from_fbs(&tuple_fbs); + + Ok(Notification::Tuple { tuple }) + } + notification::Event::PlaintransportRtcpTuple => { + let Ok(Some(notification::BodyRef::PlainTransportRtcpTupleNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let rtcp_tuple_fbs = transport::Tuple::try_from(body.tuple().unwrap()).unwrap(); + let rtcp_tuple = TransportTuple::from_fbs(&rtcp_tuple_fbs); + + Ok(Notification::RtcpTuple { rtcp_tuple }) + } + notification::Event::TransportSctpStateChange => { + let Ok(Some(notification::BodyRef::TransportSctpStateChangeNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let sctp_state = SctpState::from_fbs(&body.sctp_state().unwrap()); + + Ok(Notification::SctpStateChange { sctp_state }) + } + notification::Event::TransportTrace => { + let Ok(Some(notification::BodyRef::TransportTraceNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let trace_notification_fbs = transport::TraceNotification::try_from(body).unwrap(); + let trace_notification = TransportTraceEventData::from_fbs(trace_notification_fbs); + + Ok(Notification::Trace(trace_notification)) + } + _ => Err(NotificationParseError::InvalidEvent), + } + } +} + struct Inner { id: TransportId, next_mid_for_consumers: AtomicUsize, @@ -225,7 +404,6 @@ struct Inner { cname_for_producers: Mutex>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, data: Arc, app_data: AppData, @@ -444,21 +622,23 @@ impl TransportGeneric for PlainTransport { async fn dump(&self) -> Result { debug!("dump()"); - serde_json::from_value(self.dump_impl().await?).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) + if let response::Body::PlainTransportDumpResponse(data) = self.dump_impl().await? { + Ok(PlainTransportDump::from_fbs(*data).expect("Error parsing dump response")) + } else { + panic!("Wrong message from worker"); + } } async fn get_stats(&self) -> Result, RequestError> { debug!("get_stats()"); - serde_json::from_value(self.get_stats_impl().await?).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) + if let response::Body::PlainTransportGetStatsResponse(data) = self.get_stats_impl().await? { + Ok(vec![ + PlainTransportStat::from_fbs(*data).expect("Error parsing dump response") + ]) + } else { + panic!("Wrong message from worker"); + } } } @@ -467,10 +647,6 @@ impl TransportImpl for PlainTransport { &self.inner.channel } - fn payload_channel(&self) -> &PayloadChannel { - &self.inner.payload_channel - } - fn executor(&self) -> &Arc> { &self.inner.executor } @@ -493,7 +669,6 @@ impl PlainTransport { id: TransportId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, data: PlainTransportData, app_data: AppData, router: Router, @@ -508,7 +683,7 @@ impl PlainTransport { let data = Arc::clone(&data); channel.subscribe_to_notifications(id.into(), move |notification| { - match serde_json::from_slice::(notification) { + match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::Tuple { tuple } => { *data.tuple.lock() = tuple; @@ -568,7 +743,6 @@ impl PlainTransport { cname_for_producers, executor, channel, - payload_channel, handlers, data, app_data, @@ -699,9 +873,7 @@ impl PlainTransport { ) .await?; - if let Some(tuple) = response.tuple { - *self.inner.data.tuple.lock() = tuple; - } + *self.inner.data.tuple.lock() = response.tuple; if let Some(rtcp_tuple) = response.rtcp_tuple { self.inner.data.rtcp_tuple.lock().replace(rtcp_tuple); diff --git a/rust/src/router/plain_transport/tests.rs b/rust/src/router/plain_transport/tests.rs index 5fd65b1a40..fcff706c5f 100644 --- a/rust/src/router/plain_transport/tests.rs +++ b/rust/src/router/plain_transport/tests.rs @@ -1,4 +1,4 @@ -use crate::data_structures::ListenIp; +use crate::data_structures::{ListenInfo, Protocol}; use crate::plain_transport::PlainTransportOptions; use crate::router::{Router, RouterOptions}; use crate::transport::Transport; @@ -37,9 +37,13 @@ fn router_close_event() { let transport = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.rtcp_mux = false; diff --git a/rust/src/router/producer.rs b/rust/src/router/producer.rs index 17549fd822..b25c40a711 100644 --- a/rust/src/router/producer.rs +++ b/rust/src/router/producer.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod tests; -use crate::consumer::RtpStreamParams; +use crate::consumer::{RtpStreamParams, RtxStreamParams}; use crate::data_structures::{AppData, RtpPacketTraceInfo, SsrcTraceInfo, TraceEventDirection}; use crate::messages::{ ProducerCloseRequest, ProducerDumpRequest, ProducerEnableTraceEventRequest, @@ -12,15 +12,16 @@ use crate::rtp_parameters::{MediaKind, MimeType, RtpParameters}; use crate::transport::Transport; use crate::uuid_based_wrapper_type; use crate::worker::{ - Channel, NotificationError, PayloadChannel, RequestError, SubscriptionHandler, + Channel, NotificationError, NotificationParseError, RequestError, SubscriptionHandler, }; use async_executor::Executor; use event_listener_primitives::{Bag, BagOnce, HandlerId}; -use hash_hasher::HashedMap; use log::{debug, error}; +use mediasoup_sys::fbs::{notification, producer, response, rtp_parameters, rtp_stream}; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; +use std::error::Error; use std::fmt; use std::fmt::Debug; use std::sync::atomic::{AtomicBool, Ordering}; @@ -88,18 +89,36 @@ impl ProducerOptions { } } +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +#[doc(hidden)] +pub struct RtxStream { + pub params: RtxStreamParams, +} + #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] #[doc(hidden)] pub struct RtpStreamRecv { pub params: RtpStreamParams, pub score: u8, - // `type` field is present in worker, but ignored here - pub jitter: u32, - pub packet_count: usize, - pub byte_count: usize, - pub bitrate: u32, - pub bitrate_by_layer: Option>, + pub rtx_stream: Option, +} + +impl RtpStreamRecv { + pub(crate) fn from_fbs_ref(dump: rtp_stream::DumpRef<'_>) -> Result> { + Ok(Self { + params: RtpStreamParams::from_fbs_ref(dump.params()?)?, + score: dump.score()?, + rtx_stream: if let Some(rtx_stream) = dump.rtx_stream()? { + Some(RtxStream { + params: RtxStreamParams::from_fbs_ref(rtx_stream.params()?)?, + }) + } else { + None + }, + }) + } } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -113,10 +132,38 @@ pub struct ProducerDump { pub rtp_mapping: RtpMapping, pub rtp_parameters: RtpParameters, pub rtp_streams: Vec, - pub trace_event_types: String, + pub trace_event_types: Vec, pub r#type: ProducerType, } +impl ProducerDump { + pub(crate) fn from_fbs_ref( + dump: producer::DumpResponseRef<'_>, + ) -> Result> { + Ok(Self { + id: dump.id()?.parse()?, + kind: MediaKind::from_fbs(dump.kind()?), + paused: dump.paused()?, + rtp_mapping: RtpMapping::from_fbs_ref(dump.rtp_mapping()?)?, + rtp_parameters: RtpParameters::from_fbs_ref(dump.rtp_parameters()?)?, + rtp_streams: dump + .rtp_streams()? + .iter() + .map(|rtp_stream| RtpStreamRecv::from_fbs_ref(rtp_stream?)) + .collect::>>()?, + trace_event_types: dump + .trace_event_types()? + .iter() + .map(|trace_event_type| { + ProducerTraceEventType::from_fbs(&trace_event_type.unwrap()) + }) + .collect(), + + r#type: ProducerType::from_fbs(dump.type_()?), + }) + } +} + /// Producer type. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -129,6 +176,19 @@ pub enum ProducerType { Svc, } +impl ProducerType { + pub(crate) fn from_fbs(producer_type: rtp_parameters::Type) -> Self { + match producer_type { + rtp_parameters::Type::Simple => ProducerType::Simple, + rtp_parameters::Type::Simulcast => ProducerType::Simulcast, + rtp_parameters::Type::Svc => ProducerType::Svc, + // TODO: Create a new FBS type ProducerType with just Simple, + // Simulcast and Svc. + rtp_parameters::Type::Pipe => unimplemented!(), + } + } +} + /// Score of the RTP stream in the producer representing its transmission quality. #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -143,6 +203,17 @@ pub struct ProducerScore { pub score: u8, } +impl ProducerScore { + pub(crate) fn from_fbs(producer_score: &producer::Score) -> Self { + Self { + encoding_idx: producer_score.encoding_idx, + ssrc: producer_score.ssrc, + rid: producer_score.rid.clone(), + score: producer_score.score, + } + } +} + /// Rotation angle #[derive(Debug, Copy, Clone, Eq, PartialEq, Deserialize_repr, Serialize_repr)] #[repr(u16)] @@ -169,6 +240,34 @@ pub struct ProducerVideoOrientation { pub rotation: Rotation, } +impl ProducerVideoOrientation { + pub(crate) fn from_fbs( + video_orientation: producer::VideoOrientationChangeNotification, + ) -> Self { + Self { + camera: video_orientation.camera, + flip: video_orientation.flip, + rotation: match video_orientation.rotation { + 0 => Rotation::None, + 90 => Rotation::Clockwise, + 180 => Rotation::Rotate180, + 270 => Rotation::CounterClockwise, + _ => Rotation::None, + }, + } + } +} + +/// Bitrate by layer. +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +#[allow(missing_docs)] +pub struct BitrateByLayer { + layer: String, + bitrate: u32, +} + /// RTC statistics of the producer. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -181,26 +280,71 @@ pub struct ProducerStat { pub ssrc: u32, pub rtx_ssrc: Option, pub rid: Option, - pub kind: String, + pub kind: MediaKind, pub mime_type: MimeType, - pub packets_lost: u32, + pub packets_lost: u64, pub fraction_lost: u8, - pub packets_discarded: usize, - pub packets_retransmitted: usize, - pub packets_repaired: usize, - pub nack_count: usize, - pub nack_packet_count: usize, - pub pli_count: usize, - pub fir_count: usize, + pub packets_discarded: u64, + pub packets_retransmitted: u64, + pub packets_repaired: u64, + pub nack_count: u64, + pub nack_packet_count: u64, + pub pli_count: u64, + pub fir_count: u64, pub score: u8, - pub packet_count: usize, - pub byte_count: usize, + pub packet_count: u64, + pub byte_count: u64, pub bitrate: u32, pub round_trip_time: Option, - pub rtx_packets_discarded: Option, + pub rtx_packets_discarded: Option, // RtpStreamRecv specific. pub jitter: u32, - pub bitrate_by_layer: Option>, + pub bitrate_by_layer: Vec, +} + +impl ProducerStat { + pub(crate) fn from_fbs(stats: &rtp_stream::Stats) -> Self { + let rtp_stream::StatsData::RecvStats(ref stats) = stats.data else { + panic!("Wrong message from worker"); + }; + + let rtp_stream::StatsData::BaseStats(ref base) = stats.base.data else { + panic!("Wrong message from worker"); + }; + + Self { + timestamp: base.timestamp, + ssrc: base.ssrc, + rtx_ssrc: base.rtx_ssrc, + rid: base.rid.clone(), + kind: MediaKind::from_fbs(base.kind), + mime_type: base.mime_type.to_string().parse().unwrap(), + packets_lost: base.packets_lost, + fraction_lost: base.fraction_lost, + packets_discarded: base.packets_discarded, + packets_retransmitted: base.packets_retransmitted, + packets_repaired: base.packets_repaired, + nack_count: base.nack_count, + nack_packet_count: base.nack_packet_count, + pli_count: base.pli_count, + fir_count: base.fir_count, + score: base.score, + packet_count: stats.packet_count, + byte_count: stats.byte_count, + bitrate: stats.bitrate, + round_trip_time: Some(base.round_trip_time), + rtx_packets_discarded: Some(base.rtx_packets_discarded), + jitter: stats.jitter, + bitrate_by_layer: stats + .bitrate_by_layer + .iter() + .map(|bitrate_by_layer| BitrateByLayer { + layer: bitrate_by_layer.layer.to_string(), + bitrate: bitrate_by_layer.bitrate, + }) + .collect(), + } + } } /// 'trace' event data. @@ -252,6 +396,61 @@ pub enum ProducerTraceEventData { }, } +impl ProducerTraceEventData { + pub(crate) fn from_fbs(data: producer::TraceNotification) -> Self { + match data.type_ { + producer::TraceEventType::Rtp => ProducerTraceEventData::Rtp { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(producer::TraceInfo::RtpTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + RtpPacketTraceInfo::from_fbs(*info.rtp_packet, info.is_rtx) + }, + }, + producer::TraceEventType::Keyframe => ProducerTraceEventData::KeyFrame { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(producer::TraceInfo::KeyFrameTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + RtpPacketTraceInfo::from_fbs(*info.rtp_packet, info.is_rtx) + }, + }, + producer::TraceEventType::Nack => ProducerTraceEventData::Nack { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + }, + producer::TraceEventType::Pli => ProducerTraceEventData::Pli { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(producer::TraceInfo::PliTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + SsrcTraceInfo { ssrc: info.ssrc } + }, + }, + producer::TraceEventType::Fir => ProducerTraceEventData::Fir { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(producer::TraceInfo::FirTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + SsrcTraceInfo { ssrc: info.ssrc } + }, + }, + } + } +} + /// Types of consumer trace events. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -268,6 +467,28 @@ pub enum ProducerTraceEventType { Fir, } +impl ProducerTraceEventType { + pub(crate) fn to_fbs(self) -> producer::TraceEventType { + match self { + ProducerTraceEventType::Rtp => producer::TraceEventType::Rtp, + ProducerTraceEventType::KeyFrame => producer::TraceEventType::Keyframe, + ProducerTraceEventType::Nack => producer::TraceEventType::Nack, + ProducerTraceEventType::Pli => producer::TraceEventType::Pli, + ProducerTraceEventType::Fir => producer::TraceEventType::Fir, + } + } + + pub(crate) fn from_fbs(event_type: &producer::TraceEventType) -> Self { + match event_type { + producer::TraceEventType::Rtp => ProducerTraceEventType::Rtp, + producer::TraceEventType::Keyframe => ProducerTraceEventType::KeyFrame, + producer::TraceEventType::Nack => ProducerTraceEventType::Nack, + producer::TraceEventType::Pli => ProducerTraceEventType::Pli, + producer::TraceEventType::Fir => ProducerTraceEventType::Fir, + } + } +} + #[derive(Debug, Deserialize)] #[serde(tag = "event", rename_all = "lowercase", content = "data")] enum Notification { @@ -276,6 +497,59 @@ enum Notification { Trace(ProducerTraceEventData), } +impl Notification { + pub(crate) fn from_fbs( + notification: notification::NotificationRef<'_>, + ) -> Result { + match notification.event().unwrap() { + notification::Event::ProducerScore => { + let Ok(Some(notification::BodyRef::ProducerScoreNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let scores_fbs: Vec<_> = body + .scores() + .unwrap() + .iter() + .map(|score| producer::Score::try_from(score.unwrap()).unwrap()) + .collect(); + let scores = scores_fbs.iter().map(ProducerScore::from_fbs).collect(); + + Ok(Notification::Score(scores)) + } + notification::Event::ProducerVideoOrientationChange => { + let Ok(Some(notification::BodyRef::ProducerVideoOrientationChangeNotification( + body, + ))) = notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let video_orientation_fbs = + producer::VideoOrientationChangeNotification::try_from(body).unwrap(); + let video_orientation = ProducerVideoOrientation::from_fbs(video_orientation_fbs); + + Ok(Notification::VideoOrientationChange(video_orientation)) + } + notification::Event::ProducerTrace => { + let Ok(Some(notification::BodyRef::ProducerTraceNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let trace_notification_fbs = producer::TraceNotification::try_from(body).unwrap(); + let trace_notification = ProducerTraceEventData::from_fbs(trace_notification_fbs); + + Ok(Notification::Trace(trace_notification)) + } + _ => Err(NotificationParseError::InvalidEvent), + } + } +} + #[derive(Default)] #[allow(clippy::type_complexity)] struct Handlers { @@ -299,7 +573,6 @@ struct Inner { score: Arc>>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, transport: Arc, @@ -441,7 +714,6 @@ impl Producer { paused: bool, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, app_data: AppData, transport: Arc, direct: bool, @@ -456,7 +728,7 @@ impl Producer { let score = Arc::clone(&score); channel.subscribe_to_notifications(id.into(), move |notification| { - match serde_json::from_slice::(notification) { + match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::Score(scores) => { *score.lock() = scores.clone(); @@ -503,7 +775,6 @@ impl Producer { score, executor, channel, - payload_channel, handlers, app_data, transport, @@ -596,10 +867,17 @@ impl Producer { pub async fn get_stats(&self) -> Result, RequestError> { debug!("get_stats()"); - self.inner() + let response = self + .inner() .channel .request(self.id(), ProducerGetStatsRequest {}) - .await + .await; + + if let Ok(response::Body::ProducerGetStatsResponse(data)) = response { + Ok(data.stats.iter().map(ProducerStat::from_fbs).collect()) + } else { + panic!("Wrong message from worker"); + } } /// Pauses the producer (no RTP is sent to its associated consumers). Calls @@ -622,7 +900,7 @@ impl Producer { Ok(()) } - /// Resumes the producer (no RTP is sent to its associated consumers). Calls + /// Resumes the producer (RTP is sent to its associated consumers). Calls /// [`Consumer::on_producer_resume`](crate::consumer::Consumer::on_producer_resume) callback on /// all its associated consumers. pub async fn resume(&self) -> Result<(), RequestError> { @@ -747,8 +1025,8 @@ impl DirectProducer { /// Sends a RTP packet from the Rust process. pub fn send(&self, rtp_packet: Vec) -> Result<(), NotificationError> { self.inner - .payload_channel - .notify(self.inner.id, ProducerSendNotification {}, rtp_packet) + .channel + .notify(self.inner.id, ProducerSendNotification { rtp_packet }) } } diff --git a/rust/src/router/producer/tests.rs b/rust/src/router/producer/tests.rs index f5fd9d9e12..92533c3c32 100644 --- a/rust/src/router/producer/tests.rs +++ b/rust/src/router/producer/tests.rs @@ -1,4 +1,4 @@ -use crate::data_structures::ListenIp; +use crate::data_structures::{ListenInfo, Protocol}; use crate::producer::ProducerOptions; use crate::router::{Router, RouterOptions}; use crate::rtp_parameters::{ @@ -6,7 +6,9 @@ use crate::rtp_parameters::{ RtpParameters, }; use crate::transport::Transport; -use crate::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use crate::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use crate::worker::WorkerSettings; use crate::worker_manager::WorkerManager; use futures_lite::future; @@ -64,10 +66,15 @@ async fn init() -> (Router, WebRtcTransport) { .await .expect("Failed to create router"); - let transport_options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); let transport_1 = router .create_webrtc_transport(transport_options.clone()) diff --git a/rust/src/router/transport.rs b/rust/src/router/transport.rs index 5e7eca730b..feb1d5d012 100644 --- a/rust/src/router/transport.rs +++ b/rust/src/router/transport.rs @@ -15,18 +15,17 @@ use crate::producer::{Producer, ProducerId, ProducerOptions}; use crate::router::Router; use crate::rtp_parameters::{MediaKind, RtpEncodingParameters}; use crate::sctp_parameters::SctpStreamParameters; -use crate::worker::{Channel, PayloadChannel, RequestError}; +use crate::worker::{Channel, RequestError}; use crate::{ortc, uuid_based_wrapper_type}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::HandlerId; -use hash_hasher::HashedMap; use log::{error, warn}; +use mediasoup_sys::fbs::{response, transport}; use nohash_hasher::IntMap; use parking_lot::Mutex; -use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; -use serde_json::Value; +use std::error::Error; use std::fmt::Debug; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; @@ -65,6 +64,25 @@ pub enum TransportTraceEventData { }, } +impl TransportTraceEventData { + pub(crate) fn from_fbs(data: transport::TraceNotification) -> Self { + match data.type_ { + transport::TraceEventType::Probation => unimplemented!(), + transport::TraceEventType::Bwe => TransportTraceEventData::Bwe { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(transport::TraceInfo::BweTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + BweTraceInfo::from_fbs(*info) + }, + }, + } + } +} + /// Valid types for "trace" event. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -75,16 +93,54 @@ pub enum TransportTraceEventType { Bwe, } +impl TransportTraceEventType { + pub(crate) fn to_fbs(self) -> transport::TraceEventType { + match self { + TransportTraceEventType::Probation => transport::TraceEventType::Probation, + TransportTraceEventType::Bwe => transport::TraceEventType::Bwe, + } + } + + pub(crate) fn from_fbs(event_type: &transport::TraceEventType) -> Self { + match event_type { + transport::TraceEventType::Probation => TransportTraceEventType::Probation, + transport::TraceEventType::Bwe => TransportTraceEventType::Bwe, + } + } +} + #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] #[doc(hidden)] pub struct RtpListener { - /// Map from Ssrc (as string) to producer ID - pub mid_table: HashedMap, - /// Map from Ssrc (as string) to producer ID - pub rid_table: HashedMap, - /// Map from Ssrc (as string) to producer ID - pub ssrc_table: HashedMap, + /// Vector of mid and producer ID + pub mid_table: Vec<(String, ProducerId)>, + /// Vector of rid and producer ID + pub rid_table: Vec<(String, ProducerId)>, + /// Vector of Ssrc and producer ID + pub ssrc_table: Vec<(u32, ProducerId)>, +} + +impl RtpListener { + pub(crate) fn from_fbs(rtp_listener: &transport::RtpListener) -> Result> { + Ok(Self { + mid_table: rtp_listener + .mid_table + .iter() + .map(|key_value| Ok((key_value.key.to_string(), key_value.value.parse()?))) + .collect::>>()?, + rid_table: rtp_listener + .rid_table + .iter() + .map(|key_value| Ok((key_value.key.to_string(), key_value.value.parse()?))) + .collect::>>()?, + ssrc_table: rtp_listener + .ssrc_table + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + }) + } } #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] @@ -98,12 +154,36 @@ pub struct RecvRtpHeaderExtensions { transport_wide_cc01: Option, } +impl RecvRtpHeaderExtensions { + pub(crate) fn from_fbs(extensions: &transport::RecvRtpHeaderExtensions) -> Self { + Self { + mid: extensions.mid, + rid: extensions.rid, + rrid: extensions.rrid, + abs_send_time: extensions.abs_send_time, + transport_wide_cc01: extensions.transport_wide_cc01, + } + } +} + #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] #[doc(hidden)] pub struct SctpListener { - /// Map from stream ID (as string) to data producer ID - stream_id_table: HashedMap, + /// Vector of stream ID (as string) to data producer ID + stream_id_table: Vec<(u16, DataProducerId)>, +} + +impl SctpListener { + pub(crate) fn from_fbs(listener: &transport::SctpListener) -> Result> { + Ok(Self { + stream_id_table: listener + .stream_id_table + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + }) + } } #[derive(Debug, Copy, Clone, PartialEq)] @@ -255,9 +335,9 @@ pub trait Transport: Debug + Send + Sync { pub trait TransportGeneric: Transport + Clone + 'static { /// Dump data structure specific to each transport. #[doc(hidden)] - type Dump: Debug + DeserializeOwned + 'static; + type Dump: Debug + 'static; /// Stats data structure specific to each transport. - type Stat: Debug + DeserializeOwned + 'static; + type Stat: Debug + 'static; /// Dump Transport. async fn dump(&self) -> Result; @@ -268,7 +348,7 @@ pub trait TransportGeneric: Transport + Clone + 'static { } /// Error that caused [`Transport::produce`] to fail. -#[derive(Debug, Error, Eq, PartialEq)] +#[derive(Debug, Error)] pub enum ProduceError { /// Producer with the same id already exists. #[error("Producer with the same id \"{0}\" already exists")] @@ -285,7 +365,7 @@ pub enum ProduceError { } /// Error that caused [`Transport::consume`] to fail. -#[derive(Debug, Error, Eq, PartialEq)] +#[derive(Debug, Error)] pub enum ConsumeError { /// Producer with specified id not found. #[error("Producer with id \"{0}\" not found")] @@ -302,7 +382,7 @@ pub enum ConsumeError { } /// Error that caused [`Transport::produce_data`] to fail. -#[derive(Debug, Error, Eq, PartialEq)] +#[derive(Debug, Error)] pub enum ProduceDataError { /// Data producer with the same id already exists. #[error("Data producer with the same id \"{0}\" already exists")] @@ -316,7 +396,7 @@ pub enum ProduceDataError { } /// Error that caused [`Transport::consume_data`] to fail. -#[derive(Debug, Error, Eq, PartialEq)] +#[derive(Debug, Error)] pub enum ConsumeDataError { /// Data producer with specified id not found #[error("Data producer with id \"{0}\" not found")] @@ -333,8 +413,6 @@ pub enum ConsumeDataError { pub(super) trait TransportImpl: TransportGeneric { fn channel(&self) -> &Channel; - fn payload_channel(&self) -> &PayloadChannel; - fn executor(&self) -> &Arc>; fn next_mid_for_consumers(&self) -> &AtomicUsize; @@ -363,13 +441,13 @@ pub(super) trait TransportImpl: TransportGeneric { } } - async fn dump_impl(&self) -> Result { + async fn dump_impl(&self) -> Result { self.channel() .request(self.id(), TransportDumpRequest {}) .await } - async fn get_stats_impl(&self) -> Result { + async fn get_stats_impl(&self) -> Result { self.channel() .request(self.id(), TransportGetStatsRequest {}) .await @@ -493,7 +571,6 @@ pub(super) trait TransportImpl: TransportGeneric { paused, Arc::clone(self.executor()), self.channel().clone(), - self.payload_channel().clone(), app_data, Arc::new(self.clone()), transport_type == TransportType::Direct, @@ -597,7 +674,6 @@ pub(super) trait TransportImpl: TransportGeneric { response.paused, Arc::clone(self.executor()), self.channel().clone(), - self.payload_channel(), response.producer_paused, response.score, response.preferred_layers, @@ -638,6 +714,7 @@ pub(super) trait TransportImpl: TransportGeneric { sctp_stream_parameters, label, protocol, + paused, app_data, } = data_producer_options; @@ -655,6 +732,7 @@ pub(super) trait TransportImpl: TransportGeneric { sctp_stream_parameters, label, protocol, + paused, }, ) .await @@ -666,9 +744,9 @@ pub(super) trait TransportImpl: TransportGeneric { response.sctp_stream_parameters, response.label, response.protocol, + response.paused, Arc::clone(self.executor()), self.channel().clone(), - self.payload_channel().clone(), app_data, Arc::new(self.clone()), transport_type == TransportType::Direct, @@ -686,6 +764,8 @@ pub(super) trait TransportImpl: TransportGeneric { ordered, max_packet_life_time, max_retransmits, + paused, + subchannels, app_data, } = data_consumer_options; @@ -750,6 +830,8 @@ pub(super) trait TransportImpl: TransportGeneric { sctp_stream_parameters, label: data_producer.label().clone(), protocol: data_producer.protocol().clone(), + subchannels, + paused, }, ) .await @@ -761,10 +843,12 @@ pub(super) trait TransportImpl: TransportGeneric { response.sctp_stream_parameters, response.label, response.protocol, + response.paused, data_producer, Arc::clone(self.executor()), self.channel().clone(), - self.payload_channel().clone(), + response.data_producer_paused, + response.subchannels, app_data, Arc::new(self.clone()), transport_type == TransportType::Direct, diff --git a/rust/src/router/webrtc_transport.rs b/rust/src/router/webrtc_transport.rs index 53a1ac08ca..809b91d7dc 100644 --- a/rust/src/router/webrtc_transport.rs +++ b/rust/src/router/webrtc_transport.rs @@ -5,11 +5,11 @@ use crate::consumer::{Consumer, ConsumerId, ConsumerOptions}; use crate::data_consumer::{DataConsumer, DataConsumerId, DataConsumerOptions, DataConsumerType}; use crate::data_producer::{DataProducer, DataProducerId, DataProducerOptions, DataProducerType}; use crate::data_structures::{ - AppData, DtlsParameters, DtlsState, IceCandidate, IceParameters, IceRole, IceState, ListenIp, + AppData, DtlsParameters, DtlsState, IceCandidate, IceParameters, IceRole, IceState, ListenInfo, SctpState, TransportTuple, }; use crate::messages::{ - TransportCloseRequest, TransportConnectWebRtcRequest, TransportRestartIceRequest, + TransportCloseRequest, TransportRestartIceRequest, WebRtcTransportConnectRequest, WebRtcTransportData, }; use crate::producer::{Producer, ProducerId, ProducerOptions}; @@ -22,15 +22,17 @@ use crate::transport::{ TransportTraceEventType, }; use crate::webrtc_server::WebRtcServer; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, NotificationParseError, RequestError, SubscriptionHandler}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; +use mediasoup_sys::fbs::{notification, response, transport, web_rtc_transport}; use nohash_hasher::IntMap; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; use std::convert::TryFrom; +use std::error::Error; use std::fmt; use std::ops::Deref; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; @@ -39,25 +41,25 @@ use thiserror::Error; /// Struct that protects an invariant of having non-empty list of listen IPs #[derive(Debug, Clone, Eq, PartialEq, Serialize)] -pub struct TransportListenIps(Vec); +pub struct WebRtcTransportListenInfos(Vec); -impl TransportListenIps { +impl WebRtcTransportListenInfos { /// Create transport listen IPs with given IP populated initially. #[must_use] - pub fn new(listen_ip: ListenIp) -> Self { - Self(vec![listen_ip]) + pub fn new(listen_info: ListenInfo) -> Self { + Self(vec![listen_info]) } /// Insert another listen IP. #[must_use] - pub fn insert(mut self, listen_ip: ListenIp) -> Self { - self.0.push(listen_ip); + pub fn insert(mut self, listen_info: ListenInfo) -> Self { + self.0.push(listen_info); self } } -impl Deref for TransportListenIps { - type Target = Vec; +impl Deref for WebRtcTransportListenInfos { + type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 @@ -69,14 +71,14 @@ impl Deref for TransportListenIps { #[error("Empty list of listen IPs provided, should have at least one element")] pub struct EmptyListError; -impl TryFrom> for TransportListenIps { +impl TryFrom> for WebRtcTransportListenInfos { type Error = EmptyListError; - fn try_from(listen_ips: Vec) -> Result { - if listen_ips.is_empty() { + fn try_from(listen_infos: Vec) -> Result { + if listen_infos.is_empty() { Err(EmptyListError) } else { - Ok(Self(listen_ips)) + Ok(Self(listen_infos)) } } } @@ -84,18 +86,16 @@ impl TryFrom> for TransportListenIps { /// How [`WebRtcTransport`] should listen on interfaces. /// /// # Notes on usage -/// * Do not use "0.0.0.0" into `listen_ips`. Values in `listen_ips` must be specific bindable IPs +/// * Do not use "0.0.0.0" into `listen_infos`. Values in `listen_infos` must be specific bindable IPs /// on the host. -/// * If you use "0.0.0.0" or "::" into `listen_ips`, then you need to also provide `announced_ip` -/// in the corresponding entry in `listen_ips`. +/// * If you use "0.0.0.0" or "::" into `listen_infos`, then you need to also provide `announced_ip` +/// in the corresponding entry in `listen_infos`. #[derive(Debug, Clone)] pub enum WebRtcTransportListen { - /// Listen on individual IP/port combinations specific to this transport. + /// Listen on individual protocol/IP/port combinations specific to this transport. Individual { - /// Listening IP address or addresses in order of preference (first one is the preferred one). - listen_ips: TransportListenIps, - /// Fixed port to listen on instead of selecting automatically from Worker's port range. - port: Option, + /// Listening infos in order of preference (first one is the preferred one). + listen_infos: WebRtcTransportListenInfos, }, /// Share [`WebRtcServer`] with other transports withing the same worker. Server { @@ -114,10 +114,14 @@ pub enum WebRtcTransportListen { pub struct WebRtcTransportOptions { /// How [`WebRtcTransport`] should listen on interfaces. pub listen: WebRtcTransportListen, - /// Listen in UDP. Default true. + /// Initial available outgoing bitrate (in bps). + /// Default 600000. + pub initial_available_outgoing_bitrate: u32, + /// Enable UDP. + /// Default true. pub enable_udp: bool, - /// Listen in TCP. - /// Default false. + /// Enable TCP. + /// Default true if webrtc_server is given, false otherwise. pub enable_tcp: bool, /// Prefer UDP. /// Default false. @@ -125,9 +129,6 @@ pub struct WebRtcTransportOptions { /// Prefer TCP. /// Default false. pub prefer_tcp: bool, - /// Initial available outgoing bitrate (in bps). - /// Default 600000. - pub initial_available_outgoing_bitrate: u32, /// Create a SCTP association. /// Default false. pub enable_sctp: bool, @@ -144,19 +145,16 @@ pub struct WebRtcTransportOptions { } impl WebRtcTransportOptions { - /// Create [`WebRtcTransport`] options with given listen IPs. + /// Create [`WebRtcTransport`] options with given listen infos. #[must_use] - pub fn new(listen_ips: TransportListenIps) -> Self { + pub fn new(listen_infos: WebRtcTransportListenInfos) -> Self { Self { - listen: WebRtcTransportListen::Individual { - listen_ips, - port: None, - }, + listen: WebRtcTransportListen::Individual { listen_infos }, + initial_available_outgoing_bitrate: 600_000, enable_udp: true, enable_tcp: false, prefer_udp: false, prefer_tcp: false, - initial_available_outgoing_bitrate: 600_000, enable_sctp: false, num_sctp_streams: NumSctpStreams::default(), max_sctp_message_size: 262_144, @@ -169,11 +167,11 @@ impl WebRtcTransportOptions { pub fn new_with_server(webrtc_server: WebRtcServer) -> Self { Self { listen: WebRtcTransportListen::Server { webrtc_server }, + initial_available_outgoing_bitrate: 600_000, enable_udp: true, - enable_tcp: false, + enable_tcp: true, prefer_udp: false, prefer_tcp: false, - initial_available_outgoing_bitrate: 600_000, enable_sctp: false, num_sctp_streams: NumSctpStreams::default(), max_sctp_message_size: 262_144, @@ -199,11 +197,11 @@ pub struct WebRtcTransportDump { pub data_consumer_ids: Vec, pub recv_rtp_header_extensions: RecvRtpHeaderExtensions, pub rtp_listener: RtpListener, - pub max_message_size: usize, + pub max_message_size: u32, pub sctp_parameters: Option, pub sctp_state: Option, pub sctp_listener: Option, - pub trace_event_types: String, + pub trace_event_types: Vec, // WebRtcTransport specific. pub dtls_parameters: DtlsParameters, pub dtls_state: DtlsState, @@ -214,6 +212,89 @@ pub struct WebRtcTransportDump { pub ice_selected_tuple: Option, } +impl WebRtcTransportDump { + pub(crate) fn from_fbs(dump: web_rtc_transport::DumpResponse) -> Result> { + Ok(Self { + // Common to all Transports. + id: dump.base.id.parse()?, + direct: false, + producer_ids: dump + .base + .producer_ids + .iter() + .map(|producer_id| Ok(producer_id.parse()?)) + .collect::>>()?, + consumer_ids: dump + .base + .consumer_ids + .iter() + .map(|consumer_id| Ok(consumer_id.parse()?)) + .collect::>>()?, + map_ssrc_consumer_id: dump + .base + .map_ssrc_consumer_id + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + map_rtx_ssrc_consumer_id: dump + .base + .map_rtx_ssrc_consumer_id + .iter() + .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) + .collect::>>()?, + data_producer_ids: dump + .base + .data_producer_ids + .iter() + .map(|data_producer_id| Ok(data_producer_id.parse()?)) + .collect::>>()?, + data_consumer_ids: dump + .base + .data_consumer_ids + .iter() + .map(|data_consumer_id| Ok(data_consumer_id.parse()?)) + .collect::>>()?, + recv_rtp_header_extensions: RecvRtpHeaderExtensions::from_fbs( + dump.base.recv_rtp_header_extensions.as_ref(), + ), + rtp_listener: RtpListener::from_fbs(dump.base.rtp_listener.as_ref())?, + max_message_size: dump.base.max_message_size, + sctp_parameters: dump + .base + .sctp_parameters + .as_ref() + .map(|parameters| SctpParameters::from_fbs(parameters.as_ref())), + sctp_state: dump + .base + .sctp_state + .map(|state| SctpState::from_fbs(&state)), + sctp_listener: dump.base.sctp_listener.as_ref().map(|listener| { + SctpListener::from_fbs(listener.as_ref()).expect("Error parsing SctpListner") + }), + trace_event_types: dump + .base + .trace_event_types + .iter() + .map(TransportTraceEventType::from_fbs) + .collect(), + // WebRtcTransport specific. + dtls_parameters: DtlsParameters::from_fbs(*dump.dtls_parameters), + dtls_state: DtlsState::from_fbs(dump.dtls_state), + ice_candidates: dump + .ice_candidates + .iter() + .map(IceCandidate::from_fbs) + .collect(), + ice_parameters: IceParameters::from_fbs(*dump.ice_parameters), + ice_role: IceRole::from_fbs(dump.ice_role), + ice_state: IceState::from_fbs(dump.ice_state), + ice_selected_tuple: dump + .ice_selected_tuple + .map(|tuple| TransportTuple::from_fbs(tuple.as_ref())), + }) + } +} + /// RTC statistics of the [`WebRtcTransport`]. #[derive(Debug, Clone, PartialOrd, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -225,26 +306,27 @@ pub struct WebRtcTransportStat { pub transport_id: TransportId, pub timestamp: u64, pub sctp_state: Option, - pub bytes_received: usize, + pub bytes_received: u64, pub recv_bitrate: u32, - pub bytes_sent: usize, + pub bytes_sent: u64, pub send_bitrate: u32, - pub rtp_bytes_received: usize, + pub rtp_bytes_received: u64, pub rtp_recv_bitrate: u32, - pub rtp_bytes_sent: usize, + pub rtp_bytes_sent: u64, pub rtp_send_bitrate: u32, - pub rtx_bytes_received: usize, + pub rtx_bytes_received: u64, pub rtx_recv_bitrate: u32, - pub rtx_bytes_sent: usize, + pub rtx_bytes_sent: u64, pub rtx_send_bitrate: u32, - pub probation_bytes_sent: usize, + pub probation_bytes_sent: u64, pub probation_send_bitrate: u32, #[serde(skip_serializing_if = "Option::is_none")] pub available_outgoing_bitrate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub available_incoming_bitrate: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub max_incoming_bitrate: Option, + pub max_outgoing_bitrate: Option, + pub min_outgoing_bitrate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub rtp_packet_loss_received: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -257,6 +339,45 @@ pub struct WebRtcTransportStat { pub dtls_state: DtlsState, } +impl WebRtcTransportStat { + pub(crate) fn from_fbs( + stats: web_rtc_transport::GetStatsResponse, + ) -> Result> { + Ok(Self { + transport_id: stats.base.transport_id.parse()?, + timestamp: stats.base.timestamp, + sctp_state: stats.base.sctp_state.as_ref().map(SctpState::from_fbs), + bytes_received: stats.base.bytes_received, + recv_bitrate: stats.base.recv_bitrate, + bytes_sent: stats.base.bytes_sent, + send_bitrate: stats.base.send_bitrate, + rtp_bytes_received: stats.base.rtp_bytes_received, + rtp_recv_bitrate: stats.base.rtp_recv_bitrate, + rtp_bytes_sent: stats.base.rtp_bytes_sent, + rtp_send_bitrate: stats.base.rtp_send_bitrate, + rtx_bytes_received: stats.base.rtx_bytes_received, + rtx_recv_bitrate: stats.base.rtx_recv_bitrate, + rtx_bytes_sent: stats.base.rtx_bytes_sent, + rtx_send_bitrate: stats.base.rtx_send_bitrate, + probation_bytes_sent: stats.base.probation_bytes_sent, + probation_send_bitrate: stats.base.probation_send_bitrate, + available_outgoing_bitrate: stats.base.available_outgoing_bitrate, + available_incoming_bitrate: stats.base.available_incoming_bitrate, + max_incoming_bitrate: stats.base.max_incoming_bitrate, + max_outgoing_bitrate: stats.base.max_outgoing_bitrate, + min_outgoing_bitrate: stats.base.min_outgoing_bitrate, + rtp_packet_loss_received: stats.base.rtp_packet_loss_received, + rtp_packet_loss_sent: stats.base.rtp_packet_loss_sent, + // WebRtcTransport specific. + ice_role: IceRole::from_fbs(stats.ice_role), + ice_state: IceState::from_fbs(stats.ice_state), + ice_selected_tuple: stats + .ice_selected_tuple + .map(|tuple| TransportTuple::from_fbs(tuple.as_ref())), + dtls_state: DtlsState::from_fbs(stats.dtls_state), + }) + } +} /// Remote parameters for [`WebRtcTransport`]. #[derive(Debug, Clone, PartialOrd, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -305,6 +426,80 @@ enum Notification { Trace(TransportTraceEventData), } +impl Notification { + pub(crate) fn from_fbs( + notification: notification::NotificationRef<'_>, + ) -> Result { + match notification.event().unwrap() { + notification::Event::WebrtctransportIceStateChange => { + let Ok(Some(notification::BodyRef::WebRtcTransportIceStateChangeNotification( + body, + ))) = notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let ice_state = IceState::from_fbs(body.ice_state().unwrap()); + + Ok(Notification::IceStateChange { ice_state }) + } + notification::Event::WebrtctransportIceSelectedTupleChange => { + let Ok(Some( + notification::BodyRef::WebRtcTransportIceSelectedTupleChangeNotification(body), + )) = notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let ice_selected_tuple_fbs = + transport::Tuple::try_from(body.tuple().unwrap()).unwrap(); + let ice_selected_tuple = TransportTuple::from_fbs(&ice_selected_tuple_fbs); + + Ok(Notification::IceSelectedTupleChange { ice_selected_tuple }) + } + notification::Event::WebrtctransportDtlsStateChange => { + let Ok(Some(notification::BodyRef::WebRtcTransportDtlsStateChangeNotification( + body, + ))) = notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let dtls_state = DtlsState::from_fbs(body.dtls_state().unwrap()); + + Ok(Notification::DtlsStateChange { + dtls_state, + dtls_remote_cert: None, + }) + } + notification::Event::TransportSctpStateChange => { + let Ok(Some(notification::BodyRef::TransportSctpStateChangeNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let sctp_state = SctpState::from_fbs(&body.sctp_state().unwrap()); + + Ok(Notification::SctpStateChange { sctp_state }) + } + notification::Event::TransportTrace => { + let Ok(Some(notification::BodyRef::TransportTraceNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let trace_notification_fbs = transport::TraceNotification::try_from(body).unwrap(); + let trace_notification = TransportTraceEventData::from_fbs(trace_notification_fbs); + + Ok(Notification::Trace(trace_notification)) + } + _ => Err(NotificationParseError::InvalidEvent), + } + } +} + struct Inner { id: TransportId, next_mid_for_consumers: AtomicUsize, @@ -312,7 +507,6 @@ struct Inner { cname_for_producers: Mutex>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, data: Arc, app_data: AppData, @@ -542,21 +736,24 @@ impl TransportGeneric for WebRtcTransport { async fn dump(&self) -> Result { debug!("dump()"); - serde_json::from_value(self.dump_impl().await?).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) + if let response::Body::WebRtcTransportDumpResponse(data) = self.dump_impl().await? { + Ok(WebRtcTransportDump::from_fbs(*data).expect("Error parsing dump response")) + } else { + panic!("Wrong message from worker"); + } } async fn get_stats(&self) -> Result, RequestError> { debug!("get_stats()"); - serde_json::from_value(self.get_stats_impl().await?).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) + if let response::Body::WebRtcTransportGetStatsResponse(data) = self.get_stats_impl().await? + { + Ok(vec![ + WebRtcTransportStat::from_fbs(*data).expect("Error parsing dump response") + ]) + } else { + panic!("Wrong message from worker"); + } } } @@ -565,10 +762,6 @@ impl TransportImpl for WebRtcTransport { &self.inner.channel } - fn payload_channel(&self) -> &PayloadChannel { - &self.inner.payload_channel - } - fn executor(&self) -> &Arc> { &self.inner.executor } @@ -592,7 +785,6 @@ impl WebRtcTransport { id: TransportId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, data: WebRtcTransportData, app_data: AppData, router: Router, @@ -608,7 +800,7 @@ impl WebRtcTransport { let data = Arc::clone(&data); channel.subscribe_to_notifications(id.into(), move |notification| { - match serde_json::from_slice::(notification) { + match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::IceStateChange { ice_state } => { *data.ice_state.lock() = ice_state; @@ -697,7 +889,6 @@ impl WebRtcTransport { cname_for_producers, executor, channel, - payload_channel, handlers, data, app_data, @@ -762,7 +953,7 @@ impl WebRtcTransport { .channel .request( self.id(), - TransportConnectWebRtcRequest { + WebRtcTransportConnectRequest { dtls_parameters: remote_parameters.dtls_parameters, }, ) @@ -872,13 +1063,10 @@ impl WebRtcTransport { pub async fn restart_ice(&self) -> Result { debug!("restart_ice()"); - let response = self - .inner + self.inner .channel .request(self.id(), TransportRestartIceRequest {}) - .await?; - - Ok(response.ice_parameters) + .await } /// Callback is called when the WebRTC server used during creation of this transport is closed diff --git a/rust/src/router/webrtc_transport/tests.rs b/rust/src/router/webrtc_transport/tests.rs index 9ddf7f66f8..42d54678ee 100644 --- a/rust/src/router/webrtc_transport/tests.rs +++ b/rust/src/router/webrtc_transport/tests.rs @@ -1,11 +1,11 @@ -use crate::data_structures::{IceCandidateType, IceState, ListenIp, Protocol}; +use crate::data_structures::{ + IceCandidateTcpType, IceCandidateType, IceState, ListenInfo, Protocol, +}; use crate::prelude::WebRtcTransport; use crate::router::{NewTransport, Router, RouterOptions}; use crate::transport::Transport; -use crate::webrtc_server::{ - WebRtcServerIpPort, WebRtcServerListenInfo, WebRtcServerListenInfos, WebRtcServerOptions, -}; -use crate::webrtc_transport::{TransportListenIps, WebRtcTransportOptions}; +use crate::webrtc_server::{WebRtcServerIpPort, WebRtcServerListenInfos, WebRtcServerOptions}; +use crate::webrtc_transport::{WebRtcTransportListenInfos, WebRtcTransportOptions}; use crate::worker::{Worker, WorkerSettings}; use crate::worker_manager::WorkerManager; use async_io::Timer; @@ -52,21 +52,21 @@ fn create_with_webrtc_server_succeeds() { let webrtc_server = worker .create_webrtc_server({ - let listen_infos = WebRtcServerListenInfos::new(WebRtcServerListenInfo { + let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port1), + send_buffer_size: None, + recv_buffer_size: None, }); - let listen_infos = listen_infos.insert(WebRtcServerListenInfo { + let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port2), + send_buffer_size: None, + recv_buffer_size: None, }); WebRtcServerOptions::new(listen_infos) }) @@ -104,9 +104,14 @@ fn create_with_webrtc_server_succeeds() { }); let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new_with_server( - webrtc_server.clone(), - )) + .create_webrtc_transport({ + let mut webrtc_transport_options = + WebRtcTransportOptions::new_with_server(webrtc_server.clone()); + // Let's disable UDP so resulting ICE candidates should only contain TCP. + webrtc_transport_options.enable_udp = false; + + webrtc_transport_options + }) .await .expect("Failed to create WebRTC transport"); @@ -126,10 +131,13 @@ fn create_with_webrtc_server_succeeds() { let ice_candidates = transport.ice_candidates(); assert_eq!(ice_candidates.len(), 1); assert_eq!(ice_candidates[0].ip, IpAddr::V4(Ipv4Addr::LOCALHOST)); - assert_eq!(ice_candidates[0].protocol, Protocol::Udp); - assert_eq!(ice_candidates[0].port, port1); + assert_eq!(ice_candidates[0].protocol, Protocol::Tcp); + assert_eq!(ice_candidates[0].port, port2); assert_eq!(ice_candidates[0].r#type, IceCandidateType::Host); - assert_eq!(ice_candidates[0].tcp_type, None); + assert_eq!( + ice_candidates[0].tcp_type, + Some(IceCandidateTcpType::Passive) + ); } assert_eq!(transport.ice_state(), IceState::New); @@ -219,12 +227,16 @@ fn router_close_event() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -257,21 +269,21 @@ fn webrtc_server_close_event() { let webrtc_server = worker .create_webrtc_server({ - let listen_infos = WebRtcServerListenInfos::new(WebRtcServerListenInfo { + let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port1), + send_buffer_size: None, + recv_buffer_size: None, }); - let listen_infos = listen_infos.insert(WebRtcServerListenInfo { + let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port2), + send_buffer_size: None, + recv_buffer_size: None, }); WebRtcServerOptions::new(listen_infos) }) diff --git a/rust/src/rtp_parameters.rs b/rust/src/rtp_parameters.rs index d3563f5724..e430b3a1f3 100644 --- a/rust/src/rtp_parameters.rs +++ b/rust/src/rtp_parameters.rs @@ -5,14 +5,18 @@ mod tests; use crate::scalability_modes::ScalabilityMode; +use mediasoup_sys::fbs::rtp_parameters; use serde::de::{MapAccess, Visitor}; use serde::ser::SerializeStruct; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::Cow; use std::collections::BTreeMap; +use std::error::Error; use std::fmt; use std::iter::FromIterator; use std::num::{NonZeroU32, NonZeroU8}; +use std::str::FromStr; +use thiserror::Error; /// Codec specific parameters. Some parameters (such as `packetization-mode` and `profile-level-id` /// in H264 or `profile-id` in VP9) are critical for codec matching. @@ -200,6 +204,33 @@ pub enum MediaKind { Video, } +impl MediaKind { + pub(crate) fn to_fbs(self) -> rtp_parameters::MediaKind { + match self { + MediaKind::Audio => rtp_parameters::MediaKind::Audio, + MediaKind::Video => rtp_parameters::MediaKind::Video, + } + } + + pub(crate) fn from_fbs(kind: rtp_parameters::MediaKind) -> Self { + match kind { + rtp_parameters::MediaKind::Audio => MediaKind::Audio, + rtp_parameters::MediaKind::Video => MediaKind::Video, + } + } +} + +/// Error that caused [`MimeType`] parsing error. +#[derive(Debug, Error, Eq, PartialEq)] +pub enum ParseMimeTypeError { + /// Invalid MIME type input string + #[error("Invalid MIME type input string")] + InvalidInput, + /// Unknown MIME type + #[error("Unknown MIME type")] + UnknownMimeType, +} + /// Known Audio or Video MIME type. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] #[serde(untagged)] @@ -210,6 +241,30 @@ pub enum MimeType { Video(MimeTypeVideo), } +impl FromStr for MimeType { + type Err = ParseMimeTypeError; + + fn from_str(s: &str) -> Result { + if s.starts_with("audio/") { + MimeTypeAudio::from_str(s).map(Self::Audio) + } else if s.starts_with("video/") { + MimeTypeVideo::from_str(s).map(Self::Video) + } else { + Err(ParseMimeTypeError::InvalidInput) + } + } +} + +impl MimeType { + /// String representation of MIME type. + pub fn as_str(&self) -> &'static str { + match self { + Self::Audio(mime_type) => mime_type.as_str(), + Self::Video(mime_type) => mime_type.as_str(), + } + } +} + /// Known Audio MIME types. #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] @@ -252,6 +307,52 @@ pub enum MimeTypeAudio { Red, } +impl FromStr for MimeTypeAudio { + type Err = ParseMimeTypeError; + + fn from_str(s: &str) -> Result { + match s { + "audio/opus" => Ok(Self::Opus), + "audio/multiopus" => Ok(Self::MultiChannelOpus), + "audio/PCMU" => Ok(Self::Pcmu), + "audio/PCMA" => Ok(Self::Pcma), + "audio/ISAC" => Ok(Self::Isac), + "audio/G722" => Ok(Self::G722), + "audio/iLBC" => Ok(Self::Ilbc), + "audio/SILK" => Ok(Self::Silk), + "audio/CN" => Ok(Self::Cn), + "audio/telephone-event" => Ok(Self::TelephoneEvent), + "audio/rtx" => Ok(Self::Rtx), + "audio/red" => Ok(Self::Red), + s => Err(if s.starts_with("audio/") { + ParseMimeTypeError::UnknownMimeType + } else { + ParseMimeTypeError::InvalidInput + }), + } + } +} + +impl MimeTypeAudio { + /// String representation of MIME type. + pub fn as_str(&self) -> &'static str { + match self { + Self::Opus => "audio/opus", + Self::MultiChannelOpus => "audio/multiopus", + Self::Pcmu => "audio/PCMU", + Self::Pcma => "audio/PCMA", + Self::Isac => "audio/ISAC", + Self::G722 => "audio/G722", + Self::Ilbc => "audio/iLBC", + Self::Silk => "audio/SILK", + Self::Cn => "audio/CN", + Self::TelephoneEvent => "audio/telephone-event", + Self::Rtx => "audio/rtx", + Self::Red => "audio/red", + } + } +} + /// Known Video MIME types. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] pub enum MimeTypeVideo { @@ -281,6 +382,44 @@ pub enum MimeTypeVideo { Ulpfec, } +impl FromStr for MimeTypeVideo { + type Err = ParseMimeTypeError; + + fn from_str(s: &str) -> Result { + match s { + "video/VP8" => Ok(Self::Vp8), + "video/VP9" => Ok(Self::Vp9), + "video/H264" => Ok(Self::H264), + "video/H264-SVC" => Ok(Self::H264Svc), + "video/H265" => Ok(Self::H265), + "video/rtx" => Ok(Self::Rtx), + "video/red" => Ok(Self::Red), + "video/ulpfec" => Ok(Self::Ulpfec), + s => Err(if s.starts_with("video/") { + ParseMimeTypeError::UnknownMimeType + } else { + ParseMimeTypeError::InvalidInput + }), + } + } +} + +impl MimeTypeVideo { + /// String representation of MIME type. + pub fn as_str(&self) -> &'static str { + match self { + Self::Vp8 => "video/VP8", + Self::Vp9 => "video/VP9", + Self::H264 => "video/H264", + Self::H264Svc => "video/H264-SVC", + Self::H265 => "video/H265", + Self::Rtx => "video/rtx", + Self::Red => "video/red", + Self::Ulpfec => "video/ulpfec", + } + } +} + /// Provides information on the capabilities of a codec within the RTP capabilities. The list of /// media codecs supported by mediasoup and their settings is defined in the /// `supported_rtp_capabilities.rs` file. @@ -402,6 +541,14 @@ impl Default for RtpHeaderExtensionDirection { } } +/// Error that caused [`RtpHeaderExtensionUri`] parsing error. +#[derive(Debug, Error, Eq, PartialEq)] +pub enum RtpHeaderExtensionUriParseError { + /// Unsupported + #[error("Unsupported")] + Unsupported, +} + /// URI for supported RTP header extension #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] pub enum RtpHeaderExtensionUri { @@ -443,6 +590,100 @@ pub enum RtpHeaderExtensionUri { Unsupported, } +impl RtpHeaderExtensionUri { + pub(crate) fn to_fbs(self) -> rtp_parameters::RtpHeaderExtensionUri { + match self { + RtpHeaderExtensionUri::Mid => rtp_parameters::RtpHeaderExtensionUri::Mid, + RtpHeaderExtensionUri::RtpStreamId => { + rtp_parameters::RtpHeaderExtensionUri::RtpStreamId + } + RtpHeaderExtensionUri::RepairRtpStreamId => { + rtp_parameters::RtpHeaderExtensionUri::RepairRtpStreamId + } + RtpHeaderExtensionUri::FrameMarkingDraft07 => { + rtp_parameters::RtpHeaderExtensionUri::FrameMarkingDraft07 + } + RtpHeaderExtensionUri::FrameMarking => { + rtp_parameters::RtpHeaderExtensionUri::FrameMarking + } + RtpHeaderExtensionUri::AudioLevel => rtp_parameters::RtpHeaderExtensionUri::AudioLevel, + RtpHeaderExtensionUri::VideoOrientation => { + rtp_parameters::RtpHeaderExtensionUri::VideoOrientation + } + RtpHeaderExtensionUri::TimeOffset => rtp_parameters::RtpHeaderExtensionUri::TimeOffset, + RtpHeaderExtensionUri::TransportWideCcDraft01 => { + rtp_parameters::RtpHeaderExtensionUri::TransportWideCcDraft01 + } + RtpHeaderExtensionUri::AbsSendTime => { + rtp_parameters::RtpHeaderExtensionUri::AbsSendTime + } + RtpHeaderExtensionUri::AbsCaptureTime => { + rtp_parameters::RtpHeaderExtensionUri::AbsCaptureTime + } + RtpHeaderExtensionUri::Unsupported => panic!("Invalid RTP extension header URI"), + } + } + + pub(crate) fn from_fbs(uri: rtp_parameters::RtpHeaderExtensionUri) -> Self { + match uri { + rtp_parameters::RtpHeaderExtensionUri::Mid => RtpHeaderExtensionUri::Mid, + rtp_parameters::RtpHeaderExtensionUri::RtpStreamId => { + RtpHeaderExtensionUri::RtpStreamId + } + rtp_parameters::RtpHeaderExtensionUri::RepairRtpStreamId => { + RtpHeaderExtensionUri::RepairRtpStreamId + } + rtp_parameters::RtpHeaderExtensionUri::FrameMarkingDraft07 => { + RtpHeaderExtensionUri::FrameMarkingDraft07 + } + rtp_parameters::RtpHeaderExtensionUri::FrameMarking => { + RtpHeaderExtensionUri::FrameMarking + } + rtp_parameters::RtpHeaderExtensionUri::AudioLevel => RtpHeaderExtensionUri::AudioLevel, + rtp_parameters::RtpHeaderExtensionUri::VideoOrientation => { + RtpHeaderExtensionUri::VideoOrientation + } + rtp_parameters::RtpHeaderExtensionUri::TimeOffset => RtpHeaderExtensionUri::TimeOffset, + rtp_parameters::RtpHeaderExtensionUri::TransportWideCcDraft01 => { + RtpHeaderExtensionUri::TransportWideCcDraft01 + } + rtp_parameters::RtpHeaderExtensionUri::AbsSendTime => { + RtpHeaderExtensionUri::AbsSendTime + } + rtp_parameters::RtpHeaderExtensionUri::AbsCaptureTime => { + RtpHeaderExtensionUri::AbsCaptureTime + } + } + } +} + +impl FromStr for RtpHeaderExtensionUri { + type Err = RtpHeaderExtensionUriParseError; + + fn from_str(s: &str) -> Result { + match s { + "urn:ietf:params:rtp-hdrext:sdes:mid" => Ok(Self::Mid), + "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id" => Ok(Self::RtpStreamId), + "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id" => Ok(Self::RepairRtpStreamId), + "http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07" => { + Ok(Self::FrameMarkingDraft07) + } + "urn:ietf:params:rtp-hdrext:framemarking" => Ok(Self::FrameMarking), + "urn:ietf:params:rtp-hdrext:ssrc-audio-level" => Ok(Self::AudioLevel), + "urn:3gpp:video-orientation" => Ok(Self::VideoOrientation), + "urn:ietf:params:rtp-hdrext:toffset" => Ok(Self::TimeOffset), + "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" => { + Ok(Self::TransportWideCcDraft01) + } + "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time" => Ok(Self::AbsSendTime), + "http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time" => { + Ok(Self::AbsCaptureTime) + } + _ => Err(RtpHeaderExtensionUriParseError::Unsupported), + } + } +} + impl RtpHeaderExtensionUri { /// RTP header extension as a string #[must_use] @@ -545,6 +786,219 @@ pub struct RtpParameters { pub rtcp: RtcpParameters, } +impl RtpParameters { + pub(crate) fn from_fbs_ref( + rtp_parameters: rtp_parameters::RtpParametersRef<'_>, + ) -> Result> { + Ok(Self { + mid: rtp_parameters.mid()?.map(|mid| mid.to_string()), + codecs: rtp_parameters + .codecs()? + .into_iter() + .map(|codec| { + let parameters = codec? + .parameters()? + .unwrap_or(planus::Vector::new_empty()) + .into_iter() + .map(|parameters| { + Ok(( + Cow::Owned(parameters?.name()?.to_string()), + match parameters?.value()? { + rtp_parameters::ValueRef::Boolean(_) + | rtp_parameters::ValueRef::Double(_) + | rtp_parameters::ValueRef::Integer32Array(_) => { + // TODO: Above value variant should not exist in the + // first place + panic!("Invalid parameter") + } + rtp_parameters::ValueRef::Integer32(n) => { + RtpCodecParametersParametersValue::Number( + n.value()?.try_into()?, + ) + } + rtp_parameters::ValueRef::String(s) => { + RtpCodecParametersParametersValue::String( + s.value()?.to_string().into(), + ) + } + }, + )) + }) + .collect::>>()?; + let rtcp_feedback = codec? + .rtcp_feedback()? + .unwrap_or(planus::Vector::new_empty()) + .into_iter() + .map(|rtcp_feedback| { + Ok(RtcpFeedback::from_type_parameter( + rtcp_feedback?.type_()?, + rtcp_feedback?.parameter()?.unwrap_or_default(), + )?) + }) + .collect::>>()?; + + Ok(match MimeType::from_str(codec?.mime_type()?)? { + MimeType::Audio(mime_type) => RtpCodecParameters::Audio { + mime_type, + payload_type: codec?.payload_type()?, + clock_rate: codec?.clock_rate()?.try_into()?, + channels: codec? + .channels()? + .ok_or("Audio must have channels specified")? + .try_into()?, + parameters, + rtcp_feedback: vec![], + }, + MimeType::Video(mime_type) => RtpCodecParameters::Video { + mime_type, + payload_type: codec?.payload_type()?, + clock_rate: codec?.clock_rate()?.try_into()?, + parameters, + rtcp_feedback, + }, + }) + }) + .collect::>>()?, + header_extensions: rtp_parameters + .header_extensions()? + .into_iter() + .map(|header_extension_parameters| { + Ok(RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::from_fbs(header_extension_parameters?.uri()?), + id: u16::from(header_extension_parameters?.id()?), + encrypt: header_extension_parameters?.encrypt()?, + }) + }) + .collect::>>()?, + encodings: rtp_parameters + .encodings()? + .into_iter() + .map(|encoding| { + Ok(RtpEncodingParameters { + ssrc: encoding?.ssrc()?, + rid: encoding?.rid()?.map(|rid| rid.to_string()), + codec_payload_type: encoding?.codec_payload_type()?, + rtx: encoding?.rtx()?.map(|rtx| RtpEncodingParametersRtx { + ssrc: rtx.ssrc().unwrap(), + }), + dtx: { + match encoding?.dtx()? { + true => Some(true), + false => None, + } + }, + scalability_mode: encoding? + .scalability_mode()? + .unwrap_or(String::from("S1T1").as_str()) + .parse()?, + max_bitrate: encoding?.max_bitrate()?, + }) + }) + .collect::>>()?, + rtcp: RtcpParameters { + cname: rtp_parameters + .rtcp()? + .cname()? + .map(|cname| cname.to_string()), + reduced_size: rtp_parameters.rtcp()?.reduced_size()?, + }, + }) + } + + #[allow(dead_code)] + pub(crate) fn into_fbs(self) -> rtp_parameters::RtpParameters { + rtp_parameters::RtpParameters { + mid: self.mid, + codecs: self + .codecs + .into_iter() + .map(|codec| rtp_parameters::RtpCodecParameters { + mime_type: codec.mime_type().as_str().to_string(), + payload_type: codec.payload_type(), + clock_rate: codec.clock_rate().get(), + channels: match &codec { + RtpCodecParameters::Audio { channels, .. } => Some(channels.get()), + RtpCodecParameters::Video { .. } => None, + }, + parameters: Some( + codec + .parameters() + .iter() + .map(|(name, value)| rtp_parameters::Parameter { + name: name.to_string(), + value: match value { + RtpCodecParametersParametersValue::String(s) => { + rtp_parameters::Value::String(Box::new( + rtp_parameters::String { + value: s.to_string(), + }, + )) + } + RtpCodecParametersParametersValue::Number(n) => { + rtp_parameters::Value::Integer32(Box::new( + rtp_parameters::Integer32 { value: *n as i32 }, + )) + } + }, + }) + .collect(), + ), + rtcp_feedback: match &codec { + RtpCodecParameters::Audio { .. } => None, + RtpCodecParameters::Video { rtcp_feedback, .. } => Some( + rtcp_feedback + .iter() + .map(|rtcp_feedback| { + let (r#type, parameter) = rtcp_feedback.as_type_parameter(); + rtp_parameters::RtcpFeedback { + type_: r#type.to_string(), + parameter: Some(parameter.to_string()), + } + }) + .collect(), + ), + }, + }) + .collect(), + header_extensions: self + .header_extensions + .into_iter() + .map( + |header_extension_parameters| rtp_parameters::RtpHeaderExtensionParameters { + uri: header_extension_parameters.uri.to_fbs(), + id: header_extension_parameters.id as u8, + encrypt: header_extension_parameters.encrypt, + parameters: None, + }, + ) + .collect(), + encodings: self + .encodings + .into_iter() + .map(|encoding| rtp_parameters::RtpEncodingParameters { + ssrc: encoding.ssrc, + rid: encoding.rid, + codec_payload_type: encoding.codec_payload_type, + rtx: encoding + .rtx + .map(|rtx| Box::new(rtp_parameters::Rtx { ssrc: rtx.ssrc })), + dtx: encoding.dtx.unwrap_or_default(), + scalability_mode: if encoding.scalability_mode.is_none() { + None + } else { + Some(encoding.scalability_mode.as_str().to_string()) + }, + max_bitrate: encoding.max_bitrate, + }) + .collect(), + rtcp: Box::new(rtp_parameters::RtcpParameters { + cname: self.rtcp.cname, + reduced_size: self.rtcp.reduced_size, + }), + } + } +} + /// Single value used in RTP codec parameters. #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] #[serde(untagged)] @@ -654,6 +1108,11 @@ impl RtpCodecParameters { *payload_type } + pub(crate) fn clock_rate(&self) -> NonZeroU32 { + let (Self::Audio { clock_rate, .. } | Self::Video { clock_rate, .. }) = self; + *clock_rate + } + pub(crate) fn parameters(&self) -> &RtpCodecParametersParameters { let (Self::Audio { parameters, .. } | Self::Video { parameters, .. }) = self; parameters @@ -690,32 +1149,9 @@ impl Serialize for RtcpFeedback { S: Serializer, { let mut rtcp_feedback = serializer.serialize_struct("RtcpFeedback", 2)?; - match self { - RtcpFeedback::Nack => { - rtcp_feedback.serialize_field("type", "nack")?; - rtcp_feedback.serialize_field("parameter", "")?; - } - RtcpFeedback::NackPli => { - rtcp_feedback.serialize_field("type", "nack")?; - rtcp_feedback.serialize_field("parameter", "pli")?; - } - RtcpFeedback::CcmFir => { - rtcp_feedback.serialize_field("type", "ccm")?; - rtcp_feedback.serialize_field("parameter", "fir")?; - } - RtcpFeedback::GoogRemb => { - rtcp_feedback.serialize_field("type", "goog-remb")?; - rtcp_feedback.serialize_field("parameter", "")?; - } - RtcpFeedback::TransportCc => { - rtcp_feedback.serialize_field("type", "transport-cc")?; - rtcp_feedback.serialize_field("parameter", "")?; - } - RtcpFeedback::Unsupported => { - rtcp_feedback.serialize_field("type", "unknown")?; - rtcp_feedback.serialize_field("parameter", "")?; - } - } + let (r#type, parameter) = self.as_type_parameter(); + rtcp_feedback.serialize_field("type", r#type)?; + rtcp_feedback.serialize_field("parameter", parameter)?; rtcp_feedback.end() } } @@ -767,14 +1203,10 @@ impl<'de> Deserialize<'de> for RtcpFeedback { } let r#type = r#type.ok_or_else(|| de::Error::missing_field("type"))?; - Ok(match (r#type.as_ref(), parameter.as_ref()) { - ("nack", "") => RtcpFeedback::Nack, - ("nack", "pli") => RtcpFeedback::NackPli, - ("ccm", "fir") => RtcpFeedback::CcmFir, - ("goog-remb", "") => RtcpFeedback::GoogRemb, - ("transport-cc", "") => RtcpFeedback::TransportCc, - _ => RtcpFeedback::Unsupported, - }) + Ok( + RtcpFeedback::from_type_parameter(r#type.as_ref(), parameter.as_ref()) + .unwrap_or(RtcpFeedback::Unsupported), + ) } } @@ -783,6 +1215,42 @@ impl<'de> Deserialize<'de> for RtcpFeedback { } } +/// Error of failure to create [`RtcpFeedback`] from type and parameter. +#[derive(Debug, Error, Eq, PartialEq)] +pub enum RtcpFeedbackFromTypeParameterError { + /// Unsupported + #[error("Unsupported")] + Unsupported, +} + +impl RtcpFeedback { + pub(crate) fn from_type_parameter( + r#type: &str, + parameter: &str, + ) -> Result { + match (r#type, parameter) { + ("nack", "") => Ok(RtcpFeedback::Nack), + ("nack", "pli") => Ok(RtcpFeedback::NackPli), + ("ccm", "fir") => Ok(RtcpFeedback::CcmFir), + ("goog-remb", "") => Ok(RtcpFeedback::GoogRemb), + ("transport-cc", "") => Ok(RtcpFeedback::TransportCc), + ("unknown", "") => Ok(RtcpFeedback::Unsupported), + _ => Err(RtcpFeedbackFromTypeParameterError::Unsupported), + } + } + + pub(crate) fn as_type_parameter(&self) -> (&'static str, &'static str) { + match self { + RtcpFeedback::Nack => ("nack", ""), + RtcpFeedback::NackPli => ("nack", "pli"), + RtcpFeedback::CcmFir => ("ccm", "fir"), + RtcpFeedback::GoogRemb => ("goog-remb", ""), + RtcpFeedback::TransportCc => ("transport-cc", ""), + RtcpFeedback::Unsupported => ("unknown", ""), + } + } +} + /// RTX stream information. It must contain a numeric ssrc field indicating the RTX SSRC. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] pub struct RtpEncodingParametersRtx { @@ -816,14 +1284,58 @@ pub struct RtpEncodingParameters { /// Number of spatial and temporal layers in the RTP stream. #[serde(default, skip_serializing_if = "ScalabilityMode::is_none")] pub scalability_mode: ScalabilityMode, - /// Factor by which to reduce the size of a video track during encoding. - #[serde(skip_serializing_if = "Option::is_none")] - pub scale_resolution_down_by: Option, /// Maximum number of bits per second to allow a track encoded with this encoding to use. #[serde(skip_serializing_if = "Option::is_none")] pub max_bitrate: Option, } +impl RtpEncodingParameters { + pub(crate) fn to_fbs(&self) -> rtp_parameters::RtpEncodingParameters { + rtp_parameters::RtpEncodingParameters { + ssrc: self.ssrc, + rid: self.rid.clone(), + codec_payload_type: self.codec_payload_type, + rtx: self + .rtx + .map(|rtx| Box::new(rtp_parameters::Rtx { ssrc: rtx.ssrc })), + dtx: self.dtx.unwrap_or_default(), + scalability_mode: if self.scalability_mode.is_none() { + None + } else { + Some(self.scalability_mode.as_str().to_string()) + }, + max_bitrate: self.max_bitrate, + } + } + + pub(crate) fn from_fbs_ref( + encoding_parameters: rtp_parameters::RtpEncodingParametersRef<'_>, + ) -> Result> { + Ok(Self { + ssrc: encoding_parameters.ssrc()?, + rid: encoding_parameters.rid()?.map(|rid| rid.to_string()), + codec_payload_type: encoding_parameters.codec_payload_type()?, + rtx: if let Some(rtx) = encoding_parameters.rtx()? { + Some(RtpEncodingParametersRtx { ssrc: rtx.ssrc()? }) + } else { + None + }, + dtx: { + match encoding_parameters.dtx()? { + true => Some(true), + false => None, + } + }, + scalability_mode: encoding_parameters + .scalability_mode()? + .map(|maybe_scalability_mode| maybe_scalability_mode.parse()) + .transpose()? + .unwrap_or_default(), + max_bitrate: encoding_parameters.max_bitrate()?, + }) + } +} + /// Defines a RTP header extension within the RTP parameters. The list of RTP /// header extensions supported by mediasoup is defined in the `supported_rtp_capabilities.rs` file. /// @@ -858,9 +1370,6 @@ pub struct RtcpParameters { /// Whether reduced size RTCP RFC 5506 is configured (if true) or compound RTCP /// as specified in RFC 3550 (if false). Default true. pub reduced_size: bool, - /// Whether RTCP-mux is used. Default true. - #[serde(skip_serializing_if = "Option::is_none")] - pub mux: Option, } impl Default for RtcpParameters { @@ -868,7 +1377,6 @@ impl Default for RtcpParameters { Self { cname: None, reduced_size: true, - mux: None, } } } diff --git a/rust/src/scalability_modes.rs b/rust/src/scalability_modes.rs index 429802f8cb..de7510f5b4 100644 --- a/rust/src/scalability_modes.rs +++ b/rust/src/scalability_modes.rs @@ -118,7 +118,7 @@ impl Default for ScalabilityMode { #[derive(Debug, Error, Eq, PartialEq)] pub enum ParseScalabilityModeError { /// Invalid input string - #[error("Invalid input string")] + #[error("Invalid Scalability Mode input string")] InvalidInput, } diff --git a/rust/src/sctp_parameters.rs b/rust/src/sctp_parameters.rs index 51ac9b797a..807dafbea8 100644 --- a/rust/src/sctp_parameters.rs +++ b/rust/src/sctp_parameters.rs @@ -1,5 +1,6 @@ //! Collection of SCTP-related data structures that are used to specify SCTP association parameters. +use mediasoup_sys::fbs::sctp_parameters; use serde::{Deserialize, Serialize}; /// Number of SCTP streams. @@ -42,6 +43,15 @@ impl Default for NumSctpStreams { } } +impl NumSctpStreams { + pub(crate) fn to_fbs(self) -> sctp_parameters::NumSctpStreams { + sctp_parameters::NumSctpStreams { + os: self.os, + mis: self.mis, + } + } +} + /// Parameters of the SCTP association. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -55,7 +65,18 @@ pub struct SctpParameters { #[serde(rename = "MIS")] pub mis: u16, /// Maximum allowed size for SCTP messages. - pub max_message_size: usize, + pub max_message_size: u32, +} + +impl SctpParameters { + pub(crate) fn from_fbs(parameters: &sctp_parameters::SctpParameters) -> Self { + Self { + port: parameters.port, + os: parameters.os, + mis: parameters.mis, + max_message_size: parameters.max_message_size, + } + } } /// SCTP stream parameters describe the reliability of a certain SCTP stream. @@ -110,6 +131,26 @@ impl SctpStreamParameters { } } +impl SctpStreamParameters { + pub(crate) fn to_fbs(self) -> sctp_parameters::SctpStreamParameters { + sctp_parameters::SctpStreamParameters { + stream_id: self.stream_id, + ordered: Some(self.ordered), + max_packet_life_time: self.max_packet_life_time, + max_retransmits: self.max_retransmits, + } + } + + pub(crate) fn from_fbs(stream_parameters: sctp_parameters::SctpStreamParameters) -> Self { + Self { + stream_id: stream_parameters.stream_id, + ordered: stream_parameters.ordered.unwrap_or(false), + max_packet_life_time: stream_parameters.max_packet_life_time, + max_retransmits: stream_parameters.max_retransmits, + } + } +} + impl SctpStreamParameters { /// Messages will be sent reliably in order. #[must_use] diff --git a/rust/src/srtp_parameters.rs b/rust/src/srtp_parameters.rs index 3d5d48389c..99bb898cf8 100644 --- a/rust/src/srtp_parameters.rs +++ b/rust/src/srtp_parameters.rs @@ -1,6 +1,7 @@ //! Collection of SRTP-related data structures that are used to specify SRTP encryption/decryption //! parameters. +use mediasoup_sys::fbs::srtp_parameters; use serde::{Deserialize, Serialize}; /// SRTP parameters. @@ -13,6 +14,22 @@ pub struct SrtpParameters { pub key_base64: String, } +impl SrtpParameters { + pub(crate) fn from_fbs(tuple: &srtp_parameters::SrtpParameters) -> Self { + Self { + crypto_suite: SrtpCryptoSuite::from_fbs(tuple.crypto_suite), + key_base64: String::from(tuple.key_base64.as_str()), + } + } + + pub(crate) fn to_fbs(&self) -> srtp_parameters::SrtpParameters { + srtp_parameters::SrtpParameters { + crypto_suite: SrtpCryptoSuite::to_fbs(self.crypto_suite), + key_base64: String::from(self.key_base64.as_str()), + } + } +} + /// SRTP crypto suite. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] pub enum SrtpCryptoSuite { @@ -30,6 +47,26 @@ pub enum SrtpCryptoSuite { AesCm128HmacSha132, } +impl SrtpCryptoSuite { + pub(crate) fn from_fbs(crypto_suite: srtp_parameters::SrtpCryptoSuite) -> Self { + match crypto_suite { + srtp_parameters::SrtpCryptoSuite::AeadAes256Gcm => Self::AeadAes256Gcm, + srtp_parameters::SrtpCryptoSuite::AeadAes128Gcm => Self::AeadAes128Gcm, + srtp_parameters::SrtpCryptoSuite::AesCm128HmacSha180 => Self::AesCm128HmacSha180, + srtp_parameters::SrtpCryptoSuite::AesCm128HmacSha132 => Self::AesCm128HmacSha132, + } + } + + pub(crate) fn to_fbs(self) -> srtp_parameters::SrtpCryptoSuite { + match self { + Self::AeadAes256Gcm => srtp_parameters::SrtpCryptoSuite::AeadAes256Gcm, + Self::AeadAes128Gcm => srtp_parameters::SrtpCryptoSuite::AeadAes128Gcm, + Self::AesCm128HmacSha180 => srtp_parameters::SrtpCryptoSuite::AesCm128HmacSha180, + Self::AesCm128HmacSha132 => srtp_parameters::SrtpCryptoSuite::AesCm128HmacSha132, + } + } +} + impl Default for SrtpCryptoSuite { fn default() -> Self { Self::AesCm128HmacSha180 diff --git a/rust/src/webrtc_server.rs b/rust/src/webrtc_server.rs index 7d70430e0d..4750323c56 100644 --- a/rust/src/webrtc_server.rs +++ b/rust/src/webrtc_server.rs @@ -10,7 +10,7 @@ #[cfg(test)] mod tests; -use crate::data_structures::{AppData, ListenIp, Protocol}; +use crate::data_structures::{AppData, ListenInfo}; use crate::messages::{WebRtcServerCloseRequest, WebRtcServerDumpRequest}; use crate::transport::TransportId; use crate::uuid_based_wrapper_type; @@ -20,6 +20,7 @@ use async_executor::Executor; use event_listener_primitives::{BagOnce, HandlerId}; use hash_hasher::HashedSet; use log::{debug, error}; +use mediasoup_sys::fbs::transport; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; use std::fmt; @@ -73,41 +74,34 @@ pub struct WebRtcServerDump { pub tuple_hashes: Vec, } -/// Listening protocol, IP and port for [`WebRtcServer`] to listen on. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct WebRtcServerListenInfo { - /// Network protocol. - pub protocol: Protocol, - /// Listening IP address. - #[serde(flatten)] - pub listen_ip: ListenIp, - /// Listening port. - #[serde(skip_serializing_if = "Option::is_none")] - pub port: Option, -} - /// Struct that protects an invariant of having non-empty list of listen infos. #[derive(Debug, Clone, Eq, PartialEq, Serialize)] -pub struct WebRtcServerListenInfos(Vec); +pub struct WebRtcServerListenInfos(Vec); impl WebRtcServerListenInfos { /// Create WebRTC server listen infos with given info populated initially. #[must_use] - pub fn new(listen_info: WebRtcServerListenInfo) -> Self { + pub fn new(listen_info: ListenInfo) -> Self { Self(vec![listen_info]) } /// Insert another listen info. #[must_use] - pub fn insert(mut self, listen_info: WebRtcServerListenInfo) -> Self { + pub fn insert(mut self, listen_info: ListenInfo) -> Self { self.0.push(listen_info); self } + + pub(crate) fn to_fbs(&self) -> Vec { + self.0 + .iter() + .map(|listen_info| listen_info.to_fbs()) + .collect() + } } impl Deref for WebRtcServerListenInfos { - type Target = Vec; + type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 @@ -119,10 +113,10 @@ impl Deref for WebRtcServerListenInfos { #[error("Empty list of listen infos provided, should have at least one element")] pub struct EmptyListError; -impl TryFrom> for WebRtcServerListenInfos { +impl TryFrom> for WebRtcServerListenInfos { type Error = EmptyListError; - fn try_from(listen_infos: Vec) -> Result { + fn try_from(listen_infos: Vec) -> Result { if listen_infos.is_empty() { Err(EmptyListError) } else { diff --git a/rust/src/webrtc_server/tests.rs b/rust/src/webrtc_server/tests.rs index a87f17d653..a07c32c648 100644 --- a/rust/src/webrtc_server/tests.rs +++ b/rust/src/webrtc_server/tests.rs @@ -1,5 +1,5 @@ -use crate::data_structures::{ListenIp, Protocol}; -use crate::webrtc_server::{WebRtcServerListenInfo, WebRtcServerListenInfos, WebRtcServerOptions}; +use crate::data_structures::{ListenInfo, Protocol}; +use crate::webrtc_server::{WebRtcServerListenInfos, WebRtcServerOptions}; use crate::worker::{Worker, WorkerSettings}; use crate::worker_manager::WorkerManager; use futures_lite::future; @@ -33,13 +33,13 @@ fn worker_close_event() { let webrtc_server = worker .create_webrtc_server(WebRtcServerOptions::new(WebRtcServerListenInfos::new( - WebRtcServerListenInfo { + ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port), + send_buffer_size: None, + recv_buffer_size: None, }, ))) .await diff --git a/rust/src/worker.rs b/rust/src/worker.rs index 431b2a9222..56766bec13 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -3,7 +3,6 @@ mod channel; mod common; -mod payload_channel; mod utils; use crate::data_structures::AppData; @@ -19,14 +18,15 @@ pub use crate::worker::utils::ExitError; use crate::worker_manager::WorkerManager; use crate::{ortc, uuid_based_wrapper_type}; use async_executor::Executor; -pub(crate) use channel::Channel; +pub(crate) use channel::{Channel, NotificationError, NotificationParseError}; pub(crate) use common::{SubscriptionHandler, SubscriptionTarget}; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use futures_lite::FutureExt; use log::{debug, error, warn}; +use mediasoup_sys::fbs; use parking_lot::Mutex; -pub(crate) use payload_channel::{NotificationError, PayloadChannel}; use serde::{Deserialize, Serialize}; +use std::error::Error; use std::ops::RangeInclusive; use std::path::PathBuf; use std::sync::atomic::{AtomicBool, Ordering}; @@ -42,7 +42,7 @@ uuid_based_wrapper_type!( ); /// Error that caused request to mediasoup-worker request to fail. -#[derive(Debug, Error, Eq, PartialEq)] +#[derive(Debug, Error)] pub enum RequestError { /// Channel already closed. #[error("Channel already closed")] @@ -65,6 +65,9 @@ pub enum RequestError { /// Worker did not return any data in response. #[error("Worker did not return any data in response")] NoData, + /// Response conversion error. + #[error("Response conversion error: {0}")] + ResponseConversion(Box), } /// Logging level for logs generated by the media worker thread (check the @@ -93,7 +96,7 @@ impl Default for WorkerLogLevel { } impl WorkerLogLevel { - fn as_str(self) -> &'static str { + pub(crate) fn as_str(self) -> &'static str { match self { Self::Debug => "debug", Self::Warn => "warn", @@ -137,7 +140,7 @@ pub enum WorkerLogTag { } impl WorkerLogTag { - fn as_str(self) -> &'static str { + pub(crate) fn as_str(self) -> &'static str { match self { Self::Info => "info", Self::Ice => "ice", @@ -272,8 +275,7 @@ pub struct WorkerUpdateSettings { #[doc(hidden)] pub struct ChannelMessageHandlers { pub channel_request_handlers: Vec, - pub payload_channel_request_handlers: Vec, - pub payload_channel_notification_handlers: Vec, + pub channel_notification_handlers: Vec, } #[derive(Debug, Clone, Deserialize, Serialize)] @@ -289,7 +291,7 @@ pub struct WorkerDump { } /// Error that caused [`Worker::create_webrtc_server`] to fail. -#[derive(Debug, Error, Eq, PartialEq)] +#[derive(Debug, Error)] pub enum CreateWebRtcServerError { /// Request to worker failed #[error("Request to worker failed: {0}")] @@ -297,7 +299,7 @@ pub enum CreateWebRtcServerError { } /// Error that caused [`Worker::create_router`] to fail. -#[derive(Debug, Error, Eq, PartialEq)] +#[derive(Debug, Error)] pub enum CreateRouterError { /// RTP capabilities generation error #[error("RTP capabilities generation error: {0}")] @@ -320,7 +322,6 @@ struct Handlers { struct Inner { id: WorkerId, channel: Channel, - payload_channel: PayloadChannel, executor: Arc>, handlers: Handlers, app_data: AppData, @@ -406,7 +407,6 @@ impl Inner { let (mut status_sender, status_receiver) = async_oneshot::oneshot(); let WorkerRunResult { channel, - payload_channel, buffer_worker_messages_guard, } = utils::run_worker_with_channels( id, @@ -424,7 +424,6 @@ impl Inner { let mut inner = Self { id, channel, - payload_channel, executor, handlers, app_data, @@ -490,20 +489,19 @@ impl Inner { let id = self.id; let sender = Mutex::new(Some(sender)); let _handler = self.channel.subscribe_to_notifications( - std::process::id().into(), + SubscriptionTarget::String(std::process::id().to_string()), move |notification| { - let result = match serde_json::from_slice(notification) { - Ok(Notification::Running) => { + let result = match notification.event().unwrap() { + fbs::notification::Event::WorkerRunning => { debug!("worker thread running [id:{}]", id); Ok(()) } - Err(error) => Err(io::Error::new( + _ => Err(io::Error::new( io::ErrorKind::Other, - format!( - "unexpected first notification from worker [id:{id}]: {notification:?}; error = {error}" - ), + format!("unexpected first notification from worker [id:{id}]"), )), }; + let _ = sender .lock() .take() @@ -522,7 +520,6 @@ impl Inner { fn setup_message_handling(&mut self) { let channel_receiver = self.channel.get_internal_message_receiver(); - let payload_channel_receiver = self.payload_channel.get_internal_message_receiver(); let id = self.id; let closed = Arc::clone(&self.closed); self.executor @@ -546,20 +543,6 @@ impl Inner { } }) .detach(); - - self.executor - .spawn(async move { - while let Ok(message) = payload_channel_receiver.recv().await { - match message { - payload_channel::InternalMessage::UnexpectedData(data) => error!( - "worker[id:{}] unexpected payload channel data: {}", - id, - String::from_utf8_lossy(&data) - ), - } - } - }) - .detach(); } fn close(&self) { @@ -567,7 +550,6 @@ impl Inner { if !already_closed { let channel = self.channel.clone(); - let payload_channel = self.payload_channel.clone(); self.executor .spawn(async move { @@ -575,7 +557,6 @@ impl Inner { // Drop channels in here after response from worker drop(channel); - drop(payload_channel); }) .detach(); @@ -648,10 +629,15 @@ impl Worker { pub async fn update_settings(&self, data: WorkerUpdateSettings) -> Result<(), RequestError> { debug!("update_settings()"); - self.inner + match self + .inner .channel .request("", WorkerUpdateSettingsRequest { data }) .await + { + Ok(_) => Ok(()), + Err(error) => Err(error), + } } /// Create a WebRtcServer. @@ -661,7 +647,7 @@ impl Worker { &self, webrtc_server_options: WebRtcServerOptions, ) -> Result { - debug!("create_router()"); + debug!("create_webrtc_server()"); let WebRtcServerOptions { listen_infos, @@ -734,7 +720,6 @@ impl Worker { router_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), rtp_capabilities, app_data, self.clone(), diff --git a/rust/src/worker/channel.rs b/rust/src/worker/channel.rs index 7219903074..8dc53c9a76 100644 --- a/rust/src/worker/channel.rs +++ b/rust/src/worker/channel.rs @@ -1,4 +1,4 @@ -use crate::messages::{Request, WorkerCloseRequest}; +use crate::messages::{Notification, Request}; use crate::worker::common::{EventHandlers, SubscriptionTarget, WeakEventHandlers}; use crate::worker::utils; use crate::worker::utils::{PreparedChannelRead, PreparedChannelWrite}; @@ -7,16 +7,18 @@ use atomic_take::AtomicTake; use hash_hasher::HashedMap; use log::{debug, error, trace, warn}; use lru::LruCache; +use mediasoup_sys::fbs::{message, notification, request, response}; use mediasoup_sys::UvAsyncT; use parking_lot::Mutex; +use planus::ReadAsRoot; use serde::Deserialize; -use serde_json::Value; -use std::any::TypeId; use std::collections::VecDeque; use std::fmt::{Debug, Display}; use std::num::NonZeroUsize; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Weak}; +use thiserror::Error; +use uuid::Uuid; #[derive(Debug, Deserialize)] #[serde(untagged)] @@ -38,11 +40,26 @@ pub(super) enum InternalMessage { Unexpected(Vec), } +#[derive(Debug, Error, Eq, PartialEq)] +pub enum NotificationError { + #[error("Channel already closed")] + ChannelClosed, +} + +/// Flabtuffers notification parse error. +#[derive(Debug, Error, Eq, PartialEq)] +pub enum NotificationParseError { + /// Invalid event + #[error("Invalid event")] + InvalidEvent, +} + #[allow(clippy::type_complexity)] pub(crate) struct BufferMessagesGuard { target_id: SubscriptionTarget, buffered_notifications_for: Arc>>>>, - event_handlers_weak: WeakEventHandlers>, + event_handlers_weak: + WeakEventHandlers) + Send + Sync + 'static>>, } impl Drop for BufferMessagesGuard { @@ -50,59 +67,63 @@ impl Drop for BufferMessagesGuard { let mut buffered_notifications_for = self.buffered_notifications_for.lock(); if let Some(notifications) = buffered_notifications_for.remove(&self.target_id) { if let Some(event_handlers) = self.event_handlers_weak.upgrade() { - for notification in notifications { - event_handlers.call_callbacks_with_single_value(&self.target_id, ¬ification); + for bytes in notifications { + let message_ref = message::MessageRef::read_as_root(&bytes).unwrap(); + + let message::BodyRef::Notification(notification_ref) = + message_ref.data().unwrap() + else { + panic!("Wrong notification stored: {message_ref:?}"); + }; + + event_handlers + .call_callbacks_with_single_value(&self.target_id, notification_ref); } } } } } -#[derive(Debug, Deserialize)] -#[serde(untagged)] -enum ChannelReceiveMessage { - #[serde(rename_all = "camelCase")] - Notification { - target_id: SubscriptionTarget, - }, - ResponseSuccess { - id: u32, - // The following field is present, unused, but needed for differentiating successful - // response from error case - #[allow(dead_code)] - accepted: bool, - data: Option, - }, - ResponseError { - id: u32, - // The following field is present, but unused - // error: Value, - reason: String, - }, +#[derive(Debug)] +enum ChannelReceiveMessage<'a> { + Notification(notification::NotificationRef<'a>), + Response(response::ResponseRef<'a>), Event(InternalMessage), } -fn deserialize_message(bytes: &[u8]) -> ChannelReceiveMessage { - match bytes[0] { - // JSON message - b'{' => serde_json::from_slice(bytes).unwrap(), - // Debug log - b'D' => ChannelReceiveMessage::Event(InternalMessage::Debug( - String::from_utf8(Vec::from(&bytes[1..])).unwrap(), - )), - // Warn log - b'W' => ChannelReceiveMessage::Event(InternalMessage::Warn( - String::from_utf8(Vec::from(&bytes[1..])).unwrap(), - )), - // Error log - b'E' => ChannelReceiveMessage::Event(InternalMessage::Error( - String::from_utf8(Vec::from(&bytes[1..])).unwrap(), - )), - // Dump log - b'X' => ChannelReceiveMessage::Event(InternalMessage::Dump( - String::from_utf8(Vec::from(&bytes[1..])).unwrap(), - )), - // Unknown +// Remove the first 4 bytes which represent the buffer size. +// NOTE: The prefix is only needed for NodeJS. +fn unprefix_message(bytes: &[u8]) -> &[u8] { + &bytes[4..] +} + +fn deserialize_message(bytes: &[u8]) -> ChannelReceiveMessage<'_> { + let message_ref = message::MessageRef::read_as_root(bytes).unwrap(); + + match message_ref.data().unwrap() { + message::BodyRef::Log(data) => match data.data().unwrap().chars().next() { + // Debug log + Some('D') => ChannelReceiveMessage::Event(InternalMessage::Debug( + String::from_utf8(Vec::from(&data.data().unwrap().as_bytes()[1..])).unwrap(), + )), + // Warn log + Some('W') => ChannelReceiveMessage::Event(InternalMessage::Warn( + String::from_utf8(Vec::from(&data.data().unwrap().as_bytes()[1..])).unwrap(), + )), + // Error log + Some('E') => ChannelReceiveMessage::Event(InternalMessage::Error( + String::from_utf8(Vec::from(&data.data().unwrap().as_bytes()[1..])).unwrap(), + )), + // Dump log + Some('X') => ChannelReceiveMessage::Event(InternalMessage::Dump( + String::from_utf8(Vec::from(&data.data().unwrap().as_bytes()[1..])).unwrap(), + )), + // This should never happen. + _ => ChannelReceiveMessage::Event(InternalMessage::Unexpected(Vec::from(bytes))), + }, + message::BodyRef::Notification(data) => ChannelReceiveMessage::Notification(data), + message::BodyRef::Response(data) => ChannelReceiveMessage::Response(data), + _ => ChannelReceiveMessage::Event(InternalMessage::Unexpected(Vec::from(bytes))), } } @@ -111,7 +132,7 @@ struct ResponseError { reason: String, } -type ResponseResult = Result, ResponseError>; +type FBSResponseResult = Result>, ResponseError>; struct RequestDropGuard<'a> { id: u32, @@ -142,9 +163,9 @@ impl<'a> RequestDropGuard<'a> { } #[derive(Default)] -struct RequestsContainer { +struct FBSRequestsContainer { next_id: u32, - handlers: HashedMap>>, + handlers: HashedMap>, } struct OutgoingMessageBuffer { @@ -152,13 +173,15 @@ struct OutgoingMessageBuffer { messages: VecDeque>>>, } -#[allow(clippy::type_complexity)] +// TODO: use 'close' in 'request' method. +#[allow(clippy::type_complexity, dead_code)] struct Inner { outgoing_message_buffer: Arc>, internal_message_receiver: async_channel::Receiver, - requests_container_weak: Weak>, + requests_container_weak: Weak>, buffered_notifications_for: Arc>>>>, - event_handlers_weak: WeakEventHandlers>, + event_handlers_weak: + WeakEventHandlers) + Send + Sync + 'static>>, worker_closed: Arc, closed: AtomicBool, } @@ -182,7 +205,7 @@ impl Channel { handle: None, messages: VecDeque::with_capacity(10), })); - let requests_container = Arc::>::default(); + let requests_container = Arc::>::default(); let requests_container_weak = Arc::downgrade(&requests_container); let buffered_notifications_for = Arc::>>>>::default(); @@ -222,41 +245,61 @@ impl Channel { move |message| { trace!("received raw message: {}", String::from_utf8_lossy(message)); + let message = unprefix_message(message); + match deserialize_message(message) { - ChannelReceiveMessage::Notification { target_id } => { + ChannelReceiveMessage::Notification(notification) => { + let target_id = notification.handler_id().unwrap(); + // Target id can be either the worker PID or a UUID. + let target_id = match target_id.parse::() { + Ok(_) => SubscriptionTarget::String(target_id.to_string()), + Err(_) => SubscriptionTarget::Uuid(Uuid::parse_str(target_id).unwrap()), + }; + if !non_buffered_notifications.contains(&target_id) { let mut buffer_notifications_for = buffered_notifications_for.lock(); // Check if we need to buffer notifications for this // target_id if let Some(list) = buffer_notifications_for.get_mut(&target_id) { + // Store the whole message removing the size prefix. list.push(Vec::from(message)); return; } // Remember we don't need to buffer these - non_buffered_notifications.put(target_id, ()); + non_buffered_notifications.put(target_id.clone(), ()); } - event_handlers.call_callbacks_with_single_value(&target_id, message); + event_handlers.call_callbacks_with_single_value(&target_id, notification); } - ChannelReceiveMessage::ResponseSuccess { id, data, .. } => { - let sender = requests_container.lock().handlers.remove(&id); + ChannelReceiveMessage::Response(response) => { + let sender = requests_container + .lock() + .handlers + .remove(&response.id().unwrap()); if let Some(mut sender) = sender { - let _ = sender.send(Ok(data)); + // Request did not succeed. + if let Ok(Some(reason)) = response.reason() { + let _ = sender.send(Err(ResponseError { + reason: reason.to_string(), + })); + } + // Request succeeded. + else { + match response.body().expect("failed accessing response body") { + // Response has body. + Some(_) => { + let _ = sender.send(Ok(Some(Vec::from(message)))); + } + // Response does not have body. + None => { + let _ = sender.send(Ok(None)); + } + } + } } else { warn!( "received success response does not match any sent request [id:{}]", - id, - ); - } - } - ChannelReceiveMessage::ResponseError { id, reason } => { - let sender = requests_container.lock().handlers.remove(&id); - if let Some(mut sender) = sender { - let _ = sender.send(Err(ResponseError { reason })); - } else { - warn!( - "received error response does not match any sent request [id:{}]", - id, + response.id().unwrap(), ); } } @@ -295,7 +338,7 @@ impl Channel { let event_handlers_weak = self.inner.event_handlers_weak.clone(); buffered_notifications_for .lock() - .entry(target_id) + .entry(target_id.clone()) .or_default(); BufferMessagesGuard { target_id, @@ -313,8 +356,6 @@ impl Channel { R: Request + 'static, HandlerId: Display, { - let method = request.as_method(); - let id; let (result_sender, result_receiver) = async_oneshot::oneshot(); @@ -322,10 +363,6 @@ impl Channel { let requests_container = match self.inner.requests_container_weak.upgrade() { Some(requests_container_lock) => requests_container_lock, None => { - if let Some(default_response) = R::default_for_soft_error() { - return Ok(default_response); - } - return Err(RequestError::ChannelClosed); } }; @@ -337,35 +374,22 @@ impl Channel { requests_container_lock.handlers.insert(id, result_sender); } - debug!("request() [method:{}, id:{}]: {:?}", method, id, request); + debug!("request() [method:{:?}, id:{}]", R::METHOD, id); - // TODO: Todo pre-allocate fixed size string sufficient for most cases by default - // TODO: Refactor to avoid extra allocation during JSON serialization if possible - let message = Arc::new(AtomicTake::new( - format!( - "{id}:{method}:{handler_id}:{}", - serde_json::to_string(&request).unwrap() - ) - .into_bytes(), - )); + let data = request.into_bytes(id, handler_id); + + let buffer = Arc::new(AtomicTake::new(data)); { let mut outgoing_message_buffer = self.inner.outgoing_message_buffer.lock(); outgoing_message_buffer .messages - .push_back(Arc::clone(&message)); + .push_back(Arc::clone(&buffer)); if let Some(handle) = outgoing_message_buffer.handle { if self.inner.worker_closed.load(Ordering::Acquire) { // Forbid all requests after worker closing except one worker closing request - let first_worker_closing = TypeId::of::() - == TypeId::of::() - && !self.inner.closed.swap(true, Ordering::Relaxed); - - if !first_worker_closing { - if let Some(default_response) = R::default_for_soft_error() { - return Ok(default_response); - } - + // TODO: We were checking before that inner.closed. + if R::METHOD != request::Method::WorkerClose { return Err(RequestError::ChannelClosed); } } @@ -374,9 +398,6 @@ impl Channel { let ret = mediasoup_sys::uv_async_send(handle); if ret != 0 { error!("uv_async_send call failed with code {}", ret); - if let Some(default_response) = R::default_for_soft_error() { - return Ok(default_response); - } return Err(RequestError::ChannelClosed); } @@ -387,7 +408,7 @@ impl Channel { // Drop guard to make sure to drop pending request when future is cancelled let request_drop_guard = RequestDropGuard { id, - message, + message: buffer, channel: self, removed: false, }; @@ -398,28 +419,39 @@ impl Channel { let response_result = match response_result_fut { Ok(response_result) => response_result, - Err(_closed) => { - return if let Some(default_response) = R::default_for_soft_error() { - Ok(default_response) - } else { - Err(RequestError::ChannelClosed) - }; - } + Err(_closed) => Err(ResponseError { + reason: String::from("ChannelClosed"), + }), }; match response_result { - Ok(data) => { - debug!("request succeeded [method:{}, id:{}]", method, id); + Ok(bytes) => { + debug!("request succeeded [method:{:?}, id:{}]", R::METHOD, id); + + match bytes { + Some(bytes) => { + let message_ref = message::MessageRef::read_as_root(&bytes).unwrap(); - // Default will work for `()` response - serde_json::from_value(data.unwrap_or_default()).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), + let message::BodyRef::Response(response_ref) = message_ref.data().unwrap() + else { + panic!("Wrong response stored: {message_ref:?}"); + }; + + Ok(R::convert_response(response_ref.body().unwrap()) + .map_err(RequestError::ResponseConversion)?) + } + None => { + Ok(R::convert_response(None).map_err(RequestError::ResponseConversion)?) } - }) + } } Err(ResponseError { reason }) => { - debug!("request failed [method:{}, id:{}]: {}", method, id, reason); + debug!( + "request failed [method:{:?}, id:{}]: {}", + R::METHOD, + id, + reason + ); if reason.contains("not found") { if let Some(default_response) = R::default_for_soft_error() { Ok(default_response) @@ -433,13 +465,50 @@ impl Channel { } } + pub(crate) fn notify( + &self, + handler_id: HandlerId, + notification: N, + ) -> Result<(), NotificationError> + where + N: Notification, + HandlerId: Display, + { + debug!("notify() [{notification:?}]"); + + let data = notification.into_bytes(handler_id); + + let message = Arc::new(AtomicTake::new(data)); + + { + let mut outgoing_message_buffer = self.inner.outgoing_message_buffer.lock(); + outgoing_message_buffer + .messages + .push_back(Arc::clone(&message)); + if let Some(handle) = outgoing_message_buffer.handle { + if self.inner.worker_closed.load(Ordering::Acquire) { + return Err(NotificationError::ChannelClosed); + } + unsafe { + // Notify worker that there is something to read + let ret = mediasoup_sys::uv_async_send(handle); + if ret != 0 { + error!("uv_async_send call failed with code {}", ret); + return Err(NotificationError::ChannelClosed); + } + } + } + } + + Ok(()) + } pub(crate) fn subscribe_to_notifications( &self, target_id: SubscriptionTarget, callback: F, ) -> Option where - F: Fn(&[u8]) + Send + Sync + 'static, + F: Fn(notification::NotificationRef<'_>) + Send + Sync + 'static, { self.inner .event_handlers_weak diff --git a/rust/src/worker/common.rs b/rust/src/worker/common.rs index 6616b48c17..7259809ab2 100644 --- a/rust/src/worker/common.rs +++ b/rust/src/worker/common.rs @@ -1,4 +1,5 @@ use hash_hasher::HashedMap; +use mediasoup_sys::fbs::notification; use nohash_hasher::IntMap; use parking_lot::Mutex; use serde::Deserialize; @@ -35,7 +36,7 @@ impl EventHandlers { { let mut event_handlers = self.handlers.lock(); let list = event_handlers - .entry(target_id) + .entry(target_id.clone()) .or_insert_with(EventHandlersList::default); index = list.index; list.index += 1; @@ -79,11 +80,11 @@ impl EventHandlers { } } -impl EventHandlers> { +impl EventHandlers) + Send + Sync + 'static>> { pub(super) fn call_callbacks_with_single_value( &self, target_id: &SubscriptionTarget, - value: &V, + value: notification::NotificationRef<'_>, ) { let handlers = self.handlers.lock(); if let Some(list) = handlers.get(target_id) { @@ -94,22 +95,6 @@ impl EventHandlers> { } } -impl EventHandlers> { - pub(super) fn call_callbacks_with_two_values( - &self, - target_id: &SubscriptionTarget, - value1: &V1, - value2: &V2, - ) { - let handlers = self.handlers.lock(); - if let Some(list) = handlers.get(target_id) { - for callback in list.callbacks.values() { - callback(value1, value2); - } - } - } -} - #[derive(Clone)] pub(super) struct WeakEventHandlers { handlers: Weak>>>, @@ -123,23 +108,11 @@ impl WeakEventHandlers { } } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)] #[serde(untagged)] pub(crate) enum SubscriptionTarget { Uuid(Uuid), - Number(u64), -} - -impl From for SubscriptionTarget { - fn from(number: u32) -> Self { - Self::Number(u64::from(number)) - } -} - -impl From for SubscriptionTarget { - fn from(number: u64) -> Self { - Self::Number(number) - } + String(String), } /// Subscription handler, will remove corresponding subscription when dropped diff --git a/rust/src/worker/payload_channel.rs b/rust/src/worker/payload_channel.rs deleted file mode 100644 index c4a7ed3172..0000000000 --- a/rust/src/worker/payload_channel.rs +++ /dev/null @@ -1,398 +0,0 @@ -use crate::messages::{Notification, Request}; -use crate::worker::common::{EventHandlers, SubscriptionTarget, WeakEventHandlers}; -use crate::worker::utils::{PreparedPayloadChannelRead, PreparedPayloadChannelWrite}; -use crate::worker::{utils, RequestError, SubscriptionHandler}; -use atomic_take::AtomicTake; -use log::{debug, error, trace, warn}; -use mediasoup_sys::UvAsyncT; -use nohash_hasher::IntMap; -use parking_lot::Mutex; -use serde::Deserialize; -use serde_json::Value; -use std::collections::VecDeque; -use std::fmt::{Debug, Display}; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Weak}; -use thiserror::Error; - -#[derive(Debug)] -pub(super) enum InternalMessage { - /// Unknown data - UnexpectedData(Vec), -} - -#[derive(Debug, Deserialize)] -#[serde(untagged)] -enum PayloadChannelReceiveMessage { - #[serde(rename_all = "camelCase")] - Notification { target_id: SubscriptionTarget }, - ResponseSuccess { - id: u32, - // The following field is present, unused, but needed for differentiating successful - // response from error case - #[allow(dead_code)] - accepted: bool, - data: Option, - }, - ResponseError { - id: u32, - // The following field is present, but unused - // error: Value, - reason: String, - }, - /// Unknown data - #[serde(skip)] - Internal(InternalMessage), -} - -fn deserialize_message(bytes: &[u8]) -> PayloadChannelReceiveMessage { - match serde_json::from_slice(bytes) { - Ok(message) => message, - Err(error) => { - warn!("Failed to deserialize message: {}", error); - - PayloadChannelReceiveMessage::Internal(InternalMessage::UnexpectedData(Vec::from( - bytes, - ))) - } - } -} - -struct ResponseError { - reason: String, -} - -type ResponseResult = Result, ResponseError>; - -struct RequestDropGuard<'a> { - id: u32, - message_with_payload: Arc>, - channel: &'a PayloadChannel, - removed: bool, -} - -impl<'a> Drop for RequestDropGuard<'a> { - fn drop(&mut self) { - if self.removed { - return; - } - - // Drop pending message from memory - self.message_with_payload.take(); - // Remove request handler from the container - if let Some(requests_container) = self.channel.inner.requests_container_weak.upgrade() { - requests_container.lock().handlers.remove(&self.id); - } - } -} - -impl<'a> RequestDropGuard<'a> { - fn remove(mut self) { - self.removed = true; - } -} - -#[derive(Default)] -struct RequestsContainer { - next_id: u32, - handlers: IntMap>>, -} - -struct OutgoingMessageRequest { - message: Vec, - payload: Vec, -} - -enum OutgoingMessage { - Request(Arc>), - Notification { message: Vec, payload: Vec }, -} - -struct OutgoingMessageBuffer { - handle: Option, - messages: VecDeque, -} - -#[derive(Debug, Error, Eq, PartialEq)] -pub enum NotificationError { - #[error("Channel already closed")] - ChannelClosed, -} - -struct Inner { - outgoing_message_buffer: Arc>, - internal_message_receiver: async_channel::Receiver, - requests_container_weak: Weak>, - #[allow(clippy::type_complexity)] - event_handlers_weak: WeakEventHandlers>, - worker_closed: Arc, -} - -impl Drop for Inner { - fn drop(&mut self) { - self.internal_message_receiver.close(); - } -} - -#[derive(Clone)] -pub(crate) struct PayloadChannel { - inner: Arc, -} - -impl PayloadChannel { - pub(super) fn new( - worker_closed: Arc, - ) -> ( - Self, - PreparedPayloadChannelRead, - PreparedPayloadChannelWrite, - ) { - let outgoing_message_buffer = Arc::new(Mutex::new(OutgoingMessageBuffer { - handle: None, - messages: VecDeque::with_capacity(10), - })); - let requests_container = Arc::>::default(); - let requests_container_weak = Arc::downgrade(&requests_container); - let event_handlers = EventHandlers::new(); - let event_handlers_weak = event_handlers.downgrade(); - - let prepared_payload_channel_read = utils::prepare_payload_channel_read_fn({ - let outgoing_message_buffer = Arc::clone(&outgoing_message_buffer); - - move |handle| { - let mut outgoing_message_buffer = outgoing_message_buffer.lock(); - if outgoing_message_buffer.handle.is_none() { - outgoing_message_buffer.handle.replace(handle); - } - - while let Some(outgoing_message) = outgoing_message_buffer.messages.pop_front() { - match outgoing_message { - OutgoingMessage::Request(maybe_message) => { - // Request might have already been cancelled - if let Some(OutgoingMessageRequest { message, payload }) = - maybe_message.take() - { - return Some((message, payload)); - } - } - OutgoingMessage::Notification { message, payload } => { - return Some((message, payload)); - } - } - } - - None - } - }); - - let (internal_message_sender, internal_message_receiver) = async_channel::bounded(1); - - let prepared_payload_channel_write = - utils::prepare_payload_channel_write_fn(move |message, payload| { - trace!("received raw message: {}", String::from_utf8_lossy(message)); - - match deserialize_message(message) { - PayloadChannelReceiveMessage::Notification { target_id } => { - trace!("received notification payload of {} bytes", payload.len()); - - event_handlers.call_callbacks_with_two_values(&target_id, message, payload); - } - PayloadChannelReceiveMessage::ResponseSuccess { id, data, .. } => { - let sender = requests_container.lock().handlers.remove(&id); - if let Some(mut sender) = sender { - let _ = sender.send(Ok(data)); - } else { - warn!( - "received success response does not match any sent request [id:{}]", - id, - ); - } - } - PayloadChannelReceiveMessage::ResponseError { id, reason } => { - let sender = requests_container.lock().handlers.remove(&id); - if let Some(mut sender) = sender { - let _ = sender.send(Err(ResponseError { reason })); - } else { - warn!( - "received error response does not match any sent request [id:{}]", - id, - ); - } - } - PayloadChannelReceiveMessage::Internal(internal_message) => { - let _ = internal_message_sender.try_send(internal_message); - } - } - }); - - let inner = Arc::new(Inner { - outgoing_message_buffer, - internal_message_receiver, - requests_container_weak, - event_handlers_weak, - worker_closed, - }); - - ( - Self { inner }, - prepared_payload_channel_read, - prepared_payload_channel_write, - ) - } - - pub(super) fn get_internal_message_receiver(&self) -> async_channel::Receiver { - self.inner.internal_message_receiver.clone() - } - - pub(crate) async fn request( - &self, - handler_id: HandlerId, - request: R, - payload: Vec, - ) -> Result - where - R: Request, - HandlerId: Display, - { - let method = request.as_method(); - - let id; - let (result_sender, result_receiver) = async_oneshot::oneshot(); - - { - let requests_container_lock = self - .inner - .requests_container_weak - .upgrade() - .ok_or(RequestError::ChannelClosed)?; - let mut requests_container = requests_container_lock.lock(); - - id = requests_container.next_id; - - requests_container.next_id = requests_container.next_id.wrapping_add(1); - requests_container.handlers.insert(id, result_sender); - } - - debug!("request() [method:{}, id:{}]: {:?}", method, id, request); - - // TODO: Todo pre-allocate fixed size string sufficient for most cases by default - // TODO: Refactor to avoid extra allocation during JSON serialization if possible - let message = format!( - "r:{id}:{}:{handler_id}:{}", - request.as_method(), - serde_json::to_string(&request).unwrap() - ) - .into_bytes(); - - let message_with_payload = - Arc::new(AtomicTake::new(OutgoingMessageRequest { message, payload })); - - { - let mut outgoing_message_buffer = self.inner.outgoing_message_buffer.lock(); - outgoing_message_buffer - .messages - .push_back(OutgoingMessage::Request(Arc::clone(&message_with_payload))); - if let Some(handle) = outgoing_message_buffer.handle { - if self.inner.worker_closed.load(Ordering::Acquire) { - return Err(RequestError::ChannelClosed); - } - unsafe { - // Notify worker that there is something to read - let ret = mediasoup_sys::uv_async_send(handle); - if ret != 0 { - error!("uv_async_send call failed with code {}", ret); - return Err(RequestError::ChannelClosed); - } - } - } - } - - // Drop guard to make sure to drop pending request when future is cancelled - let request_drop_guard = RequestDropGuard { - id, - message_with_payload, - channel: self, - removed: false, - }; - - let response_result_fut = result_receiver.await; - - request_drop_guard.remove(); - - match response_result_fut.map_err(|_| RequestError::ChannelClosed {})? { - Ok(data) => { - debug!("request succeeded [method:{}, id:{}]", method, id); - - // Default will work for `()` response - serde_json::from_value(data.unwrap_or_default()).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) - } - Err(ResponseError { reason }) => { - debug!("request failed [method:{}, id:{}]: {}", method, id, reason); - - Err(RequestError::Response { reason }) - } - } - } - - pub(crate) fn notify( - &self, - handler_id: HandlerId, - notification: N, - payload: Vec, - ) -> Result<(), NotificationError> - where - N: Notification, - HandlerId: Display, - { - debug!("notify() [event:{}]", notification.as_event()); - - // TODO: Todo pre-allocate fixed size string sufficient for most cases by default - // TODO: Refactor to avoid extra allocation during JSON serialization if possible - let message = format!( - "n:{}:{handler_id}:{}", - notification.as_event(), - serde_json::to_string(¬ification).unwrap() - ) - .into_bytes(); - - { - let mut outgoing_message_buffer = self.inner.outgoing_message_buffer.lock(); - outgoing_message_buffer - .messages - .push_back(OutgoingMessage::Notification { message, payload }); - if let Some(handle) = outgoing_message_buffer.handle { - if self.inner.worker_closed.load(Ordering::Acquire) { - return Err(NotificationError::ChannelClosed); - } - unsafe { - // Notify worker that there is something to read - let ret = mediasoup_sys::uv_async_send(handle); - if ret != 0 { - error!("uv_async_send call failed with code {}", ret); - return Err(NotificationError::ChannelClosed); - } - } - } - } - - Ok(()) - } - - pub(crate) fn subscribe_to_notifications( - &self, - target_id: SubscriptionTarget, - callback: F, - ) -> Option - where - F: Fn(&[u8], &[u8]) + Send + Sync + 'static, - { - self.inner - .event_handlers_weak - .upgrade() - .map(|event_handlers| event_handlers.add(target_id, Arc::new(callback))) - } -} diff --git a/rust/src/worker/utils.rs b/rust/src/worker/utils.rs index 0c9735737c..fbbd2e1c38 100644 --- a/rust/src/worker/utils.rs +++ b/rust/src/worker/utils.rs @@ -2,15 +2,9 @@ mod channel_read_fn; mod channel_write_fn; use crate::worker::channel::BufferMessagesGuard; -use crate::worker::{Channel, PayloadChannel, WorkerId}; -pub(super) use channel_read_fn::{ - prepare_channel_read_fn, prepare_payload_channel_read_fn, PreparedChannelRead, - PreparedPayloadChannelRead, -}; -pub(super) use channel_write_fn::{ - prepare_channel_write_fn, prepare_payload_channel_write_fn, PreparedChannelWrite, - PreparedPayloadChannelWrite, -}; +use crate::worker::{Channel, SubscriptionTarget, WorkerId}; +pub(super) use channel_read_fn::{prepare_channel_read_fn, PreparedChannelRead}; +pub(super) use channel_write_fn::{prepare_channel_write_fn, PreparedChannelWrite}; use std::ffi::CString; use std::os::raw::{c_char, c_int}; use std::sync::atomic::AtomicBool; @@ -39,7 +33,6 @@ pub enum ExitError { pub(super) struct WorkerRunResult { pub(super) channel: Channel, - pub(super) payload_channel: PayloadChannel, pub(super) buffer_worker_messages_guard: BufferMessagesGuard, } @@ -55,9 +48,8 @@ where { let (channel, prepared_channel_read, prepared_channel_write) = Channel::new(Arc::clone(&worker_closed)); - let (payload_channel, prepared_payload_channel_read, prepared_payload_channel_write) = - PayloadChannel::new(worker_closed); - let buffer_worker_messages_guard = channel.buffer_messages_for(std::process::id().into()); + let buffer_worker_messages_guard = + channel.buffer_messages_for(SubscriptionTarget::String(std::process::id().to_string())); std::thread::Builder::new() .name(format!("mediasoup-worker-{id}")) @@ -81,16 +73,6 @@ where prepared_channel_read.deconstruct(); let (channel_write_fn, channel_write_ctx, _channel_read_callback) = prepared_channel_write.deconstruct(); - let ( - payload_channel_read_fn, - payload_channel_read_ctx, - _payload_channel_write_callback, - ) = prepared_payload_channel_read.deconstruct(); - let ( - payload_channel_write_fn, - payload_channel_write_ctx, - _payload_channel_read_callback, - ) = prepared_payload_channel_write.deconstruct(); mediasoup_sys::mediasoup_worker_run( argc, @@ -104,10 +86,6 @@ where channel_read_ctx, channel_write_fn, channel_write_ctx, - payload_channel_read_fn, - payload_channel_read_ctx, - payload_channel_write_fn, - payload_channel_write_ctx, ) }; @@ -122,7 +100,6 @@ where WorkerRunResult { channel, - payload_channel, buffer_worker_messages_guard, } } diff --git a/rust/src/worker/utils/channel_read_fn.rs b/rust/src/worker/utils/channel_read_fn.rs index 902f87ef66..57cf3b0bf8 100644 --- a/rust/src/worker/utils/channel_read_fn.rs +++ b/rust/src/worker/utils/channel_read_fn.rs @@ -1,7 +1,5 @@ -pub(super) use mediasoup_sys::{ - ChannelReadCtx, ChannelReadFn, PayloadChannelReadCtx, PayloadChannelReadFn, -}; -use mediasoup_sys::{ChannelReadFreeFn, PayloadChannelReadFreeFn, UvAsyncT}; +pub(super) use mediasoup_sys::{ChannelReadCtx, ChannelReadFn}; +use mediasoup_sys::{ChannelReadFreeFn, UvAsyncT}; use std::mem; use std::os::raw::c_void; @@ -76,90 +74,3 @@ where write_callback: ChannelReadCallback(read_callback), } } - -#[allow(clippy::type_complexity)] -pub(super) struct PayloadChannelReadCallback( - Box Option<(Vec, Vec)>) + Send + 'static>, -); - -pub(crate) struct PreparedPayloadChannelRead { - payload_channel_read_fn: PayloadChannelReadFn, - payload_channel_read_ctx: PayloadChannelReadCtx, - write_callback: PayloadChannelReadCallback, -} - -impl PreparedPayloadChannelRead { - /// SAFETY: - /// 1) `PayloadChannelReadCallback` returned must be dropped AFTER last usage of returned - /// function and context pointers - /// 2) `PayloadChannelReadCtx` should not be called from multiple threads concurrently - pub(super) unsafe fn deconstruct( - self, - ) -> ( - PayloadChannelReadFn, - PayloadChannelReadCtx, - PayloadChannelReadCallback, - ) { - let Self { - payload_channel_read_fn, - payload_channel_read_ctx, - write_callback, - } = self; - ( - payload_channel_read_fn, - payload_channel_read_ctx, - write_callback, - ) - } -} - -/// Given callback function, prepares a pair of channel read function and context, which can be -/// provided to of C++ worker and worker will effectively call the callback whenever it wants to -/// read something from Rust (so it is reading from C++ point of view and writing from Rust). -pub(crate) fn prepare_payload_channel_read_fn(read_callback: F) -> PreparedPayloadChannelRead -where - F: (FnMut(UvAsyncT) -> Option<(Vec, Vec)>) + Send + 'static, -{ - unsafe extern "C" fn wrapper( - message: *mut *mut u8, - message_len: *mut u32, - message_capacity: *mut usize, - payload: *mut *mut u8, - payload_len: *mut u32, - payload_capacity: *mut usize, - handle: UvAsyncT, - PayloadChannelReadCtx(ctx): PayloadChannelReadCtx, - ) -> PayloadChannelReadFreeFn - where - F: (FnMut(UvAsyncT) -> Option<(Vec, Vec)>) + Send + 'static, - { - // Call Rust and try to get a new message (if there is any) - let (mut new_message, mut new_payload) = (*(ctx as *mut F))(handle)?; - - // Set pointers, give out control over memory to C++ - *message = new_message.as_mut_ptr(); - *message_len = new_message.len() as u32; - *message_capacity = new_message.capacity(); - *payload = new_payload.as_mut_ptr(); - *payload_len = new_payload.len() as u32; - *payload_capacity = new_payload.capacity(); - - // Forget about vectors in Rust - mem::forget(new_message); - mem::forget(new_payload); - - // Function pointer that C++ can use to free vectors later - Some(free_vec) - } - - // Move to heap to make sure it doesn't change address later on - let read_callback = Box::new(read_callback); - - PreparedPayloadChannelRead { - payload_channel_read_fn: wrapper::, - payload_channel_read_ctx: PayloadChannelReadCtx( - read_callback.as_ref() as *const F as *const c_void - ), - write_callback: PayloadChannelReadCallback(read_callback), - } -} diff --git a/rust/src/worker/utils/channel_write_fn.rs b/rust/src/worker/utils/channel_write_fn.rs index 968dafb79c..c9e72077c9 100644 --- a/rust/src/worker/utils/channel_write_fn.rs +++ b/rust/src/worker/utils/channel_write_fn.rs @@ -1,6 +1,4 @@ -pub(super) use mediasoup_sys::{ - ChannelWriteCtx, ChannelWriteFn, PayloadChannelWriteCtx, PayloadChannelWriteFn, -}; +pub(super) use mediasoup_sys::{ChannelWriteCtx, ChannelWriteFn}; use std::os::raw::c_void; use std::slice; @@ -59,72 +57,3 @@ where read_callback: ChannelReadCallback(read_callback), } } - -#[allow(clippy::type_complexity)] -pub(super) struct PayloadChannelReadCallback(Box); - -pub(crate) struct PreparedPayloadChannelWrite { - channel_write_fn: PayloadChannelWriteFn, - channel_write_ctx: PayloadChannelWriteCtx, - read_callback: PayloadChannelReadCallback, -} - -unsafe impl Send for PreparedPayloadChannelWrite {} - -impl PreparedPayloadChannelWrite { - /// SAFETY: - /// 1) `PayloadChannelReadCallback` returned must be dropped AFTER last usage of returned - /// function and context pointers - /// 2) `PayloadChannelWriteCtx` should not be called from multiple threads concurrently - pub(super) unsafe fn deconstruct( - self, - ) -> ( - PayloadChannelWriteFn, - PayloadChannelWriteCtx, - PayloadChannelReadCallback, - ) { - let Self { - channel_write_fn, - channel_write_ctx, - read_callback, - } = self; - (channel_write_fn, channel_write_ctx, read_callback) - } -} - -/// Given callback function, prepares a pair of channel write function and context, which can be -/// provided to of C++ worker and worker will effectively call the callback whenever it needs to -/// send something to Rust (so it is writing from C++ point of view and reading from Rust). -pub(crate) fn prepare_payload_channel_write_fn(read_callback: F) -> PreparedPayloadChannelWrite -where - F: FnMut(&[u8], &[u8]) + Send + 'static, -{ - unsafe extern "C" fn wrapper( - message: *const u8, - message_len: u32, - payload: *const u8, - payload_len: u32, - PayloadChannelWriteCtx(ctx): PayloadChannelWriteCtx, - ) where - F: FnMut(&[u8], &[u8]) + Send + 'static, - { - let message = slice::from_raw_parts(message, message_len as usize); - let payload = if payload_len == 0 { - &[] - } else { - slice::from_raw_parts(payload, payload_len as usize) - }; - (*(ctx as *mut F))(message, payload); - } - - // Move to heap to make sure it doesn't change address later on - let read_callback = Box::new(read_callback); - - PreparedPayloadChannelWrite { - channel_write_fn: wrapper::, - channel_write_ctx: PayloadChannelWriteCtx( - read_callback.as_ref() as *const F as *const c_void - ), - read_callback: PayloadChannelReadCallback(read_callback), - } -} diff --git a/rust/tests/integration/consumer.rs b/rust/tests/integration/consumer.rs index 385c92601f..8a4746365b 100644 --- a/rust/tests/integration/consumer.rs +++ b/rust/tests/integration/consumer.rs @@ -2,10 +2,8 @@ use async_executor::Executor; use async_io::Timer; use futures_lite::future; use hash_hasher::{HashedMap, HashedSet}; -use mediasoup::consumer::{ - ConsumableRtpEncoding, ConsumerLayers, ConsumerOptions, ConsumerScore, ConsumerType, -}; -use mediasoup::data_structures::{AppData, ListenIp}; +use mediasoup::consumer::{ConsumerLayers, ConsumerOptions, ConsumerScore, ConsumerType}; +use mediasoup::data_structures::{AppData, ListenInfo, Protocol}; use mediasoup::prelude::*; use mediasoup::producer::ProducerOptions; use mediasoup::router::{Router, RouterOptions}; @@ -18,7 +16,9 @@ use mediasoup::rtp_parameters::{ }; use mediasoup::scalability_modes::ScalabilityMode; use mediasoup::transport::ConsumeError; -use mediasoup::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use mediasoup::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use mediasoup::worker::{Worker, WorkerSettings}; use mediasoup::worker_manager::WorkerManager; use parking_lot::Mutex; @@ -346,10 +346,15 @@ async fn init() -> ( .await .expect("Failed to create router"); - let transport_options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); let transport_1 = router .create_webrtc_transport(transport_options.clone()) @@ -963,7 +968,6 @@ fn dump_succeeds() { rtx: None, dtx: None, scalability_mode: ScalabilityMode::None, - scale_resolution_down_by: None, ssrc: audio_consumer .rtp_parameters() .encodings @@ -981,18 +985,14 @@ fn dump_succeeds() { .consumable_rtp_parameters() .encodings .iter() - .map(|encoding| ConsumableRtpEncoding { + .map(|encoding| RtpEncodingParameters { ssrc: encoding.ssrc, rid: None, codec_payload_type: None, rtx: None, max_bitrate: None, - max_framerate: None, dtx: None, scalability_mode: ScalabilityMode::None, - spatial_layers: None, - temporal_layers: None, - ksvc: None }) .collect::>() ); @@ -1091,7 +1091,6 @@ fn dump_succeeds() { .rtx, dtx: None, scalability_mode: "L4T1".parse().unwrap(), - scale_resolution_down_by: None, rid: None, max_bitrate: None, }], @@ -1103,18 +1102,14 @@ fn dump_succeeds() { .consumable_rtp_parameters() .encodings .iter() - .map(|encoding| ConsumableRtpEncoding { + .map(|encoding| RtpEncodingParameters { ssrc: encoding.ssrc, rid: None, codec_payload_type: None, rtx: None, max_bitrate: None, - max_framerate: None, dtx: None, scalability_mode: ScalabilityMode::None, - spatial_layers: None, - temporal_layers: None, - ksvc: None, }) .collect::>() ); diff --git a/rust/tests/integration/data_consumer.rs b/rust/tests/integration/data_consumer.rs index 37e510720d..3d0894fcc7 100644 --- a/rust/tests/integration/data_consumer.rs +++ b/rust/tests/integration/data_consumer.rs @@ -3,13 +3,15 @@ use futures_lite::future; use hash_hasher::{HashedMap, HashedSet}; use mediasoup::data_consumer::{DataConsumerOptions, DataConsumerType}; use mediasoup::data_producer::{DataProducer, DataProducerOptions}; -use mediasoup::data_structures::{AppData, ListenIp}; +use mediasoup::data_structures::{AppData, ListenInfo, Protocol}; use mediasoup::direct_transport::DirectTransportOptions; use mediasoup::plain_transport::PlainTransportOptions; use mediasoup::prelude::*; use mediasoup::router::{Router, RouterOptions}; use mediasoup::sctp_parameters::SctpStreamParameters; -use mediasoup::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use mediasoup::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use mediasoup::worker::{Worker, WorkerSettings}; use mediasoup::worker_manager::WorkerManager; use std::env; @@ -61,9 +63,13 @@ async fn init() -> (Worker, Router, WebRtcTransport, DataProducer) { let transport = router .create_webrtc_transport({ let mut transport_options = - WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, })); transport_options.enable_sctp = true; @@ -88,9 +94,13 @@ fn consume_data_succeeds() { let transport2 = router .create_plain_transport({ - let mut transport_options = PlainTransportOptions::new(ListenIp { + let mut transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); transport_options.enable_sctp = true; @@ -119,6 +129,7 @@ fn consume_data_succeeds() { 4000, ); + options.subchannels = Some(vec![0, 1, 1, 1, 2, 65535, 100]); options.app_data = AppData::new(CustomAppData { baz: "LOL" }); options @@ -142,6 +153,11 @@ fn consume_data_succeeds() { } assert_eq!(data_consumer.label().as_str(), "foo"); assert_eq!(data_consumer.protocol().as_str(), "bar"); + + let mut sorted_subchannels = data_consumer.subchannels(); + sorted_subchannels.sort(); + + assert_eq!(sorted_subchannels, [0, 1, 2, 100, 65535]); assert_eq!( data_consumer .app_data() @@ -187,9 +203,13 @@ fn weak() { let transport2 = router .create_plain_transport({ - let mut transport_options = PlainTransportOptions::new(ListenIp { + let mut transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); transport_options.enable_sctp = true; @@ -325,7 +345,7 @@ fn consume_data_on_direct_transport_succeeds() { let data_consumer = transport3 .consume_data({ - let mut options = DataConsumerOptions::new_direct(data_producer.id()); + let mut options = DataConsumerOptions::new_direct(data_producer.id(), None); options.app_data = AppData::new(CustomAppData2 { hehe: "HEHE" }); @@ -372,7 +392,7 @@ fn dump_on_direct_transport_succeeds() { let data_consumer = transport3 .consume_data({ - let mut options = DataConsumerOptions::new_direct(data_producer.id()); + let mut options = DataConsumerOptions::new_direct(data_producer.id(), None); options.app_data = AppData::new(CustomAppData2 { hehe: "HEHE" }); @@ -407,7 +427,7 @@ fn get_stats_on_direct_transport_succeeds() { let data_consumer = transport3 .consume_data({ - let mut options = DataConsumerOptions::new_direct(data_producer.id()); + let mut options = DataConsumerOptions::new_direct(data_producer.id(), None); options.app_data = AppData::new(CustomAppData2 { hehe: "HEHE" }); @@ -436,9 +456,13 @@ fn close_event() { let transport2 = router .create_plain_transport({ - let mut transport_options = PlainTransportOptions::new(ListenIp { + let mut transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); transport_options.enable_sctp = true; diff --git a/rust/tests/integration/data_producer.rs b/rust/tests/integration/data_producer.rs index 809e95bee8..e753ff5eb5 100644 --- a/rust/tests/integration/data_producer.rs +++ b/rust/tests/integration/data_producer.rs @@ -2,13 +2,15 @@ use async_io::Timer; use futures_lite::future; use hash_hasher::{HashedMap, HashedSet}; use mediasoup::data_producer::{DataProducerOptions, DataProducerType}; -use mediasoup::data_structures::{AppData, ListenIp}; +use mediasoup::data_structures::{AppData, ListenInfo, Protocol}; use mediasoup::plain_transport::{PlainTransport, PlainTransportOptions}; use mediasoup::prelude::*; use mediasoup::router::{Router, RouterOptions}; use mediasoup::sctp_parameters::SctpStreamParameters; use mediasoup::transport::ProduceDataError; -use mediasoup::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use mediasoup::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use mediasoup::worker::{RequestError, Worker, WorkerSettings}; use mediasoup::worker_manager::WorkerManager; use std::env; @@ -47,9 +49,13 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { let transport1 = router .create_webrtc_transport({ let mut transport_options = - WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, })); transport_options.enable_sctp = true; @@ -61,9 +67,13 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { let transport2 = router .create_plain_transport({ - let mut transport_options = PlainTransportOptions::new(ListenIp { + let mut transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); transport_options.enable_sctp = true; @@ -120,6 +130,7 @@ fn transport_1_produce_data_succeeds() { } assert_eq!(data_producer1.label().as_str(), "foo"); assert_eq!(data_producer1.protocol().as_str(), "bar"); + assert!(!data_producer1.paused()); assert_eq!( data_producer1 .app_data() @@ -177,6 +188,7 @@ fn transport_2_produce_data_succeeds() { options.label = "foo".to_string(); options.protocol = "bar".to_string(); + options.paused = true; options.app_data = AppData::new(CustomAppData { foo: 1, baz: "2" }); options @@ -197,6 +209,7 @@ fn transport_2_produce_data_succeeds() { } assert_eq!(data_producer2.label().as_str(), "foo"); assert_eq!(data_producer2.protocol().as_str(), "bar"); + assert!(data_producer2.paused()); assert_eq!( data_producer2 .app_data() @@ -318,6 +331,7 @@ fn dump_succeeds() { } assert_eq!(dump.label.as_str(), "foo"); assert_eq!(dump.protocol.as_str(), "bar"); + assert!(!dump.paused); } { @@ -329,6 +343,7 @@ fn dump_succeeds() { options.label = "foo".to_string(); options.protocol = "bar".to_string(); + options.paused = true; options.app_data = AppData::new(CustomAppData { foo: 1, baz: "2" }); options @@ -353,6 +368,7 @@ fn dump_succeeds() { } assert_eq!(dump.label.as_str(), "foo"); assert_eq!(dump.protocol.as_str(), "bar"); + assert!(dump.paused); } }); } @@ -419,6 +435,61 @@ fn get_stats_succeeds() { }); } +#[test] +fn pause_and_resume_succeed() { + future::block_on(async move { + let (_worker, _router, transport1, _) = init().await; + + { + let data_producer1 = transport1 + .produce_data({ + let mut options = + DataProducerOptions::new_sctp(SctpStreamParameters::new_ordered(666)); + + options.label = "foo".to_string(); + options.protocol = "bar".to_string(); + options.app_data = AppData::new(CustomAppData { foo: 1, baz: "2" }); + + options + }) + .await + .expect("Failed to produce data"); + + { + data_producer1 + .pause() + .await + .expect("Failed to pause data producer"); + + assert!(data_producer1.paused()); + + let dump = data_producer1 + .dump() + .await + .expect("Failed to dump data producer"); + + assert!(dump.paused); + } + + { + data_producer1 + .resume() + .await + .expect("Failed to resume data producer"); + + assert!(!data_producer1.paused()); + + let dump = data_producer1 + .dump() + .await + .expect("Failed to dump data producer"); + + assert!(!dump.paused); + } + } + }); +} + #[test] fn close_event() { future::block_on(async move { diff --git a/rust/tests/integration/direct_transport.rs b/rust/tests/integration/direct_transport.rs index 70e8730683..380f3e1b3e 100644 --- a/rust/tests/integration/direct_transport.rs +++ b/rust/tests/integration/direct_transport.rs @@ -135,6 +135,7 @@ fn get_stats_succeeds() { .expect("Failed to get stats on Direct transport"); assert_eq!(stats.len(), 1); + assert_eq!(stats[0].transport_id, transport.id()); assert_eq!(stats[0].bytes_received, 0); assert_eq!(stats[0].recv_bitrate, 0); @@ -174,12 +175,21 @@ fn send_succeeds() { .expect("Failed to produce data"); let data_consumer = transport - .consume_data(DataConsumerOptions::new_direct(data_producer.id())) + .consume_data(DataConsumerOptions::new_direct(data_producer.id(), None)) .await .expect("Failed to consume data"); let num_messages = 200_usize; + let pause_sending_at_message = 10_usize; + let resume_sending_at_message = 20_usize; + let pause_receiving_at_message = 40_usize; + let resume_receiving_at_message = 60_usize; + let expected_received_num_messages = num_messages + - (resume_sending_at_message - pause_sending_at_message) + - (resume_receiving_at_message - pause_receiving_at_message); + let mut sent_message_bytes = 0_usize; + let mut effectively_sent_message_bytes = 0_usize; let recv_message_bytes = Arc::new(AtomicUsize::new(0)); let mut last_sent_message_id = 0_usize; let last_recv_message_id = Arc::new(AtomicUsize::new(0)); @@ -215,7 +225,6 @@ fn send_succeeds() { } last_recv_message_id.fetch_add(1, Ordering::SeqCst); - assert_eq!(id, last_recv_message_id.load(Ordering::SeqCst)); if id == num_messages { let _ = received_messages_tx.lock().take().unwrap().send(()); @@ -234,18 +243,50 @@ fn send_succeeds() { last_sent_message_id += 1; let id = last_sent_message_id; + if id == pause_sending_at_message { + data_producer + .pause() + .await + .expect("Failed to pause data producer"); + } else if id == resume_sending_at_message { + data_producer + .resume() + .await + .expect("Failed to resume data producer"); + } else if id == pause_receiving_at_message { + data_consumer + .pause() + .await + .expect("Failed to pause data consumer"); + } else if id == resume_receiving_at_message { + data_consumer + .resume() + .await + .expect("Failed to resume data consumer"); + } + let message = if id < num_messages / 2 { let content = id.to_string(); sent_message_bytes += content.len(); + + if !data_producer.paused() && !data_consumer.paused() { + effectively_sent_message_bytes += content.len(); + } + WebRtcMessage::String(content) } else { let content = id.to_string().into_bytes(); sent_message_bytes += content.len(); + + if !data_producer.paused() && !data_consumer.paused() { + effectively_sent_message_bytes += content.len(); + } + WebRtcMessage::Binary(Cow::from(content)) }; direct_data_producer - .send(message) + .send(message, None, None) .expect("Failed to send message"); if id == num_messages { @@ -258,10 +299,13 @@ fn send_succeeds() { .expect("Failed tor receive all messages"); assert_eq!(last_sent_message_id, num_messages); - assert_eq!(last_recv_message_id.load(Ordering::SeqCst), num_messages); + assert_eq!( + last_recv_message_id.load(Ordering::SeqCst), + expected_received_num_messages + ); assert_eq!( recv_message_bytes.load(Ordering::SeqCst), - sent_message_bytes, + effectively_sent_message_bytes, ); { @@ -273,8 +317,8 @@ fn send_succeeds() { assert_eq!(stats.len(), 1); assert_eq!(&stats[0].label, data_producer.label()); assert_eq!(&stats[0].protocol, data_producer.protocol()); - assert_eq!(stats[0].messages_received, num_messages); - assert_eq!(stats[0].bytes_received, sent_message_bytes); + assert_eq!(stats[0].messages_received, num_messages as u64); + assert_eq!(stats[0].bytes_received, sent_message_bytes as u64); } { @@ -286,15 +330,224 @@ fn send_succeeds() { assert_eq!(stats.len(), 1); assert_eq!(&stats[0].label, data_consumer.label()); assert_eq!(&stats[0].protocol, data_consumer.protocol()); - assert_eq!(stats[0].messages_sent, num_messages); + assert_eq!( + stats[0].messages_sent, + expected_received_num_messages as u64 + ); assert_eq!( stats[0].bytes_sent, - recv_message_bytes.load(Ordering::SeqCst), + recv_message_bytes.load(Ordering::SeqCst) as u64, ); } }); } +#[test] +fn send_with_subchannels_succeeds() { + future::block_on(async move { + let (_worker, _router, transport) = init().await; + + let data_producer = transport + .produce_data({ + let mut options = DataProducerOptions::new_direct(); + + options.label = "foo".to_string(); + options.protocol = "bar".to_string(); + options.app_data = AppData::new(CustomAppData { foo: "bar" }); + + options + }) + .await + .expect("Failed to produce data"); + + let data_consumer_1 = transport + .consume_data(DataConsumerOptions::new_direct( + data_producer.id(), + Some(vec![1, 11, 666]), + )) + .await + .expect("Failed to consume data"); + + let data_consumer_2 = transport + .consume_data(DataConsumerOptions::new_direct( + data_producer.id(), + Some(vec![2, 22, 666]), + )) + .await + .expect("Failed to consume data"); + + let expected_received_num_messages_1 = 7; + let expected_received_num_messages_2 = 5; + let received_messages_1: Arc>> = Arc::new(Mutex::new(vec![])); + let received_messages_2: Arc>> = Arc::new(Mutex::new(vec![])); + + let (received_messages_tx_1, received_messages_rx_1) = async_oneshot::oneshot::<()>(); + let _handler_1 = data_consumer_1.on_message({ + let received_messages_tx_1 = Mutex::new(Some(received_messages_tx_1)); + let received_messages_1 = Arc::clone(&received_messages_1); + + move |message| { + let text: String = match message { + WebRtcMessage::String(string) => string.parse().unwrap(), + _ => { + panic!("Unexpected empty messages!"); + } + }; + + received_messages_1.lock().push(text); + + if received_messages_1.lock().len() == expected_received_num_messages_1 { + let _ = received_messages_tx_1.lock().take().unwrap().send(()); + } + } + }); + + let (received_messages_tx_2, received_messages_rx_2) = async_oneshot::oneshot::<()>(); + let _handler_2 = data_consumer_2.on_message({ + let received_messages_tx_2 = Mutex::new(Some(received_messages_tx_2)); + let received_messages_2 = Arc::clone(&received_messages_2); + + move |message| { + let text: String = match message { + WebRtcMessage::String(string) => string.parse().unwrap(), + _ => { + panic!("Unexpected empty messages!"); + } + }; + + received_messages_2.lock().push(text); + + if received_messages_2.lock().len() == expected_received_num_messages_2 { + let _ = received_messages_tx_2.lock().take().unwrap().send(()); + } + } + }); + + let direct_data_producer = match &data_producer { + DataProducer::Direct(direct_data_producer) => direct_data_producer, + _ => { + panic!("Expected direct data producer") + } + }; + + let direct_data_consumer_2 = match &data_consumer_2 { + DataConsumer::Direct(direct_data_consumer) => direct_data_consumer, + _ => { + panic!("Expected direct data consumer") + } + }; + + let both: &'static str = "both"; + let none: &'static str = "none"; + let dc1: &'static str = "dc1"; + let dc2: &'static str = "dc2"; + + // Must be received by dataConsumer1 and dataConsumer2. + direct_data_producer + .send(WebRtcMessage::String(both.to_string()), None, None) + .expect("Failed to send message"); + + // Must be received by dataConsumer1 and dataConsumer2. + direct_data_producer + .send( + WebRtcMessage::String(both.to_string()), + Some(vec![1, 2]), + None, + ) + .expect("Failed to send message"); + + // Must be received by dataConsumer1 and dataConsumer2. + direct_data_producer + .send( + WebRtcMessage::String(both.to_string()), + Some(vec![11, 22, 33]), + Some(666), + ) + .expect("Failed to send message"); + + // Must not be received by neither dataConsumer1 nor dataConsumer2. + direct_data_producer + .send( + WebRtcMessage::String(none.to_string()), + Some(vec![3]), + Some(666), + ) + .expect("Failed to send message"); + + // Must not be received by neither dataConsumer1 nor dataConsumer2. + direct_data_producer + .send( + WebRtcMessage::String(none.to_string()), + Some(vec![666]), + Some(3), + ) + .expect("Failed to send message"); + + // Must be received by dataConsumer1. + direct_data_producer + .send(WebRtcMessage::String(dc1.to_string()), Some(vec![1]), None) + .expect("Failed to send message"); + + // Must be received by dataConsumer1. + direct_data_producer + .send(WebRtcMessage::String(dc1.to_string()), Some(vec![11]), None) + .expect("Failed to send message"); + + // Must be received by dataConsumer1. + direct_data_producer + .send( + WebRtcMessage::String(dc1.to_string()), + Some(vec![666]), + Some(11), + ) + .expect("Failed to send message"); + + // Must be received by dataConsumer2. + direct_data_producer + .send( + WebRtcMessage::String(dc2.to_string()), + Some(vec![666]), + Some(2), + ) + .expect("Failed to send message"); + + let mut subchannels = data_consumer_2.subchannels(); + subchannels.push(1); + + direct_data_consumer_2 + .set_subchannels(subchannels) + .await + .expect("Failed to set subchannels"); + + // Must be received by dataConsumer2. + direct_data_producer + .send( + WebRtcMessage::String(both.to_string()), + Some(vec![1]), + Some(666), + ) + .expect("Failed to send message"); + + received_messages_rx_1 + .await + .expect("Failed tor receive all messages"); + + received_messages_rx_2 + .await + .expect("Failed tor receive all messages"); + + let received_messages_1 = received_messages_1.lock().clone(); + assert!(received_messages_1.contains(&both.to_string())); + assert!(received_messages_1.contains(&dc1.to_string())); + assert!(!received_messages_1.contains(&dc2.to_string())); + + let received_messages_2 = received_messages_2.lock().clone(); + assert!(received_messages_2.contains(&both.to_string())); + assert!(!received_messages_2.contains(&dc1.to_string())); + assert!(received_messages_2.contains(&dc2.to_string())); + }); +} + #[test] fn close_event() { future::block_on(async move { diff --git a/rust/tests/integration/multiopus.rs b/rust/tests/integration/multiopus.rs index 16ea0ab483..650b450cd0 100644 --- a/rust/tests/integration/multiopus.rs +++ b/rust/tests/integration/multiopus.rs @@ -1,5 +1,5 @@ use futures_lite::future; -use mediasoup::data_structures::ListenIp; +use mediasoup::data_structures::{ListenInfo, Protocol}; use mediasoup::prelude::*; use mediasoup::producer::ProducerOptions; use mediasoup::router::{Router, RouterOptions}; @@ -8,7 +8,9 @@ use mediasoup::rtp_parameters::{ RtpHeaderExtension, RtpHeaderExtensionDirection, RtpHeaderExtensionParameters, RtpHeaderExtensionUri, RtpParameters, }; -use mediasoup::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use mediasoup::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use mediasoup::worker::WorkerSettings; use mediasoup::worker_manager::WorkerManager; use std::env; @@ -127,10 +129,15 @@ async fn init() -> (Router, WebRtcTransport) { .await .expect("Failed to create router"); - let transport_options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); let transport = router .create_webrtc_transport(transport_options.clone()) diff --git a/rust/tests/integration/pipe_transport.rs b/rust/tests/integration/pipe_transport.rs index c6bc626d66..242c37a483 100644 --- a/rust/tests/integration/pipe_transport.rs +++ b/rust/tests/integration/pipe_transport.rs @@ -2,7 +2,7 @@ use futures_lite::future; use mediasoup::consumer::{ConsumerOptions, ConsumerScore, ConsumerType}; use mediasoup::data_consumer::{DataConsumerOptions, DataConsumerType}; use mediasoup::data_producer::{DataProducerOptions, DataProducerType}; -use mediasoup::data_structures::{AppData, ListenIp}; +use mediasoup::data_structures::{AppData, ListenInfo, Protocol}; use mediasoup::pipe_transport::{PipeTransportOptions, PipeTransportRemoteParameters}; use mediasoup::prelude::*; use mediasoup::producer::ProducerOptions; @@ -19,7 +19,9 @@ use mediasoup::rtp_parameters::{ use mediasoup::sctp_parameters::SctpStreamParameters; use mediasoup::srtp_parameters::{SrtpCryptoSuite, SrtpParameters}; use mediasoup::transport::ProduceError; -use mediasoup::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use mediasoup::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use mediasoup::worker::{RequestError, Worker, WorkerSettings}; use mediasoup::worker_manager::WorkerManager; use parking_lot::Mutex; @@ -253,10 +255,15 @@ async fn init() -> ( .await .expect("Failed to create router"); - let mut transport_options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let mut transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); transport_options.enable_sctp = true; let transport_1 = router1 @@ -593,9 +600,13 @@ fn weak() { let pipe_transport = router1 .create_pipe_transport({ - let mut options = PipeTransportOptions::new(ListenIp { + let mut options = PipeTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); options.enable_rtx = true; @@ -623,13 +634,14 @@ fn create_with_fixed_port_succeeds() { let pipe_transport = router1 .create_pipe_transport({ - let mut options = PipeTransportOptions::new(ListenIp { + PipeTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, - }); - options.port = Some(port); - - options + port: Some(port), + send_buffer_size: None, + recv_buffer_size: None, + }) }) .await .expect("Failed to create Pipe transport"); @@ -645,9 +657,13 @@ fn create_with_enable_rtx_succeeds() { let pipe_transport = router1 .create_pipe_transport({ - let mut options = PipeTransportOptions::new(ListenIp { + let mut options = PipeTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); options.enable_rtx = true; @@ -753,9 +769,13 @@ fn create_with_enable_srtp_succeeds() { let pipe_transport = router1 .create_pipe_transport({ - let mut options = PipeTransportOptions::new(ListenIp { + let mut options = PipeTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); options.enable_srtp = true; @@ -804,9 +824,13 @@ fn create_with_invalid_srtp_parameters_fails() { let (_worker1, _worker2, router1, _router2, _transport1, _transport2) = init().await; let pipe_transport = router1 - .create_pipe_transport(PipeTransportOptions::new(ListenIp { + .create_pipe_transport(PipeTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, })) .await .expect("Failed to create Pipe transport"); @@ -1126,9 +1150,13 @@ fn pipe_to_router_called_twice_generates_single_pair() { .expect("Failed to create router"); let mut transport_options = - WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, })); transport_options.enable_sctp = true; diff --git a/rust/tests/integration/plain_transport.rs b/rust/tests/integration/plain_transport.rs index fc4add8344..c968c395b5 100644 --- a/rust/tests/integration/plain_transport.rs +++ b/rust/tests/integration/plain_transport.rs @@ -1,6 +1,6 @@ use futures_lite::future; use hash_hasher::HashedSet; -use mediasoup::data_structures::{AppData, ListenIp, Protocol, SctpState, TransportTuple}; +use mediasoup::data_structures::{AppData, ListenInfo, Protocol, SctpState, TransportTuple}; use mediasoup::plain_transport::{PlainTransportOptions, PlainTransportRemoteParameters}; use mediasoup::prelude::*; use mediasoup::router::{Router, RouterOptions}; @@ -89,9 +89,13 @@ fn create_succeeds() { { let transport = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.rtcp_mux = false; @@ -123,9 +127,13 @@ fn create_succeeds() { let transport1 = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.rtcp_mux = true; plain_transport_options.enable_sctp = true; @@ -189,14 +197,28 @@ fn create_succeeds() { } { + let rtcp_port = pick_unused_port().unwrap(); let transport2 = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.rtcp_mux = false; + plain_transport_options.rtcp_listen_info = Some(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: Some(rtcp_port), + send_buffer_size: None, + recv_buffer_size: None, + }); + plain_transport_options }) .await @@ -217,10 +239,14 @@ fn create_succeeds() { } assert!(transport2.rtcp_tuple().is_some()); if let TransportTuple::LocalOnly { - local_ip, protocol, .. + local_ip, + local_port, + protocol, + .. } = transport2.rtcp_tuple().unwrap() { assert_eq!(local_ip, "127.0.0.1".parse::().unwrap()); + assert_eq!(local_port, rtcp_port); assert_eq!(protocol, Protocol::Udp); } assert_eq!(transport2.srtp_parameters(), None); @@ -251,13 +277,14 @@ fn create_with_fixed_port_succeeds() { let transport = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), - }); - plain_transport_options.port = Some(port); - - plain_transport_options + port: Some(port), + send_buffer_size: None, + recv_buffer_size: None, + }) }) .await .expect("Failed to create Plain transport"); @@ -273,9 +300,13 @@ fn weak() { let transport = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.rtcp_mux = false; @@ -302,9 +333,13 @@ fn create_enable_srtp_succeeds() { // Use default cryptoSuite: 'AES_CM_128_HMAC_SHA1_80'. let transport1 = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.enable_srtp = true; @@ -363,9 +398,13 @@ fn create_non_bindable_ip() { assert!(matches!( router - .create_plain_transport(PlainTransportOptions::new(ListenIp { + .create_plain_transport(PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: "8.8.8.8".parse().unwrap(), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, })) .await, Err(RequestError::Response { .. }), @@ -380,9 +419,13 @@ fn get_stats_succeeds() { let transport = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.rtcp_mux = false; @@ -414,13 +457,10 @@ fn get_stats_succeeds() { assert_eq!(stats[0].probation_send_bitrate, 0); assert_eq!(stats[0].rtp_packet_loss_received, None); assert_eq!(stats[0].rtp_packet_loss_sent, None); - assert!(matches!( - stats[0].tuple, - Some(TransportTuple::LocalOnly { .. }), - )); + assert!(matches!(stats[0].tuple, TransportTuple::LocalOnly { .. },)); if let TransportTuple::LocalOnly { local_ip, protocol, .. - } = stats[0].tuple.unwrap() + } = stats[0].tuple { assert_eq!(local_ip, "4.4.4.4".parse::().unwrap()); assert_eq!(protocol, Protocol::Udp); @@ -436,9 +476,13 @@ fn connect_succeeds() { let transport = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.rtcp_mux = false; @@ -507,9 +551,13 @@ fn connect_wrong_arguments() { let transport = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.rtcp_mux = false; @@ -543,9 +591,13 @@ fn close_event() { let transport = router .create_plain_transport({ - let mut plain_transport_options = PlainTransportOptions::new(ListenIp { + let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); plain_transport_options.rtcp_mux = false; diff --git a/rust/tests/integration/producer.rs b/rust/tests/integration/producer.rs index ee5023b1ef..7b05c34083 100644 --- a/rust/tests/integration/producer.rs +++ b/rust/tests/integration/producer.rs @@ -1,7 +1,7 @@ use async_io::Timer; use futures_lite::future; use hash_hasher::{HashedMap, HashedSet}; -use mediasoup::data_structures::{AppData, ListenIp}; +use mediasoup::data_structures::{AppData, ListenInfo, Protocol}; use mediasoup::prelude::*; use mediasoup::producer::{ProducerOptions, ProducerTraceEventType, ProducerType}; use mediasoup::router::{Router, RouterOptions}; @@ -12,7 +12,9 @@ use mediasoup::rtp_parameters::{ }; use mediasoup::scalability_modes::ScalabilityMode; use mediasoup::transport::ProduceError; -use mediasoup::webrtc_transport::{TransportListenIps, WebRtcTransport, WebRtcTransportOptions}; +use mediasoup::webrtc_transport::{ + WebRtcTransport, WebRtcTransportListenInfos, WebRtcTransportOptions, +}; use mediasoup::worker::{Worker, WorkerSettings}; use mediasoup::worker_manager::WorkerManager; use std::env; @@ -199,10 +201,15 @@ async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { .await .expect("Failed to create router"); - let transport_options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let transport_options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); let transport_1 = router .create_webrtc_transport(transport_options.clone()) @@ -635,7 +642,7 @@ fn produce_already_used_mid_ssrc() { } #[test] -fn produce_no_mid_single_encoding_without_dir_or_ssrc() { +fn produce_no_mid_single_encoding_without_rid_or_ssrc() { future::block_on(async move { let (_worker, _router, transport_1, _transport_2) = init().await; @@ -699,7 +706,6 @@ fn dump_succeeds() { rtx: None, dtx: None, scalability_mode: ScalabilityMode::None, - scale_resolution_down_by: None, max_bitrate: None }], ); @@ -737,7 +743,6 @@ fn dump_succeeds() { rtx: Some(RtpEncodingParametersRtx { ssrc: 22222223 }), dtx: None, scalability_mode: "L1T3".parse().unwrap(), - scale_resolution_down_by: None, max_bitrate: None }, RtpEncodingParameters { @@ -747,7 +752,6 @@ fn dump_succeeds() { rtx: Some(RtpEncodingParametersRtx { ssrc: 22222225 }), dtx: None, scalability_mode: ScalabilityMode::None, - scale_resolution_down_by: None, max_bitrate: None }, RtpEncodingParameters { @@ -757,7 +761,6 @@ fn dump_succeeds() { rtx: Some(RtpEncodingParametersRtx { ssrc: 22222227 }), dtx: None, scalability_mode: ScalabilityMode::None, - scale_resolution_down_by: None, max_bitrate: None }, RtpEncodingParameters { @@ -767,7 +770,6 @@ fn dump_succeeds() { rtx: Some(RtpEncodingParametersRtx { ssrc: 22222229 }), dtx: None, scalability_mode: ScalabilityMode::None, - scale_resolution_down_by: None, max_bitrate: None }, ], @@ -880,7 +882,10 @@ fn enable_trace_event_succeeds() { .await .expect("Failed to dump audio producer"); - assert_eq!(dump.trace_event_types.as_str(), "rtp,pli"); + assert_eq!( + dump.trace_event_types, + vec![ProducerTraceEventType::Rtp, ProducerTraceEventType::Pli] + ); } { @@ -894,7 +899,7 @@ fn enable_trace_event_succeeds() { .await .expect("Failed to dump audio producer"); - assert_eq!(dump.trace_event_types.as_str(), ""); + assert_eq!(dump.trace_event_types, vec![]); } }); } diff --git a/rust/tests/integration/router.rs b/rust/tests/integration/router.rs index 66889e2f5b..56d056d5a9 100644 --- a/rust/tests/integration/router.rs +++ b/rust/tests/integration/router.rs @@ -111,8 +111,7 @@ fn create_router_succeeds() { worker_dump.channel_message_handlers, ChannelMessageHandlers { channel_request_handlers: vec![router.id().into()], - payload_channel_request_handlers: vec![], - payload_channel_notification_handlers: vec![] + channel_notification_handlers: vec![] } ); diff --git a/rust/tests/integration/smoke.rs b/rust/tests/integration/smoke.rs index e6527f3671..2f1a46f658 100644 --- a/rust/tests/integration/smoke.rs +++ b/rust/tests/integration/smoke.rs @@ -4,7 +4,7 @@ use mediasoup::audio_level_observer::AudioLevelObserverOptions; use mediasoup::consumer::{ConsumerLayers, ConsumerOptions, ConsumerTraceEventType}; use mediasoup::data_consumer::DataConsumerOptions; use mediasoup::data_producer::DataProducerOptions; -use mediasoup::data_structures::ListenIp; +use mediasoup::data_structures::{ListenInfo, Protocol}; use mediasoup::direct_transport::DirectTransportOptions; use mediasoup::plain_transport::PlainTransportOptions; use mediasoup::prelude::*; @@ -17,7 +17,7 @@ use mediasoup::rtp_parameters::{ }; use mediasoup::sctp_parameters::SctpStreamParameters; use mediasoup::transport::TransportTraceEventType; -use mediasoup::webrtc_transport::{TransportListenIps, WebRtcTransportOptions}; +use mediasoup::webrtc_transport::{WebRtcTransportListenInfos, WebRtcTransportOptions}; use mediasoup::worker::{WorkerLogLevel, WorkerSettings, WorkerUpdateSettings}; use mediasoup::worker_manager::WorkerManager; use std::net::{IpAddr, Ipv4Addr}; @@ -82,10 +82,15 @@ fn smoke() { let webrtc_transport = router .create_webrtc_transport({ - let mut options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - })); + let mut options = + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, + })); options.enable_sctp = true; @@ -264,9 +269,13 @@ fn smoke() { let plain_transport = router .create_plain_transport({ - let mut options = PlainTransportOptions::new(ListenIp { + let mut options = PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }); options.enable_sctp = true; diff --git a/rust/tests/integration/webrtc_server.rs b/rust/tests/integration/webrtc_server.rs index b4600cd09f..f02cb765be 100644 --- a/rust/tests/integration/webrtc_server.rs +++ b/rust/tests/integration/webrtc_server.rs @@ -1,9 +1,7 @@ use futures_lite::future; use hash_hasher::HashedSet; -use mediasoup::data_structures::{AppData, ListenIp, Protocol}; -use mediasoup::webrtc_server::{ - WebRtcServerIpPort, WebRtcServerListenInfo, WebRtcServerListenInfos, WebRtcServerOptions, -}; +use mediasoup::data_structures::{AppData, ListenInfo, Protocol}; +use mediasoup::webrtc_server::{WebRtcServerIpPort, WebRtcServerListenInfos, WebRtcServerOptions}; use mediasoup::worker::{ChannelMessageHandlers, CreateWebRtcServerError, Worker, WorkerSettings}; use mediasoup::worker_manager::WorkerManager; use portpicker::pick_unused_port; @@ -61,21 +59,21 @@ fn create_webrtc_server_succeeds() { let webrtc_server = worker1 .create_webrtc_server({ - let listen_infos = WebRtcServerListenInfos::new(WebRtcServerListenInfo { + let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port1), + send_buffer_size: None, + recv_buffer_size: None, }); - let listen_infos = listen_infos.insert(WebRtcServerListenInfo { + let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), port: Some(port2), + send_buffer_size: None, + recv_buffer_size: None, }); let mut webrtc_server_options = WebRtcServerOptions::new(listen_infos); @@ -101,8 +99,7 @@ fn create_webrtc_server_succeeds() { worker_dump.channel_message_handlers, ChannelMessageHandlers { channel_request_handlers: vec![webrtc_server.id().into()], - payload_channel_request_handlers: vec![], - payload_channel_notification_handlers: vec![] + channel_notification_handlers: vec![] } ); @@ -156,21 +153,21 @@ fn create_webrtc_server_without_specifying_port_succeeds() { let webrtc_server = worker1 .create_webrtc_server({ - let listen_infos = WebRtcServerListenInfos::new(WebRtcServerListenInfo { + let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: None, + send_buffer_size: None, + recv_buffer_size: None, }); - let listen_infos = listen_infos.insert(WebRtcServerListenInfo { + let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), port: None, + send_buffer_size: None, + recv_buffer_size: None, }); let mut webrtc_server_options = WebRtcServerOptions::new(listen_infos); @@ -237,21 +234,21 @@ fn unavailable_infos_fails() { { let create_result = worker1 .create_webrtc_server({ - let listen_infos = WebRtcServerListenInfos::new(WebRtcServerListenInfo { + let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port1), + send_buffer_size: None, + recv_buffer_size: None, }); - let listen_infos = listen_infos.insert(WebRtcServerListenInfo { + let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)), + announced_ip: None, port: Some(port2), + send_buffer_size: None, + recv_buffer_size: None, }); WebRtcServerOptions::new(listen_infos) @@ -268,21 +265,21 @@ fn unavailable_infos_fails() { { let create_result = worker1 .create_webrtc_server({ - let listen_infos = WebRtcServerListenInfos::new(WebRtcServerListenInfo { + let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port1), + send_buffer_size: None, + recv_buffer_size: None, }); - let listen_infos = listen_infos.insert(WebRtcServerListenInfo { + let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), - announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), - }, + ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), + announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), port: Some(port1), + send_buffer_size: None, + recv_buffer_size: None, }); WebRtcServerOptions::new(listen_infos) @@ -299,13 +296,13 @@ fn unavailable_infos_fails() { { let _webrtc_server = worker1 .create_webrtc_server(WebRtcServerOptions::new(WebRtcServerListenInfos::new( - WebRtcServerListenInfo { + ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port1), + send_buffer_size: None, + recv_buffer_size: None, }, ))) .await @@ -313,13 +310,13 @@ fn unavailable_infos_fails() { let create_result = worker2 .create_webrtc_server(WebRtcServerOptions::new(WebRtcServerListenInfos::new( - WebRtcServerListenInfo { + ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port1), + send_buffer_size: None, + recv_buffer_size: None, }, ))) .await; @@ -341,13 +338,13 @@ fn close_event() { let webrtc_server = worker1 .create_webrtc_server(WebRtcServerOptions::new(WebRtcServerListenInfos::new( - WebRtcServerListenInfo { + ListenInfo { protocol: Protocol::Udp, - listen_ip: ListenIp { - ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, - }, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_ip: None, port: Some(port), + send_buffer_size: None, + recv_buffer_size: None, }, ))) .await diff --git a/rust/tests/integration/webrtc_transport.rs b/rust/tests/integration/webrtc_transport.rs index f50bae6a28..e8c45b6761 100644 --- a/rust/tests/integration/webrtc_transport.rs +++ b/rust/tests/integration/webrtc_transport.rs @@ -1,8 +1,8 @@ use futures_lite::future; use hash_hasher::HashedSet; use mediasoup::data_structures::{ - AppData, DtlsFingerprint, DtlsParameters, DtlsRole, DtlsState, IceCandidateTcpType, - IceCandidateType, IceRole, IceState, ListenIp, Protocol, SctpState, + AppData, DtlsFingerprint, DtlsParameters, DtlsRole, DtlsState, IceCandidateType, IceRole, + IceState, ListenInfo, Protocol, SctpState, }; use mediasoup::prelude::*; use mediasoup::router::{Router, RouterOptions}; @@ -12,8 +12,7 @@ use mediasoup::rtp_parameters::{ use mediasoup::sctp_parameters::{NumSctpStreams, SctpParameters}; use mediasoup::transport::TransportTraceEventType; use mediasoup::webrtc_transport::{ - TransportListenIps, WebRtcTransportListen, WebRtcTransportOptions, - WebRtcTransportRemoteParameters, + WebRtcTransportListenInfos, WebRtcTransportOptions, WebRtcTransportRemoteParameters, }; use mediasoup::worker::{RequestError, Worker, WorkerSettings}; use mediasoup::worker_manager::WorkerManager; @@ -95,12 +94,16 @@ fn create_succeeds() { { let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -129,24 +132,34 @@ fn create_succeeds() { .create_webrtc_transport({ let mut webrtc_transport_options = WebRtcTransportOptions::new( vec![ - ListenIp { + ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }, - ListenIp { + ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::UNSPECIFIED), announced_ip: Some("9.9.9.2".parse().unwrap()), + port: None, + send_buffer_size: None, + recv_buffer_size: None, }, - ListenIp { + ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, + port: None, + send_buffer_size: None, + recv_buffer_size: None, }, ] .try_into() .unwrap(), ); - webrtc_transport_options.enable_tcp = true; - webrtc_transport_options.prefer_udp = true; webrtc_transport_options.enable_sctp = true; webrtc_transport_options.num_sctp_streams = NumSctpStreams { os: 2048, @@ -182,42 +195,25 @@ fn create_succeeds() { ); { let ice_candidates = transport1.ice_candidates(); - assert_eq!(ice_candidates.len(), 6); + assert_eq!(ice_candidates.len(), 3); assert_eq!(ice_candidates[0].ip, "9.9.9.1".parse::().unwrap()); assert_eq!(ice_candidates[0].protocol, Protocol::Udp); assert_eq!(ice_candidates[0].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[0].tcp_type, None); - assert_eq!(ice_candidates[1].ip, "9.9.9.1".parse::().unwrap()); - assert_eq!(ice_candidates[1].protocol, Protocol::Tcp); + assert_eq!(ice_candidates[1].ip, "9.9.9.2".parse::().unwrap()); + assert_eq!(ice_candidates[1].protocol, Protocol::Udp); assert_eq!(ice_candidates[1].r#type, IceCandidateType::Host); - assert_eq!( - ice_candidates[1].tcp_type, - Some(IceCandidateTcpType::Passive), - ); - assert_eq!(ice_candidates[2].ip, "9.9.9.2".parse::().unwrap()); + assert_eq!(ice_candidates[1].tcp_type, None); + assert_eq!(ice_candidates[2].ip, "127.0.0.1".parse::().unwrap()); + assert_eq!(ice_candidates[2].protocol, Protocol::Udp); + assert_eq!(ice_candidates[2].r#type, IceCandidateType::Host); + assert_eq!(ice_candidates[2].tcp_type, None); + assert_eq!(ice_candidates[2].ip, "127.0.0.1".parse::().unwrap()); assert_eq!(ice_candidates[2].protocol, Protocol::Udp); assert_eq!(ice_candidates[2].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[2].tcp_type, None); - assert_eq!(ice_candidates[3].ip, "9.9.9.2".parse::().unwrap()); - assert_eq!(ice_candidates[3].protocol, Protocol::Tcp); - assert_eq!(ice_candidates[3].r#type, IceCandidateType::Host); - assert_eq!( - ice_candidates[3].tcp_type, - Some(IceCandidateTcpType::Passive), - ); - assert_eq!(ice_candidates[4].ip, "127.0.0.1".parse::().unwrap()); - assert_eq!(ice_candidates[4].protocol, Protocol::Udp); - assert_eq!(ice_candidates[4].r#type, IceCandidateType::Host); - assert_eq!(ice_candidates[4].tcp_type, None); - assert_eq!(ice_candidates[4].ip, "127.0.0.1".parse::().unwrap()); - assert_eq!(ice_candidates[4].protocol, Protocol::Udp); - assert_eq!(ice_candidates[4].r#type, IceCandidateType::Host); - assert_eq!(ice_candidates[4].tcp_type, None); assert!(ice_candidates[0].priority > ice_candidates[1].priority); - assert!(ice_candidates[2].priority > ice_candidates[1].priority); - assert!(ice_candidates[2].priority > ice_candidates[3].priority); - assert!(ice_candidates[4].priority > ice_candidates[3].priority); - assert!(ice_candidates[4].priority > ice_candidates[5].priority); + assert!(ice_candidates[1].priority > ice_candidates[2].priority); } assert_eq!(transport1.ice_state(), IceState::New); @@ -258,29 +254,23 @@ fn create_with_fixed_port_succeeds() { future::block_on(async move { let (_worker, router) = init().await; - let port1 = pick_unused_port().unwrap(); + let port = pick_unused_port().unwrap(); let transport = router .create_webrtc_transport({ - let mut options = WebRtcTransportOptions::new(TransportListenIps::new(ListenIp { + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - })); - match &mut options.listen { - WebRtcTransportListen::Individual { port, .. } => { - port.replace(port1); - } - WebRtcTransportListen::Server { .. } => { - unreachable!(); - } - } - - options + port: Some(port), + send_buffer_size: None, + recv_buffer_size: None, + })) }) .await .expect("Failed to create WebRTC transport"); - assert_eq!(transport.ice_candidates().get(0).unwrap().port, port1); + assert_eq!(transport.ice_candidates().get(0).unwrap().port, port); }); } @@ -290,12 +280,16 @@ fn weak() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -316,12 +310,16 @@ fn create_non_bindable_ip() { assert!(matches!( router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: "8.8.8.8".parse().unwrap(), announced_ip: None, - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + },) + )) .await, Err(RequestError::Response { .. }), )); @@ -334,12 +332,16 @@ fn get_stats_succeeds() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -381,12 +383,16 @@ fn connect_succeeds() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -426,12 +432,16 @@ fn set_max_incoming_bitrate_succeeds() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -454,12 +464,16 @@ fn set_max_outgoing_bitrate_succeeds() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -482,12 +496,16 @@ fn set_min_outgoing_bitrate_succeeds() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -510,12 +528,16 @@ fn set_max_outgoing_bitrate_fails_if_value_is_lower_than_current_min_limit() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -543,12 +565,16 @@ fn set_min_outgoing_bitrate_fails_if_value_is_higher_than_current_max_limit() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -576,12 +602,16 @@ fn restart_ice_succeeds() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -607,12 +637,16 @@ fn enable_trace_event_succeeds() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); @@ -627,7 +661,10 @@ fn enable_trace_event_succeeds() { .await .expect("Failed to dump WebRTC transport"); - assert_eq!(dump.trace_event_types.as_str(), "probation"); + assert_eq!( + dump.trace_event_types, + vec![TransportTraceEventType::Probation] + ); } { @@ -644,7 +681,13 @@ fn enable_trace_event_succeeds() { .await .expect("Failed to dump WebRTC transport"); - assert_eq!(dump.trace_event_types.as_str(), "probation,bwe"); + assert_eq!( + dump.trace_event_types, + vec![ + TransportTraceEventType::Probation, + TransportTraceEventType::Bwe, + ] + ); } { @@ -658,7 +701,7 @@ fn enable_trace_event_succeeds() { .await .expect("Failed to dump WebRTC transport"); - assert_eq!(dump.trace_event_types.as_str(), ""); + assert_eq!(dump.trace_event_types, vec![]); } }); } @@ -669,12 +712,16 @@ fn close_event() { let (_worker, router) = init().await; let transport = router - .create_webrtc_transport(WebRtcTransportOptions::new(TransportListenIps::new( - ListenIp { + .create_webrtc_transport(WebRtcTransportOptions::new( + WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), - }, - ))) + port: None, + send_buffer_size: None, + recv_buffer_size: None, + }), + )) .await .expect("Failed to create WebRTC transport"); diff --git a/rust/tests/integration/worker.rs b/rust/tests/integration/worker.rs index 1ae513b746..ad0a3d7d9a 100644 --- a/rust/tests/integration/worker.rs +++ b/rust/tests/integration/worker.rs @@ -150,8 +150,7 @@ fn dump_succeeds() { dump.channel_message_handlers, ChannelMessageHandlers { channel_request_handlers: vec![], - payload_channel_request_handlers: vec![], - payload_channel_notification_handlers: vec![] + channel_notification_handlers: vec![] } ); }); diff --git a/worker/.clang-format b/worker/.clang-format index 00181a08c8..e4b051bfbe 100644 --- a/worker/.clang-format +++ b/worker/.clang-format @@ -49,11 +49,11 @@ FixNamespaceComments: true IncludeCategories: - Regex: '"common.hpp"' Priority: 1 - - Regex: '^"(Channel|PayloadChannel|RTC|Utils|handles)/' + - Regex: '^"(Channel|PayloadChannel|FBS|RTC|Utils|handles)/' Priority: 3 - Regex: '"*"' Priority: 2 - - Regex: '^<(json|uv|openssl|srtp|usrsctp|libwebrtc)(.|/)' + - Regex: '^<(flatbuffers|uv|openssl|srtp|usrsctp|libwebrtc)(.|/)' Priority: 4 - Regex: '<*>' Priority: 5 diff --git a/worker/.clang-tidy b/worker/.clang-tidy index f3ade0aca9..2394ea1409 100644 --- a/worker/.clang-tidy +++ b/worker/.clang-tidy @@ -2,10 +2,12 @@ Checks: "*,\ -altera*,\ -boost-use-to-string,\ + -bugprone-easily-swappable-parameters,\ -cert-*,\ -clang-analyzer-optin.osx.*,\ -clang-analyzer-osx.*,\ -cppcoreguidelines-avoid-c-arrays,\ + -cppcoreguidelines-avoid-do-while,\ -cppcoreguidelines-avoid-goto,\ -cppcoreguidelines-avoid-magic-numbers,\ -cppcoreguidelines-init-variables,\ diff --git a/worker/Cargo.toml b/worker/Cargo.toml index c7b3ad6639..9116fc8444 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -9,6 +9,7 @@ documentation = "https://docs.rs/mediasoup-sys" repository = "https://github.com/versatica/mediasoup/tree/v3/worker" include = [ "/deps/libwebrtc", + "/fbs", "/fuzzer/include", "/fuzzer/src", "/include", @@ -28,3 +29,14 @@ include = [ [package.metadata.docs.rs] default-target = "x86_64-unknown-linux-gnu" targets = [] + +[build-dependencies] +planus-codegen = "0.4.0" +planus-translation = "0.4.0" + +[dependencies] +planus = "0.4.0" + +[dependencies.serde] +features = ["derive"] +version = "1.0.190" diff --git a/worker/Makefile b/worker/Makefile index 45e39f5496..be41dd515f 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -77,6 +77,7 @@ endif update-wrap-file \ mediasoup-worker \ libmediasoup-worker \ + flatc \ xcode \ lint \ format \ @@ -195,16 +196,19 @@ clean-all: clean-subprojects update-wrap-file: meson-ninja $(MESON) subprojects update --reset $(SUBPROJECT) -mediasoup-worker: setup +mediasoup-worker: setup flatc ifeq ($(MEDIASOUP_WORKER_BIN),) $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker endif -libmediasoup-worker: setup +libmediasoup-worker: setup flatc $(MESON) compile -C $(BUILD_DIR) -j $(CORES) libmediasoup-worker $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags libmediasoup-worker +flatc: setup + $(MESON) compile -C $(BUILD_DIR) flatbuffers-generator + xcode: setup $(MESON) setup --buildtype debug --backend xcode $(MEDIASOUP_OUT_DIR)/xcode @@ -214,7 +218,7 @@ lint: format: $(GULP) --gulpfile ./scripts/gulpfile.mjs format:worker -test: setup +test: setup flatc $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-test ifeq ($(OS),Windows_NT) diff --git a/worker/build.rs b/worker/build.rs index 2caf96525b..8bf0b836fe 100644 --- a/worker/build.rs +++ b/worker/build.rs @@ -1,5 +1,5 @@ -use std::env; use std::process::Command; +use std::{env, fs}; fn main() { if env::var("DOCS_RS").is_ok() { @@ -16,6 +16,35 @@ fn main() { }; let out_dir = env::var("OUT_DIR").unwrap(); + + // Compile Rust flatbuffers + let flatbuffers_declarations = planus_translation::translate_files( + &fs::read_dir("fbs") + .expect("Failed to read `fbs` directory") + .filter_map(|maybe_entry| { + maybe_entry + .map(|entry| { + let path = entry.path(); + if path.extension() == Some("fbs".as_ref()) { + Some(path) + } else { + None + } + }) + .transpose() + }) + .collect::, _>>() + .expect("Failed to collect flatbuffers files"), + ) + .expect("Failed to translate flatbuffers files"); + + fs::write( + format!("{out_dir}/fbs.rs"), + planus_codegen::generate_rust(&flatbuffers_declarations) + .expect("Failed to generate Rust code from flatbuffers"), + ) + .expect("Failed to write generated Rust flatbuffers into fbs.rs"); + // Force forward slashes on Windows too so that is plays well with our dumb `Makefile`. let mediasoup_out_dir = format!("{}/out", out_dir.replace('\\', "/")); diff --git a/worker/deps/libwebrtc/meson.build b/worker/deps/libwebrtc/meson.build index 7d2c54e219..5e91710aa5 100644 --- a/worker/deps/libwebrtc/meson.build +++ b/worker/deps/libwebrtc/meson.build @@ -51,7 +51,6 @@ abseil_cpp_proj = subproject( 'warning_level=0', ], ) - local_include_directories = declare_dependency( include_directories: include_directories('libwebrtc') ) @@ -64,7 +63,7 @@ libwebrtc = library( openssl_proj.get_variable('openssl_dep'), abseil_cpp_proj.get_variable('absl_strings_dep'), abseil_cpp_proj.get_variable('absl_types_dep'), - nlohmann_json_proj.get_variable('nlohmann_json_dep'), + flatbuffers_proj.get_variable('flatbuffers_dep'), libuv_proj.get_variable('libuv_dep'), ], include_directories: libwebrtc_include_directories, diff --git a/worker/fbs/activeSpeakerObserver.fbs b/worker/fbs/activeSpeakerObserver.fbs new file mode 100644 index 0000000000..e2de103fd4 --- /dev/null +++ b/worker/fbs/activeSpeakerObserver.fbs @@ -0,0 +1,12 @@ +namespace FBS.ActiveSpeakerObserver; + +table ActiveSpeakerObserverOptions { + interval: uint16; +} + +// Notifications from Worker. + +table DominantSpeakerNotification { + producer_id: string (required); +} + diff --git a/worker/fbs/audioLevelObserver.fbs b/worker/fbs/audioLevelObserver.fbs new file mode 100644 index 0000000000..1ce66e402b --- /dev/null +++ b/worker/fbs/audioLevelObserver.fbs @@ -0,0 +1,19 @@ +namespace FBS.AudioLevelObserver; + +table AudioLevelObserverOptions { + max_entries: uint16; + threshold: int8; + interval: uint16; +} + +// Notifications from Worker. + +table Volume { + producer_id: string (required); + volume: int8; +} + +table VolumesNotification { + volumes: [Volume] (required); +} + diff --git a/worker/fbs/common.fbs b/worker/fbs/common.fbs new file mode 100644 index 0000000000..85093fc747 --- /dev/null +++ b/worker/fbs/common.fbs @@ -0,0 +1,33 @@ +namespace FBS.Common; + +table StringString { + key: string (required); + value: string (required); +} + +table StringUint8 { + key: string (required); + value: uint8; +} + +table Uint16String { + key: uint16; + value: string (required); +} + +table Uint32String { + key: uint32; + value: string (required); +} + +table StringStringArray { + key: string (required); + values: [string] (required); +} + +// NOTE (windows): IN|OUT are macros defined in windef.h. +enum TraceDirection: uint8 { + DIRECTION_IN = 0, + DIRECTION_OUT +} + diff --git a/worker/fbs/consumer.fbs b/worker/fbs/consumer.fbs new file mode 100644 index 0000000000..660e1dedc9 --- /dev/null +++ b/worker/fbs/consumer.fbs @@ -0,0 +1,125 @@ +include "common.fbs"; +include "rtpPacket.fbs"; +include "rtpParameters.fbs"; +include "rtpStream.fbs"; + +namespace FBS.Consumer; + +table ConsumerLayers { + spatial_layer: uint8; + temporal_layer: uint8 = null; +} + +table ConsumerScore { + score: uint8; + producer_score: uint8; + producer_scores: [uint8] (required); +} + +table SetPreferredLayersRequest { + preferred_layers: ConsumerLayers (required); +} + +table SetPreferredLayersResponse { + preferred_layers: ConsumerLayers; +} + +table SetPriorityRequest { + priority: uint8; +} + +table SetPriorityResponse { + priority: uint8; +} + +enum TraceEventType: uint8 { + KEYFRAME = 0, + FIR, + NACK, + PLI, + RTP, +} + +table EnableTraceEventRequest { + events: [TraceEventType] (required); +} + +table DumpResponse { + data: ConsumerDump (required); +} + +table BaseConsumerDump { + id: string (required); + type: FBS.RtpParameters.Type; + producer_id: string (required); + kind: FBS.RtpParameters.MediaKind; + rtp_parameters: FBS.RtpParameters.RtpParameters (required); + consumable_rtp_encodings: [FBS.RtpParameters.RtpEncodingParameters] (required); + supported_codec_payload_types: [uint8] (required); + trace_event_types: [TraceEventType] (required); + paused: bool; + producer_paused: bool; + priority: uint8; +} + +table ConsumerDump { + base: BaseConsumerDump (required); + rtp_streams: [FBS.RtpStream.Dump] (required); + preferred_spatial_layer: int16 = null; + target_spatial_layer: int16 = null; + current_spatial_layer: int16 = null; + preferred_temporal_layer: int16 = null; + target_temporal_layer: int16 = null; + current_temporal_layer: int16 = null; +} + +table GetStatsResponse { + stats: [FBS.RtpStream.Stats] (required); +} + +// Notifications from Worker. + +table LayersChangeNotification { + layers: ConsumerLayers (required); +} + +table RtpNotification { + data: [ubyte] (required); +} + +table ScoreNotification { + score: ConsumerScore (required); +} + +union TraceInfo { + KeyFrameTraceInfo, + FirTraceInfo, + PliTraceInfo, + RtpTraceInfo, +} + +table KeyFrameTraceInfo { + rtp_packet: FBS.RtpPacket.Dump (required); + is_rtx: bool; +} + +table FirTraceInfo { + ssrc: uint32; +} + +table PliTraceInfo { + ssrc: uint32; +} + +table RtpTraceInfo { + rtp_packet: FBS.RtpPacket.Dump (required); + is_rtx: bool; +} + +table TraceNotification { + type: TraceEventType; + timestamp: uint64; + direction: FBS.Common.TraceDirection; + info: TraceInfo; +} + diff --git a/worker/fbs/dataConsumer.fbs b/worker/fbs/dataConsumer.fbs new file mode 100644 index 0000000000..2bebe33191 --- /dev/null +++ b/worker/fbs/dataConsumer.fbs @@ -0,0 +1,60 @@ +include "common.fbs"; +include "dataProducer.fbs"; +include "sctpParameters.fbs"; + +namespace FBS.DataConsumer; + +table GetBufferedAmountResponse { + buffered_amount: uint32; +} + +table SetBufferedAmountLowThresholdRequest { + threshold: uint32; +} + +table DumpResponse { + id: string (required); + data_producer_id: string (required); + type: FBS.DataProducer.Type; + sctp_stream_parameters: FBS.SctpParameters.SctpStreamParameters; + label: string (required); + protocol: string (required); + buffered_amount_low_threshold: uint32; + paused: bool; + data_producer_paused: bool; + subchannels: [uint16] (required); +} + +table GetStatsResponse { + timestamp: uint64; + label: string (required); + protocol: string (required); + messages_sent: uint64; + bytes_sent: uint64; + buffered_amount: uint32; +} + +table SendRequest { + ppid: uint32; + data: [uint8] (required); +} + +table SetSubchannelsRequest { + subchannels: [uint16] (required); +} + +table SetSubchannelsResponse { + subchannels: [uint16] (required); +} + +// Notifications from Worker. + +table BufferedAmountLowNotification { + buffered_amount: uint32; +} + +table MessageNotification { + ppid: uint32; + data: [uint8] (required); +} + diff --git a/worker/fbs/dataProducer.fbs b/worker/fbs/dataProducer.fbs new file mode 100644 index 0000000000..3d8dbd367b --- /dev/null +++ b/worker/fbs/dataProducer.fbs @@ -0,0 +1,34 @@ +include "sctpParameters.fbs"; + +namespace FBS.DataProducer; + +enum Type: uint8 { + SCTP, + DIRECT +} + +table DumpResponse { + id: string (required); + type: Type; + sctp_stream_parameters: FBS.SctpParameters.SctpStreamParameters; + label: string (required); + protocol: string (required); + paused: bool; +} + +table GetStatsResponse { + timestamp: uint64; + label: string (required); + protocol: string (required); + messages_received: uint64; + bytes_received: uint64; + buffered_amount: uint32; +} + +table SendNotification { + ppid: uint32; + data: [uint8] (required); + subchannels: [uint16]; + required_subchannel: uint16 = null; +} + diff --git a/worker/fbs/directTransport.fbs b/worker/fbs/directTransport.fbs new file mode 100644 index 0000000000..28dd372281 --- /dev/null +++ b/worker/fbs/directTransport.fbs @@ -0,0 +1,22 @@ +include "transport.fbs"; + +namespace FBS.DirectTransport; + +table DirectTransportOptions { + base: FBS.Transport.Options (required); +} + +table DumpResponse { + base: FBS.Transport.Dump (required); +} + +table GetStatsResponse { + base: FBS.Transport.Stats (required); +} + +// Notifications from Worker. + +table RtcpNotification { + data: [uint8] (required); +} + diff --git a/worker/fbs/log.fbs b/worker/fbs/log.fbs new file mode 100644 index 0000000000..562fa58d35 --- /dev/null +++ b/worker/fbs/log.fbs @@ -0,0 +1,6 @@ +namespace FBS.Log; + +table Log { + data: string (required); +} + diff --git a/worker/fbs/meson.build b/worker/fbs/meson.build new file mode 100644 index 0000000000..6ef2c022d6 --- /dev/null +++ b/worker/fbs/meson.build @@ -0,0 +1,54 @@ +flatbuffers_schemas = [ + 'activeSpeakerObserver.fbs', + 'audioLevelObserver.fbs', + 'common.fbs', + 'consumer.fbs', + 'dataConsumer.fbs', + 'dataProducer.fbs', + 'directTransport.fbs', + 'log.fbs', + 'message.fbs', + 'notification.fbs', + 'pipeTransport.fbs', + 'plainTransport.fbs', + 'producer.fbs', + 'request.fbs', + 'response.fbs', + 'router.fbs', + 'rtpObserver.fbs', + 'rtpPacket.fbs', + 'rtpParameters.fbs', + 'rtpStream.fbs', + 'rtxStream.fbs', + 'sctpAssociation.fbs', + 'sctpParameters.fbs', + 'srtpParameters.fbs', + 'transport.fbs', + 'webRtcServer.fbs', + 'webRtcTransport.fbs', + 'worker.fbs', +] + +# Directory from which worker code will include the header files. +flatbuffers_cpp_out_dir = 'FBS' + +flatc = find_program('flatc') +flatbuffers_generator = custom_target('flatbuffers-generator', + output: flatbuffers_cpp_out_dir, + input: flatbuffers_schemas, + command : [ + flatc, + '--cpp', + '--cpp-field-case-style', 'lower', + '--reflect-names', + '--scoped-enums', + '--filename-suffix', '', + '-o', '@OUTPUT@', + '@INPUT@' + ], + build_by_default: true, +) + +flatbuffers_generator_dep = declare_dependency( + include_directories: '.', +) diff --git a/worker/fbs/message.fbs b/worker/fbs/message.fbs new file mode 100644 index 0000000000..233ff28b08 --- /dev/null +++ b/worker/fbs/message.fbs @@ -0,0 +1,20 @@ +include "log.fbs"; +include "notification.fbs"; +include "request.fbs"; +include "response.fbs"; + +namespace FBS.Message; + +union Body { + Request: FBS.Request.Request, + Response: FBS.Response.Response, + Notification: FBS.Notification.Notification, + Log: FBS.Log.Log, +} + +table Message { + data: Body (required); +} + +root_type Message; + diff --git a/worker/fbs/notification.fbs b/worker/fbs/notification.fbs new file mode 100644 index 0000000000..10725c1843 --- /dev/null +++ b/worker/fbs/notification.fbs @@ -0,0 +1,83 @@ +include "transport.fbs"; +include "webRtcTransport.fbs"; +include "plainTransport.fbs"; +include "directTransport.fbs"; +include "producer.fbs"; +include "dataProducer.fbs"; +include "dataConsumer.fbs"; +include "activeSpeakerObserver.fbs"; +include "audioLevelObserver.fbs"; + +namespace FBS.Notification; + +enum Event: uint8 { + // Notifications to worker. + TRANSPORT_SEND_RTCP = 0, + PRODUCER_SEND, + DATAPRODUCER_SEND, + + // Notifications from worker. + WORKER_RUNNING, + TRANSPORT_SCTP_STATE_CHANGE, + TRANSPORT_TRACE, + WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, + WEBRTCTRANSPORT_ICE_STATE_CHANGE, + WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + PLAINTRANSPORT_TUPLE, + PLAINTRANSPORT_RTCP_TUPLE, + DIRECTTRANSPORT_RTCP, + PRODUCER_SCORE, + PRODUCER_TRACE, + PRODUCER_VIDEO_ORIENTATION_CHANGE, + CONSUMER_PRODUCER_PAUSE, + CONSUMER_PRODUCER_RESUME, + CONSUMER_PRODUCER_CLOSE, + CONSUMER_LAYERS_CHANGE, + CONSUMER_RTP, + CONSUMER_SCORE, + CONSUMER_TRACE, + DATACONSUMER_BUFFERED_AMOUNT_LOW, + DATACONSUMER_SCTP_SENDBUFFER_FULL, + DATACONSUMER_DATAPRODUCER_PAUSE, + DATACONSUMER_DATAPRODUCER_RESUME, + DATACONSUMER_DATAPRODUCER_CLOSE, + DATACONSUMER_MESSAGE, + ACTIVESPEAKEROBSERVER_DOMINANT_SPEAKER, + AUDIOLEVELOBSERVER_SILENCE, + AUDIOLEVELOBSERVER_VOLUMES, +} + +union Body { + // Notifications to worker. + Transport_SendRtcpNotification: FBS.Transport.SendRtcpNotification, + Transport_SctpStateChangeNotification: FBS.Transport.SctpStateChangeNotification, + Producer_SendNotification: FBS.Producer.SendNotification, + DataProducer_SendNotification: FBS.DataProducer.SendNotification, + + // Notifications from worker. + Transport_TraceNotification: FBS.Transport.TraceNotification, + WebRtcTransport_IceSelectedTupleChangeNotification: FBS.WebRtcTransport.IceSelectedTupleChangeNotification, + WebRtcTransport_IceStateChangeNotification: FBS.WebRtcTransport.IceStateChangeNotification, + WebRtcTransport_DtlsStateChangeNotification: FBS.WebRtcTransport.DtlsStateChangeNotification, + PlainTransport_TupleNotification: FBS.PlainTransport.TupleNotification, + PlainTransport_RtcpTupleNotification: FBS.PlainTransport.RtcpTupleNotification, + DirectTransport_RtcpNotification: FBS.DirectTransport.RtcpNotification, + Producer_ScoreNotification: FBS.Producer.ScoreNotification, + Producer_TraceNotification: FBS.Producer.TraceNotification, + Producer_VideoOrientationChangeNotification: FBS.Producer.VideoOrientationChangeNotification, + Consumer_LayersChangeNotification: FBS.Consumer.LayersChangeNotification, + Consumer_RtpNotification: FBS.Consumer.RtpNotification, + Consumer_ScoreNotification: FBS.Consumer.ScoreNotification, + Consumer_TraceNotification: FBS.Consumer.TraceNotification, + DataConsumer_MessageNotification: FBS.DataConsumer.MessageNotification, + DataConsumer_BufferedAmountLowNotification: FBS.DataConsumer.BufferedAmountLowNotification, + ActiveSpeakerObserver_DominantSpeakerNotification: FBS.ActiveSpeakerObserver.DominantSpeakerNotification, + AudioLevelObserver_VolumesNotification: FBS.AudioLevelObserver.VolumesNotification, +} + +table Notification { + handler_id: string (required); + event: Event; + body: Body; +} + diff --git a/worker/fbs/pipeTransport.fbs b/worker/fbs/pipeTransport.fbs new file mode 100644 index 0000000000..6d86b9dce6 --- /dev/null +++ b/worker/fbs/pipeTransport.fbs @@ -0,0 +1,34 @@ +include "transport.fbs"; +include "srtpParameters.fbs"; + +namespace FBS.PipeTransport; + +table PipeTransportOptions { + base: FBS.Transport.Options (required); + listen_info: FBS.Transport.ListenInfo (required); + enable_rtx: bool; + enable_srtp: bool; +} + +table ConnectRequest { + ip: string (required); + port: uint16 = null; + srtp_parameters: FBS.SrtpParameters.SrtpParameters; +} + +table ConnectResponse { + tuple: FBS.Transport.Tuple (required); +} + +table DumpResponse { + base: FBS.Transport.Dump (required); + tuple: FBS.Transport.Tuple (required); + rtx: bool; + srtp_parameters: FBS.SrtpParameters.SrtpParameters; +} + +table GetStatsResponse { + base: FBS.Transport.Stats (required); + tuple: FBS.Transport.Tuple (required); +} + diff --git a/worker/fbs/plainTransport.fbs b/worker/fbs/plainTransport.fbs new file mode 100644 index 0000000000..670443e721 --- /dev/null +++ b/worker/fbs/plainTransport.fbs @@ -0,0 +1,56 @@ +include "transport.fbs"; +include "sctpParameters.fbs"; +include "srtpParameters.fbs"; + +namespace FBS.PlainTransport; + +table PlainTransportOptions { + base: FBS.Transport.Options (required); + listen_info: FBS.Transport.ListenInfo (required); + rtcp_listen_info: FBS.Transport.ListenInfo; + rtcp_mux: bool; + comedia: bool; + enable_srtp: bool; + srtp_crypto_suite: FBS.SrtpParameters.SrtpCryptoSuite = null; +} + +table ConnectRequest { + ip: string; + port: uint16 = null; + rtcp_port: uint16 = null; + srtp_parameters: FBS.SrtpParameters.SrtpParameters; +} + +table ConnectResponse { + tuple: FBS.Transport.Tuple (required); + rtcp_tuple: FBS.Transport.Tuple; + srtp_parameters: FBS.SrtpParameters.SrtpParameters; +} + +table DumpResponse { + base: FBS.Transport.Dump (required); + rtcp_mux: bool; + comedia: bool; + tuple: FBS.Transport.Tuple (required); + rtcp_tuple: FBS.Transport.Tuple; + srtp_parameters: FBS.SrtpParameters.SrtpParameters; +} + +table GetStatsResponse { + base: FBS.Transport.Stats (required); + rtcp_mux: bool; + comedia: bool; + tuple: FBS.Transport.Tuple (required); + rtcp_tuple: FBS.Transport.Tuple; +} + +// Notifications from Worker. + +table TupleNotification { + tuple: FBS.Transport.Tuple (required); +} + +table RtcpTupleNotification { + tuple: FBS.Transport.Tuple (required); +} + diff --git a/worker/fbs/producer.fbs b/worker/fbs/producer.fbs new file mode 100644 index 0000000000..d3ec14a7b8 --- /dev/null +++ b/worker/fbs/producer.fbs @@ -0,0 +1,89 @@ +include "common.fbs"; +include "rtpPacket.fbs"; +include "rtpParameters.fbs"; +include "rtpStream.fbs"; + +namespace FBS.Producer; + +enum TraceEventType: uint8 { + KEYFRAME = 0, + FIR, + NACK, + PLI, + RTP, +} + +table EnableTraceEventRequest { + events: [TraceEventType] (required); +} + +table DumpResponse { + id: string (required); + kind: FBS.RtpParameters.MediaKind; + type: FBS.RtpParameters.Type; + rtp_parameters: FBS.RtpParameters.RtpParameters (required); + rtp_mapping: FBS.RtpParameters.RtpMapping (required); + rtp_streams: [FBS.RtpStream.Dump] (required); + trace_event_types: [TraceEventType] (required); + paused: bool; +} + +table GetStatsResponse { + stats: [FBS.RtpStream.Stats] (required); +} + +table SendNotification { + data: [uint8] (required); +} + +// Notifications from Worker. + +table Score { + encoding_idx: uint32; + ssrc: uint32; + rid: string; + score: uint8; +} + +table ScoreNotification { + scores: [Score] (required); +} + +table VideoOrientationChangeNotification { + camera: bool; + flip: bool; + rotation: uint16; +} + +union TraceInfo { + KeyFrameTraceInfo, + FirTraceInfo, + PliTraceInfo, + RtpTraceInfo, +} + +table KeyFrameTraceInfo { + rtp_packet: FBS.RtpPacket.Dump (required); + is_rtx: bool; +} + +table FirTraceInfo { + ssrc: uint32; +} + +table PliTraceInfo { + ssrc: uint32; +} + +table RtpTraceInfo { + rtp_packet: FBS.RtpPacket.Dump (required); + is_rtx: bool; +} + +table TraceNotification { + type: TraceEventType; + timestamp: uint64; + direction: FBS.Common.TraceDirection; + info: TraceInfo; +} + diff --git a/worker/fbs/request.fbs b/worker/fbs/request.fbs new file mode 100644 index 0000000000..56eca5674d --- /dev/null +++ b/worker/fbs/request.fbs @@ -0,0 +1,129 @@ +include "worker.fbs"; +include "router.fbs"; +include "transport.fbs"; +include "producer.fbs"; +include "consumer.fbs"; +include "dataConsumer.fbs"; +include "rtpObserver.fbs"; + +namespace FBS.Request; + +enum Method: uint8 { + WORKER_CLOSE = 0, + WORKER_DUMP, + WORKER_GET_RESOURCE_USAGE, + WORKER_UPDATE_SETTINGS, + WORKER_CREATE_WEBRTCSERVER, + WORKER_CREATE_ROUTER, + WORKER_WEBRTCSERVER_CLOSE, + WORKER_CLOSE_ROUTER, + WEBRTCSERVER_DUMP, + ROUTER_DUMP, + ROUTER_CREATE_WEBRTCTRANSPORT, + ROUTER_CREATE_WEBRTCTRANSPORT_WITH_SERVER, + ROUTER_CREATE_PLAINTRANSPORT, + ROUTER_CREATE_PIPETRANSPORT, + ROUTER_CREATE_DIRECTTRANSPORT, + ROUTER_CLOSE_TRANSPORT, + ROUTER_CREATE_ACTIVESPEAKEROBSERVER, + ROUTER_CREATE_AUDIOLEVELOBSERVER, + ROUTER_CLOSE_RTPOBSERVER, + TRANSPORT_DUMP, + TRANSPORT_GET_STATS, + TRANSPORT_CONNECT, + TRANSPORT_SET_MAX_INCOMING_BITRATE, + TRANSPORT_SET_MAX_OUTGOING_BITRATE, + TRANSPORT_SET_MIN_OUTGOING_BITRATE, + TRANSPORT_RESTART_ICE, + TRANSPORT_PRODUCE, + TRANSPORT_PRODUCE_DATA, + TRANSPORT_CONSUME, + TRANSPORT_CONSUME_DATA, + TRANSPORT_ENABLE_TRACE_EVENT, + TRANSPORT_CLOSE_PRODUCER, + TRANSPORT_CLOSE_CONSUMER, + TRANSPORT_CLOSE_DATAPRODUCER, + TRANSPORT_CLOSE_DATACONSUMER, + PLAINTRANSPORT_CONNECT, + PIPETRANSPORT_CONNECT, + WEBRTCTRANSPORT_CONNECT, + PRODUCER_DUMP, + PRODUCER_GET_STATS, + PRODUCER_PAUSE, + PRODUCER_RESUME, + PRODUCER_ENABLE_TRACE_EVENT, + CONSUMER_DUMP, + CONSUMER_GET_STATS, + CONSUMER_PAUSE, + CONSUMER_RESUME, + CONSUMER_SET_PREFERRED_LAYERS, + CONSUMER_SET_PRIORITY, + CONSUMER_REQUEST_KEY_FRAME, + CONSUMER_ENABLE_TRACE_EVENT, + DATAPRODUCER_DUMP, + DATAPRODUCER_GET_STATS, + DATAPRODUCER_PAUSE, + DATAPRODUCER_RESUME, + DATACONSUMER_DUMP, + DATACONSUMER_GET_STATS, + DATACONSUMER_PAUSE, + DATACONSUMER_RESUME, + DATACONSUMER_GET_BUFFERED_AMOUNT, + DATACONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, + DATACONSUMER_SEND, + DATACONSUMER_SET_SUBCHANNELS, + RTPOBSERVER_PAUSE, + RTPOBSERVER_RESUME, + RTPOBSERVER_ADD_PRODUCER, + RTPOBSERVER_REMOVE_PRODUCER, +} + +union Body { + Worker_UpdateSettingsRequest: FBS.Worker.UpdateSettingsRequest, + Worker_CreateWebRtcServerRequest: FBS.Worker.CreateWebRtcServerRequest, + Worker_CloseWebRtcServerRequest: FBS.Worker.CloseWebRtcServerRequest, + Worker_CreateRouterRequest: FBS.Worker.CreateRouterRequest, + Worker_CloseRouterRequest: FBS.Worker.CloseRouterRequest, + Router_CreateWebRtcTransportRequest: FBS.Router.CreateWebRtcTransportRequest, + Router_CreatePlainTransportRequest: FBS.Router.CreatePlainTransportRequest, + Router_CreatePipeTransportRequest: FBS.Router.CreatePipeTransportRequest, + Router_CreateDirectTransportRequest: FBS.Router.CreateDirectTransportRequest, + Router_CreateActiveSpeakerObserverRequest: FBS.Router.CreateActiveSpeakerObserverRequest, + Router_CreateAudioLevelObserverRequest: FBS.Router.CreateAudioLevelObserverRequest, + Router_CloseTransportRequest: FBS.Router.CloseTransportRequest, + Router_CloseRtpObserverRequest: FBS.Router.CloseRtpObserverRequest, + Transport_SetMaxIncomingBitrateRequest: FBS.Transport.SetMaxIncomingBitrateRequest, + Transport_SetMaxOutgoingBitrateRequest: FBS.Transport.SetMaxOutgoingBitrateRequest, + Transport_SetMinOutgoingBitrateRequest: FBS.Transport.SetMinOutgoingBitrateRequest, + Transport_ProduceRequest: FBS.Transport.ProduceRequest, + Transport_ConsumeRequest: FBS.Transport.ConsumeRequest, + Transport_ProduceDataRequest: FBS.Transport.ProduceDataRequest, + Transport_ConsumeDataRequest: FBS.Transport.ConsumeDataRequest, + Transport_EnableTraceEventRequest: FBS.Transport.EnableTraceEventRequest, + Transport_CloseProducerRequest: FBS.Transport.CloseProducerRequest, + Transport_CloseConsumerRequest: FBS.Transport.CloseConsumerRequest, + Transport_CloseDataProducerRequest: FBS.Transport.CloseDataProducerRequest, + Transport_CloseDataConsumerRequest: FBS.Transport.CloseDataConsumerRequest, + PlainTransport_ConnectRequest: FBS.PlainTransport.ConnectRequest, + PipeTransport_ConnectRequest: FBS.PipeTransport.ConnectRequest, + WebRtcTransport_ConnectRequest: FBS.WebRtcTransport.ConnectRequest, + Producer_EnableTraceEventRequest: FBS.Producer.EnableTraceEventRequest, + Consumer_SetPreferredLayersRequest: FBS.Consumer.SetPreferredLayersRequest, + Consumer_SetPriorityRequest: FBS.Consumer.SetPriorityRequest, + Consumer_EnableTraceEventRequest: FBS.Consumer.EnableTraceEventRequest, + DataConsumer_SetBufferedAmountLowThresholdRequest: FBS.DataConsumer.SetBufferedAmountLowThresholdRequest, + DataConsumer_SendRequest: FBS.DataConsumer.SendRequest, + DataConsumer_SetSubchannelsRequest: FBS.DataConsumer.SetSubchannelsRequest, + RtpObserver_AddProducerRequest: FBS.RtpObserver.AddProducerRequest, + RtpObserver_RemoveProducerRequest: FBS.RtpObserver.RemoveProducerRequest, +} + +table Request { + id: uint32; + method: Method; + handler_id: string (required); + body: Body; +} + +root_type Request; + diff --git a/worker/fbs/response.fbs b/worker/fbs/response.fbs new file mode 100644 index 0000000000..539d36a72a --- /dev/null +++ b/worker/fbs/response.fbs @@ -0,0 +1,52 @@ +include "worker.fbs"; +include "router.fbs"; +include "webRtcServer.fbs"; +include "transport.fbs"; +include "producer.fbs"; +include "consumer.fbs"; +include "dataProducer.fbs"; +include "dataConsumer.fbs"; + +namespace FBS.Response; + +union Body { + Worker_DumpResponse: FBS.Worker.DumpResponse, + Worker_ResourceUsageResponse: FBS.Worker.ResourceUsageResponse, + WebRtcServer_DumpResponse: FBS.WebRtcServer.DumpResponse, + Router_DumpResponse: FBS.Router.DumpResponse, + Transport_ProduceResponse: FBS.Transport.ProduceResponse, + Transport_ConsumeResponse: FBS.Transport.ConsumeResponse, + Transport_RestartIceResponse: FBS.Transport.RestartIceResponse, + PlainTransport_ConnectResponse: FBS.PlainTransport.ConnectResponse, + PlainTransport_DumpResponse: FBS.PlainTransport.DumpResponse, + PlainTransport_GetStatsResponse: FBS.PlainTransport.GetStatsResponse, + PipeTransport_ConnectResponse: FBS.PipeTransport.ConnectResponse, + PipeTransport_DumpResponse: FBS.PipeTransport.DumpResponse, + PipeTransport_GetStatsResponse: FBS.PipeTransport.GetStatsResponse, + DirectTransport_DumpResponse: FBS.DirectTransport.DumpResponse, + DirectTransport_GetStatsResponse: FBS.DirectTransport.GetStatsResponse, + WebRtcTransport_ConnectResponse: FBS.WebRtcTransport.ConnectResponse, + WebRtcTransport_DumpResponse: FBS.WebRtcTransport.DumpResponse, + WebRtcTransport_GetStatsResponse: FBS.WebRtcTransport.GetStatsResponse, + Producer_DumpResponse: FBS.Producer.DumpResponse, + Producer_GetStatsResponse: FBS.Producer.GetStatsResponse, + Consumer_DumpResponse: FBS.Consumer.DumpResponse, + Consumer_GetStatsResponse: FBS.Consumer.GetStatsResponse, + Consumer_SetPreferredLayersResponse: FBS.Consumer.SetPreferredLayersResponse, + Consumer_SetPriorityResponse: FBS.Consumer.SetPriorityResponse, + DataProducer_DumpResponse: FBS.DataProducer.DumpResponse, + DataProducer_GetStatsResponse: FBS.DataProducer.GetStatsResponse, + DataConsumer_GetBufferedAmountResponse: FBS.DataConsumer.GetBufferedAmountResponse, + DataConsumer_DumpResponse: FBS.DataConsumer.DumpResponse, + DataConsumer_GetStatsResponse: FBS.DataConsumer.GetStatsResponse, + DataConsumer_SetSubchannelsResponse: FBS.DataConsumer.SetSubchannelsResponse, +} + +table Response { + id: uint32; + accepted: bool; + body: Body; + error: string; + reason: string; +} + diff --git a/worker/fbs/router.fbs b/worker/fbs/router.fbs new file mode 100644 index 0000000000..6c0a34b256 --- /dev/null +++ b/worker/fbs/router.fbs @@ -0,0 +1,60 @@ +include "common.fbs"; +include "activeSpeakerObserver.fbs"; +include "audioLevelObserver.fbs"; +include "transport.fbs"; +include "pipeTransport.fbs"; +include "plainTransport.fbs"; +include "webRtcTransport.fbs"; +include "directTransport.fbs"; + +namespace FBS.Router; + +table DumpResponse { + id: string (required); + transport_ids: [string] (required); + rtp_observer_ids: [string] (required); + map_producer_id_consumer_ids: [FBS.Common.StringStringArray] (required); + map_consumer_id_producer_id: [FBS.Common.StringString] (required); + map_producer_id_observer_ids: [FBS.Common.StringStringArray] (required); + map_data_producer_id_data_consumer_ids: [FBS.Common.StringStringArray] (required); + map_data_consumer_id_data_producer_id: [FBS.Common.StringString] (required); +} + +table CreatePipeTransportRequest { + transport_id: string (required); + options: FBS.PipeTransport.PipeTransportOptions (required); +} + +table CreatePlainTransportRequest { + transport_id: string (required); + options: FBS.PlainTransport.PlainTransportOptions (required); +} + +table CreateWebRtcTransportRequest { + transport_id: string (required); + options: FBS.WebRtcTransport.WebRtcTransportOptions (required); +} + +table CreateDirectTransportRequest { + transport_id: string (required); + options: FBS.DirectTransport.DirectTransportOptions (required); +} + +table CreateAudioLevelObserverRequest { + rtp_observer_id: string (required); + options: FBS.AudioLevelObserver.AudioLevelObserverOptions (required); +} + +table CreateActiveSpeakerObserverRequest { + rtp_observer_id: string (required); + options: FBS.ActiveSpeakerObserver.ActiveSpeakerObserverOptions (required); +} + +table CloseTransportRequest { + transport_id: string (required); +} + +table CloseRtpObserverRequest { + rtp_observer_id: string (required); +} + diff --git a/worker/fbs/rtpObserver.fbs b/worker/fbs/rtpObserver.fbs new file mode 100644 index 0000000000..68f2a40c14 --- /dev/null +++ b/worker/fbs/rtpObserver.fbs @@ -0,0 +1,10 @@ +namespace FBS.RtpObserver; + +table AddProducerRequest { + producer_id: string (required); +} + +table RemoveProducerRequest { + producer_id: string (required); +} + diff --git a/worker/fbs/rtpPacket.fbs b/worker/fbs/rtpPacket.fbs new file mode 100644 index 0000000000..3975d9d748 --- /dev/null +++ b/worker/fbs/rtpPacket.fbs @@ -0,0 +1,21 @@ +include "common.fbs"; + +namespace FBS.RtpPacket; + +table Dump { + payload_type: uint8; + sequence_number: uint16; + timestamp: uint32; + marker: bool; + ssrc: uint32; + is_key_frame: bool; + size: uint64; + payload_size: uint64; + spatial_layer: uint8; + temporal_layer: uint8; + mid: string; + rid: string; + rrid: string; + wide_sequence_number: uint16 = null; +} + diff --git a/worker/fbs/rtpParameters.fbs b/worker/fbs/rtpParameters.fbs new file mode 100644 index 0000000000..8bd8d7066c --- /dev/null +++ b/worker/fbs/rtpParameters.fbs @@ -0,0 +1,128 @@ +namespace FBS.RtpParameters; + +enum MediaKind: uint8 { + AUDIO, + VIDEO +} + +enum Type: uint8 { + SIMPLE, + SIMULCAST, + SVC, + PIPE +} + +// Boolean is a uint8/byte type. +table Boolean { + value: uint8; +} + +table Integer32 { + value: int32; +} + +table Integer32Array { + value: [int32]; +} + +table Double { + value: double; +} + +table String { + value: string (required); +} + +union Value { + Boolean, + Integer32, + Double, + String, + Integer32Array, +} + +table Parameter { + name: string (required); + value: Value (required); +} + +table RtcpFeedback { + // TODO: Create a specifc type. + type: string (required); + parameter: string; +} + +table RtpCodecParameters { + mime_type: string (required); + payload_type: uint8; + clock_rate: uint32; + channels: uint8 = null; + parameters: [Parameter]; + rtcp_feedback: [RtcpFeedback]; +} + +enum RtpHeaderExtensionUri: uint8 { + Mid, + RtpStreamId, + RepairRtpStreamId, + FrameMarkingDraft07, + FrameMarking, + AudioLevel, + VideoOrientation, + TimeOffset, + TransportWideCcDraft01, + AbsSendTime, + AbsCaptureTime, +} + +table RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri; + id: uint8; + encrypt: bool = false; + parameters: [Parameter]; +} + +table Rtx { + ssrc: uint32; +} + +table RtpEncodingParameters { + ssrc: uint32 = null; + rid: string; + codec_payload_type: uint8 = null; + rtx: Rtx; + dtx: bool = false; + scalability_mode: string; + max_bitrate: uint32 = null; +} + +table RtcpParameters { + cname: string; + reduced_size: bool = true; +} + +table RtpParameters { + mid: string; + codecs: [RtpCodecParameters] (required); + header_extensions: [RtpHeaderExtensionParameters] (required); + encodings: [RtpEncodingParameters] (required); + rtcp: RtcpParameters (required); +} + +table CodecMapping { + payload_type: uint8; + mapped_payload_type: uint8; +} + +table EncodingMapping { + rid: string; + ssrc: uint32 = null; + scalability_mode: string; + mapped_ssrc: uint32; +} + +table RtpMapping { + codecs: [CodecMapping] (required); + encodings: [EncodingMapping] (required); +} + diff --git a/worker/fbs/rtpStream.fbs b/worker/fbs/rtpStream.fbs new file mode 100644 index 0000000000..e30713ce4a --- /dev/null +++ b/worker/fbs/rtpStream.fbs @@ -0,0 +1,82 @@ +include "rtpParameters.fbs"; +include "rtxStream.fbs"; + +namespace FBS.RtpStream; + +table Params { + encoding_idx: uint32; + ssrc: uint32; + payload_type: uint8; + mime_type: string (required); + clock_rate: uint32; + rid: string; + cname: string (required); + rtx_ssrc: uint32 = null; + rtx_payload_type: uint8 = null; + use_nack: bool; + use_pli: bool; + use_fir: bool; + use_in_band_fec: bool; + use_dtx: bool; + spatial_layers: uint8; + temporal_layers: uint8; +} + +table Dump { + params: Params (required); + score: uint8; + rtx_stream: FBS.RtxStream.RtxDump; +} + +table BitrateByLayer { + layer: string (required); + bitrate: uint32; +} + +union StatsData { + BaseStats, + RecvStats, + SendStats, +} + +table Stats { + data: StatsData (required); +} + +table BaseStats { + timestamp: uint64; + ssrc: uint32; + kind: FBS.RtpParameters.MediaKind; + mime_type: string (required); + packets_lost: uint64; + fraction_lost: uint8; + packets_discarded: uint64; + packets_retransmitted: uint64; + packets_repaired: uint64; + nack_count: uint64; + nack_packet_count: uint64; + pli_count: uint64; + fir_count: uint64; + score: uint8; + rid: string; + rtx_ssrc: uint32 = null; + rtx_packets_discarded: uint64; + round_trip_time: float; +} + +table RecvStats { + base: Stats (required); + jitter: uint32; + packet_count: uint64; + byte_count: uint64; + bitrate: uint32; + bitrate_by_layer: [BitrateByLayer] (required); +} + +table SendStats { + base: Stats (required); + packet_count: uint64; + byte_count: uint64; + bitrate: uint32; +} + diff --git a/worker/fbs/rtxStream.fbs b/worker/fbs/rtxStream.fbs new file mode 100644 index 0000000000..693d27ab77 --- /dev/null +++ b/worker/fbs/rtxStream.fbs @@ -0,0 +1,16 @@ +namespace FBS.RtxStream; + +table Params { + ssrc: uint32; + payload_type: uint8; + mime_type: string (required); + clock_rate: uint32; + rrid: string; + cname: string (required); +} + +// NOTE: Naming this Dump collides in TS generation for Producer.DumpResponse. +table RtxDump { + params: Params (required); +} + diff --git a/worker/fbs/sctpAssociation.fbs b/worker/fbs/sctpAssociation.fbs new file mode 100644 index 0000000000..85e83c12a6 --- /dev/null +++ b/worker/fbs/sctpAssociation.fbs @@ -0,0 +1,10 @@ +namespace FBS.SctpAssociation; + +enum SctpState: uint8 { + NEW = 0, + CONNECTING, + CONNECTED, + FAILED, + CLOSED, +} + diff --git a/worker/fbs/sctpParameters.fbs b/worker/fbs/sctpParameters.fbs new file mode 100644 index 0000000000..019eecd9b2 --- /dev/null +++ b/worker/fbs/sctpParameters.fbs @@ -0,0 +1,25 @@ +namespace FBS.SctpParameters; + +table NumSctpStreams { + os: uint16 = 1024; + mis: uint16 = 1024; +} + +table SctpParameters { + // Port is always 5000. + port: uint16 = 5000; + os: uint16; + mis: uint16; + max_message_size: uint32; + send_buffer_size: uint32; + sctp_buffered_amount: uint32; + is_data_channel: bool; +} + +table SctpStreamParameters { + stream_id: uint16; + ordered: bool = null; + max_packet_life_time: uint16 = null; + max_retransmits: uint16 = null; +} + diff --git a/worker/fbs/srtpParameters.fbs b/worker/fbs/srtpParameters.fbs new file mode 100644 index 0000000000..8f6a194469 --- /dev/null +++ b/worker/fbs/srtpParameters.fbs @@ -0,0 +1,14 @@ +namespace FBS.SrtpParameters; + +enum SrtpCryptoSuite: uint8 { + AEAD_AES_256_GCM, + AEAD_AES_128_GCM, + AES_CM_128_HMAC_SHA1_80, + AES_CM_128_HMAC_SHA1_32, +} + +table SrtpParameters { + crypto_suite: FBS.SrtpParameters.SrtpCryptoSuite; + key_base64: string (required); +} + diff --git a/worker/fbs/transport.fbs b/worker/fbs/transport.fbs new file mode 100644 index 0000000000..d2a77d4ae9 --- /dev/null +++ b/worker/fbs/transport.fbs @@ -0,0 +1,242 @@ +include "common.fbs"; +include "consumer.fbs"; +include "dataProducer.fbs"; +include "rtpParameters.fbs"; +include "sctpAssociation.fbs"; +include "sctpParameters.fbs"; +include "srtpParameters.fbs"; + +namespace FBS.Transport; + +enum Protocol: uint8 { + UDP = 1, + TCP +} + +table ListenInfo { + protocol: FBS.Transport.Protocol = UDP; + ip: string (required); + announced_ip: string; + port: uint16 = 0; + send_buffer_size: uint32 = 0; + recv_buffer_size: uint32 = 0; +} + +table RestartIceResponse { + username_fragment: string (required); + password: string (required); + ice_lite: bool; +} + +table ProduceRequest { + producer_id: string (required); + kind: FBS.RtpParameters.MediaKind; + rtp_parameters: FBS.RtpParameters.RtpParameters (required); + rtp_mapping: FBS.RtpParameters.RtpMapping (required); + key_frame_request_delay: uint32; + paused: bool = false; +} + +table ProduceResponse { + type: FBS.RtpParameters.Type; +} + +table ConsumeRequest { + consumer_id: string (required); + producer_id: string (required); + kind: FBS.RtpParameters.MediaKind; + rtp_parameters: FBS.RtpParameters.RtpParameters (required); + type: FBS.RtpParameters.Type; + consumable_rtp_encodings: [FBS.RtpParameters.RtpEncodingParameters] (required); + paused: bool = false; + preferred_layers: FBS.Consumer.ConsumerLayers; + ignore_dtx: bool = false; +} + +table ConsumeResponse { + paused: bool; + producer_paused: bool; + score: FBS.Consumer.ConsumerScore (required); + preferred_layers: FBS.Consumer.ConsumerLayers; +} + +table ProduceDataRequest { + data_producer_id: string (required); + type: FBS.DataProducer.Type; + sctp_stream_parameters: FBS.SctpParameters.SctpStreamParameters; + label: string; + protocol: string; + paused: bool = false; +} + +table ConsumeDataRequest { + data_consumer_id: string (required); + data_producer_id: string (required); + type: FBS.DataProducer.Type; + sctp_stream_parameters: FBS.SctpParameters.SctpStreamParameters; + label: string; + protocol: string; + paused: bool = false; + subchannels: [uint16]; +} + +table Tuple { + local_ip: string (required); + local_port: uint16; + remote_ip: string; + remote_port: uint16; + protocol: FBS.Transport.Protocol = UDP; +} + +table RtpListener { + ssrc_table: [FBS.Common.Uint32String] (required); + mid_table: [FBS.Common.StringString] (required); + rid_table: [FBS.Common.StringString] (required); +} + +table SctpListener { + stream_id_table: [FBS.Common.Uint16String] (required); +} + +table RecvRtpHeaderExtensions { + mid: uint8 = null; + rid: uint8 = null; + rrid: uint8 = null; + abs_send_time: uint8 = null; + transport_wide_cc01: uint8 = null; +} + +table Options { + direct: bool = false; + + /// Only needed for DirectTransport. This value is handled by base Transport. + max_message_size: uint32 = null; + initial_available_outgoing_bitrate: uint32 = null; + enable_sctp: bool = false; + num_sctp_streams: FBS.SctpParameters.NumSctpStreams; + max_sctp_message_size: uint32; + sctp_send_buffer_size: uint32; + is_data_channel: bool = false; +} + +enum TraceEventType: uint8 { + PROBATION = 0, + BWE +} + +table Dump { + id: string (required); + direct: bool = false; + producer_ids: [string] (required); + consumer_ids: [string] (required); + map_ssrc_consumer_id: [FBS.Common.Uint32String] (required); + map_rtx_ssrc_consumer_id: [FBS.Common.Uint32String] (required); + data_producer_ids: [string] (required); + data_consumer_ids: [string] (required); + recv_rtp_header_extensions: RecvRtpHeaderExtensions (required); + rtp_listener: RtpListener (required); + max_message_size: uint32; + sctp_parameters: FBS.SctpParameters.SctpParameters; + sctp_state: FBS.SctpAssociation.SctpState = null; + sctp_listener: SctpListener; + trace_event_types: [TraceEventType] (required); +} + +table Stats { + transport_id: string (required); + timestamp: uint64; + sctp_state: FBS.SctpAssociation.SctpState = null; + bytes_received: uint64; + recv_bitrate: uint32; + bytes_sent: uint64; + send_bitrate: uint32; + rtp_bytes_received: uint64; + rtp_recv_bitrate: uint32; + rtp_bytes_sent: uint64; + rtp_send_bitrate: uint32; + rtx_bytes_received: uint64; + rtx_recv_bitrate: uint32; + rtx_bytes_sent: uint64; + rtx_send_bitrate: uint32; + probation_bytes_sent: uint64; + probation_send_bitrate: uint32; + available_outgoing_bitrate: uint32 = null; + available_incoming_bitrate: uint32 = null; + max_incoming_bitrate: uint32 = null; + max_outgoing_bitrate: uint32 = null; + min_outgoing_bitrate: uint32 = null; + rtp_packet_loss_received: float64 = null; + rtp_packet_loss_sent: float64 = null; +} + +table SetMaxIncomingBitrateRequest { + max_incoming_bitrate: uint32; +} + +table SetMaxOutgoingBitrateRequest { + max_outgoing_bitrate: uint32; +} + +table SetMinOutgoingBitrateRequest { + min_outgoing_bitrate: uint32; +} + +table EnableTraceEventRequest { + events: [TraceEventType] (required); +} + +table CloseProducerRequest { + producer_id: string (required); +} + +table CloseConsumerRequest { + consumer_id: string (required); +} + +table CloseDataProducerRequest { + data_producer_id: string (required); +} + +table CloseDataConsumerRequest { + data_consumer_id: string (required); +} + +// Notifications to Worker. + +table SendRtcpNotification { + data: [uint8] (required); +} + +// Notifications from Worker. + +table SctpStateChangeNotification { + sctp_state: FBS.SctpAssociation.SctpState; +} + +union TraceInfo { + BweTraceInfo, +} + +enum BweType: uint8 { + TRANSPORT_CC = 0, + REMB +} + +table BweTraceInfo { + bwe_type: BweType; + desired_bitrate: uint32; + effective_desired_bitrate: uint32; + min_bitrate: uint32; + max_bitrate: uint32; + start_bitrate: uint32; + max_padding_bitrate: uint32; + available_bitrate: uint32; +} + +table TraceNotification { + type: TraceEventType; + timestamp: uint64; + direction: FBS.Common.TraceDirection; + info: TraceInfo; +} + diff --git a/worker/fbs/webRtcServer.fbs b/worker/fbs/webRtcServer.fbs new file mode 100644 index 0000000000..7d9c4edde1 --- /dev/null +++ b/worker/fbs/webRtcServer.fbs @@ -0,0 +1,28 @@ +include "transport.fbs"; + +namespace FBS.WebRtcServer; + +table IpPort { + ip: string (required); + port: uint16; +} + +table IceUserNameFragment { + local_ice_username_fragment: string (required); + web_rtc_transport_id: string (required); +} + +table TupleHash { + tuple_hash: uint64; + web_rtc_transport_id: string (required); +} + +table DumpResponse { + id: string (required); + udp_sockets: [IpPort] (required); + tcp_servers: [IpPort] (required); + web_rtc_transport_ids: [string] (required); + local_ice_username_fragments: [IceUserNameFragment] (required); + tuple_hashes: [TupleHash] (required); +} + diff --git a/worker/fbs/webRtcTransport.fbs b/worker/fbs/webRtcTransport.fbs new file mode 100644 index 0000000000..ad0a8e0fc8 --- /dev/null +++ b/worker/fbs/webRtcTransport.fbs @@ -0,0 +1,137 @@ +include "transport.fbs"; +include "sctpParameters.fbs"; + +namespace FBS.WebRtcTransport; + +table ListenIndividual { + listen_infos: [FBS.Transport.ListenInfo] (required); +} + +table ListenServer { + web_rtc_server_id: string (required); +} + +union Listen { + ListenIndividual, + ListenServer, +} + +table WebRtcTransportOptions { + base: FBS.Transport.Options (required); + listen: Listen (required); + enable_udp: bool = true; + enable_tcp: bool = true; + prefer_udp: bool = false; + prefer_tcp: bool = false; +} + +enum FingerprintAlgorithm: uint8 { + SHA1, + SHA224, + SHA256, + SHA384, + SHA512, +} + +table Fingerprint { + algorithm: FingerprintAlgorithm; + value: string (required); +} + +enum DtlsRole: uint8 { + AUTO, + CLIENT, + SERVER +} + +enum DtlsState: uint8 { + NEW, + CONNECTING, + CONNECTED, + FAILED, + CLOSED +} + +table DtlsParameters { + fingerprints: [Fingerprint] (required); + role: DtlsRole = AUTO; +} + +table IceParameters { + username_fragment: string (required); + password: string (required); + ice_lite: bool = true; +} + +enum IceCandidateType: uint8 { + HOST +} + +enum IceCandidateTcpType: uint8 { + PASSIVE +} + +enum IceRole: uint8 { + CONTROLLED, + CONTROLLING +} + +enum IceState: uint8 { + NEW, + CONNECTED, + COMPLETED, + DISCONNECTED, +} + +table IceCandidate { + foundation: string (required); + priority: uint32; + ip: string (required); + protocol: FBS.Transport.Protocol = UDP; + port: uint16; + type: IceCandidateType; + tcp_type: IceCandidateTcpType = null; +} + +table ConnectRequest { + dtls_parameters: DtlsParameters (required); +} + +table ConnectResponse { + dtls_local_role: DtlsRole; +} + +table DumpResponse { + base: FBS.Transport.Dump (required); + ice_role: IceRole; + ice_parameters: IceParameters (required); + ice_candidates: [IceCandidate] (required); + ice_state: IceState; + ice_selected_tuple: FBS.Transport.Tuple; + dtls_parameters: DtlsParameters (required); + dtls_state: DtlsState; +} + +table GetStatsResponse { + base: FBS.Transport.Stats (required); + ice_role: IceRole; + ice_state: IceState; + ice_selected_tuple: FBS.Transport.Tuple; + dtls_state: DtlsState; +} + +// Notifications from Worker. + +table IceSelectedTupleChangeNotification { + tuple: FBS.Transport.Tuple (required); +} + +table IceStateChangeNotification { + ice_state: IceState; +} + +table DtlsStateChangeNotification { + dtls_state: DtlsState; + remote_cert: string; +} + diff --git a/worker/fbs/worker.fbs b/worker/fbs/worker.fbs new file mode 100644 index 0000000000..392598a732 --- /dev/null +++ b/worker/fbs/worker.fbs @@ -0,0 +1,57 @@ +include "transport.fbs"; + +namespace FBS.Worker; + +table ChannelMessageHandlers { + channel_request_handlers: [string] (required); + channel_notification_handlers: [string] (required); +} + +table DumpResponse { + pid: uint32; + web_rtc_server_ids: [string] (required); + router_ids: [string] (required); + channel_message_handlers: ChannelMessageHandlers (required); +} + +table ResourceUsageResponse { + ru_utime: uint64; + ru_stime: uint64; + ru_maxrss: uint64; + ru_ixrss: uint64; + ru_idrss: uint64; + ru_isrss: uint64; + ru_minflt: uint64; + ru_majflt: uint64; + ru_nswap: uint64; + ru_inblock: uint64; + ru_oublock: uint64; + ru_msgsnd: uint64; + ru_msgrcv: uint64; + ru_nsignals: uint64; + ru_nvcsw: uint64; + ru_nivcsw: uint64; +} + +table UpdateSettingsRequest { + log_level: string; + log_tags: [string]; +} + +table CreateWebRtcServerRequest { + web_rtc_server_id: string (required); + listen_infos: [FBS.Transport.ListenInfo]; +} + +table CloseWebRtcServerRequest { + web_rtc_server_id: string (required); +} + +table CreateRouterRequest { + router_id: string (required); +} + +table CloseRouterRequest { + router_id: string (required); +} + diff --git a/worker/include/Channel/ChannelNotification.hpp b/worker/include/Channel/ChannelNotification.hpp new file mode 100644 index 0000000000..2aa940656d --- /dev/null +++ b/worker/include/Channel/ChannelNotification.hpp @@ -0,0 +1,33 @@ +#ifndef MS_CHANNEL_NOTIFICATION_HPP +#define MS_CHANNEL_NOTIFICATION_HPP + +#include "common.hpp" +#include "FBS/notification.h" +#include +#include + +namespace Channel +{ + class ChannelNotification + { + public: + using Event = FBS::Notification::Event; + + private: + static absl::flat_hash_map event2String; + + public: + explicit ChannelNotification(const FBS::Notification::Notification* notification); + ~ChannelNotification() = default; + + public: + // Passed by argument. + Event event; + // Others. + const char* eventCStr; + std::string handlerId; + const FBS::Notification::Notification* data{ nullptr }; + }; +} // namespace Channel + +#endif diff --git a/worker/include/Channel/ChannelNotifier.hpp b/worker/include/Channel/ChannelNotifier.hpp index 5f3eabf5be..098b4366df 100644 --- a/worker/include/Channel/ChannelNotifier.hpp +++ b/worker/include/Channel/ChannelNotifier.hpp @@ -3,11 +3,8 @@ #include "common.hpp" #include "Channel/ChannelSocket.hpp" -#include #include -using json = nlohmann::json; - namespace Channel { class ChannelNotifier @@ -16,14 +13,50 @@ namespace Channel explicit ChannelNotifier(Channel::ChannelSocket* channel); public: - void Emit(uint64_t targetId, const char* event); - void Emit(const std::string& targetId, const char* event); - void Emit(const std::string& targetId, const char* event, json& data); - void Emit(const std::string& targetId, const char* event, const std::string& data); + flatbuffers::FlatBufferBuilder& GetBufferBuilder() + { + return this->bufferBuilder; + } + + template + void Emit( + const std::string& targetId, + FBS::Notification::Event event, + FBS::Notification::Body type, + flatbuffers::Offset& body) + { + auto& builder = ChannelNotifier::bufferBuilder; + auto notification = FBS::Notification::CreateNotificationDirect( + builder, targetId.c_str(), event, type, body.Union()); + + auto message = + FBS::Message::CreateMessage(builder, FBS::Message::Body::Notification, notification.Union()); + + builder.FinishSizePrefixed(message); + this->channel->Send(builder.GetBufferPointer(), builder.GetSize()); + builder.Reset(); + } + + void Emit(const std::string& targetId, FBS::Notification::Event event) + { + auto& builder = ChannelNotifier::bufferBuilder; + auto notification = + FBS::Notification::CreateNotificationDirect(builder, targetId.c_str(), event); + + auto message = + FBS::Message::CreateMessage(builder, FBS::Message::Body::Notification, notification.Union()); + + builder.FinishSizePrefixed(message); + this->channel->Send(builder.GetBufferPointer(), builder.GetSize()); + builder.Reset(); + } + void Emit(const FBS::Notification::Notification& notification); private: // Passed by argument. Channel::ChannelSocket* channel{ nullptr }; + // Others. + flatbuffers::FlatBufferBuilder bufferBuilder{}; }; } // namespace Channel diff --git a/worker/include/Channel/ChannelRequest.hpp b/worker/include/Channel/ChannelRequest.hpp index 7381c94d7e..5ae484798e 100644 --- a/worker/include/Channel/ChannelRequest.hpp +++ b/worker/include/Channel/ChannelRequest.hpp @@ -2,12 +2,13 @@ #define MS_CHANNEL_REQUEST_HPP #include "common.hpp" +#include "FBS/message.h" +#include "FBS/request.h" +#include "FBS/response.h" +#include #include -#include #include -using json = nlohmann::json; - namespace Channel { // Avoid cyclic #include problem by declaring classes instead of including @@ -17,89 +18,54 @@ namespace Channel class ChannelRequest { public: - enum class MethodId - { - WORKER_CLOSE = 1, - WORKER_DUMP, - WORKER_GET_RESOURCE_USAGE, - WORKER_UPDATE_SETTINGS, - WORKER_CREATE_WEBRTC_SERVER, - WORKER_CREATE_ROUTER, - WORKER_WEBRTC_SERVER_CLOSE, - WEBRTC_SERVER_DUMP, - WORKER_CLOSE_ROUTER, - ROUTER_DUMP, - ROUTER_CREATE_WEBRTC_TRANSPORT, - ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER, - ROUTER_CREATE_PLAIN_TRANSPORT, - ROUTER_CREATE_PIPE_TRANSPORT, - ROUTER_CREATE_DIRECT_TRANSPORT, - ROUTER_CLOSE_TRANSPORT, - ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER, - ROUTER_CREATE_AUDIO_LEVEL_OBSERVER, - ROUTER_CLOSE_RTP_OBSERVER, - TRANSPORT_DUMP, - TRANSPORT_GET_STATS, - TRANSPORT_CONNECT, - TRANSPORT_SET_MAX_INCOMING_BITRATE, - TRANSPORT_SET_MAX_OUTGOING_BITRATE, - TRANSPORT_SET_MIN_OUTGOING_BITRATE, - TRANSPORT_RESTART_ICE, - TRANSPORT_PRODUCE, - TRANSPORT_CONSUME, - TRANSPORT_PRODUCE_DATA, - TRANSPORT_CONSUME_DATA, - TRANSPORT_ENABLE_TRACE_EVENT, - TRANSPORT_CLOSE_PRODUCER, - PRODUCER_DUMP, - PRODUCER_GET_STATS, - PRODUCER_PAUSE, - PRODUCER_RESUME, - PRODUCER_ENABLE_TRACE_EVENT, - TRANSPORT_CLOSE_CONSUMER, - CONSUMER_DUMP, - CONSUMER_GET_STATS, - CONSUMER_PAUSE, - CONSUMER_RESUME, - CONSUMER_SET_PREFERRED_LAYERS, - CONSUMER_SET_PRIORITY, - CONSUMER_REQUEST_KEY_FRAME, - CONSUMER_ENABLE_TRACE_EVENT, - TRANSPORT_CLOSE_DATA_PRODUCER, - DATA_PRODUCER_DUMP, - DATA_PRODUCER_GET_STATS, - TRANSPORT_CLOSE_DATA_CONSUMER, - DATA_CONSUMER_DUMP, - DATA_CONSUMER_GET_STATS, - DATA_CONSUMER_GET_BUFFERED_AMOUNT, - DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, - RTP_OBSERVER_PAUSE, - RTP_OBSERVER_RESUME, - RTP_OBSERVER_ADD_PRODUCER, - RTP_OBSERVER_REMOVE_PRODUCER - }; + using Method = FBS::Request::Method; - private: - static absl::flat_hash_map string2MethodId; + public: + static absl::flat_hash_map method2String; public: - ChannelRequest(Channel::ChannelSocket* channel, const char* msg, size_t msgLen); - virtual ~ChannelRequest(); + ChannelRequest(Channel::ChannelSocket* channel, const FBS::Request::Request* request); + ~ChannelRequest() = default; + flatbuffers::FlatBufferBuilder& GetBufferBuilder() + { + return this->bufferBuilder; + } void Accept(); - void Accept(json& data); + template + void Accept(FBS::Response::Body type, flatbuffers::Offset& body) + { + assert(!this->replied); + + this->replied = true; + + auto& builder = this->bufferBuilder; + auto response = FBS::Response::CreateResponse(builder, this->id, true, type, body.Union()); + + auto message = + FBS::Message::CreateMessage(builder, FBS::Message::Body::Response, response.Union()); + + builder.FinishSizePrefixed(message); + this->Send(builder.GetBufferPointer(), builder.GetSize()); + builder.Reset(); + } void Error(const char* reason = nullptr); void TypeError(const char* reason = nullptr); + private: + void Send(uint8_t* buffer, size_t size); + void SendResponse(const flatbuffers::Offset& response); + public: // Passed by argument. Channel::ChannelSocket* channel{ nullptr }; + const FBS::Request::Request* data{ nullptr }; + // Others. + flatbuffers::FlatBufferBuilder bufferBuilder{}; uint32_t id{ 0u }; - std::string method; - MethodId methodId; + Method method; + const char* methodCStr; std::string handlerId; - json data; - // Others. bool replied{ false }; }; } // namespace Channel diff --git a/worker/include/Channel/ChannelSocket.hpp b/worker/include/Channel/ChannelSocket.hpp index fdc98b8e7e..188ec03abb 100644 --- a/worker/include/Channel/ChannelSocket.hpp +++ b/worker/include/Channel/ChannelSocket.hpp @@ -2,16 +2,14 @@ #define MS_CHANNEL_SOCKET_HPP #include "common.hpp" +#include "Channel/ChannelNotification.hpp" #include "Channel/ChannelRequest.hpp" -#include "handles/UnixStreamSocket.hpp" -#include +#include "handles/UnixStreamSocketHandle.hpp" #include -using json = nlohmann::json; - namespace Channel { - class ConsumerSocket : public ::UnixStreamSocket + class ConsumerSocket : public ::UnixStreamSocketHandle { public: class Listener @@ -28,7 +26,7 @@ namespace Channel ConsumerSocket(int fd, size_t bufferSize, Listener* listener); ~ConsumerSocket(); - /* Pure virtual methods inherited from ::UnixStreamSocket. */ + /* Pure virtual methods inherited from ::UnixStreamSocketHandle. */ public: void UserOnUnixStreamRead() override; void UserOnUnixStreamSocketClosed() override; @@ -38,12 +36,12 @@ namespace Channel Listener* listener{ nullptr }; }; - class ProducerSocket : public ::UnixStreamSocket + class ProducerSocket : public ::UnixStreamSocketHandle { public: ProducerSocket(int fd, size_t bufferSize); - /* Pure virtual methods inherited from ::UnixStreamSocket. */ + /* Pure virtual methods inherited from ::UnixStreamSocketHandle. */ public: void UserOnUnixStreamRead() override { @@ -65,7 +63,16 @@ namespace Channel virtual void HandleRequest(Channel::ChannelRequest* request) = 0; }; - class Listener : public RequestHandler + class NotificationHandler + { + public: + virtual ~NotificationHandler() = default; + + public: + virtual void HandleNotification(Channel::ChannelNotification* notification) = 0; + }; + + class Listener : public RequestHandler, public NotificationHandler { public: virtual ~Listener() = default; @@ -86,8 +93,7 @@ namespace Channel public: void Close(); void SetListener(Listener* listener); - void Send(json& jsonMessage); - void Send(const std::string& message); + void Send(const uint8_t* message, uint32_t messageLen); void SendLog(const char* message, uint32_t messageLen); bool CallbackRead(); @@ -111,7 +117,7 @@ namespace Channel ChannelWriteFn channelWriteFn{ nullptr }; ChannelWriteCtx channelWriteCtx{ nullptr }; uv_async_t* uvReadHandle{ nullptr }; - uint8_t* writeBuffer{ nullptr }; + flatbuffers::FlatBufferBuilder bufferBuilder{}; }; } // namespace Channel diff --git a/worker/include/ChannelMessageRegistrator.hpp b/worker/include/ChannelMessageRegistrator.hpp index f01300a658..f27e708ff1 100644 --- a/worker/include/ChannelMessageRegistrator.hpp +++ b/worker/include/ChannelMessageRegistrator.hpp @@ -3,9 +3,7 @@ #include "common.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include -#include #include class ChannelMessageRegistrator @@ -15,25 +13,19 @@ class ChannelMessageRegistrator ~ChannelMessageRegistrator(); public: - void FillJson(json& jsonObject); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder); void RegisterHandler( const std::string& id, Channel::ChannelSocket::RequestHandler* channelRequestHandler, - PayloadChannel::PayloadChannelSocket::RequestHandler* payloadChannelRequestHandler, - PayloadChannel::PayloadChannelSocket::NotificationHandler* payloadChannelNotificationHandler); + Channel::ChannelSocket::NotificationHandler* channelNotificationHandler); void UnregisterHandler(const std::string& id); Channel::ChannelSocket::RequestHandler* GetChannelRequestHandler(const std::string& id); - PayloadChannel::PayloadChannelSocket::RequestHandler* GetPayloadChannelRequestHandler( - const std::string& id); - PayloadChannel::PayloadChannelSocket::NotificationHandler* GetPayloadChannelNotificationHandler( - const std::string& id); + Channel::ChannelSocket::NotificationHandler* GetChannelNotificationHandler(const std::string& id); private: absl::flat_hash_map mapChannelRequestHandlers; - absl::flat_hash_map - mapPayloadChannelRequestHandlers; - absl::flat_hash_map - mapPayloadChannelNotificationHandlers; + absl::flat_hash_map mapChannelNotificationHandlers; }; #endif diff --git a/worker/include/DepUsrSCTP.hpp b/worker/include/DepUsrSCTP.hpp index b7df08620b..122cb63c47 100644 --- a/worker/include/DepUsrSCTP.hpp +++ b/worker/include/DepUsrSCTP.hpp @@ -3,13 +3,13 @@ #include "common.hpp" #include "RTC/SctpAssociation.hpp" -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include class DepUsrSCTP { private: - class Checker : public Timer::Listener + class Checker : public TimerHandle::Listener { public: Checker(); @@ -19,12 +19,12 @@ class DepUsrSCTP void Start(); void Stop(); - /* Pure virtual methods inherited from Timer::Listener. */ + /* Pure virtual methods inherited from TimerHandle::Listener. */ public: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; private: - Timer* timer{ nullptr }; + TimerHandle* timer{ nullptr }; uint64_t lastCalledAtMs{ 0u }; }; diff --git a/worker/include/PayloadChannel/PayloadChannelNotification.hpp b/worker/include/PayloadChannel/PayloadChannelNotification.hpp deleted file mode 100644 index 5f4f3c2f86..0000000000 --- a/worker/include/PayloadChannel/PayloadChannelNotification.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef MS_PAYLOAD_CHANNEL_NOTIFICATION_HPP -#define MS_PAYLOAD_CHANNEL_NOTIFICATION_HPP - -#include "common.hpp" -#include -#include - -namespace PayloadChannel -{ - class PayloadChannelNotification - { - public: - enum class EventId - { - TRANSPORT_SEND_RTCP = 1, - PRODUCER_SEND, - DATA_PRODUCER_SEND - }; - - public: - static bool IsNotification(const char* msg, size_t msgLen); - - private: - static absl::flat_hash_map string2EventId; - - public: - PayloadChannelNotification(const char* msg, size_t msgLen); - virtual ~PayloadChannelNotification(); - - public: - void SetPayload(const uint8_t* payload, size_t payloadLen); - - public: - // Passed by argument. - std::string event; - EventId eventId; - std::string handlerId; - std::string data; - const uint8_t* payload{ nullptr }; - size_t payloadLen{ 0u }; - }; -} // namespace PayloadChannel - -#endif diff --git a/worker/include/PayloadChannel/PayloadChannelNotifier.hpp b/worker/include/PayloadChannel/PayloadChannelNotifier.hpp deleted file mode 100644 index c7df84a484..0000000000 --- a/worker/include/PayloadChannel/PayloadChannelNotifier.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef MS_PAYLOAD_CHANNEL_NOTIFIER_HPP -#define MS_PAYLOAD_CHANNEL_NOTIFIER_HPP - -#include "common.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" -#include -#include - -using json = nlohmann::json; - -namespace PayloadChannel -{ - class PayloadChannelNotifier - { - public: - explicit PayloadChannelNotifier(PayloadChannel::PayloadChannelSocket* payloadChannel); - - public: - void Emit(const std::string& targetId, const char* event, const uint8_t* payload, size_t payloadLen); - void Emit( - const std::string& targetId, - const char* event, - json& data, - const uint8_t* payload, - size_t payloadLen); - void Emit( - const std::string& targetId, - const char* event, - const std::string& data, - const uint8_t* payload, - size_t payloadLen); - - private: - // Passed by argument. - PayloadChannel::PayloadChannelSocket* payloadChannel{ nullptr }; - }; -} // namespace PayloadChannel - -#endif diff --git a/worker/include/PayloadChannel/PayloadChannelRequest.hpp b/worker/include/PayloadChannel/PayloadChannelRequest.hpp deleted file mode 100644 index 0ae60fec3b..0000000000 --- a/worker/include/PayloadChannel/PayloadChannelRequest.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef MS_PAYLOAD_CHANNEL_REQUEST_HPP -#define MS_PAYLOAD_CHANNEL_REQUEST_HPP - -#include "common.hpp" -#include -#include -#include - -using json = nlohmann::json; - -namespace PayloadChannel -{ - // Avoid cyclic #include problem by declaring classes instead of including - // the corresponding header files. - class PayloadChannelSocket; - - class PayloadChannelRequest - { - public: - enum class MethodId - { - DATA_CONSUMER_SEND - }; - - public: - static bool IsRequest(const char* msg, size_t msgLen); - - private: - static absl::flat_hash_map string2MethodId; - - public: - PayloadChannelRequest(PayloadChannel::PayloadChannelSocket* channel, char* msg, size_t msgLen); - virtual ~PayloadChannelRequest(); - - public: - void Accept(); - void Accept(json& data); - void Error(const char* reason = nullptr); - void TypeError(const char* reason = nullptr); - void SetPayload(const uint8_t* payload, size_t payloadLen); - - public: - // Passed by argument. - PayloadChannel::PayloadChannelSocket* channel{ nullptr }; - uint32_t id{ 0u }; - std::string method; - MethodId methodId; - std::string handlerId; - std::string data; - const uint8_t* payload{ nullptr }; - size_t payloadLen{ 0u }; - // Others. - bool replied{ false }; - }; -} // namespace PayloadChannel - -#endif diff --git a/worker/include/PayloadChannel/PayloadChannelSocket.hpp b/worker/include/PayloadChannel/PayloadChannelSocket.hpp deleted file mode 100644 index 4191706246..0000000000 --- a/worker/include/PayloadChannel/PayloadChannelSocket.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef MS_PAYLOAD_CHANNEL_SOCKET_HPP -#define MS_PAYLOAD_CHANNEL_SOCKET_HPP - -#include "common.hpp" -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include "handles/UnixStreamSocket.hpp" -#include -#include - -using json = nlohmann::json; - -namespace PayloadChannel -{ - class ConsumerSocket : public ::UnixStreamSocket - { - public: - class Listener - { - public: - virtual ~Listener() = default; - - public: - virtual void OnConsumerSocketMessage(ConsumerSocket* consumerSocket, char* msg, size_t msgLen) = 0; - virtual void OnConsumerSocketClosed(ConsumerSocket* consumerSocket) = 0; - }; - - public: - ConsumerSocket(int fd, size_t bufferSize, Listener* listener); - ~ConsumerSocket(); - - /* Pure virtual methods inherited from ::UnixStreamSocket. */ - public: - void UserOnUnixStreamRead() override; - void UserOnUnixStreamSocketClosed() override; - - private: - // Passed by argument. - Listener* listener{ nullptr }; - }; - - class ProducerSocket : public ::UnixStreamSocket - { - public: - ProducerSocket(int fd, size_t bufferSize); - - /* Pure virtual methods inherited from ::UnixStreamSocket. */ - public: - void UserOnUnixStreamRead() override - { - } - void UserOnUnixStreamSocketClosed() override - { - } - }; - - class PayloadChannelSocket : public ConsumerSocket::Listener - { - public: - class RequestHandler - { - public: - virtual ~RequestHandler() = default; - - public: - virtual void HandleRequest(PayloadChannel::PayloadChannelRequest* request) = 0; - }; - - class NotificationHandler - { - public: - virtual ~NotificationHandler() = default; - - public: - virtual void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) = 0; - }; - - class Listener : public RequestHandler, public NotificationHandler - { - public: - virtual ~Listener() = default; - - public: - virtual void OnPayloadChannelClosed(PayloadChannel::PayloadChannelSocket* payloadChannel) = 0; - }; - - public: - explicit PayloadChannelSocket(int consumerFd, int producerFd); - explicit PayloadChannelSocket( - PayloadChannelReadFn payloadChannelReadFn, - PayloadChannelReadCtx payloadChannelReadCtx, - PayloadChannelWriteFn payloadChannelWriteFn, - PayloadChannelWriteCtx payloadChannelWriteCtx); - virtual ~PayloadChannelSocket(); - - public: - void Close(); - void SetListener(Listener* listener); - void Send(json& jsonMessage, const uint8_t* payload, size_t payloadLen); - void Send(const std::string& message, const uint8_t* payload, size_t payloadLen); - void Send(json& jsonMessage); - void Send(const std::string& message); - bool CallbackRead(); - - private: - void SendImpl(const uint8_t* message, uint32_t messageLen); - void SendImpl( - const uint8_t* message, uint32_t messageLen, const uint8_t* payload, uint32_t payloadLen); - - /* Pure virtual methods inherited from ConsumerSocket::Listener. */ - public: - void OnConsumerSocketMessage(ConsumerSocket* consumerSocket, char* msg, size_t msgLen) override; - void OnConsumerSocketClosed(ConsumerSocket* consumerSocket) override; - - private: - // Passed by argument. - Listener* listener{ nullptr }; - // Others. - bool closed{ false }; - ConsumerSocket* consumerSocket{ nullptr }; - ProducerSocket* producerSocket{ nullptr }; - PayloadChannelReadFn payloadChannelReadFn{ nullptr }; - PayloadChannelReadCtx payloadChannelReadCtx{ nullptr }; - PayloadChannelWriteFn payloadChannelWriteFn{ nullptr }; - PayloadChannelWriteCtx payloadChannelWriteCtx{ nullptr }; - PayloadChannel::PayloadChannelNotification* ongoingNotification{ nullptr }; - PayloadChannel::PayloadChannelRequest* ongoingRequest{ nullptr }; - uv_async_t* uvReadHandle{ nullptr }; - uint8_t* writeBuffer{ nullptr }; - }; -} // namespace PayloadChannel - -#endif diff --git a/worker/include/RTC/ActiveSpeakerObserver.hpp b/worker/include/RTC/ActiveSpeakerObserver.hpp index cf4be62223..556e6c0e02 100644 --- a/worker/include/RTC/ActiveSpeakerObserver.hpp +++ b/worker/include/RTC/ActiveSpeakerObserver.hpp @@ -3,9 +3,8 @@ #include "RTC/RtpObserver.hpp" #include "RTC/Shared.hpp" -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include -#include #include #include @@ -16,7 +15,7 @@ // https://github.com/jitsi/jitsi-utils/blob/master/src/main/java/org/jitsi/utils/dsi/DominantSpeakerIdentification.java namespace RTC { - class ActiveSpeakerObserver : public RTC::RtpObserver, public Timer::Listener + class ActiveSpeakerObserver : public RTC::RtpObserver, public TimerHandle::Listener { private: class Speaker @@ -71,7 +70,10 @@ namespace RTC public: ActiveSpeakerObserver( - RTC::Shared* shared, const std::string& id, RTC::RtpObserver::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::RtpObserver::Listener* listener, + const FBS::ActiveSpeakerObserver::ActiveSpeakerObserverOptions* options); ~ActiveSpeakerObserver() override; public: @@ -88,14 +90,14 @@ namespace RTC bool CalculateActiveSpeaker(); void TimeoutIdleLevels(uint64_t now); - /* Pure virtual methods inherited from Timer. */ + /* Pure virtual methods inherited from TimerHandle. */ protected: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; private: double relativeSpeachActivities[RelativeSpeachActivitiesLen]; std::string dominantId; - Timer* periodicTimer{ nullptr }; + TimerHandle* periodicTimer{ nullptr }; uint16_t interval{ 300u }; // Map of ProducerSpeakers indexed by Producer id. absl::flat_hash_map mapProducerSpeakers; diff --git a/worker/include/RTC/AudioLevelObserver.hpp b/worker/include/RTC/AudioLevelObserver.hpp index c0007e7301..49b17dcaf8 100644 --- a/worker/include/RTC/AudioLevelObserver.hpp +++ b/worker/include/RTC/AudioLevelObserver.hpp @@ -3,15 +3,12 @@ #include "RTC/RtpObserver.hpp" #include "RTC/Shared.hpp" -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include -#include - -using json = nlohmann::json; namespace RTC { - class AudioLevelObserver : public RTC::RtpObserver, public Timer::Listener + class AudioLevelObserver : public RTC::RtpObserver, public TimerHandle::Listener { private: struct DBovs @@ -22,7 +19,10 @@ namespace RTC public: AudioLevelObserver( - RTC::Shared* shared, const std::string& id, RTC::RtpObserver::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::RtpObserver::Listener* listener, + const FBS::AudioLevelObserver::AudioLevelObserverOptions* options); ~AudioLevelObserver() override; public: @@ -38,9 +38,9 @@ namespace RTC void Update(); void ResetMapProducerDBovs(); - /* Pure virtual methods inherited from Timer. */ + /* Pure virtual methods inherited from TimerHandle. */ protected: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; private: // Passed by argument. @@ -48,7 +48,7 @@ namespace RTC int8_t threshold{ -80 }; uint16_t interval{ 1000u }; // Allocated by this. - Timer* periodicTimer{ nullptr }; + TimerHandle* periodicTimer{ nullptr }; // Others. absl::flat_hash_map mapProducerDBovs; bool silence{ true }; diff --git a/worker/include/RTC/Codecs/Tools.hpp b/worker/include/RTC/Codecs/Tools.hpp index 33c9d0768a..6604e2c86b 100644 --- a/worker/include/RTC/Codecs/Tools.hpp +++ b/worker/include/RTC/Codecs/Tools.hpp @@ -106,11 +106,6 @@ namespace RTC { switch (type) { - case RTC::RtpParameters::Type::NONE: - { - return false; - } - case RTC::RtpParameters::Type::SIMPLE: { return true; @@ -166,11 +161,6 @@ namespace RTC { return true; } - - default: - { - return false; - } } } diff --git a/worker/include/RTC/Consumer.hpp b/worker/include/RTC/Consumer.hpp index 20961ad340..8d3a25c95e 100644 --- a/worker/include/RTC/Consumer.hpp +++ b/worker/include/RTC/Consumer.hpp @@ -4,6 +4,7 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" +#include "FBS/consumer.h" #include "RTC/RTCP/CompoundPacket.hpp" #include "RTC/RTCP/FeedbackPs.hpp" #include "RTC/RTCP/FeedbackPsFir.hpp" @@ -18,12 +19,9 @@ #include "RTC/RtpStreamSend.hpp" #include "RTC/Shared.hpp" #include -#include #include #include -using json = nlohmann::json; - namespace RTC { class Consumer : public Channel::ChannelSocket::RequestHandler @@ -66,14 +64,20 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data, + const FBS::Transport::ConsumeRequest* data, RTC::RtpParameters::Type type); virtual ~Consumer(); public: - virtual void FillJson(json& jsonObject) const; - virtual void FillJsonStats(json& jsonArray) const = 0; - virtual void FillJsonScore(json& jsonObject) const = 0; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + virtual flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) = 0; + virtual flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const + { + return 0; + }; RTC::Media::Kind GetKind() const { return this->kind; @@ -167,6 +171,7 @@ namespace RTC void EmitTraceEventPliType(uint32_t ssrc) const; void EmitTraceEventFirType(uint32_t ssrc) const; void EmitTraceEventNackType() const; + void EmitTraceEvent(flatbuffers::Offset& notification) const; private: virtual void UserOnTransportConnected() = 0; @@ -185,7 +190,7 @@ namespace RTC RTC::Consumer::Listener* listener{ nullptr }; RTC::Media::Kind kind; RTC::RtpParameters rtpParameters; - RTC::RtpParameters::Type type{ RTC::RtpParameters::Type::NONE }; + RTC::RtpParameters::Type type; std::vector consumableRtpEncodings; struct RTC::RtpHeaderExtensionIds rtpHeaderExtensionIds; const std::vector* producerRtpStreamScores{ nullptr }; diff --git a/worker/include/RTC/DataConsumer.hpp b/worker/include/RTC/DataConsumer.hpp index 46d1f15629..f732726c83 100644 --- a/worker/include/RTC/DataConsumer.hpp +++ b/worker/include/RTC/DataConsumer.hpp @@ -4,11 +4,9 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include "RTC/SctpDictionaries.hpp" #include "RTC/Shared.hpp" -#include +#include #include namespace RTC @@ -17,8 +15,7 @@ namespace RTC // (this is to avoid circular dependencies). class SctpAssociation; - class DataConsumer : public Channel::ChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::RequestHandler + class DataConsumer : public Channel::ChannelSocket::RequestHandler { protected: using onQueuedCallback = const std::function; @@ -32,9 +29,9 @@ namespace RTC public: virtual void OnDataConsumerSendMessage( RTC::DataConsumer* dataConsumer, - uint32_t ppid, const uint8_t* msg, size_t len, + uint32_t ppid, onQueuedCallback* cb) = 0; virtual void OnDataConsumerDataProducerClosed(RTC::DataConsumer* dataConsumer) = 0; }; @@ -53,13 +50,15 @@ namespace RTC const std::string& dataProducerId, RTC::SctpAssociation* sctpAssociation, RTC::DataConsumer::Listener* listener, - json& data, + const FBS::Transport::ConsumeDataRequest* data, size_t maxMessageSize); virtual ~DataConsumer(); public: - void FillJson(json& jsonObject) const; - void FillJsonStats(json& jsonArray) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) const; Type GetType() const { return this->type; @@ -70,31 +69,47 @@ namespace RTC } bool IsActive() const { + // It's active it DataConsumer and DataProducer are not paused and the transport + // is connected. // clang-format off return ( this->transportConnected && (this->type == DataConsumer::Type::DIRECT || this->sctpAssociationConnected) && + !this->paused && + !this->dataProducerPaused && !this->dataProducerClosed ); // clang-format on } void TransportConnected(); void TransportDisconnected(); + bool IsPaused() const + { + return this->paused; + } + bool IsDataProducerPaused() const + { + return this->dataProducerPaused; + } + void DataProducerPaused(); + void DataProducerResumed(); void SctpAssociationConnected(); void SctpAssociationClosed(); void SctpAssociationBufferedAmount(uint32_t bufferedAmount); void SctpAssociationSendBufferFull(); void DataProducerClosed(); - void SendMessage(uint32_t ppid, const uint8_t* msg, size_t len, onQueuedCallback* = nullptr); + void SendMessage( + const uint8_t* msg, + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel, + onQueuedCallback* = nullptr); /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::RequestHandler. */ - public: - void HandleRequest(PayloadChannel::PayloadChannelRequest* request) override; - public: // Passed by argument. const std::string id; @@ -108,12 +123,14 @@ namespace RTC size_t maxMessageSize{ 0u }; // Others. Type type; - std::string typeString; RTC::SctpStreamParameters sctpStreamParameters; std::string label; std::string protocol; + absl::flat_hash_set subchannels; bool transportConnected{ false }; bool sctpAssociationConnected{ false }; + bool paused{ false }; + bool dataProducerPaused{ false }; bool dataProducerClosed{ false }; size_t messagesSent{ 0u }; size_t bytesSent{ 0u }; diff --git a/worker/include/RTC/DataProducer.hpp b/worker/include/RTC/DataProducer.hpp index 952cc0df9f..474ebb8214 100644 --- a/worker/include/RTC/DataProducer.hpp +++ b/worker/include/RTC/DataProducer.hpp @@ -4,17 +4,16 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include "RTC/RTCP/Packet.hpp" #include "RTC/SctpDictionaries.hpp" #include "RTC/Shared.hpp" -#include #include +#include namespace RTC { class DataProducer : public Channel::ChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::NotificationHandler + public Channel::ChannelSocket::NotificationHandler { public: class Listener @@ -25,7 +24,14 @@ namespace RTC public: virtual void OnDataProducerReceiveData(RTC::DataProducer* producer, size_t len) = 0; virtual void OnDataProducerMessageReceived( - RTC::DataProducer* dataProducer, uint32_t ppid, const uint8_t* msg, size_t len) = 0; + RTC::DataProducer* dataProducer, + const uint8_t* msg, + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel) = 0; + virtual void OnDataProducerPaused(RTC::DataProducer* dataProducer) = 0; + virtual void OnDataProducerResumed(RTC::DataProducer* dataProducer) = 0; }; public: @@ -41,12 +47,14 @@ namespace RTC const std::string& id, size_t maxMessageSize, RTC::DataProducer::Listener* listener, - json& data); + const FBS::Transport::ProduceDataRequest* data); virtual ~DataProducer(); public: - void FillJson(json& jsonObject) const; - void FillJsonStats(json& jsonArray) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) const; Type GetType() const { return this->type; @@ -55,15 +63,24 @@ namespace RTC { return this->sctpStreamParameters; } - void ReceiveMessage(uint32_t ppid, const uint8_t* msg, size_t len); + bool IsPaused() const + { + return this->paused; + } + void ReceiveMessage( + const uint8_t* msg, + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel); /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; public: // Passed by argument. @@ -76,10 +93,10 @@ namespace RTC RTC::DataProducer::Listener* listener{ nullptr }; // Others. Type type; - std::string typeString; RTC::SctpStreamParameters sctpStreamParameters; std::string label; std::string protocol; + bool paused{ false }; size_t messagesReceived{ 0u }; size_t bytesReceived{ 0u }; }; diff --git a/worker/include/RTC/DirectTransport.hpp b/worker/include/RTC/DirectTransport.hpp index 046ac8d0ce..7352f0ad75 100644 --- a/worker/include/RTC/DirectTransport.hpp +++ b/worker/include/RTC/DirectTransport.hpp @@ -10,12 +10,17 @@ namespace RTC { public: DirectTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::DirectTransport::DirectTransportOptions* options); ~DirectTransport() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; private: bool IsConnected() const override; @@ -27,9 +32,9 @@ namespace RTC void SendRtcpCompoundPacket(RTC::RTCP::CompoundPacket* packet) override; void SendMessage( RTC::DataConsumer* dataConsumer, - uint32_t ppid, const uint8_t* msg, size_t len, + uint32_t ppid, onQueuedCallback* cb = nullptr) override; void SendSctpData(const uint8_t* data, size_t len) override; void RecvStreamClosed(uint32_t ssrc) override; @@ -39,9 +44,9 @@ namespace RTC public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; }; } // namespace RTC diff --git a/worker/include/RTC/DtlsTransport.hpp b/worker/include/RTC/DtlsTransport.hpp index be0e0fdeb9..bb635ea42f 100644 --- a/worker/include/RTC/DtlsTransport.hpp +++ b/worker/include/RTC/DtlsTransport.hpp @@ -2,8 +2,9 @@ #define MS_RTC_DTLS_TRANSPORT_HPP #include "common.hpp" +#include "FBS/webRtcTransport.h" #include "RTC/SrtpSession.hpp" -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include #include #include @@ -13,7 +14,7 @@ namespace RTC { - class DtlsTransport : public Timer::Listener + class DtlsTransport : public TimerHandle::Listener { public: enum class DtlsState @@ -28,7 +29,6 @@ namespace RTC public: enum class Role { - NONE = 0, AUTO = 1, CLIENT, SERVER @@ -37,7 +37,6 @@ namespace RTC public: enum class FingerprintAlgorithm { - NONE = 0, SHA1 = 1, SHA224, SHA256, @@ -48,7 +47,7 @@ namespace RTC public: struct Fingerprint { - FingerprintAlgorithm algorithm{ FingerprintAlgorithm::NONE }; + FingerprintAlgorithm algorithm; std::string value; }; @@ -97,30 +96,11 @@ namespace RTC public: static void ClassInit(); static void ClassDestroy(); - static Role StringToRole(const std::string& role) - { - auto it = DtlsTransport::string2Role.find(role); - - if (it != DtlsTransport::string2Role.end()) - return it->second; - else - return DtlsTransport::Role::NONE; - } - static FingerprintAlgorithm GetFingerprintAlgorithm(const std::string& fingerprint) - { - auto it = DtlsTransport::string2FingerprintAlgorithm.find(fingerprint); - - if (it != DtlsTransport::string2FingerprintAlgorithm.end()) - return it->second; - else - return DtlsTransport::FingerprintAlgorithm::NONE; - } - static std::string& GetFingerprintAlgorithmString(FingerprintAlgorithm fingerprint) - { - auto it = DtlsTransport::fingerprintAlgorithm2String.find(fingerprint); - - return it->second; - } + static Role RoleFromFbs(FBS::WebRtcTransport::DtlsRole role); + static FBS::WebRtcTransport::DtlsRole RoleToFbs(Role role); + static FBS::WebRtcTransport::DtlsState StateToFbs(DtlsState state); + static FingerprintAlgorithm AlgorithmFromFbs(FBS::WebRtcTransport::FingerprintAlgorithm algorithm); + static FBS::WebRtcTransport::FingerprintAlgorithm AlgorithmToFbs(FingerprintAlgorithm algorithm); static bool IsDtls(const uint8_t* data, size_t len) { // clang-format off @@ -167,11 +147,13 @@ namespace RTC { return this->state; } - Role GetLocalRole() const + std::optional GetLocalRole() const { return this->localRole; } void SendApplicationData(const uint8_t* data, size_t len); + // This method must be public since it's called within an OpenSSL callback. + void SendDtlsData(const uint8_t* data, size_t len); private: bool IsRunning() const @@ -193,20 +175,19 @@ namespace RTC } void Reset(); bool CheckStatus(int returnCode); - void SendPendingOutgoingDtlsData(); bool SetTimeout(); bool ProcessHandshake(); bool CheckRemoteFingerprint(); void ExtractSrtpKeys(RTC::SrtpSession::CryptoSuite srtpCryptoSuite); - RTC::SrtpSession::CryptoSuite GetNegotiatedSrtpCryptoSuite(); + std::optional GetNegotiatedSrtpCryptoSuite(); /* Callbacks fired by OpenSSL events. */ public: void OnSslInfo(int where, int ret); - /* Pure virtual methods inherited from Timer::Listener. */ + /* Pure virtual methods inherited from TimerHandle::Listener. */ public: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; private: // Passed by argument. @@ -215,11 +196,11 @@ namespace RTC SSL* ssl{ nullptr }; BIO* sslBioFromNetwork{ nullptr }; // The BIO from which ssl reads. BIO* sslBioToNetwork{ nullptr }; // The BIO in which ssl writes. - Timer* timer{ nullptr }; + TimerHandle* timer{ nullptr }; // Others. DtlsState state{ DtlsState::NEW }; - Role localRole{ Role::NONE }; - Fingerprint remoteFingerprint; + std::optional localRole; + std::optional remoteFingerprint; bool handshakeDone{ false }; bool handshakeDoneNow{ false }; std::string remoteCert; diff --git a/worker/include/RTC/IceCandidate.hpp b/worker/include/RTC/IceCandidate.hpp index 7b684365a0..3993b9bef1 100644 --- a/worker/include/RTC/IceCandidate.hpp +++ b/worker/include/RTC/IceCandidate.hpp @@ -2,23 +2,18 @@ #define MS_RTC_ICE_CANDIDATE_HPP #include "common.hpp" +#include "FBS/webRtcTransport.h" #include "RTC/TcpServer.hpp" +#include "RTC/TransportTuple.hpp" #include "RTC/UdpSocket.hpp" -#include +#include #include -using json = nlohmann::json; - namespace RTC { class IceCandidate { - public: - enum class Protocol - { - UDP = 1, - TCP - }; + using Protocol = TransportTuple::Protocol; public: enum class CandidateType @@ -32,6 +27,12 @@ namespace RTC PASSIVE = 1 }; + public: + static CandidateType CandidateTypeFromFbs(FBS::WebRtcTransport::IceCandidateType type); + static FBS::WebRtcTransport::IceCandidateType CandidateTypeToFbs(CandidateType type); + static TcpCandidateType TcpCandidateTypeFromFbs(FBS::WebRtcTransport::IceCandidateTcpType type); + static FBS::WebRtcTransport::IceCandidateTcpType TcpCandidateTypeToFbs(TcpCandidateType type); + public: IceCandidate(RTC::UdpSocket* udpSocket, uint32_t priority) : foundation("udpcandidate"), priority(priority), ip(udpSocket->GetLocalIp()), @@ -59,7 +60,8 @@ namespace RTC { } - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; private: // Others. diff --git a/worker/include/RTC/IceServer.hpp b/worker/include/RTC/IceServer.hpp index b213189ff5..bde22a4642 100644 --- a/worker/include/RTC/IceServer.hpp +++ b/worker/include/RTC/IceServer.hpp @@ -2,6 +2,7 @@ #define MS_RTC_ICE_SERVER_HPP #include "common.hpp" +#include "FBS/webRtcTransport.h" #include "RTC/StunPacket.hpp" #include "RTC/TransportTuple.hpp" #include @@ -17,9 +18,13 @@ namespace RTC NEW = 1, CONNECTED, COMPLETED, - DISCONNECTED + DISCONNECTED, }; + public: + static IceState RoleFromFbs(FBS::WebRtcTransport::IceState state); + static FBS::WebRtcTransport::IceState IceStateToFbs(IceState state); + public: class Listener { diff --git a/worker/include/RTC/KeyFrameRequestManager.hpp b/worker/include/RTC/KeyFrameRequestManager.hpp index d3d52c6b34..e56482c2a6 100644 --- a/worker/include/RTC/KeyFrameRequestManager.hpp +++ b/worker/include/RTC/KeyFrameRequestManager.hpp @@ -1,12 +1,12 @@ #ifndef MS_KEY_FRAME_REQUEST_MANAGER_HPP #define MS_KEY_FRAME_REQUEST_MANAGER_HPP -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include namespace RTC { - class PendingKeyFrameInfo : public Timer::Listener + class PendingKeyFrameInfo : public TimerHandle::Listener { public: class Listener @@ -39,18 +39,18 @@ namespace RTC return this->timer->Restart(); } - /* Pure virtual methods inherited from Timer::Listener. */ + /* Pure virtual methods inherited from TimerHandle::Listener. */ public: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; private: Listener* listener{ nullptr }; uint32_t ssrc; - Timer* timer{ nullptr }; + TimerHandle* timer{ nullptr }; bool retryOnTimeout{ true }; }; - class KeyFrameRequestDelayer : public Timer::Listener + class KeyFrameRequestDelayer : public TimerHandle::Listener { public: class Listener @@ -79,14 +79,14 @@ namespace RTC this->keyFrameRequested = flag; } - /* Pure virtual methods inherited from Timer::Listener. */ + /* Pure virtual methods inherited from TimerHandle::Listener. */ public: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; private: Listener* listener{ nullptr }; uint32_t ssrc; - Timer* timer{ nullptr }; + TimerHandle* timer{ nullptr }; bool keyFrameRequested{ false }; }; diff --git a/worker/include/RTC/NackGenerator.hpp b/worker/include/RTC/NackGenerator.hpp index f7924f6bd0..3195267729 100644 --- a/worker/include/RTC/NackGenerator.hpp +++ b/worker/include/RTC/NackGenerator.hpp @@ -4,7 +4,7 @@ #include "common.hpp" #include "RTC/RtpPacket.hpp" #include "RTC/SeqManager.hpp" -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include #include #include @@ -13,7 +13,7 @@ namespace RTC { - class NackGenerator : public Timer::Listener + class NackGenerator : public TimerHandle::Listener { public: class Listener @@ -69,16 +69,16 @@ namespace RTC std::vector GetNackBatch(NackFilter filter); void MayRunTimer() const; - /* Pure virtual methods inherited from Timer::Listener. */ + /* Pure virtual methods inherited from TimerHandle::Listener. */ public: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; private: // Passed by argument. Listener* listener{ nullptr }; unsigned int sendNackDelayMs{ 0u }; // Allocated by this. - Timer* timer{ nullptr }; + TimerHandle* timer{ nullptr }; // Others. absl::btree_map::SeqLowerThan> nackList; absl::btree_set::SeqLowerThan> keyFrameList; diff --git a/worker/include/RTC/Parameters.hpp b/worker/include/RTC/Parameters.hpp index eb7cd8f188..0bbd89cde6 100644 --- a/worker/include/RTC/Parameters.hpp +++ b/worker/include/RTC/Parameters.hpp @@ -2,13 +2,11 @@ #define MS_RTC_PARAMETERS_HPP #include "common.hpp" +#include "FBS/rtpParameters.h" #include -#include #include #include -using json = nlohmann::json; - namespace RTC { class Parameters @@ -62,8 +60,9 @@ namespace RTC }; public: - void FillJson(json& jsonObject) const; - void Set(json& data); + std::vector> FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + void Set(const flatbuffers::Vector>* data); bool HasBoolean(const std::string& key) const; bool HasInteger(const std::string& key) const; bool HasPositiveInteger(const std::string& key) const; diff --git a/worker/include/RTC/PipeConsumer.hpp b/worker/include/RTC/PipeConsumer.hpp index 924a3015f6..39066f4140 100644 --- a/worker/include/RTC/PipeConsumer.hpp +++ b/worker/include/RTC/PipeConsumer.hpp @@ -1,5 +1,5 @@ -#ifndef MS_RTC_PIPE_CONSUMER_HPP -#define MS_RTC_PIPE_CONSUMER_HPP +#ifndef MS_RTC_PIPECONSUMER_HPP +#define MS_RTC_PIPECONSUMER_HPP #include "RTC/Consumer.hpp" #include "RTC/SeqManager.hpp" @@ -15,13 +15,16 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data); + const FBS::Transport::ConsumeRequest* data); ~PipeConsumer() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) const override; - void FillJsonScore(json& jsonObject) const override; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; + flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const override; void ProducerRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; void ProducerNewRtpStream(RTC::RtpStreamRecv* rtpStream, uint32_t mappedSsrc) override; void ProducerRtpStreamScore( diff --git a/worker/include/RTC/PipeTransport.hpp b/worker/include/RTC/PipeTransport.hpp index 2f0b9c39eb..1c08492a42 100644 --- a/worker/include/RTC/PipeTransport.hpp +++ b/worker/include/RTC/PipeTransport.hpp @@ -1,6 +1,7 @@ #ifndef MS_RTC_PIPE_TRANSPORT_HPP #define MS_RTC_PIPE_TRANSPORT_HPP +#include "FBS/pipeTransport.h" #include "RTC/Shared.hpp" #include "RTC/SrtpSession.hpp" #include "RTC/Transport.hpp" @@ -11,13 +12,6 @@ namespace RTC { class PipeTransport : public RTC::Transport, public RTC::UdpSocket::Listener { - private: - struct ListenIp - { - std::string ip; - std::string announcedIp; - }; - private: static RTC::SrtpSession::CryptoSuite srtpCryptoSuite; static std::string srtpCryptoSuiteString; @@ -25,20 +19,25 @@ namespace RTC public: PipeTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::PipeTransport::PipeTransportOptions* options); ~PipeTransport() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; private: bool IsConnected() const override; @@ -51,9 +50,9 @@ namespace RTC void SendRtcpCompoundPacket(RTC::RTCP::CompoundPacket* packet) override; void SendMessage( RTC::DataConsumer* dataConsumer, - uint32_t ppid, const uint8_t* msg, size_t len, + uint32_t ppid, onQueuedCallback* cb = nullptr) override; void SendSctpData(const uint8_t* data, size_t len) override; void RecvStreamClosed(uint32_t ssrc) override; @@ -75,7 +74,7 @@ namespace RTC RTC::SrtpSession* srtpRecvSession{ nullptr }; RTC::SrtpSession* srtpSendSession{ nullptr }; // Others. - ListenIp listenIp; + ListenInfo listenInfo; struct sockaddr_storage remoteAddrStorage; bool rtx{ false }; std::string srtpKey; diff --git a/worker/include/RTC/PlainTransport.hpp b/worker/include/RTC/PlainTransport.hpp index 2df62205d1..ad9783618f 100644 --- a/worker/include/RTC/PlainTransport.hpp +++ b/worker/include/RTC/PlainTransport.hpp @@ -1,6 +1,7 @@ #ifndef MS_RTC_PLAIN_TRANSPORT_HPP #define MS_RTC_PLAIN_TRANSPORT_HPP +#include "FBS/plainTransport.h" #include "RTC/Shared.hpp" #include "RTC/SrtpSession.hpp" #include "RTC/Transport.hpp" @@ -12,33 +13,24 @@ namespace RTC { class PlainTransport : public RTC::Transport, public RTC::UdpSocket::Listener { - private: - struct ListenIp - { - std::string ip; - std::string announcedIp; - }; - - private: - static absl::flat_hash_map string2SrtpCryptoSuite; - static absl::flat_hash_map srtpCryptoSuite2String; - public: PlainTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::PlainTransport::PlainTransportOptions* options); ~PlainTransport() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; - - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ - public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; private: bool IsConnected() const override; @@ -52,9 +44,9 @@ namespace RTC void SendRtcpCompoundPacket(RTC::RTCP::CompoundPacket* packet) override; void SendMessage( RTC::DataConsumer* dataConsumer, - uint32_t ppid, const uint8_t* msg, size_t len, + uint32_t ppid, onQueuedCallback* cb = nullptr) override; void SendSctpData(const uint8_t* data, size_t len) override; void RecvStreamClosed(uint32_t ssrc) override; @@ -63,6 +55,8 @@ namespace RTC void OnRtpDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnRtcpDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnSctpDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); + void EmitTuple() const; + void EmitRtcpTuple() const; /* Pure virtual methods inherited from RTC::UdpSocket::Listener. */ public: @@ -78,7 +72,8 @@ namespace RTC RTC::SrtpSession* srtpRecvSession{ nullptr }; RTC::SrtpSession* srtpSendSession{ nullptr }; // Others. - ListenIp listenIp; + ListenInfo listenInfo; + ListenInfo rtcpListenInfo; bool rtcpMux{ true }; bool comedia{ false }; struct sockaddr_storage remoteAddrStorage; diff --git a/worker/include/RTC/PortManager.hpp b/worker/include/RTC/PortManager.hpp index ca925ef46f..4300548385 100644 --- a/worker/include/RTC/PortManager.hpp +++ b/worker/include/RTC/PortManager.hpp @@ -5,7 +5,6 @@ #include "Settings.hpp" #include #include -#include #include #include @@ -45,7 +44,6 @@ namespace RTC { return Unbind(Transport::TCP, ip, port); } - static void FillJson(json& jsonObject); private: static uv_handle_t* Bind(Transport transport, std::string& ip); diff --git a/worker/include/RTC/Producer.hpp b/worker/include/RTC/Producer.hpp index 46ceeceb9a..59e7ddab00 100644 --- a/worker/include/RTC/Producer.hpp +++ b/worker/include/RTC/Producer.hpp @@ -4,7 +4,6 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include "RTC/KeyFrameRequestManager.hpp" #include "RTC/RTCP/CompoundPacket.hpp" #include "RTC/RTCP/Packet.hpp" @@ -15,18 +14,15 @@ #include "RTC/RtpPacket.hpp" #include "RTC/RtpStreamRecv.hpp" #include "RTC/Shared.hpp" -#include #include #include -using json = nlohmann::json; - namespace RTC { class Producer : public RTC::RtpStreamRecv::Listener, public RTC::KeyFrameRequestManager::Listener, public Channel::ChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::NotificationHandler + public Channel::ChannelSocket::NotificationHandler { public: class Listener @@ -96,12 +92,18 @@ namespace RTC }; public: - Producer(RTC::Shared* shared, const std::string& id, RTC::Producer::Listener* listener, json& data); + Producer( + RTC::Shared* shared, + const std::string& id, + RTC::Producer::Listener* listener, + const FBS::Transport::ProduceRequest* data); virtual ~Producer(); public: - void FillJson(json& jsonObject) const; - void FillJsonStats(json& jsonArray) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); RTC::Media::Kind GetKind() const { return this->kind; @@ -140,9 +142,9 @@ namespace RTC public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; private: RTC::RtpStreamRecv* GetRtpStream(RTC::RtpPacket* packet); @@ -158,6 +160,7 @@ namespace RTC void EmitTraceEventPliType(uint32_t ssrc) const; void EmitTraceEventFirType(uint32_t ssrc) const; void EmitTraceEventNackType() const; + void EmitTraceEvent(flatbuffers::Offset& notification) const; /* Pure virtual methods inherited from RTC::RtpStreamRecv::Listener. */ public: @@ -184,7 +187,7 @@ namespace RTC // Others. RTC::Media::Kind kind; RTC::RtpParameters rtpParameters; - RTC::RtpParameters::Type type{ RTC::RtpParameters::Type::NONE }; + RTC::RtpParameters::Type type; struct RtpMapping rtpMapping; std::vector rtpStreamByEncodingIdx; std::vector rtpStreamScores; diff --git a/worker/include/RTC/Router.hpp b/worker/include/RTC/Router.hpp index 4ab7a8e6b2..46b96f7d65 100644 --- a/worker/include/RTC/Router.hpp +++ b/worker/include/RTC/Router.hpp @@ -2,9 +2,8 @@ #define MS_RTC_ROUTER_HPP #include "common.hpp" +#include "Channel/ChannelNotification.hpp" #include "Channel/ChannelRequest.hpp" -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" #include "RTC/Consumer.hpp" #include "RTC/DataConsumer.hpp" #include "RTC/DataProducer.hpp" @@ -16,11 +15,9 @@ #include "RTC/Transport.hpp" #include "RTC/WebRtcServer.hpp" #include -#include +#include #include -#include - -using json = nlohmann::json; +#include namespace RTC { @@ -44,17 +41,18 @@ namespace RTC virtual ~Router(); public: - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; private: - void SetNewTransportIdFromData(json& data, std::string& transportId) const; - RTC::Transport* GetTransportFromData(json& data) const; - void SetNewRtpObserverIdFromData(json& data, std::string& rtpObserverId) const; - RTC::RtpObserver* GetRtpObserverFromData(json& data) const; + RTC::Transport* GetTransportById(const std::string& transportId) const; + RTC::RtpObserver* GetRtpObserverById(const std::string& rtpObserverId) const; + void CheckNoTransport(const std::string& transportId) const; + void CheckNoRtpObserver(const std::string& rtpObserverId) const; /* Pure virtual methods inherited from RTC::Transport::Listener. */ public: @@ -86,19 +84,24 @@ namespace RTC uint32_t mappedSsrc, uint8_t& worstRemoteFractionLost) override; void OnTransportNewConsumer( - RTC::Transport* transport, RTC::Consumer* consumer, std::string& producerId) override; + RTC::Transport* transport, RTC::Consumer* consumer, const std::string& producerId) override; void OnTransportConsumerClosed(RTC::Transport* transport, RTC::Consumer* consumer) override; void OnTransportConsumerProducerClosed(RTC::Transport* transport, RTC::Consumer* consumer) override; void OnTransportConsumerKeyFrameRequested( RTC::Transport* transport, RTC::Consumer* consumer, uint32_t mappedSsrc) override; void OnTransportNewDataProducer(RTC::Transport* transport, RTC::DataProducer* dataProducer) override; void OnTransportDataProducerClosed(RTC::Transport* transport, RTC::DataProducer* dataProducer) override; + void OnTransportDataProducerPaused(RTC::Transport* transport, RTC::DataProducer* dataProducer) override; + void OnTransportDataProducerResumed( + RTC::Transport* transport, RTC::DataProducer* dataProducer) override; void OnTransportDataProducerMessageReceived( RTC::Transport* transport, RTC::DataProducer* dataProducer, - uint32_t ppid, const uint8_t* msg, - size_t len) override; + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel) override; void OnTransportNewDataConsumer( RTC::Transport* transport, RTC::DataConsumer* dataConsumer, std::string& dataProducerId) override; void OnTransportDataConsumerClosed(RTC::Transport* transport, RTC::DataConsumer* dataConsumer) override; diff --git a/worker/include/RTC/RtpDictionaries.hpp b/worker/include/RTC/RtpDictionaries.hpp index 7cf12f2afa..caf3211f1a 100644 --- a/worker/include/RTC/RtpDictionaries.hpp +++ b/worker/include/RTC/RtpDictionaries.hpp @@ -2,14 +2,12 @@ #define MS_RTC_RTP_DICTIONARIES_HPP #include "common.hpp" +#include "FBS/rtpParameters.h" #include "RTC/Parameters.hpp" #include -#include #include #include -using json = nlohmann::json; - namespace RTC { class Media @@ -17,19 +15,9 @@ namespace RTC public: enum class Kind : uint8_t { - ALL = 0, AUDIO, VIDEO }; - - public: - static Kind GetKind(std::string& str); - static Kind GetKind(std::string&& str); - static const std::string& GetString(Kind kind); - - private: - static absl::flat_hash_map string2Kind; - static absl::flat_hash_map kind2String; }; class RtpCodecMimeType @@ -37,7 +25,6 @@ namespace RTC public: enum class Type : uint8_t { - UNSET = 0, AUDIO, VIDEO }; @@ -45,7 +32,6 @@ namespace RTC public: enum class Subtype : uint16_t { - UNSET = 0, // Audio codecs: OPUS = 100, // Multi-channel Opus. @@ -118,8 +104,8 @@ namespace RTC } public: - Type type{ Type::UNSET }; - Subtype subtype{ Subtype::UNSET }; + Type type; + Subtype subtype; private: std::string mimeType; @@ -130,7 +116,6 @@ namespace RTC public: enum class Type : uint8_t { - UNKNOWN = 0, MID = 1, RTP_STREAM_ID = 2, REPAIRED_RTP_STREAM_ID = 3, @@ -144,20 +129,19 @@ namespace RTC ABS_CAPTURE_TIME = 13, }; - private: - static absl::flat_hash_map string2Type; - public: - static Type GetType(std::string& uri); + static RtpHeaderExtensionUri::Type TypeFromFbs(FBS::RtpParameters::RtpHeaderExtensionUri uri); + static FBS::RtpParameters::RtpHeaderExtensionUri TypeToFbs(RtpHeaderExtensionUri::Type uri); }; class RtcpFeedback { public: RtcpFeedback() = default; - explicit RtcpFeedback(json& data); + explicit RtcpFeedback(const FBS::RtpParameters::RtcpFeedback* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: std::string type; @@ -168,9 +152,10 @@ namespace RTC { public: RtpCodecParameters() = default; - explicit RtpCodecParameters(json& data); + explicit RtpCodecParameters(const FBS::RtpParameters::RtpCodecParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; private: void CheckCodec(); @@ -188,9 +173,9 @@ namespace RTC { public: RtpRtxParameters() = default; - explicit RtpRtxParameters(json& data); + explicit RtpRtxParameters(const FBS::RtpParameters::Rtx* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; public: uint32_t ssrc{ 0u }; @@ -200,9 +185,10 @@ namespace RTC { public: RtpEncodingParameters() = default; - explicit RtpEncodingParameters(json& data); + explicit RtpEncodingParameters(const FBS::RtpParameters::RtpEncodingParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: uint32_t ssrc{ 0u }; @@ -214,7 +200,7 @@ namespace RTC uint32_t maxBitrate{ 0u }; double maxFramerate{ 0 }; bool dtx{ false }; - std::string scalabilityMode; + std::string scalabilityMode{ "S1T1" }; uint8_t spatialLayers{ 1u }; uint8_t temporalLayers{ 1u }; bool ksvc{ false }; @@ -224,12 +210,13 @@ namespace RTC { public: RtpHeaderExtensionParameters() = default; - explicit RtpHeaderExtensionParameters(json& data); + explicit RtpHeaderExtensionParameters( + const FBS::RtpParameters::RtpHeaderExtensionParameters* const data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: - std::string uri; RtpHeaderExtensionUri::Type type; uint8_t id{ 0u }; bool encrypt{ false }; @@ -240,13 +227,13 @@ namespace RTC { public: RtcpParameters() = default; - explicit RtcpParameters(json& data); + explicit RtcpParameters(const FBS::RtpParameters::RtcpParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: std::string cname; - uint32_t ssrc{ 0u }; bool reducedSize{ true }; }; @@ -255,7 +242,6 @@ namespace RTC public: enum class Type : uint8_t { - NONE = 0, SIMPLE, SIMULCAST, SVC, @@ -263,20 +249,19 @@ namespace RTC }; public: - static Type GetType(const RtpParameters& rtpParameters); - static Type GetType(std::string& str); - static Type GetType(std::string&& str); + static std::optional GetType(const RtpParameters& rtpParameters); static std::string& GetTypeString(Type type); + static FBS::RtpParameters::Type TypeToFbs(Type type); private: - static absl::flat_hash_map string2Type; static absl::flat_hash_map type2String; public: RtpParameters() = default; - explicit RtpParameters(json& data); + explicit RtpParameters(const FBS::RtpParameters::RtpParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; const RTC::RtpCodecParameters* GetCodecForEncoding(RtpEncodingParameters& encoding) const; const RTC::RtpCodecParameters* GetRtxCodecForEncoding(RtpEncodingParameters& encoding) const; @@ -291,7 +276,6 @@ namespace RTC std::vector encodings; std::vector headerExtensions; RtcpParameters rtcp; - bool hasRtcp{ false }; }; } // namespace RTC diff --git a/worker/include/RTC/RtpListener.hpp b/worker/include/RTC/RtpListener.hpp index b6f6d65d37..0591c4ba4f 100644 --- a/worker/include/RTC/RtpListener.hpp +++ b/worker/include/RTC/RtpListener.hpp @@ -4,18 +4,16 @@ #include "common.hpp" #include "RTC/Producer.hpp" #include "RTC/RtpPacket.hpp" -#include #include #include -using json = nlohmann::json; - namespace RTC { class RtpListener { public: - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; void AddProducer(RTC::Producer* producer); void RemoveProducer(RTC::Producer* producer); RTC::Producer* GetProducer(const RTC::RtpPacket* packet); diff --git a/worker/include/RTC/RtpObserver.hpp b/worker/include/RTC/RtpObserver.hpp index 00c8010456..c17efdc5ad 100644 --- a/worker/include/RTC/RtpObserver.hpp +++ b/worker/include/RTC/RtpObserver.hpp @@ -1,5 +1,5 @@ -#ifndef MS_RTC_RTP_PACKET_OBSERVER_HPP -#define MS_RTC_RTP_PACKET_OBSERVER_HPP +#ifndef MS_RTC_RTP_OBSERVER_HPP +#define MS_RTC_RTP_OBSERVER_HPP #include "common.hpp" #include "RTC/Producer.hpp" @@ -50,9 +50,6 @@ namespace RTC virtual void Paused() = 0; virtual void Resumed() = 0; - private: - std::string GetProducerIdFromData(json& data) const; - public: // Passed by argument. const std::string id; diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index a585a3babc..0f555c4320 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -3,16 +3,15 @@ #include "common.hpp" #include "Utils.hpp" +#include "FBS/rtpPacket.h" #include "RTC/Codecs/PayloadDescriptorHandler.hpp" #include "RTC/RtcLogger.hpp" +#include #include #include -#include #include #include -using json = nlohmann::json; - namespace RTC { // Max MTU size. @@ -147,8 +146,7 @@ namespace RTC ~RtpPacket(); void Dump() const; - - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; const uint8_t* GetData() const { diff --git a/worker/include/RTC/RtpStream.hpp b/worker/include/RTC/RtpStream.hpp index e404013a56..80e86a0dd5 100644 --- a/worker/include/RTC/RtpStream.hpp +++ b/worker/include/RTC/RtpStream.hpp @@ -3,6 +3,7 @@ #include "common.hpp" #include "DepLibUV.hpp" +#include "FBS/rtpStream.h" #include "RTC/RTCP/FeedbackPsFir.hpp" #include "RTC/RTCP/FeedbackPsPli.hpp" #include "RTC/RTCP/FeedbackRtpNack.hpp" @@ -15,12 +16,9 @@ #include "RTC/RtpDictionaries.hpp" #include "RTC/RtpPacket.hpp" #include "RTC/RtxStream.hpp" -#include #include #include -using json = nlohmann::json; - namespace RTC { class RtpStream @@ -38,7 +36,8 @@ namespace RTC public: struct Params { - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; size_t encodingIdx{ 0u }; uint32_t ssrc{ 0u }; @@ -62,8 +61,9 @@ namespace RTC RtpStream(RTC::RtpStream::Listener* listener, RTC::RtpStream::Params& params, uint8_t initialScore); virtual ~RtpStream(); - void FillJson(json& jsonObject) const; - virtual void FillJsonStats(json& jsonObject); + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; + virtual flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); uint32_t GetEncodingIdx() const { return this->params.encodingIdx; diff --git a/worker/include/RTC/RtpStreamRecv.hpp b/worker/include/RTC/RtpStreamRecv.hpp index e4ad525ecb..19b25fa8df 100644 --- a/worker/include/RTC/RtpStreamRecv.hpp +++ b/worker/include/RTC/RtpStreamRecv.hpp @@ -5,14 +5,14 @@ #include "RTC/RTCP/XrDelaySinceLastRr.hpp" #include "RTC/RateCalculator.hpp" #include "RTC/RtpStream.hpp" -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include namespace RTC { class RtpStreamRecv : public RTC::RtpStream, public RTC::NackGenerator::Listener, - public Timer::Listener + public TimerHandle::Listener { public: class Listener : public RTC::RtpStream::Listener @@ -49,7 +49,8 @@ namespace RTC bool useRtpInactivityCheck); ~RtpStreamRecv(); - void FillJsonStats(json& jsonObject) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; bool ReceivePacket(RTC::RtpPacket* packet); bool ReceiveRtxPacket(RTC::RtpPacket* packet); RTC::RTCP::ReceiverReport* GetRtcpReceiverReport(); @@ -89,9 +90,9 @@ namespace RTC public: void UserOnSequenceNumberReset() override; - /* Pure virtual methods inherited from Timer. */ + /* Pure virtual methods inherited from TimerHandle. */ protected: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; /* Pure virtual methods inherited from RTC::NackGenerator. */ protected: @@ -124,7 +125,7 @@ namespace RTC uint8_t firSeqNumber{ 0u }; uint32_t reportedPacketLost{ 0u }; std::unique_ptr nackGenerator; - Timer* inactivityCheckPeriodicTimer{ nullptr }; + TimerHandle* inactivityCheckPeriodicTimer{ nullptr }; bool inactive{ false }; // Valid media + valid RTX. TransmissionCounter transmissionCounter; diff --git a/worker/include/RTC/RtpStreamSend.hpp b/worker/include/RTC/RtpStreamSend.hpp index 9c59c897dd..f98d399aca 100644 --- a/worker/include/RTC/RtpStreamSend.hpp +++ b/worker/include/RTC/RtpStreamSend.hpp @@ -28,7 +28,8 @@ namespace RTC RTC::RtpStreamSend::Listener* listener, RTC::RtpStream::Params& params, std::string& mid); ~RtpStreamSend() override; - void FillJsonStats(json& jsonObject) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; void SetRtx(uint8_t payloadType, uint32_t ssrc) override; bool ReceivePacket(RTC::RtpPacket* packet, std::shared_ptr& sharedPacket); void ReceiveNack(RTC::RTCP::FeedbackRtpNackPacket* nackPacket); diff --git a/worker/include/RTC/RtxStream.hpp b/worker/include/RTC/RtxStream.hpp index 216c3ba201..e8c312ab92 100644 --- a/worker/include/RTC/RtxStream.hpp +++ b/worker/include/RTC/RtxStream.hpp @@ -3,16 +3,14 @@ #include "common.hpp" #include "DepLibUV.hpp" +#include "FBS/rtxStream.h" #include "RTC/RTCP/Packet.hpp" #include "RTC/RTCP/ReceiverReport.hpp" #include "RTC/RTCP/SenderReport.hpp" #include "RTC/RtpDictionaries.hpp" #include "RTC/RtpPacket.hpp" -#include #include -using json = nlohmann::json; - namespace RTC { class RtxStream @@ -20,7 +18,8 @@ namespace RTC public: struct Params { - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; uint32_t ssrc{ 0 }; uint8_t payloadType{ 0 }; @@ -34,7 +33,7 @@ namespace RTC explicit RtxStream(RTC::RtxStream::Params& params); virtual ~RtxStream(); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; uint32_t GetSsrc() const { return this->params.ssrc; diff --git a/worker/include/RTC/SctpAssociation.hpp b/worker/include/RTC/SctpAssociation.hpp index 6b6626f04d..146aca32bd 100644 --- a/worker/include/RTC/SctpAssociation.hpp +++ b/worker/include/RTC/SctpAssociation.hpp @@ -6,9 +6,6 @@ #include "RTC/DataConsumer.hpp" #include "RTC/DataProducer.hpp" #include -#include - -using json = nlohmann::json; namespace RTC { @@ -50,9 +47,9 @@ namespace RTC virtual void OnSctpAssociationMessageReceived( RTC::SctpAssociation* sctpAssociation, uint16_t streamId, - uint32_t ppid, const uint8_t* msg, - size_t len) = 0; + size_t len, + uint32_t ppid) = 0; virtual void OnSctpAssociationBufferedAmount( RTC::SctpAssociation* sctpAssociation, uint32_t len) = 0; }; @@ -81,7 +78,8 @@ namespace RTC ~SctpAssociation(); public: - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; void TransportConnected(); SctpState GetState() const { @@ -94,9 +92,9 @@ namespace RTC void ProcessSctpData(const uint8_t* data, size_t len); void SendSctpMessage( RTC::DataConsumer* dataConsumer, - uint32_t ppid, const uint8_t* msg, size_t len, + uint32_t ppid, onQueuedCallback* cb = nullptr); void HandleDataConsumer(RTC::DataConsumer* dataConsumer); void DataProducerClosed(RTC::DataProducer* dataProducer); diff --git a/worker/include/RTC/SctpDictionaries.hpp b/worker/include/RTC/SctpDictionaries.hpp index 9ceebb03a8..25862a70a1 100644 --- a/worker/include/RTC/SctpDictionaries.hpp +++ b/worker/include/RTC/SctpDictionaries.hpp @@ -2,10 +2,7 @@ #define MS_RTC_SCTP_DICTIONARIES_HPP #include "common.hpp" -#include -#include - -using json = nlohmann::json; +#include namespace RTC { @@ -13,9 +10,10 @@ namespace RTC { public: SctpStreamParameters() = default; - explicit SctpStreamParameters(json& data); + explicit SctpStreamParameters(const FBS::SctpParameters::SctpStreamParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: uint16_t streamId{ 0u }; diff --git a/worker/include/RTC/SctpListener.hpp b/worker/include/RTC/SctpListener.hpp index 4988805e65..504d7d978a 100644 --- a/worker/include/RTC/SctpListener.hpp +++ b/worker/include/RTC/SctpListener.hpp @@ -3,17 +3,15 @@ #include "common.hpp" #include "RTC/DataProducer.hpp" -#include #include -using json = nlohmann::json; - namespace RTC { class SctpListener { public: - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; void AddDataProducer(RTC::DataProducer* dataProducer); void RemoveDataProducer(RTC::DataProducer* dataProducer); RTC::DataProducer* GetDataProducer(uint16_t streamId); diff --git a/worker/include/RTC/Shared.hpp b/worker/include/RTC/Shared.hpp index 90e07f058a..2a71781283 100644 --- a/worker/include/RTC/Shared.hpp +++ b/worker/include/RTC/Shared.hpp @@ -3,7 +3,6 @@ #include "ChannelMessageRegistrator.hpp" #include "Channel/ChannelNotifier.hpp" -#include "PayloadChannel/PayloadChannelNotifier.hpp" namespace RTC { @@ -12,14 +11,12 @@ namespace RTC public: explicit Shared( ChannelMessageRegistrator* channelMessageRegistrator, - Channel::ChannelNotifier* channelNotifier, - PayloadChannel::PayloadChannelNotifier* payloadChannelNotifier); + Channel::ChannelNotifier* channelNotifier); ~Shared(); public: ChannelMessageRegistrator* channelMessageRegistrator{ nullptr }; Channel::ChannelNotifier* channelNotifier{ nullptr }; - PayloadChannel::PayloadChannelNotifier* payloadChannelNotifier{ nullptr }; }; } // namespace RTC diff --git a/worker/include/RTC/SimpleConsumer.hpp b/worker/include/RTC/SimpleConsumer.hpp index 4822677969..d502801e9b 100644 --- a/worker/include/RTC/SimpleConsumer.hpp +++ b/worker/include/RTC/SimpleConsumer.hpp @@ -1,6 +1,7 @@ #ifndef MS_RTC_SIMPLE_CONSUMER_HPP #define MS_RTC_SIMPLE_CONSUMER_HPP +#include "FBS/transport.h" #include "RTC/Consumer.hpp" #include "RTC/SeqManager.hpp" #include "RTC/Shared.hpp" @@ -15,13 +16,16 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data); + const FBS::Transport::ConsumeRequest* data); ~SimpleConsumer() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) const override; - void FillJsonScore(json& jsonObject) const override; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; + flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const override; bool IsActive() const override { // clang-format off diff --git a/worker/include/RTC/SimulcastConsumer.hpp b/worker/include/RTC/SimulcastConsumer.hpp index d9fbd33983..fcce57adb4 100644 --- a/worker/include/RTC/SimulcastConsumer.hpp +++ b/worker/include/RTC/SimulcastConsumer.hpp @@ -1,6 +1,7 @@ #ifndef MS_RTC_SIMULCAST_CONSUMER_HPP #define MS_RTC_SIMULCAST_CONSUMER_HPP +#include "FBS/consumer.h" #include "RTC/Codecs/PayloadDescriptorHandler.hpp" #include "RTC/Consumer.hpp" #include "RTC/SeqManager.hpp" @@ -16,13 +17,16 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data); + const FBS::Transport::ConsumeRequest* data); ~SimulcastConsumer() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) const override; - void FillJsonScore(json& jsonObject) const override; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; + flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const override; RTC::Consumer::Layers GetPreferredLayers() const override { RTC::Consumer::Layers layers; diff --git a/worker/include/RTC/SrtpSession.hpp b/worker/include/RTC/SrtpSession.hpp index 7b6f34c0f0..fa14a14760 100644 --- a/worker/include/RTC/SrtpSession.hpp +++ b/worker/include/RTC/SrtpSession.hpp @@ -2,6 +2,7 @@ #define MS_RTC_SRTP_SESSION_HPP #include "common.hpp" +#include "FBS/srtpParameters.h" #include namespace RTC @@ -11,8 +12,7 @@ namespace RTC public: enum class CryptoSuite { - NONE = 0, - AEAD_AES_256_GCM = 1, + AEAD_AES_256_GCM = 0, AEAD_AES_128_GCM, AES_CM_128_HMAC_SHA1_80, AES_CM_128_HMAC_SHA1_32, @@ -27,6 +27,8 @@ namespace RTC public: static void ClassInit(); + static FBS::SrtpParameters::SrtpCryptoSuite CryptoSuiteToFbs(CryptoSuite cryptoSuite); + static CryptoSuite CryptoSuiteFromFbs(FBS::SrtpParameters::SrtpCryptoSuite cryptoSuite); private: static void OnSrtpEvent(srtp_event_data_t* data); diff --git a/worker/include/RTC/SvcConsumer.hpp b/worker/include/RTC/SvcConsumer.hpp index 3e85536cf9..c61220293f 100644 --- a/worker/include/RTC/SvcConsumer.hpp +++ b/worker/include/RTC/SvcConsumer.hpp @@ -17,13 +17,16 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data); + const FBS::Transport::ConsumeRequest* data); ~SvcConsumer() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) const override; - void FillJsonScore(json& jsonObject) const override; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; + flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const override; RTC::Consumer::Layers GetPreferredLayers() const override { RTC::Consumer::Layers layers; diff --git a/worker/include/RTC/TcpConnection.hpp b/worker/include/RTC/TcpConnection.hpp index 0aa17ebb62..27d5aaa786 100644 --- a/worker/include/RTC/TcpConnection.hpp +++ b/worker/include/RTC/TcpConnection.hpp @@ -2,11 +2,11 @@ #define MS_RTC_TCP_CONNECTION_HPP #include "common.hpp" -#include "handles/TcpConnectionHandler.hpp" +#include "handles/TcpConnectionHandle.hpp" namespace RTC { - class TcpConnection : public ::TcpConnectionHandler + class TcpConnection : public ::TcpConnectionHandle { public: class Listener @@ -24,9 +24,9 @@ namespace RTC ~TcpConnection() override; public: - void Send(const uint8_t* data, size_t len, ::TcpConnectionHandler::onSendCallback* cb); + void Send(const uint8_t* data, size_t len, ::TcpConnectionHandle::onSendCallback* cb); - /* Pure virtual methods inherited from ::TcpConnectionHandler. */ + /* Pure virtual methods inherited from ::TcpConnectionHandle. */ public: void UserOnTcpConnectionRead() override; diff --git a/worker/include/RTC/TcpServer.hpp b/worker/include/RTC/TcpServer.hpp index 859785cce5..89e03ca6b8 100644 --- a/worker/include/RTC/TcpServer.hpp +++ b/worker/include/RTC/TcpServer.hpp @@ -3,13 +3,13 @@ #include "common.hpp" #include "RTC/TcpConnection.hpp" -#include "handles/TcpConnectionHandler.hpp" -#include "handles/TcpServerHandler.hpp" +#include "handles/TcpConnectionHandle.hpp" +#include "handles/TcpServerHandle.hpp" #include namespace RTC { - class TcpServer : public ::TcpServerHandler + class TcpServer : public ::TcpServerHandle { public: class Listener @@ -28,10 +28,10 @@ namespace RTC Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, uint16_t port); ~TcpServer() override; - /* Pure virtual methods inherited from ::TcpServerHandler. */ + /* Pure virtual methods inherited from ::TcpServerHandle. */ public: void UserOnTcpConnectionAlloc() override; - void UserOnTcpConnectionClosed(::TcpConnectionHandler* connection) override; + void UserOnTcpConnectionClosed(::TcpConnectionHandle* connection) override; private: // Passed by argument. diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index 08450ae58a..61bdd3ec65 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -4,10 +4,10 @@ #include "common.hpp" #include "DepLibUV.hpp" +#include "Channel/ChannelNotification.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" +#include "FBS/transport.h" #include "RTC/Consumer.hpp" #include "RTC/DataConsumer.hpp" #include "RTC/DataProducer.hpp" @@ -27,12 +27,10 @@ #endif #include "RTC/TransportCongestionControlClient.hpp" #include "RTC/TransportCongestionControlServer.hpp" -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include -#include #include - -using json = nlohmann::json; +#include namespace RTC { @@ -44,12 +42,11 @@ namespace RTC public RTC::TransportCongestionControlClient::Listener, public RTC::TransportCongestionControlServer::Listener, public Channel::ChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::NotificationHandler, + public Channel::ChannelSocket::NotificationHandler, #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR public RTC::SenderBandwidthEstimator::Listener, #endif - public Timer::Listener + public TimerHandle::Listener { protected: using onSendCallback = const std::function; @@ -90,10 +87,14 @@ namespace RTC uint32_t mappedSsrc, uint8_t& worstRemoteFractionLost) = 0; virtual void OnTransportNewConsumer( - RTC::Transport* transport, RTC::Consumer* consumer, std::string& producerId) = 0; + RTC::Transport* transport, RTC::Consumer* consumer, const std::string& producerId) = 0; virtual void OnTransportConsumerClosed(RTC::Transport* transport, RTC::Consumer* consumer) = 0; virtual void OnTransportConsumerProducerClosed( RTC::Transport* transport, RTC::Consumer* consumer) = 0; + virtual void OnTransportDataProducerPaused( + RTC::Transport* transport, RTC::DataProducer* dataProducer) = 0; + virtual void OnTransportDataProducerResumed( + RTC::Transport* transport, RTC::DataProducer* dataProducer) = 0; virtual void OnTransportConsumerKeyFrameRequested( RTC::Transport* transport, RTC::Consumer* consumer, uint32_t mappedSsrc) = 0; virtual void OnTransportNewDataProducer( @@ -103,9 +104,11 @@ namespace RTC virtual void OnTransportDataProducerMessageReceived( RTC::Transport* transport, RTC::DataProducer* dataProducer, - uint32_t ppid, const uint8_t* msg, - size_t len) = 0; + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel) = 0; virtual void OnTransportNewDataConsumer( RTC::Transport* transport, RTC::DataConsumer* dataConsumer, std::string& dataProducerId) = 0; virtual void OnTransportDataConsumerClosed( @@ -115,6 +118,16 @@ namespace RTC virtual void OnTransportListenServerClosed(RTC::Transport* transport) = 0; }; + public: + struct ListenInfo + { + std::string ip; + std::string announcedIp; + uint16_t port{ 0u }; + uint32_t sendBufferSize{ 0u }; + uint32_t recvBufferSize{ 0u }; + }; + private: struct TraceEventTypes { @@ -123,27 +136,27 @@ namespace RTC }; public: - Transport(RTC::Shared* shared, const std::string& id, Listener* listener, json& data); + Transport( + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::Transport::Options* options); virtual ~Transport(); public: void CloseProducersAndConsumers(); void ListenServerClosed(); // Subclasses must also invoke the parent Close(). - virtual void FillJson(json& jsonObject) const; - virtual void FillJsonStats(json& jsonArray); + flatbuffers::Offset FillBufferStats(flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::RequestHandler. */ - public: - void HandleRequest(PayloadChannel::PayloadChannelRequest* request) override; - - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; protected: // Must be called from the subclass. @@ -161,16 +174,12 @@ namespace RTC void ReceiveRtpPacket(RTC::RtpPacket* packet); void ReceiveRtcpPacket(RTC::RTCP::Packet* packet); void ReceiveSctpData(const uint8_t* data, size_t len); - void SetNewProducerIdFromData(json& data, std::string& producerId) const; - RTC::Producer* GetProducerFromData(json& data) const; - void SetNewConsumerIdFromData(json& data, std::string& consumerId) const; - RTC::Consumer* GetConsumerFromData(json& data) const; + RTC::Producer* GetProducerById(const std::string& producerId) const; + RTC::Consumer* GetConsumerById(const std::string& consumerId) const; RTC::Consumer* GetConsumerByMediaSsrc(uint32_t ssrc) const; RTC::Consumer* GetConsumerByRtxSsrc(uint32_t ssrc) const; - void SetNewDataProducerIdFromData(json& data, std::string& dataProducerId) const; - RTC::DataProducer* GetDataProducerFromData(json& data) const; - void SetNewDataConsumerIdFromData(json& data, std::string& dataConsumerId) const; - RTC::DataConsumer* GetDataConsumerFromData(json& data) const; + RTC::DataProducer* GetDataProducerById(const std::string& dataProducerId) const; + RTC::DataConsumer* GetDataConsumerById(const std::string& dataConsumerId) const; private: virtual bool IsConnected() const = 0; @@ -182,9 +191,9 @@ namespace RTC virtual void SendRtcpCompoundPacket(RTC::RTCP::CompoundPacket* packet) = 0; virtual void SendMessage( RTC::DataConsumer* dataConsumer, - uint32_t ppid, const uint8_t* msg, size_t len, + uint32_t ppid, onQueuedCallback* = nullptr) = 0; virtual void SendSctpData(const uint8_t* data, size_t len) = 0; virtual void RecvStreamClosed(uint32_t ssrc) = 0; @@ -193,6 +202,9 @@ namespace RTC void ComputeOutgoingDesiredBitrate(bool forceBitrate = false); void EmitTraceEventProbationType(RTC::RtpPacket* packet) const; void EmitTraceEventBweType(RTC::TransportCongestionControlClient::Bitrates& bitrates) const; + void CheckNoProducer(const std::string& producerId) const; + void CheckNoDataProducer(const std::string& dataProducerId) const; + void CheckNoDataConsumer(const std::string& dataConsumerId) const; /* Pure virtual methods inherited from RTC::Producer::Listener. */ public: @@ -236,15 +248,22 @@ namespace RTC this->DataReceived(len); } void OnDataProducerMessageReceived( - RTC::DataProducer* dataProducer, uint32_t ppid, const uint8_t* msg, size_t len) override; + RTC::DataProducer* dataProducer, + const uint8_t* msg, + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel) override; + void OnDataProducerPaused(RTC::DataProducer* dataProducer) override; + void OnDataProducerResumed(RTC::DataProducer* dataProducer) override; /* Pure virtual methods inherited from RTC::DataConsumer::Listener. */ public: void OnDataConsumerSendMessage( RTC::DataConsumer* dataConsumer, - uint32_t ppid, const uint8_t* msg, size_t len, + uint32_t ppid, onQueuedCallback* = nullptr) override; void OnDataConsumerDataProducerClosed(RTC::DataConsumer* dataConsumer) override; @@ -259,9 +278,9 @@ namespace RTC void OnSctpAssociationMessageReceived( RTC::SctpAssociation* sctpAssociation, uint16_t streamId, - uint32_t ppid, const uint8_t* msg, - size_t len) override; + size_t len, + uint32_t ppid) override; void OnSctpAssociationBufferedAmount( RTC::SctpAssociation* sctpAssociation, uint32_t bufferedAmount) override; @@ -289,9 +308,9 @@ namespace RTC uint32_t previousAvailableBitrate) override; #endif - /* Pure virtual methods inherited from Timer::Listener. */ + /* Pure virtual methods inherited from TimerHandle::Listener. */ public: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; public: // Passed by argument. @@ -313,14 +332,14 @@ namespace RTC absl::flat_hash_map mapDataConsumers; absl::flat_hash_map mapSsrcConsumer; absl::flat_hash_map mapRtxSsrcConsumer; - Timer* rtcpTimer{ nullptr }; + TimerHandle* rtcpTimer{ nullptr }; std::shared_ptr tccClient{ nullptr }; std::shared_ptr tccServer{ nullptr }; #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR std::shared_ptr senderBwe{ nullptr }; #endif // Others. - bool direct{ false }; // Whether this Transport allows PayloadChannel comm. + bool direct{ false }; // Whether this Transport allows direct communication. bool destroying{ false }; struct RTC::RtpHeaderExtensionIds recvRtpHeaderExtensionIds; RTC::RtpListener rtpListener; diff --git a/worker/include/RTC/TransportCongestionControlClient.hpp b/worker/include/RTC/TransportCongestionControlClient.hpp index dd58ed943c..1c2fb61f6c 100644 --- a/worker/include/RTC/TransportCongestionControlClient.hpp +++ b/worker/include/RTC/TransportCongestionControlClient.hpp @@ -8,7 +8,7 @@ #include "RTC/RtpPacket.hpp" #include "RTC/RtpProbationGenerator.hpp" #include "RTC/TrendCalculator.hpp" -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include #include #include @@ -21,7 +21,7 @@ namespace RTC class TransportCongestionControlClient : public webrtc::PacketRouter, public webrtc::TargetTransferRateObserver, - public Timer::Listener + public TimerHandle::Listener { public: struct Bitrates @@ -104,9 +104,9 @@ namespace RTC void SendPacket(RTC::RtpPacket* packet, const webrtc::PacedPacketInfo& pacingInfo) override; RTC::RtpPacket* GeneratePadding(size_t size) override; - /* Pure virtual methods inherited from RTC::Timer. */ + /* Pure virtual methods inherited from RTC::TimerHandle. */ public: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; private: // Passed by argument. @@ -115,7 +115,7 @@ namespace RTC webrtc::NetworkControllerFactoryInterface* controllerFactory{ nullptr }; webrtc::RtpTransportControllerSend* rtpTransportControllerSend{ nullptr }; RTC::RtpProbationGenerator* probationGenerator{ nullptr }; - Timer* processTimer{ nullptr }; + TimerHandle* processTimer{ nullptr }; // Others. RTC::BweType bweType; uint32_t initialAvailableBitrate{ 0u }; diff --git a/worker/include/RTC/TransportCongestionControlServer.hpp b/worker/include/RTC/TransportCongestionControlServer.hpp index 5747d13d03..ae1e307707 100644 --- a/worker/include/RTC/TransportCongestionControlServer.hpp +++ b/worker/include/RTC/TransportCongestionControlServer.hpp @@ -6,14 +6,14 @@ #include "RTC/RTCP/FeedbackRtpTransport.hpp" #include "RTC/RTCP/Packet.hpp" #include "RTC/RtpPacket.hpp" -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include #include namespace RTC { class TransportCongestionControlServer : public webrtc::RemoteBitrateEstimator::Listener, - public Timer::Listener + public TimerHandle::Listener { public: class Listener @@ -67,15 +67,15 @@ namespace RTC const std::vector& ssrcs, uint32_t availableBitrate) override; - /* Pure virtual methods inherited from Timer::Listener. */ + /* Pure virtual methods inherited from TimerHandle::Listener. */ public: - void OnTimer(Timer* timer) override; + void OnTimer(TimerHandle* timer) override; private: // Passed by argument. Listener* listener{ nullptr }; // Allocated by this. - Timer* transportCcFeedbackSendPeriodicTimer{ nullptr }; + TimerHandle* transportCcFeedbackSendPeriodicTimer{ nullptr }; std::unique_ptr transportCcFeedbackPacket; webrtc::RemoteBitrateEstimatorAbsSendTime* rembServer{ nullptr }; // Others. diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 535d221a68..75c124ecd4 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -3,13 +3,12 @@ #include "common.hpp" #include "Utils.hpp" +#include "FBS/transport.h" #include "RTC/TcpConnection.hpp" #include "RTC/UdpSocket.hpp" -#include +#include #include -using json = nlohmann::json; - namespace RTC { class TransportTuple @@ -24,6 +23,9 @@ namespace RTC TCP }; + static Protocol ProtocolFromFbs(FBS::Transport::Protocol protocol); + static FBS::Transport::Protocol ProtocolToFbs(Protocol protocol); + public: TransportTuple(RTC::UdpSocket* udpSocket, const struct sockaddr* udpRemoteAddr) : udpSocket(udpSocket), udpRemoteAddr((struct sockaddr*)udpRemoteAddr), protocol(Protocol::UDP) @@ -63,7 +65,7 @@ namespace RTC return this->tcpConnection->IsClosed(); } - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; void Dump() const; diff --git a/worker/include/RTC/UdpSocket.hpp b/worker/include/RTC/UdpSocket.hpp index 070209f734..46e90f3edd 100644 --- a/worker/include/RTC/UdpSocket.hpp +++ b/worker/include/RTC/UdpSocket.hpp @@ -2,12 +2,12 @@ #define MS_RTC_UDP_SOCKET_HPP #include "common.hpp" -#include "handles/UdpSocketHandler.hpp" +#include "handles/UdpSocketHandle.hpp" #include namespace RTC { - class UdpSocket : public ::UdpSocketHandler + class UdpSocket : public ::UdpSocketHandle { public: class Listener @@ -25,7 +25,7 @@ namespace RTC UdpSocket(Listener* listener, std::string& ip, uint16_t port); ~UdpSocket() override; - /* Pure virtual methods inherited from ::UdpSocketHandler. */ + /* Pure virtual methods inherited from ::UdpSocketHandle. */ public: void UserOnUdpDatagramReceived(const uint8_t* data, size_t len, const struct sockaddr* addr) override; diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index f0197b2d3a..49803dd6ec 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -10,9 +10,9 @@ #include "RTC/TransportTuple.hpp" #include "RTC/UdpSocket.hpp" #include "RTC/WebRtcTransport.hpp" +#include #include #include -#include #include #include @@ -24,15 +24,6 @@ namespace RTC public RTC::WebRtcTransport::WebRtcTransportListener, public Channel::ChannelSocket::RequestHandler { - private: - struct ListenInfo - { - RTC::TransportTuple::Protocol protocol; - std::string ip; - std::string announcedIp; - uint16_t port; - }; - private: struct UdpSocketOrTcpServer { @@ -48,13 +39,17 @@ namespace RTC }; public: - WebRtcServer(RTC::Shared* shared, const std::string& id, json& data); + WebRtcServer( + RTC::Shared* shared, + const std::string& id, + const flatbuffers::Vector>* listenInfos); ~WebRtcServer(); public: - void FillJson(json& jsonObject) const; - std::vector GetIceCandidates( - bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + const std::vector GetIceCandidates( + bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index 2eae6d856a..e88047980c 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -23,13 +23,6 @@ namespace RTC public RTC::IceServer::Listener, public RTC::DtlsTransport::Listener { - private: - struct ListenIp - { - std::string ip; - std::string announcedIp; - }; - public: class WebRtcTransportListener { @@ -51,19 +44,24 @@ namespace RTC public: WebRtcTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::WebRtcTransport::WebRtcTransportOptions* options); WebRtcTransport( RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, WebRtcTransportListener* webRtcTransportListener, - std::vector& iceCandidates, - json& data); + const std::vector& iceCandidates, + const FBS::WebRtcTransport::WebRtcTransportOptions* options); ~WebRtcTransport() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; void ProcessStunPacketFromWebRtcServer(RTC::TransportTuple* tuple, RTC::StunPacket* packet); void ProcessNonStunPacketFromWebRtcServer( RTC::TransportTuple* tuple, const uint8_t* data, size_t len); @@ -73,9 +71,9 @@ namespace RTC public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; private: bool IsConnected() const override; @@ -88,9 +86,9 @@ namespace RTC void SendRtcpCompoundPacket(RTC::RTCP::CompoundPacket* packet) override; void SendMessage( RTC::DataConsumer* dataConsumer, - uint32_t ppid, const uint8_t* msg, size_t len, + uint32_t ppid, onQueuedCallback* cb = nullptr) override; void SendSctpData(const uint8_t* data, size_t len) override; void RecvStreamClosed(uint32_t ssrc) override; @@ -162,7 +160,8 @@ namespace RTC RTC::SrtpSession* srtpRecvSession{ nullptr }; RTC::SrtpSession* srtpSendSession{ nullptr }; // Others. - bool connectCalled{ false }; // Whether connect() was succesfully called. + // Whether connect() was succesfully called. + bool connectCalled{ false }; std::vector iceCandidates; RTC::DtlsTransport::Role dtlsRole{ RTC::DtlsTransport::Role::AUTO }; }; diff --git a/worker/include/Utils.hpp b/worker/include/Utils.hpp index 96ee42a13a..b11b9a18fc 100644 --- a/worker/include/Utils.hpp +++ b/worker/include/Utils.hpp @@ -5,7 +5,6 @@ #include #include #include // std::memcmp(), std::memcpy() -#include #include #include #ifdef _WIN32 @@ -15,8 +14,6 @@ #define __builtin_popcount __popcnt #endif -using json = nlohmann::json; - namespace Utils { class IP @@ -311,8 +308,6 @@ namespace Utils static uint8_t* Base64Decode(const uint8_t* data, size_t len, size_t& outLen); static uint8_t* Base64Decode(const std::string& str, size_t& outLen); - - static std::vector Split(const std::string& str, char separator, size_t limit = 0); }; class Time @@ -375,26 +370,6 @@ namespace Utils return static_cast(((ms << 18) + 500) / 1000) & 0x00FFFFFF; } }; - - class Json - { - public: - static bool IsPositiveInteger(const json& value) - { - if (value.is_number_unsigned()) - { - return true; - } - else if (value.is_number_integer()) - { - return value.get() >= 0; - } - else - { - return false; - } - } - }; } // namespace Utils #endif diff --git a/worker/include/Worker.hpp b/worker/include/Worker.hpp index 48d993bf7a..9bb91b8fed 100644 --- a/worker/include/Worker.hpp +++ b/worker/include/Worker.hpp @@ -4,60 +4,46 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" +#include "FBS/worker.h" #include "RTC/Router.hpp" #include "RTC/Shared.hpp" #include "RTC/WebRtcServer.hpp" -#include "handles/SignalsHandler.hpp" +#include "handles/SignalHandle.hpp" +#include #include -#include #include -using json = nlohmann::json; - class Worker : public Channel::ChannelSocket::Listener, - public PayloadChannel::PayloadChannelSocket::Listener, - public SignalsHandler::Listener, + public SignalHandle::Listener, public RTC::Router::Listener { public: - explicit Worker(Channel::ChannelSocket* channel, PayloadChannel::PayloadChannelSocket* payloadChannel); + explicit Worker(Channel::ChannelSocket* channel); ~Worker(); private: void Close(); - void FillJson(json& jsonObject) const; - void FillJsonResourceUsage(json& jsonObject) const; - void SetNewWebRtcServerIdFromData(json& data, std::string& webRtcServerId) const; - RTC::WebRtcServer* GetWebRtcServerFromData(json& data) const; - void SetNewRouterIdFromData(json& data, std::string& routerId) const; - RTC::Router* GetRouterFromData(json& data) const; + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferResourceUsage( + flatbuffers::FlatBufferBuilder& builder) const; + void SetNewRouterId(std::string& routerId) const; + RTC::WebRtcServer* GetWebRtcServer(const std::string& webRtcServerId) const; + RTC::Router* GetRouter(const std::string& routerId) const; + void CheckNoWebRtcServer(const std::string& webRtcServerId) const; + void CheckNoRouter(const std::string& webRtcServerId) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; + void HandleNotification(Channel::ChannelNotification* notification) override; /* Methods inherited from Channel::ChannelSocket::Listener. */ public: void OnChannelClosed(Channel::ChannelSocket* channel) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::RequestHandler. */ -public: - void HandleRequest(PayloadChannel::PayloadChannelRequest* request) override; - - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ -public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; - - /* Methods inherited from PayloadChannel::PayloadChannelSocket::Listener. */ -public: - void OnPayloadChannelClosed(PayloadChannel::PayloadChannelSocket* payloadChannel) override; - - /* Methods inherited from SignalsHandler::Listener. */ + /* Methods inherited from SignalHandle::Listener. */ public: - void OnSignal(SignalsHandler* signalsHandler, int signum) override; + void OnSignal(SignalHandle* signalsHandler, int signum) override; /* Pure virtual methods inherited from RTC::Router::Listener. */ public: @@ -66,9 +52,8 @@ class Worker : public Channel::ChannelSocket::Listener, private: // Passed by argument. Channel::ChannelSocket* channel{ nullptr }; - PayloadChannel::PayloadChannelSocket* payloadChannel{ nullptr }; // Allocated by this. - SignalsHandler* signalsHandler{ nullptr }; + SignalHandle* signalHandle{ nullptr }; RTC::Shared* shared{ nullptr }; absl::flat_hash_map mapWebRtcServers; absl::flat_hash_map mapRouters; diff --git a/worker/include/common.hpp b/worker/include/common.hpp index f019dd411c..3934db04b8 100644 --- a/worker/include/common.hpp +++ b/worker/include/common.hpp @@ -7,6 +7,7 @@ #include // uint8_t, etc #include // std::function #include // std::addressof() +#include #ifdef _WIN32 #include // Avoid uv/win.h: error C2628 'intptr_t' followed by 'int' is illegal. @@ -41,28 +42,4 @@ using ChannelWriteCtx = void*; using ChannelWriteFn = void (*)(const uint8_t* /* message */, uint32_t /* messageLen */, ChannelWriteCtx /* ctx */); -using PayloadChannelReadCtx = void*; -using PayloadChannelReadFreeFn = void (*)(uint8_t*, uint32_t, size_t); -// Returns `PayloadChannelReadFree` on successful read that must be used to free -// `message` and `payload`. -using PayloadChannelReadFn = PayloadChannelReadFreeFn (*)( - uint8_t** /* message */, - uint32_t* /* messageLen */, - size_t* /* messageCtx */, - uint8_t** /* payload */, - uint32_t* /* payloadLen */, - size_t* /* payloadCapacity */, - // This is `uv_async_t` handle that can be called later with `uv_async_send()` - // when there is more data to read. - const void* /* handle */, - PayloadChannelReadCtx /* ctx */); - -using PayloadChannelWriteCtx = void*; -using PayloadChannelWriteFn = void (*)( - const uint8_t* /* message */, - uint32_t /* messageLen */, - const uint8_t* /* payload */, - uint32_t /* payloadLen */, - ChannelWriteCtx /* ctx */); - #endif diff --git a/worker/include/handles/SignalsHandler.hpp b/worker/include/handles/SignalHandle.hpp similarity index 68% rename from worker/include/handles/SignalsHandler.hpp rename to worker/include/handles/SignalHandle.hpp index 7c9407b7d4..ff32054389 100644 --- a/worker/include/handles/SignalsHandler.hpp +++ b/worker/include/handles/SignalHandle.hpp @@ -1,11 +1,11 @@ -#ifndef MS_SIGNALS_HANDLER_HPP -#define MS_SIGNALS_HANDLER_HPP +#ifndef MS_SIGNAL_HANDLE_HPP +#define MS_SIGNAL_HANDLE_HPP #include #include #include -class SignalsHandler +class SignalHandle { public: class Listener @@ -14,12 +14,12 @@ class SignalsHandler virtual ~Listener() = default; public: - virtual void OnSignal(SignalsHandler* signalsHandler, int signum) = 0; + virtual void OnSignal(SignalHandle* signalsHandler, int signum) = 0; }; public: - explicit SignalsHandler(Listener* listener); - ~SignalsHandler(); + explicit SignalHandle(Listener* listener); + ~SignalHandle(); public: void Close(); diff --git a/worker/include/handles/TcpConnectionHandler.hpp b/worker/include/handles/TcpConnectionHandle.hpp similarity index 85% rename from worker/include/handles/TcpConnectionHandler.hpp rename to worker/include/handles/TcpConnectionHandle.hpp index 0b536225ba..fd5b8c291d 100644 --- a/worker/include/handles/TcpConnectionHandler.hpp +++ b/worker/include/handles/TcpConnectionHandle.hpp @@ -1,11 +1,11 @@ -#ifndef MS_TCP_CONNECTION_HPP -#define MS_TCP_CONNECTION_HPP +#ifndef MS_TCP_CONNECTION_HANDLE_HPP +#define MS_TCP_CONNECTION_HANDLE_HPP #include "common.hpp" #include #include -class TcpConnectionHandler +class TcpConnectionHandle { protected: using onSendCallback = const std::function; @@ -17,7 +17,7 @@ class TcpConnectionHandler virtual ~Listener() = default; public: - virtual void OnTcpConnectionClosed(TcpConnectionHandler* connection) = 0; + virtual void OnTcpConnectionClosed(TcpConnectionHandle* connection) = 0; }; public: @@ -40,14 +40,14 @@ class TcpConnectionHandler uv_write_t req; uint8_t* store{ nullptr }; - TcpConnectionHandler::onSendCallback* cb{ nullptr }; + TcpConnectionHandle::onSendCallback* cb{ nullptr }; }; public: - explicit TcpConnectionHandler(size_t bufferSize); - TcpConnectionHandler& operator=(const TcpConnectionHandler&) = delete; - TcpConnectionHandler(const TcpConnectionHandler&) = delete; - virtual ~TcpConnectionHandler(); + explicit TcpConnectionHandle(size_t bufferSize); + TcpConnectionHandle& operator=(const TcpConnectionHandle&) = delete; + TcpConnectionHandle(const TcpConnectionHandle&) = delete; + virtual ~TcpConnectionHandle(); public: void Close(); @@ -71,7 +71,7 @@ class TcpConnectionHandler size_t len1, const uint8_t* data2, size_t len2, - TcpConnectionHandler::onSendCallback* cb); + TcpConnectionHandle::onSendCallback* cb); void ErrorReceiving(); const struct sockaddr* GetLocalAddress() const { diff --git a/worker/include/handles/TcpServerHandler.hpp b/worker/include/handles/TcpServerHandle.hpp similarity index 61% rename from worker/include/handles/TcpServerHandler.hpp rename to worker/include/handles/TcpServerHandle.hpp index ad7b52e8aa..3d7608d88d 100644 --- a/worker/include/handles/TcpServerHandler.hpp +++ b/worker/include/handles/TcpServerHandle.hpp @@ -1,20 +1,20 @@ -#ifndef MS_TCP_SERVER_HPP -#define MS_TCP_SERVER_HPP +#ifndef MS_TCP_SERVER_HANDLE_HPP +#define MS_TCP_SERVER_HANDLE_HPP #include "common.hpp" -#include "handles/TcpConnectionHandler.hpp" +#include "handles/TcpConnectionHandle.hpp" #include #include #include -class TcpServerHandler : public TcpConnectionHandler::Listener +class TcpServerHandle : public TcpConnectionHandle::Listener { public: /** * uvHandle must be an already initialized and binded uv_tcp_t pointer. */ - TcpServerHandler(uv_tcp_t* uvHandle); - virtual ~TcpServerHandler() override; + TcpServerHandle(uv_tcp_t* uvHandle); + virtual ~TcpServerHandle() override; public: void Close(); @@ -39,25 +39,29 @@ class TcpServerHandler : public TcpConnectionHandler::Listener { return this->connections.size(); } + uint32_t GetSendBufferSize() const; + void SetSendBufferSize(uint32_t size); + uint32_t GetRecvBufferSize() const; + void SetRecvBufferSize(uint32_t size); protected: - void AcceptTcpConnection(TcpConnectionHandler* connection); + void AcceptTcpConnection(TcpConnectionHandle* connection); private: bool SetLocalAddress(); /* Pure virtual methods that must be implemented by the subclass. */ protected: - virtual void UserOnTcpConnectionAlloc() = 0; - virtual void UserOnTcpConnectionClosed(TcpConnectionHandler* connection) = 0; + virtual void UserOnTcpConnectionAlloc() = 0; + virtual void UserOnTcpConnectionClosed(TcpConnectionHandle* connection) = 0; /* Callbacks fired by UV events. */ public: void OnUvConnection(int status); - /* Methods inherited from TcpConnectionHandler::Listener. */ + /* Methods inherited from TcpConnectionHandle::Listener. */ public: - void OnTcpConnectionClosed(TcpConnectionHandler* connection) override; + void OnTcpConnectionClosed(TcpConnectionHandle* connection) override; protected: struct sockaddr_storage localAddr; @@ -68,7 +72,7 @@ class TcpServerHandler : public TcpConnectionHandler::Listener // Allocated by this (may be passed by argument). uv_tcp_t* uvHandle{ nullptr }; // Others. - absl::flat_hash_set connections; + absl::flat_hash_set connections; bool closed{ false }; }; diff --git a/worker/include/handles/Timer.hpp b/worker/include/handles/TimerHandle.hpp similarity index 72% rename from worker/include/handles/Timer.hpp rename to worker/include/handles/TimerHandle.hpp index dfb9c47ee7..09ea83b5a8 100644 --- a/worker/include/handles/Timer.hpp +++ b/worker/include/handles/TimerHandle.hpp @@ -1,10 +1,10 @@ -#ifndef MS_TIMER_HPP -#define MS_TIMER_HPP +#ifndef MS_TIMER_HANDLE_HPP +#define MS_TIMER_HANDLE_HPP #include "common.hpp" #include -class Timer +class TimerHandle { public: class Listener @@ -13,14 +13,14 @@ class Timer virtual ~Listener() = default; public: - virtual void OnTimer(Timer* timer) = 0; + virtual void OnTimer(TimerHandle* timer) = 0; }; public: - explicit Timer(Listener* listener); - Timer& operator=(const Timer&) = delete; - Timer(const Timer&) = delete; - ~Timer(); + explicit TimerHandle(Listener* listener); + TimerHandle& operator=(const TimerHandle&) = delete; + TimerHandle(const TimerHandle&) = delete; + ~TimerHandle(); public: void Close(); diff --git a/worker/include/handles/UdpSocketHandler.hpp b/worker/include/handles/UdpSocketHandle.hpp similarity index 77% rename from worker/include/handles/UdpSocketHandler.hpp rename to worker/include/handles/UdpSocketHandle.hpp index 188f23b4fa..486ed5bebf 100644 --- a/worker/include/handles/UdpSocketHandler.hpp +++ b/worker/include/handles/UdpSocketHandle.hpp @@ -1,11 +1,11 @@ -#ifndef MS_UDP_SOCKET_HPP -#define MS_UDP_SOCKET_HPP +#ifndef MS_UDP_SOCKET_HANDLE_HPP +#define MS_UDP_SOCKET_HANDLE_HPP #include "common.hpp" #include #include -class UdpSocketHandler +class UdpSocketHandle { protected: using onSendCallback = const std::function; @@ -30,17 +30,17 @@ class UdpSocketHandler uv_udp_send_t req; uint8_t* store{ nullptr }; - UdpSocketHandler::onSendCallback* cb{ nullptr }; + UdpSocketHandle::onSendCallback* cb{ nullptr }; }; public: /** * uvHandle must be an already initialized and binded uv_udp_t pointer. */ - explicit UdpSocketHandler(uv_udp_t* uvHandle); - UdpSocketHandler& operator=(const UdpSocketHandler&) = delete; - UdpSocketHandler(const UdpSocketHandler&) = delete; - virtual ~UdpSocketHandler(); + explicit UdpSocketHandle(uv_udp_t* uvHandle); + UdpSocketHandle& operator=(const UdpSocketHandle&) = delete; + UdpSocketHandle(const UdpSocketHandle&) = delete; + virtual ~UdpSocketHandle(); public: void Close(); @@ -50,7 +50,7 @@ class UdpSocketHandler } virtual void Dump() const; void Send( - const uint8_t* data, size_t len, const struct sockaddr* addr, UdpSocketHandler::onSendCallback* cb); + const uint8_t* data, size_t len, const struct sockaddr* addr, UdpSocketHandle::onSendCallback* cb); const struct sockaddr* GetLocalAddress() const { return reinterpret_cast(&this->localAddr); @@ -75,6 +75,10 @@ class UdpSocketHandler { return this->sentBytes; } + uint32_t GetSendBufferSize() const; + void SetSendBufferSize(uint32_t size); + uint32_t GetRecvBufferSize() const; + void SetRecvBufferSize(uint32_t size); private: bool SetLocalAddress(); @@ -83,7 +87,7 @@ class UdpSocketHandler public: void OnUvRecvAlloc(size_t suggestedSize, uv_buf_t* buf); void OnUvRecv(ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned int flags); - void OnUvSend(int status, UdpSocketHandler::onSendCallback* cb); + void OnUvSend(int status, UdpSocketHandle::onSendCallback* cb); /* Pure virtual methods that must be implemented by the subclass. */ protected: diff --git a/worker/include/handles/UnixStreamSocket.hpp b/worker/include/handles/UnixStreamSocketHandle.hpp similarity index 70% rename from worker/include/handles/UnixStreamSocket.hpp rename to worker/include/handles/UnixStreamSocketHandle.hpp index 5d3f05764e..164ab02ec6 100644 --- a/worker/include/handles/UnixStreamSocket.hpp +++ b/worker/include/handles/UnixStreamSocketHandle.hpp @@ -1,11 +1,11 @@ -#ifndef MS_UNIX_STREAM_SOCKET_HPP -#define MS_UNIX_STREAM_SOCKET_HPP +#ifndef MS_UNIX_STREAM_SOCKET_HANDLE_HPP +#define MS_UNIX_STREAM_SOCKET_HANDLE_HPP #include "common.hpp" #include #include -class UnixStreamSocket +class UnixStreamSocketHandle { public: /* Struct for the data field of uv_req_t when writing data. */ @@ -35,10 +35,10 @@ class UnixStreamSocket }; public: - UnixStreamSocket(int fd, size_t bufferSize, UnixStreamSocket::Role role); - UnixStreamSocket& operator=(const UnixStreamSocket&) = delete; - UnixStreamSocket(const UnixStreamSocket&) = delete; - virtual ~UnixStreamSocket(); + UnixStreamSocketHandle(int fd, size_t bufferSize, UnixStreamSocketHandle::Role role); + UnixStreamSocketHandle& operator=(const UnixStreamSocketHandle&) = delete; + UnixStreamSocketHandle(const UnixStreamSocketHandle&) = delete; + virtual ~UnixStreamSocketHandle(); public: void Close(); @@ -47,6 +47,10 @@ class UnixStreamSocket return this->closed; } void Write(const uint8_t* data, size_t len); + uint32_t GetSendBufferSize() const; + void SetSendBufferSize(uint32_t size); + uint32_t GetRecvBufferSize() const; + void SetRecvBufferSize(uint32_t size); /* Callbacks fired by UV events. */ public: @@ -70,7 +74,7 @@ class UnixStreamSocket protected: // Passed by argument. size_t bufferSize{ 0u }; - UnixStreamSocket::Role role; + UnixStreamSocketHandle::Role role; // Allocated by this. uint8_t* buffer{ nullptr }; // Others. diff --git a/worker/include/lib.hpp b/worker/include/lib.hpp index 36d86d2d74..513e354b7d 100644 --- a/worker/include/lib.hpp +++ b/worker/include/lib.hpp @@ -11,8 +11,4 @@ extern "C" int mediasoup_worker_run( ChannelReadFn channelReadFn, ChannelReadCtx channelReadCtx, ChannelWriteFn channelWriteFn, - ChannelWriteCtx channelWriteCtx, - PayloadChannelReadFn payloadChannelReadFn, - PayloadChannelReadCtx payloadChannelReadCtx, - PayloadChannelWriteFn payloadChannelWriteFn, - PayloadChannelWriteCtx payloadChannelWriteCtx); + ChannelWriteCtx channelWriteCtx); diff --git a/worker/meson.build b/worker/meson.build index 45c5528f41..52c2244af4 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -60,19 +60,16 @@ common_sources = [ 'src/Utils/File.cpp', 'src/Utils/IP.cpp', 'src/Utils/String.cpp', - 'src/handles/SignalsHandler.cpp', - 'src/handles/TcpConnectionHandler.cpp', - 'src/handles/TcpServerHandler.cpp', - 'src/handles/Timer.cpp', - 'src/handles/UdpSocketHandler.cpp', - 'src/handles/UnixStreamSocket.cpp', + 'src/handles/SignalHandle.cpp', + 'src/handles/TcpConnectionHandle.cpp', + 'src/handles/TcpServerHandle.cpp', + 'src/handles/TimerHandle.cpp', + 'src/handles/UdpSocketHandle.cpp', + 'src/handles/UnixStreamSocketHandle.cpp', 'src/Channel/ChannelNotifier.cpp', 'src/Channel/ChannelRequest.cpp', + 'src/Channel/ChannelNotification.cpp', 'src/Channel/ChannelSocket.cpp', - 'src/PayloadChannel/PayloadChannelNotification.cpp', - 'src/PayloadChannel/PayloadChannelNotifier.cpp', - 'src/PayloadChannel/PayloadChannelRequest.cpp', - 'src/PayloadChannel/PayloadChannelSocket.cpp', 'src/RTC/ActiveSpeakerObserver.cpp', 'src/RTC/AudioLevelObserver.cpp', 'src/RTC/Consumer.cpp', @@ -126,7 +123,6 @@ common_sources = [ 'src/RTC/Codecs/VP8.cpp', 'src/RTC/Codecs/VP9.cpp', 'src/RTC/Codecs/Opus.cpp', - 'src/RTC/RtpDictionaries/Media.cpp', 'src/RTC/RtpDictionaries/Parameters.cpp', 'src/RTC/RtpDictionaries/RtcpFeedback.cpp', 'src/RTC/RtpDictionaries/RtcpParameters.cpp', @@ -175,12 +171,6 @@ openssl_proj = subproject( 'warning_level=0', ], ) -nlohmann_json_proj = subproject( - 'nlohmann_json', - default_options: [ - 'warning_level=0', - ], -) libuv_proj = subproject( 'libuv', default_options: [ @@ -217,16 +207,26 @@ catch2_proj = subproject( 'warning_level=0', ], ) -libwebrtc_include_directories = include_directories('include') +flatbuffers_proj = subproject( + 'flatbuffers', + default_options: [ + 'warning_level=0', + ], +) +# flatbuffers schemas subdirectory. +subdir('fbs') +# Add current build directory so libwebrtc has access to FBS folder. +libwebrtc_include_directories = include_directories('include', 'fbs') subdir('deps/libwebrtc') dependencies = [ abseil_cpp_proj.get_variable('absl_container_dep'), openssl_proj.get_variable('openssl_dep'), - nlohmann_json_proj.get_variable('nlohmann_json_dep'), libuv_proj.get_variable('libuv_dep'), libsrtp2_proj.get_variable('libsrtp2_dep'), usrsctp_proj.get_variable('usrsctp_dep'), + flatbuffers_proj.get_variable('flatbuffers_dep'), + flatbuffers_generator_dep, libwebrtc_dep, ] @@ -237,6 +237,7 @@ link_whole = [ libuv_proj.get_variable('libuv'), libsrtp2_proj.get_variable('libsrtp2'), usrsctp_proj.get_variable('usrsctp'), + flatbuffers_proj.get_variable('flatbuffers_lib'), libwebrtc, ] @@ -282,8 +283,6 @@ executable( test_sources = [ 'test/src/tests.cpp', - 'test/src/PayloadChannel/TestPayloadChannelNotification.cpp', - 'test/src/PayloadChannel/TestPayloadChannelRequest.cpp', 'test/src/RTC/TestKeyFrameRequestManager.cpp', 'test/src/RTC/TestNackGenerator.cpp', 'test/src/RTC/TestRateCalculator.cpp', @@ -323,7 +322,6 @@ test_sources = [ 'test/src/Utils/TestBits.cpp', 'test/src/Utils/TestByte.cpp', 'test/src/Utils/TestIP.cpp', - 'test/src/Utils/TestJson.cpp', 'test/src/Utils/TestString.cpp', 'test/src/Utils/TestTime.cpp', ] diff --git a/worker/scripts/package-lock.json b/worker/scripts/package-lock.json index 6d187c60d3..be2dde4032 100644 --- a/worker/scripts/package-lock.json +++ b/worker/scripts/package-lock.json @@ -1,16 +1,19 @@ { - "name": "clang-tools", + "name": "mediasoup-worker-dev-tools", "version": "0.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "clang-tools", + "name": "mediasoup-worker-dev-tools", "version": "0.0.1", "devDependencies": { "clang-tools-prebuilt": "^0.1.4", "gulp": "^4.0.2", "gulp-clang-format": "^1.0.27" + }, + "peerDependencies": { + "uuid": "^3.3.2" } }, "node_modules/ajv": { @@ -5123,7 +5126,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, "bin": { "uuid": "bin/uuid" } @@ -9644,8 +9646,7 @@ "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v8flags": { "version": "3.2.0", diff --git a/worker/scripts/package.json b/worker/scripts/package.json index c6d17b7639..fc42fde271 100644 --- a/worker/scripts/package.json +++ b/worker/scripts/package.json @@ -1,10 +1,13 @@ { - "name": "clang-tools", + "name": "mediasoup-worker-dev-tools", "version": "0.0.1", "description": "mediasoup worker dev tools", "devDependencies": { "clang-tools-prebuilt": "^0.1.4", "gulp": "^4.0.2", "gulp-clang-format": "^1.0.27" + }, + "peerDependencies": { + "uuid": "^3.3.2" } } diff --git a/worker/src/Channel/ChannelNotification.cpp b/worker/src/Channel/ChannelNotification.cpp new file mode 100644 index 0000000000..6dc4d2a89c --- /dev/null +++ b/worker/src/Channel/ChannelNotification.cpp @@ -0,0 +1,45 @@ +#define MS_CLASS "Channel::ChannelNotification" +// #define MS_LOG_DEV_LEVEL 3 + +#include "Channel/ChannelNotification.hpp" +#include "Logger.hpp" +#include "MediaSoupErrors.hpp" + +namespace Channel +{ + /* Class variables. */ + + // clang-format off + absl::flat_hash_map ChannelNotification::event2String = + { + { FBS::Notification::Event::TRANSPORT_SEND_RTCP, "transport.sendRtcp" }, + { FBS::Notification::Event::PRODUCER_SEND, "producer.send" }, + { FBS::Notification::Event::DATAPRODUCER_SEND, "dataProducer.send" }, + }; + // clang-format on + + /* Instance methods. */ + + ChannelNotification::ChannelNotification(const FBS::Notification::Notification* notification) + { + MS_TRACE(); + + this->data = notification; + this->event = notification->event(); + + auto eventCStrIt = ChannelNotification::event2String.find(this->event); + + if (eventCStrIt == ChannelNotification::event2String.end()) + { + MS_THROW_ERROR("unknown event '%" PRIu8 "'", static_cast(this->event)); + } + + this->eventCStr = eventCStrIt->second; + + // Handler ID is optional. + if (flatbuffers::IsFieldPresent(this->data, FBS::Notification::Notification::VT_HANDLERID)) + { + this->handlerId = this->data->handlerId()->str(); + } + } +} // namespace Channel diff --git a/worker/src/Channel/ChannelNotifier.cpp b/worker/src/Channel/ChannelNotifier.cpp index 8ef6b23b2a..78a354940b 100644 --- a/worker/src/Channel/ChannelNotifier.cpp +++ b/worker/src/Channel/ChannelNotifier.cpp @@ -10,57 +10,4 @@ namespace Channel { MS_TRACE(); } - - void ChannelNotifier::Emit(uint64_t targetId, const char* event) - { - MS_TRACE(); - - json jsonNotification = json::object(); - - jsonNotification["targetId"] = targetId; - jsonNotification["event"] = event; - - this->channel->Send(jsonNotification); - } - - void ChannelNotifier::Emit(const std::string& targetId, const char* event) - { - MS_TRACE(); - - json jsonNotification = json::object(); - - jsonNotification["targetId"] = targetId; - jsonNotification["event"] = event; - - this->channel->Send(jsonNotification); - } - - void ChannelNotifier::Emit(const std::string& targetId, const char* event, json& data) - { - MS_TRACE(); - - json jsonNotification = json::object(); - - jsonNotification["targetId"] = targetId; - jsonNotification["event"] = event; - jsonNotification["data"] = data; - - this->channel->Send(jsonNotification); - } - - void ChannelNotifier::Emit(const std::string& targetId, const char* event, const std::string& data) - { - MS_TRACE(); - - std::string notification("{\"targetId\":\""); - - notification.append(targetId); - notification.append("\",\"event\":\""); - notification.append(event); - notification.append("\",\"data\":"); - notification.append(data); - notification.append("}"); - - this->channel->Send(notification); - } } // namespace Channel diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index d107b39329..01b56cf5de 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -4,140 +4,114 @@ #include "Channel/ChannelRequest.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" namespace Channel { /* Class variables. */ // clang-format off - absl::flat_hash_map ChannelRequest::string2MethodId = + absl::flat_hash_map ChannelRequest::method2String = { - { "worker.close", ChannelRequest::MethodId::WORKER_CLOSE }, - { "worker.dump", ChannelRequest::MethodId::WORKER_DUMP }, - { "worker.getResourceUsage", ChannelRequest::MethodId::WORKER_GET_RESOURCE_USAGE }, - { "worker.updateSettings", ChannelRequest::MethodId::WORKER_UPDATE_SETTINGS }, - { "worker.createWebRtcServer", ChannelRequest::MethodId::WORKER_CREATE_WEBRTC_SERVER }, - { "worker.createRouter", ChannelRequest::MethodId::WORKER_CREATE_ROUTER }, - { "worker.closeWebRtcServer", ChannelRequest::MethodId::WORKER_WEBRTC_SERVER_CLOSE }, - { "webRtcServer.dump", ChannelRequest::MethodId::WEBRTC_SERVER_DUMP }, - { "worker.closeRouter", ChannelRequest::MethodId::WORKER_CLOSE_ROUTER }, - { "router.dump", ChannelRequest::MethodId::ROUTER_DUMP }, - { "router.createWebRtcTransport", ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT }, - { "router.createWebRtcTransportWithServer", ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER }, - { "router.createPlainTransport", ChannelRequest::MethodId::ROUTER_CREATE_PLAIN_TRANSPORT }, - { "router.createPipeTransport", ChannelRequest::MethodId::ROUTER_CREATE_PIPE_TRANSPORT }, - { "router.createDirectTransport", ChannelRequest::MethodId::ROUTER_CREATE_DIRECT_TRANSPORT }, - { "router.closeTransport", ChannelRequest::MethodId::ROUTER_CLOSE_TRANSPORT }, - { "router.createActiveSpeakerObserver", ChannelRequest::MethodId::ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER }, - { "router.createAudioLevelObserver", ChannelRequest::MethodId::ROUTER_CREATE_AUDIO_LEVEL_OBSERVER }, - { "router.closeRtpObserver", ChannelRequest::MethodId::ROUTER_CLOSE_RTP_OBSERVER }, - { "transport.dump", ChannelRequest::MethodId::TRANSPORT_DUMP }, - { "transport.getStats", ChannelRequest::MethodId::TRANSPORT_GET_STATS }, - { "transport.connect", ChannelRequest::MethodId::TRANSPORT_CONNECT }, - { "transport.setMaxIncomingBitrate", ChannelRequest::MethodId::TRANSPORT_SET_MAX_INCOMING_BITRATE }, - { "transport.setMaxOutgoingBitrate", ChannelRequest::MethodId::TRANSPORT_SET_MAX_OUTGOING_BITRATE }, - { "transport.setMinOutgoingBitrate", ChannelRequest::MethodId::TRANSPORT_SET_MIN_OUTGOING_BITRATE }, - { "transport.restartIce", ChannelRequest::MethodId::TRANSPORT_RESTART_ICE }, - { "transport.produce", ChannelRequest::MethodId::TRANSPORT_PRODUCE }, - { "transport.consume", ChannelRequest::MethodId::TRANSPORT_CONSUME }, - { "transport.produceData", ChannelRequest::MethodId::TRANSPORT_PRODUCE_DATA }, - { "transport.consumeData", ChannelRequest::MethodId::TRANSPORT_CONSUME_DATA }, - { "transport.enableTraceEvent", ChannelRequest::MethodId::TRANSPORT_ENABLE_TRACE_EVENT }, - { "transport.closeProducer", ChannelRequest::MethodId::TRANSPORT_CLOSE_PRODUCER }, - { "transport.closeConsumer", ChannelRequest::MethodId::TRANSPORT_CLOSE_CONSUMER }, - { "transport.closeDataProducer", ChannelRequest::MethodId::TRANSPORT_CLOSE_DATA_PRODUCER }, - { "transport.closeDataConsumer", ChannelRequest::MethodId::TRANSPORT_CLOSE_DATA_CONSUMER }, - { "producer.dump", ChannelRequest::MethodId::PRODUCER_DUMP }, - { "producer.getStats", ChannelRequest::MethodId::PRODUCER_GET_STATS }, - { "producer.pause", ChannelRequest::MethodId::PRODUCER_PAUSE }, - { "producer.resume" , ChannelRequest::MethodId::PRODUCER_RESUME }, - { "producer.enableTraceEvent", ChannelRequest::MethodId::PRODUCER_ENABLE_TRACE_EVENT }, - { "consumer.dump", ChannelRequest::MethodId::CONSUMER_DUMP }, - { "consumer.getStats", ChannelRequest::MethodId::CONSUMER_GET_STATS }, - { "consumer.pause", ChannelRequest::MethodId::CONSUMER_PAUSE }, - { "consumer.resume", ChannelRequest::MethodId::CONSUMER_RESUME }, - { "consumer.setPreferredLayers", ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS }, - { "consumer.setPriority", ChannelRequest::MethodId::CONSUMER_SET_PRIORITY }, - { "consumer.requestKeyFrame", ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME }, - { "consumer.enableTraceEvent", ChannelRequest::MethodId::CONSUMER_ENABLE_TRACE_EVENT }, - { "dataProducer.dump", ChannelRequest::MethodId::DATA_PRODUCER_DUMP }, - { "dataProducer.getStats", ChannelRequest::MethodId::DATA_PRODUCER_GET_STATS }, - { "dataConsumer.dump", ChannelRequest::MethodId::DATA_CONSUMER_DUMP }, - { "dataConsumer.getStats", ChannelRequest::MethodId::DATA_CONSUMER_GET_STATS }, - { "dataConsumer.getBufferedAmount", ChannelRequest::MethodId::DATA_CONSUMER_GET_BUFFERED_AMOUNT }, - { "dataConsumer.setBufferedAmountLowThreshold", ChannelRequest::MethodId::DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD }, - { "rtpObserver.pause", ChannelRequest::MethodId::RTP_OBSERVER_PAUSE }, - { "rtpObserver.resume", ChannelRequest::MethodId::RTP_OBSERVER_RESUME }, - { "rtpObserver.addProducer", ChannelRequest::MethodId::RTP_OBSERVER_ADD_PRODUCER }, - { "rtpObserver.removeProducer", ChannelRequest::MethodId::RTP_OBSERVER_REMOVE_PRODUCER } + { FBS::Request::Method::WORKER_CLOSE, "worker.close" }, + { FBS::Request::Method::WORKER_DUMP, "worker.dump" }, + { FBS::Request::Method::WORKER_GET_RESOURCE_USAGE, "worker.getResourceUsage" }, + { FBS::Request::Method::WORKER_UPDATE_SETTINGS, "worker.updateSettings" }, + { FBS::Request::Method::WORKER_CREATE_WEBRTCSERVER, "worker.createWebRtcServer" }, + { FBS::Request::Method::WORKER_CREATE_ROUTER, "worker.createRouter" }, + { FBS::Request::Method::WORKER_WEBRTCSERVER_CLOSE, "worker.closeWebRtcServer" }, + { FBS::Request::Method::WORKER_CLOSE_ROUTER, "worker.closeRouter" }, + { FBS::Request::Method::WEBRTCSERVER_DUMP, "webRtcServer.dump" }, + { FBS::Request::Method::ROUTER_DUMP, "router.dump" }, + { FBS::Request::Method::ROUTER_CREATE_WEBRTCTRANSPORT, "router.createWebRtcTransport" }, + { FBS::Request::Method::ROUTER_CREATE_WEBRTCTRANSPORT_WITH_SERVER, "router.createWebRtcTransportWithServer" }, + { FBS::Request::Method::ROUTER_CREATE_PLAINTRANSPORT, "router.createPlainTransport" }, + { FBS::Request::Method::ROUTER_CREATE_PIPETRANSPORT, "router.createPipeTransport" }, + { FBS::Request::Method::ROUTER_CREATE_DIRECTTRANSPORT, "router.createDirectTransport" }, + { FBS::Request::Method::ROUTER_CLOSE_TRANSPORT, "router.closeTransport" }, + { FBS::Request::Method::ROUTER_CREATE_ACTIVESPEAKEROBSERVER, "router.createActiveSpeakerObserver" }, + { FBS::Request::Method::ROUTER_CREATE_AUDIOLEVELOBSERVER, "router.createAudioLevelObserver" }, + { FBS::Request::Method::ROUTER_CLOSE_RTPOBSERVER, "router.closeRtpObserver" }, + { FBS::Request::Method::TRANSPORT_DUMP, "transport.dump" }, + { FBS::Request::Method::TRANSPORT_GET_STATS, "transport.getStats" }, + { FBS::Request::Method::TRANSPORT_CONNECT, "transport.connect" }, + { FBS::Request::Method::TRANSPORT_SET_MAX_INCOMING_BITRATE, "transport.setMaxIncomingBitrate" }, + { FBS::Request::Method::TRANSPORT_SET_MAX_OUTGOING_BITRATE, "transport.setMaxOutgoingBitrate" }, + { FBS::Request::Method::TRANSPORT_SET_MIN_OUTGOING_BITRATE, "transport.setMinOutgoingBitrate" }, + { FBS::Request::Method::TRANSPORT_RESTART_ICE, "transport.restartIce" }, + { FBS::Request::Method::TRANSPORT_PRODUCE, "transport.produce" }, + { FBS::Request::Method::TRANSPORT_PRODUCE_DATA, "transport.produceData" }, + { FBS::Request::Method::TRANSPORT_CONSUME, "transport.consume" }, + { FBS::Request::Method::TRANSPORT_CONSUME_DATA, "transport.consumeData" }, + { FBS::Request::Method::TRANSPORT_ENABLE_TRACE_EVENT, "transport.enableTraceEvent" }, + { FBS::Request::Method::TRANSPORT_CLOSE_PRODUCER, "transport.closeProducer" }, + { FBS::Request::Method::TRANSPORT_CLOSE_CONSUMER, "transport.closeConsumer" }, + { FBS::Request::Method::TRANSPORT_CLOSE_DATAPRODUCER, "transport.closeDataProducer" }, + { FBS::Request::Method::TRANSPORT_CLOSE_DATACONSUMER, "transport.closeDataConsumer" }, + { FBS::Request::Method::PLAINTRANSPORT_CONNECT, "plainTransport.connect" }, + { FBS::Request::Method::PIPETRANSPORT_CONNECT, "pipeTransport.connect" }, + { FBS::Request::Method::WEBRTCTRANSPORT_CONNECT, "webRtcTransport.connect" }, + { FBS::Request::Method::PRODUCER_DUMP, "producer.dump" }, + { FBS::Request::Method::PRODUCER_GET_STATS, "producer.getStats" }, + { FBS::Request::Method::PRODUCER_PAUSE, "producer.pause" }, + { FBS::Request::Method::PRODUCER_RESUME, "producer.resume" }, + { FBS::Request::Method::PRODUCER_ENABLE_TRACE_EVENT, "producer.enableTraceEvent" }, + { FBS::Request::Method::CONSUMER_DUMP, "consumer.dump" }, + { FBS::Request::Method::CONSUMER_GET_STATS, "consumer.getStats" }, + { FBS::Request::Method::CONSUMER_PAUSE, "consumer.pause" }, + { FBS::Request::Method::CONSUMER_RESUME, "consumer.resume" }, + { FBS::Request::Method::CONSUMER_SET_PREFERRED_LAYERS, "consumer.setPreferredLayers" }, + { FBS::Request::Method::CONSUMER_SET_PRIORITY, "consumer.setPriority" }, + { FBS::Request::Method::CONSUMER_REQUEST_KEY_FRAME, "consumer.requestKeyFrame" }, + { FBS::Request::Method::CONSUMER_ENABLE_TRACE_EVENT, "consumer.enableTraceEvent" }, + { FBS::Request::Method::DATAPRODUCER_DUMP, "dataProducer.dump" }, + { FBS::Request::Method::DATAPRODUCER_GET_STATS, "dataProducer.getStats" }, + { FBS::Request::Method::DATAPRODUCER_PAUSE, "dataProducer.pause" }, + { FBS::Request::Method::DATAPRODUCER_RESUME, "dataProducer.resume" }, + { FBS::Request::Method::DATACONSUMER_DUMP, "dataConsumer.dump" }, + { FBS::Request::Method::DATACONSUMER_GET_STATS, "dataConsumer.getStats" }, + { FBS::Request::Method::DATACONSUMER_PAUSE, "dataConsumer.pause" }, + { FBS::Request::Method::DATACONSUMER_RESUME, "dataConsumer.resume" }, + { FBS::Request::Method::DATACONSUMER_GET_BUFFERED_AMOUNT, "dataConsumer.getBufferedAmount" }, + { FBS::Request::Method::DATACONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, "dataConsumer.setBufferedAmountLowThreshold" }, + { FBS::Request::Method::DATACONSUMER_SEND, "dataConsumer.send" }, + { FBS::Request::Method::DATACONSUMER_SET_SUBCHANNELS, "dataConsumer.setSubchannels" }, + { FBS::Request::Method::RTPOBSERVER_PAUSE, "rtpObserver.pause" }, + { FBS::Request::Method::RTPOBSERVER_RESUME, "rtpObserver.resume" }, + { FBS::Request::Method::RTPOBSERVER_ADD_PRODUCER, "rtpObserver.addProducer" }, + { FBS::Request::Method::RTPOBSERVER_REMOVE_PRODUCER, "rtpObserver.removeProducer" }, }; // clang-format on /* Instance methods. */ /** - * msg contains "id:method:handlerId:data" where: - * - id: The ID of the request. - * - handlerId: The ID of the target entity - * - data: JSON object. + * msg contains the request flatbuffer. */ - ChannelRequest::ChannelRequest(Channel::ChannelSocket* channel, const char* msg, size_t msgLen) + ChannelRequest::ChannelRequest(Channel::ChannelSocket* channel, const FBS::Request::Request* request) : channel(channel) { MS_TRACE(); - auto info = Utils::String::Split(std::string(msg, msgLen), ':', 3); + this->data = request; + this->id = request->id(); + this->method = request->method(); - if (info.size() < 2) - MS_THROW_ERROR("too few arguments"); + auto methodCStrIt = ChannelRequest::method2String.find(this->method); - this->id = std::stoul(info[0]); - this->method = info[1]; - - auto methodIdIt = ChannelRequest::string2MethodId.find(this->method); - - if (methodIdIt == ChannelRequest::string2MethodId.end()) + if (methodCStrIt == ChannelRequest::method2String.end()) { Error("unknown method"); - MS_THROW_ERROR("unknown method '%s'", this->method.c_str()); + MS_THROW_ERROR("unknown method '%" PRIu8 "'", static_cast(this->method)); } - this->methodId = methodIdIt->second; + this->methodCStr = methodCStrIt->second; - if (info.size() > 2) + // Handler ID is optional. + if (flatbuffers::IsFieldPresent(this->data, FBS::Request::Request::VT_HANDLERID)) { - auto& handlerId = info[2]; - - if (handlerId != "undefined") - this->handlerId = handlerId; + this->handlerId = this->data->handlerId()->str(); } - - if (info.size() > 3) - { - auto& data = info[3]; - - if (data != "undefined") - { - try - { - this->data = json::parse(data); - - if (!this->data.is_object()) - this->data = json::object(); - } - catch (const json::parse_error& error) - { - MS_THROW_TYPE_ERROR("JSON parsing error: %s", error.what()); - } - } - } - } - - ChannelRequest::~ChannelRequest() - { - MS_TRACE(); } void ChannelRequest::Accept() @@ -148,15 +122,14 @@ namespace Channel this->replied = true; - std::string response("{\"id\":"); - - response.append(std::to_string(this->id)); - response.append(",\"accepted\":true}"); + auto& builder = this->bufferBuilder; + auto response = + FBS::Response::CreateResponse(builder, this->id, true, FBS::Response::Body::NONE, 0); - this->channel->Send(response); + this->SendResponse(response); } - void ChannelRequest::Accept(json& data) + void ChannelRequest::Error(const char* reason) { MS_TRACE(); @@ -164,18 +137,14 @@ namespace Channel this->replied = true; - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["accepted"] = true; - - if (data.is_structured()) - jsonResponse["data"] = data; + auto& builder = this->bufferBuilder; + auto response = FBS::Response::CreateResponseDirect( + builder, this->id, false /*accepted*/, FBS::Response::Body::NONE, 0, "Error" /*Error*/, reason); - this->channel->Send(jsonResponse); + this->SendResponse(response); } - void ChannelRequest::Error(const char* reason) + void ChannelRequest::TypeError(const char* reason) { MS_TRACE(); @@ -183,33 +152,26 @@ namespace Channel this->replied = true; - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["error"] = "Error"; - - if (reason != nullptr) - jsonResponse["reason"] = reason; + auto& builder = this->bufferBuilder; + auto response = FBS::Response::CreateResponseDirect( + builder, this->id, false /*accepted*/, FBS::Response::Body::NONE, 0, "TypeError" /*Error*/, reason); - this->channel->Send(jsonResponse); + this->SendResponse(response); } - void ChannelRequest::TypeError(const char* reason) + void ChannelRequest::Send(uint8_t* buffer, size_t size) { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["error"] = "TypeError"; + this->channel->Send(buffer, size); + } - if (reason != nullptr) - jsonResponse["reason"] = reason; + void ChannelRequest::SendResponse(const flatbuffers::Offset& response) + { + auto& builder = this->bufferBuilder; + auto message = + FBS::Message::CreateMessage(builder, FBS::Message::Body::Response, response.Union()); - this->channel->Send(jsonResponse); + builder.FinishSizePrefixed(message); + this->Send(builder.GetBufferPointer(), builder.GetSize()); + builder.Reset(); } } // namespace Channel diff --git a/worker/src/Channel/ChannelSocket.cpp b/worker/src/Channel/ChannelSocket.cpp index 473b8927f2..570bc6c2f5 100644 --- a/worker/src/Channel/ChannelSocket.cpp +++ b/worker/src/Channel/ChannelSocket.cpp @@ -5,7 +5,6 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include // std::ceil() #include // std::memcpy(), std::memmove() namespace Channel @@ -33,8 +32,7 @@ namespace Channel ChannelSocket::ChannelSocket(int consumerFd, int producerFd) : consumerSocket(new ConsumerSocket(consumerFd, MessageMaxLen, this)), - producerSocket(new ProducerSocket(producerFd, MessageMaxLen)), - writeBuffer(static_cast(std::malloc(MessageMaxLen))) + producerSocket(new ProducerSocket(producerFd, MessageMaxLen)) { MS_TRACE_STD(); } @@ -80,8 +78,6 @@ namespace Channel { MS_TRACE_STD(); - std::free(this->writeBuffer); - if (!this->closed) Close(); @@ -122,45 +118,24 @@ namespace Channel this->listener = listener; } - void ChannelSocket::Send(json& jsonMessage) + void ChannelSocket::Send(const uint8_t* message, uint32_t messageLen) { MS_TRACE_STD(); if (this->closed) return; - std::string message = jsonMessage.dump(); - - if (message.length() > PayloadMaxLen) - { - MS_ERROR_STD("message too big"); - - return; - } - - SendImpl( - reinterpret_cast(message.c_str()), static_cast(message.length())); - } - - void ChannelSocket::Send(const std::string& message) - { - MS_TRACE_STD(); - - if (this->closed) - return; - - if (message.length() > PayloadMaxLen) + if (messageLen > PayloadMaxLen) { MS_ERROR_STD("message too big"); return; } - SendImpl( - reinterpret_cast(message.c_str()), static_cast(message.length())); + SendImpl(reinterpret_cast(message), messageLen); } - void ChannelSocket::SendLog(const char* message, uint32_t messageLen) + void ChannelSocket::SendLog(const char* msg, uint32_t messageLen) { MS_TRACE_STD(); @@ -174,7 +149,13 @@ namespace Channel return; } - SendImpl(reinterpret_cast(message), messageLen); + auto log = FBS::Log::CreateLogDirect(this->bufferBuilder, msg); + auto message = + FBS::Message::CreateMessage(this->bufferBuilder, FBS::Message::Body::Log, log.Union()); + + this->bufferBuilder.FinishSizePrefixed(message); + this->Send(this->bufferBuilder.GetBufferPointer(), this->bufferBuilder.GetSize()); + this->bufferBuilder.Reset(); } bool ChannelSocket::CallbackRead() @@ -184,28 +165,35 @@ namespace Channel if (this->closed) return false; - uint8_t* message{ nullptr }; - uint32_t messageLen; - size_t messageCtx; + uint8_t* msg{ nullptr }; + uint32_t msgLen; + size_t msgCtx; // Try to read next message using `channelReadFn`, message, its length and context will be // stored in provided arguments. - auto free = this->channelReadFn( - &message, &messageLen, &messageCtx, this->uvReadHandle, this->channelReadCtx); + auto free = this->channelReadFn(&msg, &msgLen, &msgCtx, this->uvReadHandle, this->channelReadCtx); // Non-null free function pointer means message was successfully read above and will need to be // freed later. if (free) { - try - { - char* charMessage{ reinterpret_cast(message) }; + const auto* message = FBS::Message::GetMessage(msg); - auto* request = new Channel::ChannelRequest(this, charMessage, messageLen); +#if MS_LOG_DEV_LEVEL == 3 + auto s = flatbuffers::FlatBufferToString( + reinterpret_cast(msg), FBS::Message::MessageTypeTable()); + MS_DUMP("%s", s.c_str()); +#endif + + if (message->data_type() == FBS::Message::Body::Request) + { + ChannelRequest* request; - // Notify the listener. try { + request = new ChannelRequest(this, message->data_as()); + + // Notify the listener. this->listener->HandleRequest(request); } catch (const MediaSoupTypeError& error) @@ -217,20 +205,33 @@ namespace Channel request->Error(error.what()); } - // Delete the Request. delete request; } - catch (const json::parse_error& error) + else if (message->data_type() == FBS::Message::Body::Notification) { - MS_ERROR_STD("message parsing error: %s", error.what()); + ChannelNotification* notification; + + try + { + notification = new ChannelNotification(message->data_as()); + + // Notify the listener. + this->listener->HandleNotification(notification); + } + catch (const MediaSoupError& error) + { + MS_ERROR("notification failed: %s", error.what()); + } + + delete notification; } - catch (const MediaSoupError& error) + else { - MS_ERROR_STD("discarding wrong Channel request: %s", error.what()); + MS_ERROR("discarding wrong Channel data"); } // Message needs to be freed using stored function pointer. - free(message, messageLen, messageCtx); + free(msg, msgLen, msgCtx); } // Return `true` if something was processed. @@ -248,30 +249,31 @@ namespace Channel } else { - std::memcpy(this->writeBuffer, &payloadLen, sizeof(uint32_t)); - - if (payloadLen != 0) - { - std::memcpy(this->writeBuffer + sizeof(uint32_t), payload, payloadLen); - } - - size_t len = sizeof(uint32_t) + payloadLen; - - this->producerSocket->Write(this->writeBuffer, len); + this->producerSocket->Write(payload, payloadLen); } } void ChannelSocket::OnConsumerSocketMessage(ConsumerSocket* /*consumerSocket*/, char* msg, size_t msgLen) { - MS_TRACE_STD(); + MS_TRACE(); + + const auto* message = FBS::Message::GetMessage(msg); - try +#if MS_LOG_DEV_LEVEL == 3 + auto s = flatbuffers::FlatBufferToString( + reinterpret_cast(msg), FBS::Message::MessageTypeTable()); + MS_DUMP("%s", s.c_str()); +#endif + + if (message->data_type() == FBS::Message::Body::Request) { - auto* request = new Channel::ChannelRequest(this, msg, msgLen); + ChannelRequest* request; - // Notify the listener. try { + request = new ChannelRequest(this, message->data_as()); + + // Notify the listener. this->listener->HandleRequest(request); } catch (const MediaSoupTypeError& error) @@ -283,16 +285,29 @@ namespace Channel request->Error(error.what()); } - // Delete the Request. delete request; } - catch (const json::parse_error& error) + else if (message->data_type() == FBS::Message::Body::Notification) { - MS_ERROR_STD("JSON parsing error: %s", error.what()); + ChannelNotification* notification; + + try + { + notification = new ChannelNotification(message->data_as()); + + // Notify the listener. + this->listener->HandleNotification(notification); + } + catch (const MediaSoupError& error) + { + MS_ERROR("notification failed: %s", error.what()); + } + + delete notification; } - catch (const MediaSoupError& error) + else { - MS_ERROR_STD("discarding wrong Channel request: %s", error.what()); + MS_ERROR("discarding wrong Channel data"); } } @@ -306,7 +321,8 @@ namespace Channel /* Instance methods. */ ConsumerSocket::ConsumerSocket(int fd, size_t bufferSize, Listener* listener) - : ::UnixStreamSocket(fd, bufferSize, ::UnixStreamSocket::Role::CONSUMER), listener(listener) + : ::UnixStreamSocketHandle(fd, bufferSize, ::UnixStreamSocketHandle::Role::CONSUMER), + listener(listener) { MS_TRACE_STD(); } @@ -376,7 +392,7 @@ namespace Channel /* Instance methods. */ ProducerSocket::ProducerSocket(int fd, size_t bufferSize) - : ::UnixStreamSocket(fd, bufferSize, ::UnixStreamSocket::Role::PRODUCER) + : ::UnixStreamSocketHandle(fd, bufferSize, ::UnixStreamSocketHandle::Role::PRODUCER) { MS_TRACE_STD(); } diff --git a/worker/src/ChannelMessageRegistrator.cpp b/worker/src/ChannelMessageRegistrator.cpp index 4f5c9bbe50..647994d35c 100644 --- a/worker/src/ChannelMessageRegistrator.cpp +++ b/worker/src/ChannelMessageRegistrator.cpp @@ -15,54 +15,38 @@ ChannelMessageRegistrator::~ChannelMessageRegistrator() MS_TRACE(); this->mapChannelRequestHandlers.clear(); - this->mapPayloadChannelRequestHandlers.clear(); - this->mapPayloadChannelNotificationHandlers.clear(); + this->mapChannelNotificationHandlers.clear(); } -void ChannelMessageRegistrator::FillJson(json& jsonObject) +flatbuffers::Offset ChannelMessageRegistrator::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) { - MS_TRACE(); - - // Add channelRequestHandlers. - jsonObject["channelRequestHandlers"] = json::array(); - auto jsonChannelRequestHandlersIt = jsonObject.find("channelRequestHandlers"); - + // Add channelRequestHandlerIds. + std::vector> channelRequestHandlerIds; for (const auto& kv : this->mapChannelRequestHandlers) { const auto& handlerId = kv.first; - jsonChannelRequestHandlersIt->emplace_back(handlerId); + channelRequestHandlerIds.push_back(builder.CreateString(handlerId)); } - // Add payloadChannelRequestHandlers. - jsonObject["payloadChannelRequestHandlers"] = json::array(); - auto jsonPayloadChannelRequestHandlersIt = jsonObject.find("payloadChannelRequestHandlers"); - - for (const auto& kv : this->mapPayloadChannelRequestHandlers) + // Add channelNotificationHandlerIds. + std::vector> channelNotificationHandlerIds; + for (const auto& kv : this->mapChannelNotificationHandlers) { const auto& handlerId = kv.first; - jsonPayloadChannelRequestHandlersIt->emplace_back(handlerId); + channelNotificationHandlerIds.push_back(builder.CreateString(handlerId)); } - // Add payloadChannelNotificationHandlers. - jsonObject["payloadChannelNotificationHandlers"] = json::array(); - auto jsonPayloadChannelNotificationHandlersIt = - jsonObject.find("payloadChannelNotificationHandlers"); - - for (const auto& kv : this->mapPayloadChannelNotificationHandlers) - { - const auto& handlerId = kv.first; - - jsonPayloadChannelNotificationHandlersIt->emplace_back(handlerId); - } + return FBS::Worker::CreateChannelMessageHandlersDirect( + builder, &channelRequestHandlerIds, &channelNotificationHandlerIds); } void ChannelMessageRegistrator::RegisterHandler( const std::string& id, Channel::ChannelSocket::RequestHandler* channelRequestHandler, - PayloadChannel::PayloadChannelSocket::RequestHandler* payloadChannelRequestHandler, - PayloadChannel::PayloadChannelSocket::NotificationHandler* payloadChannelNotificationHandler) + Channel::ChannelSocket::NotificationHandler* channelNotificationHandler) { MS_TRACE(); @@ -76,41 +60,19 @@ void ChannelMessageRegistrator::RegisterHandler( this->mapChannelRequestHandlers[id] = channelRequestHandler; } - if (payloadChannelRequestHandler != nullptr) - { - if (this->mapPayloadChannelRequestHandlers.find(id) != this->mapPayloadChannelRequestHandlers.end()) - { - if (channelRequestHandler != nullptr) - { - this->mapChannelRequestHandlers.erase(id); - } - - MS_THROW_ERROR("PayloadChannel request handler with ID %s already exists", id.c_str()); - } - - this->mapPayloadChannelRequestHandlers[id] = payloadChannelRequestHandler; - } - - if (payloadChannelNotificationHandler != nullptr) + if (channelNotificationHandler != nullptr) { - if ( - this->mapPayloadChannelNotificationHandlers.find(id) != - this->mapPayloadChannelNotificationHandlers.end()) + if (this->mapChannelNotificationHandlers.find(id) != this->mapChannelNotificationHandlers.end()) { if (channelRequestHandler != nullptr) { this->mapChannelRequestHandlers.erase(id); } - if (payloadChannelRequestHandler != nullptr) - { - this->mapPayloadChannelRequestHandlers.erase(id); - } - - MS_THROW_ERROR("PayloadChannel notification handler with ID %s already exists", id.c_str()); + MS_THROW_ERROR("Channel notification handler with ID %s already exists", id.c_str()); } - this->mapPayloadChannelNotificationHandlers[id] = payloadChannelNotificationHandler; + this->mapChannelNotificationHandlers[id] = channelNotificationHandler; } } @@ -119,8 +81,7 @@ void ChannelMessageRegistrator::UnregisterHandler(const std::string& id) MS_TRACE(); this->mapChannelRequestHandlers.erase(id); - this->mapPayloadChannelRequestHandlers.erase(id); - this->mapPayloadChannelNotificationHandlers.erase(id); + this->mapChannelNotificationHandlers.erase(id); } Channel::ChannelSocket::RequestHandler* ChannelMessageRegistrator::GetChannelRequestHandler( @@ -140,31 +101,14 @@ Channel::ChannelSocket::RequestHandler* ChannelMessageRegistrator::GetChannelReq } } -PayloadChannel::PayloadChannelSocket::RequestHandler* ChannelMessageRegistrator::GetPayloadChannelRequestHandler( +Channel::ChannelSocket::NotificationHandler* ChannelMessageRegistrator::GetChannelNotificationHandler( const std::string& id) { MS_TRACE(); - auto it = this->mapPayloadChannelRequestHandlers.find(id); - - if (it != this->mapPayloadChannelRequestHandlers.end()) - { - return it->second; - } - else - { - return nullptr; - } -} - -PayloadChannel::PayloadChannelSocket::NotificationHandler* ChannelMessageRegistrator:: - GetPayloadChannelNotificationHandler(const std::string& id) -{ - MS_TRACE(); - - auto it = this->mapPayloadChannelNotificationHandlers.find(id); + auto it = this->mapChannelNotificationHandlers.find(id); - if (it != this->mapPayloadChannelNotificationHandlers.end()) + if (it != this->mapChannelNotificationHandlers.end()) { return it->second; } diff --git a/worker/src/DepUsrSCTP.cpp b/worker/src/DepUsrSCTP.cpp index 0a969de927..57b0a3cd51 100644 --- a/worker/src/DepUsrSCTP.cpp +++ b/worker/src/DepUsrSCTP.cpp @@ -200,7 +200,7 @@ DepUsrSCTP::Checker::Checker() { MS_TRACE(); - this->timer = new Timer(this); + this->timer = new TimerHandle(this); } DepUsrSCTP::Checker::~Checker() @@ -232,7 +232,7 @@ void DepUsrSCTP::Checker::Stop() this->timer->Stop(); } -void DepUsrSCTP::Checker::OnTimer(Timer* /*timer*/) +void DepUsrSCTP::Checker::OnTimer(TimerHandle* /*timer*/) { MS_TRACE(); diff --git a/worker/src/PayloadChannel/PayloadChannelNotification.cpp b/worker/src/PayloadChannel/PayloadChannelNotification.cpp deleted file mode 100644 index 8805323d6d..0000000000 --- a/worker/src/PayloadChannel/PayloadChannelNotification.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#define MS_CLASS "PayloadChannel::PayloadChannelNotification" -// #define MS_LOG_DEV_LEVEL 3 - -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "Logger.hpp" -#include "MediaSoupErrors.hpp" -#include "Utils.hpp" - -namespace PayloadChannel -{ - /* Class variables. */ - - // clang-format off - absl::flat_hash_map PayloadChannelNotification::string2EventId = - { - { "transport.sendRtcp", PayloadChannelNotification::EventId::TRANSPORT_SEND_RTCP }, - { "producer.send", PayloadChannelNotification::EventId::PRODUCER_SEND }, - { "dataProducer.send", PayloadChannelNotification::EventId::DATA_PRODUCER_SEND } - }; - // clang-format on - - /* Class methods. */ - - bool PayloadChannelNotification::IsNotification(const char* msg, size_t msgLen) - { - MS_TRACE(); - - return (msgLen > 2 && msg[0] == 'n' && msg[1] == ':'); - } - - /* Instance methods. */ - - PayloadChannelNotification::PayloadChannelNotification(const char* msg, size_t msgLen) - { - MS_TRACE(); - - auto info = Utils::String::Split(std::string(msg, msgLen), ':'); - - if (info.size() < 1) - MS_THROW_ERROR("too few arguments"); - - this->event = info[0]; - - auto eventIdIt = PayloadChannelNotification::string2EventId.find(this->event); - - if (eventIdIt == PayloadChannelNotification::string2EventId.end()) - MS_THROW_ERROR("unknown event '%s'", this->event.c_str()); - - this->eventId = eventIdIt->second; - - if (info.size() > 1) - { - auto& handlerId = info[1]; - - if (handlerId != "undefined") - this->handlerId = handlerId; - } - - if (info.size() > 2) - { - auto& data = info[2]; - - if (data != "undefined") - this->data = data; - } - } - - PayloadChannelNotification::~PayloadChannelNotification() - { - MS_TRACE(); - } - - void PayloadChannelNotification::SetPayload(const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - this->payload = payload; - this->payloadLen = payloadLen; - } -} // namespace PayloadChannel diff --git a/worker/src/PayloadChannel/PayloadChannelNotifier.cpp b/worker/src/PayloadChannel/PayloadChannelNotifier.cpp deleted file mode 100644 index 57090ff80d..0000000000 --- a/worker/src/PayloadChannel/PayloadChannelNotifier.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#define MS_CLASS "PayloadChannel::Notifier" -// #define MS_LOG_DEV_LEVEL 3 - -#include "PayloadChannel/PayloadChannelNotifier.hpp" -#include "Logger.hpp" - -namespace PayloadChannel -{ - PayloadChannelNotifier::PayloadChannelNotifier(PayloadChannel::PayloadChannelSocket* payloadChannel) - : payloadChannel(payloadChannel) - { - MS_TRACE(); - } - - void PayloadChannelNotifier::Emit( - const std::string& targetId, const char* event, const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - std::string notification("{\"targetId\":\""); - - notification.append(targetId); - notification.append("\",\"event\":\""); - notification.append(event); - notification.append("\"}"); - - this->payloadChannel->Send(notification, payload, payloadLen); - } - - void PayloadChannelNotifier::Emit( - const std::string& targetId, const char* event, json& data, const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - json jsonNotification = json::object(); - - jsonNotification["targetId"] = targetId; - jsonNotification["event"] = event; - jsonNotification["data"] = data; - - this->payloadChannel->Send(jsonNotification, payload, payloadLen); - } -} // namespace PayloadChannel diff --git a/worker/src/PayloadChannel/PayloadChannelRequest.cpp b/worker/src/PayloadChannel/PayloadChannelRequest.cpp deleted file mode 100644 index 9e074695d2..0000000000 --- a/worker/src/PayloadChannel/PayloadChannelRequest.cpp +++ /dev/null @@ -1,165 +0,0 @@ -#define MS_CLASS "PayloadChannel::PayloadChannelRequest" -// #define MS_LOG_DEV_LEVEL 3 - -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include "Logger.hpp" -#include "MediaSoupErrors.hpp" -#include "Utils.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" - -namespace PayloadChannel -{ - /* Class variables. */ - - // clang-format off - absl::flat_hash_map PayloadChannelRequest::string2MethodId = - { - { "dataConsumer.send", PayloadChannelRequest::MethodId::DATA_CONSUMER_SEND }, - }; - // clang-format on - - /* Class methods. */ - - bool PayloadChannelRequest::IsRequest(const char* msg, size_t msgLen) - { - MS_TRACE(); - - return (msgLen > 2 && msg[0] == 'r' && msg[1] == ':'); - } - - /* Instance methods. */ - - /** - * msg contains "id:method:handlerId:data" where: - * - id: The ID of the request. - * - handlerId: The ID of the target entity - * - data: JSON object. - */ - PayloadChannelRequest::PayloadChannelRequest( - PayloadChannel::PayloadChannelSocket* channel, char* msg, size_t msgLen) - : channel(channel) - { - MS_TRACE(); - - auto info = Utils::String::Split(std::string(msg, msgLen), ':', 3); - - if (info.size() < 2) - MS_THROW_ERROR("too few arguments"); - - this->id = std::stoul(info[0]); - this->method = info[1]; - - auto methodIdIt = PayloadChannelRequest::string2MethodId.find(this->method); - - if (methodIdIt == PayloadChannelRequest::string2MethodId.end()) - { - Error("unknown method"); - - MS_THROW_ERROR("unknown method '%s'", this->method.c_str()); - } - - this->methodId = methodIdIt->second; - - if (info.size() > 2) - { - auto& handlerId = info[2]; - - if (handlerId != "undefined") - this->handlerId = handlerId; - } - - if (info.size() > 3) - { - auto& data = info[3]; - - if (data != "undefined") - this->data = data; - } - } - - PayloadChannelRequest::~PayloadChannelRequest() - { - MS_TRACE(); - } - - void PayloadChannelRequest::Accept() - { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - std::string response("{\"id\":"); - - response.append(std::to_string(this->id)); - response.append(",\"accepted\":true}"); - - this->channel->Send(response); - } - - void PayloadChannelRequest::Accept(json& data) - { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["accepted"] = true; - - if (data.is_structured()) - jsonResponse["data"] = data; - - this->channel->Send(jsonResponse); - } - - void PayloadChannelRequest::Error(const char* reason) - { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["error"] = "Error"; - - if (reason != nullptr) - jsonResponse["reason"] = reason; - - this->channel->Send(jsonResponse); - } - - void PayloadChannelRequest::TypeError(const char* reason) - { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["error"] = "TypeError"; - - if (reason != nullptr) - jsonResponse["reason"] = reason; - - this->channel->Send(jsonResponse); - } - - void PayloadChannelRequest::SetPayload(const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - this->payload = payload; - this->payloadLen = payloadLen; - } -} // namespace PayloadChannel diff --git a/worker/src/PayloadChannel/PayloadChannelSocket.cpp b/worker/src/PayloadChannel/PayloadChannelSocket.cpp deleted file mode 100644 index 6f407a09de..0000000000 --- a/worker/src/PayloadChannel/PayloadChannelSocket.cpp +++ /dev/null @@ -1,539 +0,0 @@ -#define MS_CLASS "PayloadChannel::PayloadChannelSocket" -// #define MS_LOG_DEV_LEVEL 3 - -#include "PayloadChannel/PayloadChannelSocket.hpp" -#include "DepLibUV.hpp" -#include "Logger.hpp" -#include "MediaSoupErrors.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include // std::ceil() -#include // std::memcpy(), std::memmove() - -namespace PayloadChannel -{ - // Binary length for a 4194304 bytes payload. - static constexpr size_t MessageMaxLen{ 4194308 }; - static constexpr size_t PayloadMaxLen{ 4194304 }; - - /* Static methods for UV callbacks. */ - - inline static void onAsync(uv_handle_t* handle) - { - while (static_cast(handle->data)->CallbackRead()) - { - // Read while there are new messages. - } - } - - inline static void onCloseAsync(uv_handle_t* handle) - { - delete reinterpret_cast(handle); - } - - /* Instance methods. */ - - PayloadChannelSocket::PayloadChannelSocket(int consumerFd, int producerFd) - : consumerSocket(new ConsumerSocket(consumerFd, MessageMaxLen, this)), - producerSocket(new ProducerSocket(producerFd, MessageMaxLen)), - writeBuffer(static_cast(std::malloc(MessageMaxLen))) - { - MS_TRACE(); - } - - PayloadChannelSocket::PayloadChannelSocket( - PayloadChannelReadFn payloadChannelReadFn, - PayloadChannelReadCtx payloadChannelReadCtx, - PayloadChannelWriteFn payloadChannelWriteFn, - PayloadChannelWriteCtx payloadChannelWriteCtx) - : payloadChannelReadFn(payloadChannelReadFn), payloadChannelReadCtx(payloadChannelReadCtx), - payloadChannelWriteFn(payloadChannelWriteFn), payloadChannelWriteCtx(payloadChannelWriteCtx) - { - MS_TRACE(); - - int err; - - this->uvReadHandle = new uv_async_t; - this->uvReadHandle->data = static_cast(this); - - err = - uv_async_init(DepLibUV::GetLoop(), this->uvReadHandle, reinterpret_cast(onAsync)); - - if (err != 0) - { - delete this->uvReadHandle; - this->uvReadHandle = nullptr; - - MS_THROW_ERROR("uv_async_init() failed: %s", uv_strerror(err)); - } - - err = uv_async_send(this->uvReadHandle); - - if (err != 0) - { - delete this->uvReadHandle; - this->uvReadHandle = nullptr; - - MS_THROW_ERROR("uv_async_send() failed: %s", uv_strerror(err)); - } - } - - PayloadChannelSocket::~PayloadChannelSocket() - { - MS_TRACE(); - - std::free(this->writeBuffer); - delete this->ongoingNotification; - - if (!this->closed) - Close(); - - delete this->consumerSocket; - delete this->producerSocket; - } - - void PayloadChannelSocket::Close() - { - MS_TRACE_STD(); - - if (this->closed) - return; - - this->closed = true; - - if (this->uvReadHandle) - { - uv_close( - reinterpret_cast(this->uvReadHandle), static_cast(onCloseAsync)); - } - - if (this->consumerSocket) - { - this->consumerSocket->Close(); - } - - if (this->producerSocket) - { - this->producerSocket->Close(); - } - } - - void PayloadChannelSocket::SetListener(Listener* listener) - { - MS_TRACE(); - - this->listener = listener; - } - - void PayloadChannelSocket::Send(json& jsonMessage, const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - if (this->closed) - return; - - std::string message = jsonMessage.dump(); - - this->Send(message, payload, payloadLen); - } - - void PayloadChannelSocket::Send(const std::string& message, const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - if (this->closed) - return; - - if (message.length() > PayloadMaxLen) - { - MS_ERROR("message too big"); - - return; - } - else if (payloadLen > PayloadMaxLen) - { - MS_ERROR("payload too big"); - - return; - } - - SendImpl( - reinterpret_cast(message.c_str()), - static_cast(message.length()), - payload, - static_cast(payloadLen)); - } - - void PayloadChannelSocket::Send(json& jsonMessage) - { - MS_TRACE_STD(); - - if (this->closed) - return; - - std::string message = jsonMessage.dump(); - - if (message.length() > PayloadMaxLen) - { - MS_ERROR_STD("message too big"); - - return; - } - - SendImpl( - reinterpret_cast(message.c_str()), static_cast(message.length())); - } - - void PayloadChannelSocket::Send(const std::string& message) - { - MS_TRACE(); - - if (this->closed) - return; - - if (message.length() > PayloadMaxLen) - { - MS_ERROR("message too big"); - - return; - } - - SendImpl( - reinterpret_cast(message.c_str()), static_cast(message.length())); - } - - bool PayloadChannelSocket::CallbackRead() - { - MS_TRACE(); - - if (this->closed) - return false; - - uint8_t* message{ nullptr }; - uint32_t messageLen; - size_t messageCtx; - - uint8_t* payload{ nullptr }; - uint32_t payloadLen; - size_t payloadCapacity; - - // Try to read next message and payload using `payloadChannelReadFn`, message and payload, - // alongside their lengths and contexts will be stored in provided arguments. - auto free = this->payloadChannelReadFn( - &message, - &messageLen, - &messageCtx, - &payload, - &payloadLen, - &payloadCapacity, - this->uvReadHandle, - this->payloadChannelReadCtx); - - // Non-null free function pointer means message was successfully read above and will need to be - // freed later. - if (free) - { - try - { - char* charMessage{ reinterpret_cast(message) }; - - if (PayloadChannelRequest::IsRequest(charMessage, messageLen)) - { - try - { - auto* request = - new PayloadChannel::PayloadChannelRequest(this, charMessage + 2, messageLen - 2); - request->SetPayload(payload, payloadLen); - - // Notify the listener. - try - { - this->listener->HandleRequest(request); - } - catch (const MediaSoupTypeError& error) - { - request->TypeError(error.what()); - } - catch (const MediaSoupError& error) - { - request->Error(error.what()); - } - - // Delete the Request. - delete request; - } - catch (const json::parse_error& error) - { - MS_ERROR_STD("message parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong PayloadChannel request: %s", error.what()); - } - } - - else if (PayloadChannelNotification::IsNotification(charMessage, messageLen)) - { - try - { - auto* notification = - new PayloadChannel::PayloadChannelNotification(charMessage + 2, messageLen - 2); - notification->SetPayload(payload, payloadLen); - - // Notify the listener. - try - { - this->listener->HandleNotification(notification); - } - catch (const MediaSoupError& error) - { - MS_ERROR("notification failed: %s", error.what()); - } - - // Delete the Notification. - delete notification; - } - catch (const json::parse_error& error) - { - MS_ERROR_STD("message parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong PayloadChannel notification: %s", error.what()); - } - } - - else - { - MS_ERROR("discarding wrong PayloadChannel data"); - } - } - catch (const json::parse_error& error) - { - MS_ERROR("JSON parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong Channel request: %s", error.what()); - } - - // Message and payload need to be freed using stored function pointer. - free(message, messageLen, messageCtx); - free(payload, payloadLen, payloadCapacity); - } - - // Return `true` if something was processed. - return free != nullptr; - } - - inline void PayloadChannelSocket::SendImpl(const uint8_t* message, uint32_t messageLen) - { - MS_TRACE(); - - // Write using function call if provided. - if (this->payloadChannelWriteFn) - { - this->payloadChannelWriteFn(message, messageLen, nullptr, 0, this->payloadChannelWriteCtx); - } - else - { - std::memcpy(this->writeBuffer, &messageLen, sizeof(uint32_t)); - - if (messageLen != 0) - { - std::memcpy(this->writeBuffer + sizeof(uint32_t), message, messageLen); - } - - size_t len = sizeof(uint32_t) + messageLen; - - this->producerSocket->Write(this->writeBuffer, len); - } - } - - inline void PayloadChannelSocket::SendImpl( - const uint8_t* message, uint32_t messageLen, const uint8_t* payload, uint32_t payloadLen) - { - MS_TRACE(); - - // Write using function call if provided. - if (this->payloadChannelWriteFn) - { - this->payloadChannelWriteFn( - message, messageLen, payload, payloadLen, this->payloadChannelWriteCtx); - } - else - { - SendImpl(message, messageLen); - SendImpl(payload, payloadLen); - } - } - - void PayloadChannelSocket::OnConsumerSocketMessage( - ConsumerSocket* /*consumerSocket*/, char* msg, size_t msgLen) - { - MS_TRACE(); - - if (!this->ongoingNotification && !this->ongoingRequest) - { - if (PayloadChannelRequest::IsRequest(msg, msgLen)) - { - try - { - this->ongoingRequest = new PayloadChannel::PayloadChannelRequest(this, msg + 2, msgLen - 2); - } - catch (const json::parse_error& error) - { - MS_ERROR_STD("msg parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong PayloadChannel request: %s", error.what()); - } - } - else if (PayloadChannelNotification::IsNotification(msg, msgLen)) - { - try - { - this->ongoingNotification = - new PayloadChannel::PayloadChannelNotification(msg + 2, msgLen - 2); - } - catch (const json::parse_error& error) - { - MS_ERROR_STD("msg parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong PayloadChannel notification: %s", error.what()); - } - } - else - { - MS_ERROR("discarding wrong PayloadChannel data"); - } - } - else if (this->ongoingNotification) - { - this->ongoingNotification->SetPayload(reinterpret_cast(msg), msgLen); - - // Notify the listener. - try - { - this->listener->HandleNotification(this->ongoingNotification); - } - catch (const MediaSoupError& error) - { - MS_ERROR("notification failed: %s", error.what()); - } - - // Delete the Notification. - delete this->ongoingNotification; - this->ongoingNotification = nullptr; - } - else if (this->ongoingRequest) - { - this->ongoingRequest->SetPayload(reinterpret_cast(msg), msgLen); - - // Notify the listener. - try - { - this->listener->HandleRequest(this->ongoingRequest); - } - catch (const MediaSoupTypeError& error) - { - this->ongoingRequest->TypeError(error.what()); - } - catch (const MediaSoupError& error) - { - this->ongoingRequest->Error(error.what()); - } - - // Delete the Request. - delete this->ongoingRequest; - this->ongoingRequest = nullptr; - } - } - - void PayloadChannelSocket::OnConsumerSocketClosed(ConsumerSocket* /*consumerSocket*/) - { - MS_TRACE(); - - this->listener->OnPayloadChannelClosed(this); - } - - /* Instance methods. */ - - ConsumerSocket::ConsumerSocket(int fd, size_t bufferSize, Listener* listener) - : ::UnixStreamSocket(fd, bufferSize, ::UnixStreamSocket::Role::CONSUMER), listener(listener) - { - MS_TRACE(); - } - - ConsumerSocket::~ConsumerSocket() - { - MS_TRACE(); - } - - void ConsumerSocket::UserOnUnixStreamRead() - { - MS_TRACE(); - - size_t msgStart{ 0 }; - - // Be ready to parse more than a single message in a single chunk. - while (true) - { - if (IsClosed()) - return; - - size_t readLen = this->bufferDataLen - msgStart; - - if (readLen < sizeof(uint32_t)) - { - // Incomplete data. - break; - } - - uint32_t msgLen; - // Read message length. - std::memcpy(&msgLen, this->buffer + msgStart, sizeof(uint32_t)); - - if (readLen < sizeof(uint32_t) + static_cast(msgLen)) - { - // Incomplete data. - break; - } - - this->listener->OnConsumerSocketMessage( - this, - reinterpret_cast(this->buffer + msgStart + sizeof(uint32_t)), - static_cast(msgLen)); - - msgStart += sizeof(uint32_t) + static_cast(msgLen); - } - - if (msgStart != 0) - { - this->bufferDataLen = this->bufferDataLen - msgStart; - - if (this->bufferDataLen != 0) - { - std::memmove(this->buffer, this->buffer + msgStart, this->bufferDataLen); - } - } - } - - void ConsumerSocket::UserOnUnixStreamSocketClosed() - { - MS_TRACE(); - - // Notify the listener. - this->listener->OnConsumerSocketClosed(this); - } - - /* Instance methods. */ - - ProducerSocket::ProducerSocket(int fd, size_t bufferSize) - : ::UnixStreamSocket(fd, bufferSize, ::UnixStreamSocket::Role::PRODUCER) - { - MS_TRACE(); - } -} // namespace PayloadChannel diff --git a/worker/src/RTC/ActiveSpeakerObserver.cpp b/worker/src/RTC/ActiveSpeakerObserver.cpp index e86bdfcdb1..ad332f6f51 100644 --- a/worker/src/RTC/ActiveSpeakerObserver.cpp +++ b/worker/src/RTC/ActiveSpeakerObserver.cpp @@ -95,26 +95,22 @@ namespace RTC } ActiveSpeakerObserver::ActiveSpeakerObserver( - RTC::Shared* shared, const std::string& id, RTC::RtpObserver::Listener* listener, json& data) + RTC::Shared* shared, + const std::string& id, + RTC::RtpObserver::Listener* listener, + const FBS::ActiveSpeakerObserver::ActiveSpeakerObserverOptions* options) : RTC::RtpObserver(shared, id, listener) { MS_TRACE(); - auto jsonIntervalIt = data.find("interval"); - - if (jsonIntervalIt == data.end() || !jsonIntervalIt->is_number()) - { - MS_THROW_TYPE_ERROR("missing interval"); - } - - this->interval = jsonIntervalIt->get(); + this->interval = options->interval(); if (this->interval < 100) this->interval = 100; else if (this->interval > 5000) this->interval = 5000; - this->periodicTimer = new Timer(this); + this->periodicTimer = new TimerHandle(this); this->periodicTimer->Start(interval, interval); @@ -122,8 +118,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } ActiveSpeakerObserver::~ActiveSpeakerObserver() @@ -250,7 +245,7 @@ namespace RTC this->periodicTimer->Restart(); } - void ActiveSpeakerObserver::OnTimer(Timer* timer) + void ActiveSpeakerObserver::OnTimer(TimerHandle* timer) { MS_TRACE(); @@ -275,10 +270,14 @@ namespace RTC if (!this->mapProducerSpeakers.empty() && CalculateActiveSpeaker()) { - json data = json::object(); - data["producerId"] = this->dominantId; - - this->shared->channelNotifier->Emit(this->id, "dominantspeaker", data); + auto notification = FBS::ActiveSpeakerObserver::CreateDominantSpeakerNotificationDirect( + this->shared->channelNotifier->GetBufferBuilder(), this->dominantId.c_str()); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::ACTIVESPEAKEROBSERVER_DOMINANT_SPEAKER, + FBS::Notification::Body::ActiveSpeakerObserver_DominantSpeakerNotification, + notification); } } @@ -324,7 +323,7 @@ namespace RTC { auto* producerSpeaker = kv.second; auto* speaker = producerSpeaker->speaker; - auto& id = producerSpeaker->producer->id; + const auto& id = producerSpeaker->producer->id; if (id == this->dominantId || speaker->paused) { @@ -370,7 +369,7 @@ namespace RTC { auto* producerSpeaker = kv.second; auto* speaker = producerSpeaker->speaker; - auto& id = producerSpeaker->producer->id; + const auto& id = producerSpeaker->producer->id; uint64_t idle = now - speaker->lastLevelChangeTime; if (SpeakerIdleTimeout < idle && (this->dominantId.empty() || id != this->dominantId)) diff --git a/worker/src/RTC/AudioLevelObserver.cpp b/worker/src/RTC/AudioLevelObserver.cpp index 4339e49d16..2b0b6ccda4 100644 --- a/worker/src/RTC/AudioLevelObserver.cpp +++ b/worker/src/RTC/AudioLevelObserver.cpp @@ -14,51 +14,27 @@ namespace RTC /* Instance methods. */ AudioLevelObserver::AudioLevelObserver( - RTC::Shared* shared, const std::string& id, RTC::RtpObserver::Listener* listener, json& data) + RTC::Shared* shared, + const std::string& id, + RTC::RtpObserver::Listener* listener, + const FBS::AudioLevelObserver::AudioLevelObserverOptions* options) : RTC::RtpObserver(shared, id, listener) { MS_TRACE(); - auto jsonMaxEntriesIt = data.find("maxEntries"); + this->maxEntries = options->maxEntries(); + this->threshold = options->threshold(); + this->interval = options->interval(); - // clang-format off - if ( - jsonMaxEntriesIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonMaxEntriesIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing maxEntries"); - } - - this->maxEntries = jsonMaxEntriesIt->get(); - - if (this->maxEntries < 1) - MS_THROW_TYPE_ERROR("invalid maxEntries value %" PRIu16, this->maxEntries); - - auto jsonThresholdIt = data.find("threshold"); - - if (jsonThresholdIt == data.end() || !jsonThresholdIt->is_number()) - MS_THROW_TYPE_ERROR("missing threshold"); - - this->threshold = jsonThresholdIt->get(); - - if (this->threshold < -127 || this->threshold > 0) + if (this->threshold > 0) MS_THROW_TYPE_ERROR("invalid threshold value %" PRIi8, this->threshold); - auto jsonIntervalIt = data.find("interval"); - - if (jsonIntervalIt == data.end() || !jsonIntervalIt->is_number()) - MS_THROW_TYPE_ERROR("missing interval"); - - this->interval = jsonIntervalIt->get(); - if (this->interval < 250) this->interval = 250; else if (this->interval > 5000) this->interval = 5000; - this->periodicTimer = new Timer(this); + this->periodicTimer = new TimerHandle(this); this->periodicTimer->Start(this->interval, this->interval); @@ -66,8 +42,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } AudioLevelObserver::~AudioLevelObserver() @@ -141,7 +116,8 @@ namespace RTC { this->silence = true; - this->shared->channelNotifier->Emit(this->id, "silence"); + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::AUDIOLEVELOBSERVER_SILENCE); } } @@ -184,25 +160,31 @@ namespace RTC this->silence = false; uint16_t idx{ 0 }; - auto rit = mapDBovsProducer.crbegin(); - json data = json::array(); + auto rit = mapDBovsProducer.crbegin(); + + std::vector> volumes; for (; idx < this->maxEntries && rit != mapDBovsProducer.crend(); ++idx, ++rit) { - data.emplace_back(json::value_t::object); - - auto& jsonEntry = data[idx]; - - jsonEntry["producerId"] = rit->second->id; - jsonEntry["volume"] = rit->first; + volumes.emplace_back(FBS::AudioLevelObserver::CreateVolumeDirect( + this->shared->channelNotifier->GetBufferBuilder(), rit->second->id.c_str(), rit->first)); } - this->shared->channelNotifier->Emit(this->id, "volumes", data); + auto notification = FBS::AudioLevelObserver::CreateVolumesNotificationDirect( + this->shared->channelNotifier->GetBufferBuilder(), &volumes); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::AUDIOLEVELOBSERVER_VOLUMES, + FBS::Notification::Body::AudioLevelObserver_VolumesNotification, + notification); } else if (!this->silence) { this->silence = true; - this->shared->channelNotifier->Emit(this->id, "silence"); + + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::AUDIOLEVELOBSERVER_SILENCE); } } @@ -219,7 +201,7 @@ namespace RTC } } - inline void AudioLevelObserver::OnTimer(Timer* /*timer*/) + inline void AudioLevelObserver::OnTimer(TimerHandle* /*timer*/) { MS_TRACE(); diff --git a/worker/src/RTC/Consumer.cpp b/worker/src/RTC/Consumer.cpp index 0d1cc9dd9a..796924f795 100644 --- a/worker/src/RTC/Consumer.cpp +++ b/worker/src/RTC/Consumer.cpp @@ -17,56 +17,45 @@ namespace RTC const std::string& id, const std::string& producerId, Listener* listener, - json& data, + const FBS::Transport::ConsumeRequest* data, RTC::RtpParameters::Type type) : id(id), producerId(producerId), shared(shared), listener(listener), type(type) { MS_TRACE(); - auto jsonKindIt = data.find("kind"); - - if (jsonKindIt == data.end() || !jsonKindIt->is_string()) - MS_THROW_TYPE_ERROR("missing kind"); + this->kind = RTC::Media::Kind(data->kind()); // This may throw. - this->kind = RTC::Media::GetKind(jsonKindIt->get()); - - if (this->kind == RTC::Media::Kind::ALL) - MS_THROW_TYPE_ERROR("invalid empty kind"); - - auto jsonRtpParametersIt = data.find("rtpParameters"); - - if (jsonRtpParametersIt == data.end() || !jsonRtpParametersIt->is_object()) - MS_THROW_TYPE_ERROR("missing rtpParameters"); - - // This may throw. - this->rtpParameters = RTC::RtpParameters(*jsonRtpParametersIt); + this->rtpParameters = RTC::RtpParameters(data->rtpParameters()); if (this->rtpParameters.encodings.empty()) + { MS_THROW_TYPE_ERROR("empty rtpParameters.encodings"); + } // All encodings must have SSRCs. for (auto& encoding : this->rtpParameters.encodings) { if (encoding.ssrc == 0) + { MS_THROW_TYPE_ERROR("invalid encoding in rtpParameters (missing ssrc)"); + } else if (encoding.hasRtx && encoding.rtx.ssrc == 0) + { MS_THROW_TYPE_ERROR("invalid encoding in rtpParameters (missing rtx.ssrc)"); + } } - auto jsonConsumableRtpEncodingsIt = data.find("consumableRtpEncodings"); - - if (jsonConsumableRtpEncodingsIt == data.end() || !jsonConsumableRtpEncodingsIt->is_array()) - MS_THROW_TYPE_ERROR("missing consumableRtpEncodings"); - - if (jsonConsumableRtpEncodingsIt->empty()) + if (data->consumableRtpEncodings()->size() == 0) + { MS_THROW_TYPE_ERROR("empty consumableRtpEncodings"); + } - this->consumableRtpEncodings.reserve(jsonConsumableRtpEncodingsIt->size()); + this->consumableRtpEncodings.reserve(data->consumableRtpEncodings()->size()); - for (size_t i{ 0 }; i < jsonConsumableRtpEncodingsIt->size(); ++i) + for (size_t i{ 0 }; i < data->consumableRtpEncodings()->size(); ++i) { - auto& entry = (*jsonConsumableRtpEncodingsIt)[i]; + const auto* entry = data->consumableRtpEncodings()->Get(i); // This may throw due the constructor of RTC::RtpEncodingParameters. this->consumableRtpEncodings.emplace_back(entry); @@ -75,7 +64,9 @@ namespace RTC auto& encoding = this->consumableRtpEncodings[i]; if (encoding.ssrc == 0u) + { MS_THROW_TYPE_ERROR("wrong encoding in consumableRtpEncodings (missing ssrc)"); + } } // Fill RTP header extension ids and their mapped values. @@ -83,7 +74,9 @@ namespace RTC for (auto& exten : this->rtpParameters.headerExtensions) { if (exten.id == 0u) + { MS_THROW_TYPE_ERROR("RTP extension id cannot be 0"); + } if (this->rtpHeaderExtensionIds.ssrcAudioLevel == 0u && exten.type == RTC::RtpHeaderExtensionUri::Type::SSRC_AUDIO_LEVEL) { @@ -121,16 +114,16 @@ namespace RTC } } - auto jsonPausedIt = data.find("paused"); - - if (jsonPausedIt != data.end() && jsonPausedIt->is_boolean()) - this->paused = jsonPausedIt->get(); + // paused is set to false by default. + this->paused = data->paused(); // Fill supported codec payload types. for (auto& codec : this->rtpParameters.codecs) { if (codec.mimeType.IsMediaCodec()) + { this->supportedCodecPayloadTypes[codec.payloadType] = true; + } } // Fill media SSRCs vector. @@ -143,14 +136,20 @@ namespace RTC for (auto& encoding : this->rtpParameters.encodings) { if (encoding.hasRtx) + { this->rtxSsrcs.push_back(encoding.rtx.ssrc); + } } // Set the RTCP report generation interval. if (this->kind == RTC::Media::Kind::AUDIO) + { this->maxRtcpInterval = RTC::RTCP::MaxAudioIntervalMs; + } else + { this->maxRtcpInterval = RTC::RTCP::MaxVideoIntervalMs; + } } Consumer::~Consumer() @@ -158,119 +157,96 @@ namespace RTC MS_TRACE(); } - void Consumer::FillJson(json& jsonObject) const + flatbuffers::Offset Consumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add producerId. - jsonObject["producerId"] = this->producerId; - - // Add kind. - jsonObject["kind"] = RTC::Media::GetString(this->kind); - // Add rtpParameters. - this->rtpParameters.FillJson(jsonObject["rtpParameters"]); - - // Add type. - jsonObject["type"] = RTC::RtpParameters::GetTypeString(this->type); + auto rtpParameters = this->rtpParameters.FillBuffer(builder); // Add consumableRtpEncodings. - jsonObject["consumableRtpEncodings"] = json::array(); - auto jsonConsumableRtpEncodingsIt = jsonObject.find("consumableRtpEncodings"); + std::vector> consumableRtpEncodings; + consumableRtpEncodings.reserve(this->consumableRtpEncodings.size()); - for (size_t i{ 0 }; i < this->consumableRtpEncodings.size(); ++i) + for (const auto& encoding : this->consumableRtpEncodings) { - jsonConsumableRtpEncodingsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonConsumableRtpEncodingsIt)[i]; - const auto& encoding = this->consumableRtpEncodings[i]; - - encoding.FillJson(jsonEntry); + consumableRtpEncodings.emplace_back(encoding.FillBuffer(builder)); } // Add supportedCodecPayloadTypes. - jsonObject["supportedCodecPayloadTypes"] = json::array(); + std::vector supportedCodecPayloadTypes; for (auto i = 0; i < 128; ++i) { if (this->supportedCodecPayloadTypes[i]) - jsonObject["supportedCodecPayloadTypes"].push_back(i); + { + supportedCodecPayloadTypes.push_back(i); + } } - // Add paused. - jsonObject["paused"] = this->paused; - - // Add producerPaused. - jsonObject["producerPaused"] = this->producerPaused; - - // Add priority. - jsonObject["priority"] = this->priority; - // Add traceEventTypes. - std::vector traceEventTypes; - std::ostringstream traceEventTypesStream; + std::vector traceEventTypes; if (this->traceEventTypes.rtp) - traceEventTypes.emplace_back("rtp"); + { + traceEventTypes.emplace_back(FBS::Consumer::TraceEventType::RTP); + } if (this->traceEventTypes.keyframe) - traceEventTypes.emplace_back("keyframe"); + { + traceEventTypes.emplace_back(FBS::Consumer::TraceEventType::KEYFRAME); + } if (this->traceEventTypes.nack) - traceEventTypes.emplace_back("nack"); + { + traceEventTypes.emplace_back(FBS::Consumer::TraceEventType::NACK); + } if (this->traceEventTypes.pli) - traceEventTypes.emplace_back("pli"); + { + traceEventTypes.emplace_back(FBS::Consumer::TraceEventType::PLI); + } if (this->traceEventTypes.fir) - traceEventTypes.emplace_back("fir"); - - if (!traceEventTypes.empty()) { - std::copy( - traceEventTypes.begin(), - traceEventTypes.end() - 1, - std::ostream_iterator(traceEventTypesStream, ",")); - traceEventTypesStream << traceEventTypes.back(); + traceEventTypes.emplace_back(FBS::Consumer::TraceEventType::FIR); } - jsonObject["traceEventTypes"] = traceEventTypesStream.str(); + return FBS::Consumer::CreateBaseConsumerDumpDirect( + builder, + this->id.c_str(), + RTC::RtpParameters::TypeToFbs(this->type), + this->producerId.c_str(), + this->kind == RTC::Media::Kind::AUDIO ? FBS::RtpParameters::MediaKind::AUDIO + : FBS::RtpParameters::MediaKind::VIDEO, + rtpParameters, + &consumableRtpEncodings, + &supportedCodecPayloadTypes, + &traceEventTypes, + this->paused, + this->producerPaused, + this->priority); } void Consumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_DUMP: + case Channel::ChannelRequest::Method::CONSUMER_GET_STATS: { - json data = json::object(); + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); - FillJson(data); - - request->Accept(data); - - break; - } - - case Channel::ChannelRequest::MethodId::CONSUMER_GET_STATS: - { - json data = json::array(); - - FillJsonStats(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::Consumer_GetStatsResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::CONSUMER_PAUSE: + case Channel::ChannelRequest::Method::CONSUMER_PAUSE: { if (this->paused) { request->Accept(); - return; + break; } const bool wasActive = IsActive(); @@ -280,20 +256,22 @@ namespace RTC MS_DEBUG_DEV("Consumer paused [consumerId:%s]", this->id.c_str()); if (wasActive) + { UserOnPaused(); + } request->Accept(); break; } - case Channel::ChannelRequest::MethodId::CONSUMER_RESUME: + case Channel::ChannelRequest::Method::CONSUMER_RESUME: { if (!this->paused) { request->Accept(); - return; + break; } this->paused = false; @@ -301,64 +279,76 @@ namespace RTC MS_DEBUG_DEV("Consumer resumed [consumerId:%s]", this->id.c_str()); if (IsActive()) + { UserOnResumed(); + } request->Accept(); break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PRIORITY: + case Channel::ChannelRequest::Method::CONSUMER_SET_PRIORITY: { - auto jsonPriorityIt = request->data.find("priority"); + const auto* body = request->data->body_as(); - if (jsonPriorityIt == request->data.end() || !jsonPriorityIt->is_number()) - MS_THROW_TYPE_ERROR("wrong priority (not a number)"); - - auto priority = jsonPriorityIt->get(); - - if (priority < 1u) + if (body->priority() < 1u) + { MS_THROW_TYPE_ERROR("wrong priority (must be higher than 0)"); + } - this->priority = priority; - - json data = json::object(); + this->priority = body->priority(); - data["priority"] = this->priority; + auto responseOffset = + FBS::Consumer::CreateSetPriorityResponse(request->GetBufferBuilder(), this->priority); - request->Accept(data); + request->Accept(FBS::Response::Body::Consumer_SetPriorityResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::CONSUMER_ENABLE_TRACE_EVENT: + case Channel::ChannelRequest::Method::CONSUMER_ENABLE_TRACE_EVENT: { - auto jsonTypesIt = request->data.find("types"); - - // Disable all if no entries. - if (jsonTypesIt == request->data.end() || !jsonTypesIt->is_array()) - MS_THROW_TYPE_ERROR("wrong types (not an array)"); + const auto* body = request->data->body_as(); // Reset traceEventTypes. struct TraceEventTypes newTraceEventTypes; - for (const auto& type : *jsonTypesIt) + for (const auto& type : *body->events()) { - if (!type.is_string()) - MS_THROW_TYPE_ERROR("wrong type (not a string)"); - - const std::string typeStr = type.get(); - - if (typeStr == "rtp") - newTraceEventTypes.rtp = true; - else if (typeStr == "keyframe") - newTraceEventTypes.keyframe = true; - else if (typeStr == "nack") - newTraceEventTypes.nack = true; - else if (typeStr == "pli") - newTraceEventTypes.pli = true; - else if (typeStr == "fir") - newTraceEventTypes.fir = true; + switch (type) + { + case FBS::Consumer::TraceEventType::KEYFRAME: + { + newTraceEventTypes.keyframe = true; + + break; + } + case FBS::Consumer::TraceEventType::FIR: + { + newTraceEventTypes.fir = true; + + break; + } + case FBS::Consumer::TraceEventType::NACK: + { + newTraceEventTypes.nack = true; + + break; + } + case FBS::Consumer::TraceEventType::PLI: + { + newTraceEventTypes.pli = true; + + break; + } + case FBS::Consumer::TraceEventType::RTP: + { + newTraceEventTypes.rtp = true; + + break; + } + } } this->traceEventTypes = newTraceEventTypes; @@ -370,7 +360,7 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } @@ -380,7 +370,9 @@ namespace RTC MS_TRACE(); if (this->transportConnected) + { return; + } this->transportConnected = true; @@ -394,7 +386,9 @@ namespace RTC MS_TRACE(); if (!this->transportConnected) + { return; + } this->transportConnected = false; @@ -408,7 +402,9 @@ namespace RTC MS_TRACE(); if (this->producerPaused) + { return; + } const bool wasActive = IsActive(); @@ -417,9 +413,11 @@ namespace RTC MS_DEBUG_DEV("Producer paused [consumerId:%s]", this->id.c_str()); if (wasActive) + { UserOnPaused(); + } - this->shared->channelNotifier->Emit(this->id, "producerpause"); + this->shared->channelNotifier->Emit(this->id, FBS::Notification::Event::CONSUMER_PRODUCER_PAUSE); } void Consumer::ProducerResumed() @@ -427,16 +425,20 @@ namespace RTC MS_TRACE(); if (!this->producerPaused) + { return; + } this->producerPaused = false; MS_DEBUG_DEV("Producer resumed [consumerId:%s]", this->id.c_str()); if (IsActive()) + { UserOnResumed(); + } - this->shared->channelNotifier->Emit(this->id, "producerresume"); + this->shared->channelNotifier->Emit(this->id, FBS::Notification::Event::CONSUMER_PRODUCER_RESUME); } void Consumer::ProducerRtpStreamScores(const std::vector* scores) @@ -457,7 +459,7 @@ namespace RTC MS_DEBUG_DEV("Producer closed [consumerId:%s]", this->id.c_str()); - this->shared->channelNotifier->Emit(this->id, "producerclose"); + this->shared->channelNotifier->Emit(this->id, FBS::Notification::Event::CONSUMER_PRODUCER_CLOSE); this->listener->OnConsumerProducerClosed(this); } @@ -468,33 +470,35 @@ namespace RTC if (this->traceEventTypes.keyframe && packet->IsKeyFrame()) { - json data = json::object(); - - data["type"] = "keyframe"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - - packet->FillJson(data["info"]); - - if (isRtx) - data["info"]["isRtx"] = true; - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto rtpPacketDump = packet->FillBuffer(this->shared->channelNotifier->GetBufferBuilder()); + auto traceInfo = FBS::Consumer::CreateKeyFrameTraceInfo( + this->shared->channelNotifier->GetBufferBuilder(), rtpPacketDump, isRtx); + + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceEventType::KEYFRAME, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_OUT, + FBS::Consumer::TraceInfo::KeyFrameTraceInfo, + traceInfo.Union()); + + EmitTraceEvent(notification); } else if (this->traceEventTypes.rtp) { - json data = json::object(); - - data["type"] = "rtp"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - - packet->FillJson(data["info"]); - - if (isRtx) - data["info"]["isRtx"] = true; - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto rtpPacketDump = packet->FillBuffer(this->shared->channelNotifier->GetBufferBuilder()); + auto traceInfo = FBS::Consumer::CreateRtpTraceInfo( + this->shared->channelNotifier->GetBufferBuilder(), rtpPacketDump, isRtx); + + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceEventType::RTP, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_OUT, + FBS::Consumer::TraceInfo::RtpTraceInfo, + traceInfo.Union()); + + EmitTraceEvent(notification); } } @@ -503,16 +507,22 @@ namespace RTC MS_TRACE(); if (!this->traceEventTypes.pli) + { return; + } - json data = json::object(); + auto traceInfo = + FBS::Consumer::CreatePliTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), ssrc); - data["type"] = "pli"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - data["info"]["ssrc"] = ssrc; + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceEventType::PLI, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_IN, + FBS::Consumer::TraceInfo::PliTraceInfo, + traceInfo.Union()); - this->shared->channelNotifier->Emit(this->id, "trace", data); + EmitTraceEvent(notification); } void Consumer::EmitTraceEventFirType(uint32_t ssrc) const @@ -520,16 +530,22 @@ namespace RTC MS_TRACE(); if (!this->traceEventTypes.fir) + { return; + } - json data = json::object(); + auto traceInfo = + FBS::Consumer::CreateFirTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), ssrc); - data["type"] = "fir"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - data["info"]["ssrc"] = ssrc; + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceEventType::FIR, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_IN, + FBS::Consumer::TraceInfo::FirTraceInfo, + traceInfo.Union()); - this->shared->channelNotifier->Emit(this->id, "trace", data); + EmitTraceEvent(notification); } void Consumer::EmitTraceEventNackType() const @@ -537,15 +553,27 @@ namespace RTC MS_TRACE(); if (!this->traceEventTypes.nack) + { return; + } + + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceEventType::NACK, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_IN); - json data = json::object(); + EmitTraceEvent(notification); + } - data["type"] = "nack"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - data["info"] = json::object(); + void Consumer::EmitTraceEvent(flatbuffers::Offset& notification) const + { + MS_TRACE(); - this->shared->channelNotifier->Emit(this->id, "trace", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_TRACE, + FBS::Notification::Body::Consumer_TraceNotification, + notification); } } // namespace RTC diff --git a/worker/src/RTC/DataConsumer.cpp b/worker/src/RTC/DataConsumer.cpp index f96fd64ad7..3f5fd69ffd 100644 --- a/worker/src/RTC/DataConsumer.cpp +++ b/worker/src/RTC/DataConsumer.cpp @@ -19,58 +19,67 @@ namespace RTC const std::string& dataProducerId, RTC::SctpAssociation* sctpAssociation, RTC::DataConsumer::Listener* listener, - json& data, + const FBS::Transport::ConsumeDataRequest* data, size_t maxMessageSize) : id(id), dataProducerId(dataProducerId), shared(shared), sctpAssociation(sctpAssociation), listener(listener), maxMessageSize(maxMessageSize) { MS_TRACE(); - auto jsonTypeIt = data.find("type"); - auto jsonSctpStreamParametersIt = data.find("sctpStreamParameters"); - auto jsonLabelIt = data.find("label"); - auto jsonProtocolIt = data.find("protocol"); - - if (jsonTypeIt == data.end() || !jsonTypeIt->is_string()) - MS_THROW_TYPE_ERROR("missing type"); + switch (data->type()) + { + case FBS::DataProducer::Type::SCTP: + { + this->type = DataConsumer::Type::SCTP; - this->typeString = jsonTypeIt->get(); + break; + } + case FBS::DataProducer::Type::DIRECT: + { + this->type = DataConsumer::Type::DIRECT; - if (this->typeString == "sctp") - this->type = DataConsumer::Type::SCTP; - else if (this->typeString == "direct") - this->type = DataConsumer::Type::DIRECT; - else - MS_THROW_TYPE_ERROR("invalid type"); + break; + } + } if (this->type == DataConsumer::Type::SCTP) { - // clang-format off - if ( - jsonSctpStreamParametersIt == data.end() || - !jsonSctpStreamParametersIt->is_object() - ) - // clang-format on + if (!flatbuffers::IsFieldPresent( + data, FBS::Transport::ConsumeDataRequest::VT_SCTPSTREAMPARAMETERS)) { MS_THROW_TYPE_ERROR("missing sctpStreamParameters"); } // This may throw. - this->sctpStreamParameters = RTC::SctpStreamParameters(*jsonSctpStreamParametersIt); + this->sctpStreamParameters = RTC::SctpStreamParameters(data->sctpStreamParameters()); } - if (jsonLabelIt != data.end() && jsonLabelIt->is_string()) - this->label = jsonLabelIt->get(); + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeDataRequest::VT_LABEL)) + { + this->label = data->label()->str(); + } + + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeDataRequest::VT_PROTOCOL)) + { + this->protocol = data->protocol()->str(); + } - if (jsonProtocolIt != data.end() && jsonProtocolIt->is_string()) - this->protocol = jsonProtocolIt->get(); + // paused is set to false by default. + this->paused = data->paused(); + + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeDataRequest::VT_SUBCHANNELS)) + { + for (const auto subchannel : *data->subchannels()) + { + this->subchannels.insert(subchannel); + } + } // NOTE: This may throw. this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } DataConsumer::~DataConsumer() @@ -80,93 +89,125 @@ namespace RTC this->shared->channelMessageRegistrator->UnregisterHandler(this->id); } - void DataConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset DataConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add type. - jsonObject["type"] = this->typeString; - - // Add dataProducerId. - jsonObject["dataProducerId"] = this->dataProducerId; + flatbuffers::Offset sctpStreamParameters; // Add sctpStreamParameters. if (this->type == DataConsumer::Type::SCTP) { - this->sctpStreamParameters.FillJson(jsonObject["sctpStreamParameters"]); + sctpStreamParameters = this->sctpStreamParameters.FillBuffer(builder); } - // Add label. - jsonObject["label"] = this->label; + std::vector subchannels; - // Add protocol. - jsonObject["protocol"] = this->protocol; + subchannels.reserve(this->subchannels.size()); - // Add bufferedAmountLowThreshold. - jsonObject["bufferedAmountLowThreshold"] = this->bufferedAmountLowThreshold; + for (auto subchannel : this->subchannels) + { + subchannels.emplace_back(subchannel); + } + + return FBS::DataConsumer::CreateDumpResponseDirect( + builder, + this->id.c_str(), + this->dataProducerId.c_str(), + this->type == DataConsumer::Type::SCTP ? FBS::DataProducer::Type::SCTP + : FBS::DataProducer::Type::DIRECT, + sctpStreamParameters, + this->label.c_str(), + this->protocol.c_str(), + this->bufferedAmountLowThreshold, + this->paused, + this->dataProducerPaused, + std::addressof(subchannels)); } - void DataConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset DataConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonArray.emplace_back(json::value_t::object); - auto& jsonObject = jsonArray[0]; - - // Add type. - jsonObject["type"] = "data-consumer"; + return FBS::DataConsumer::CreateGetStatsResponseDirect( + builder, + // timestamp. + DepLibUV::GetTimeMs(), + // label. + this->label.c_str(), + // protocol. + this->protocol.c_str(), + // messagesSent. + this->messagesSent, + // bytesSent. + this->bytesSent, + // bufferedAmount. + this->bufferedAmount); + } - // Add timestamp. - jsonObject["timestamp"] = DepLibUV::GetTimeMs(); + void DataConsumer::HandleRequest(Channel::ChannelRequest* request) + { + MS_TRACE(); - // Add label. - jsonObject["label"] = this->label; + switch (request->method) + { + case Channel::ChannelRequest::Method::DATACONSUMER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - // Add protocol. - jsonObject["protocol"] = this->protocol; + request->Accept(FBS::Response::Body::DataConsumer_DumpResponse, dumpOffset); - // Add messagesSent. - jsonObject["messagesSent"] = this->messagesSent; + break; + } - // Add bytesSent. - jsonObject["bytesSent"] = this->bytesSent; + case Channel::ChannelRequest::Method::DATACONSUMER_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); - // Add bufferedAmount. - jsonObject["bufferedAmount"] = this->bufferedAmount; - } + request->Accept(FBS::Response::Body::DataConsumer_GetStatsResponse, responseOffset); - void DataConsumer::HandleRequest(Channel::ChannelRequest* request) - { - MS_TRACE(); + break; + } - switch (request->methodId) - { - case Channel::ChannelRequest::MethodId::DATA_CONSUMER_DUMP: + case Channel::ChannelRequest::Method::DATACONSUMER_PAUSE: { - json data = json::object(); + if (this->paused) + { + request->Accept(); - FillJson(data); + break; + } + + this->paused = true; - request->Accept(data); + MS_DEBUG_DEV("DataConsumer paused [dataConsumerId:%s]", this->id.c_str()); + + request->Accept(); break; } - case Channel::ChannelRequest::MethodId::DATA_CONSUMER_GET_STATS: + case Channel::ChannelRequest::Method::DATACONSUMER_RESUME: { - json data = json::array(); + if (!this->paused) + { + request->Accept(); + + break; + } - FillJsonStats(data); + this->paused = false; - request->Accept(data); + MS_DEBUG_DEV("DataConsumer resumed [dataConsumerId:%s]", this->id.c_str()); + + request->Accept(); break; } - case Channel::ChannelRequest::MethodId::DATA_CONSUMER_GET_BUFFERED_AMOUNT: + case Channel::ChannelRequest::Method::DATACONSUMER_GET_BUFFERED_AMOUNT: { if (this->GetType() != RTC::DataConsumer::Type::SCTP) { @@ -179,28 +220,25 @@ namespace RTC } // Create status response. - json data = json::object(); - - data["bufferedAmount"] = this->sctpAssociation->GetSctpBufferedAmount(); + auto responseOffset = FBS::DataConsumer::CreateGetBufferedAmountResponse( + request->GetBufferBuilder(), this->sctpAssociation->GetSctpBufferedAmount()); - request->Accept(data); + request->Accept(FBS::Response::Body::DataConsumer_GetBufferedAmountResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD: + case Channel::ChannelRequest::Method::DATACONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD: { if (this->GetType() != DataConsumer::Type::SCTP) { MS_THROW_TYPE_ERROR("invalid DataConsumer type"); } - auto jsonThresholdIt = request->data.find("threshold"); + const auto* body = + request->data->body_as(); - if (jsonThresholdIt == request->data.end() || !jsonThresholdIt->is_number_unsigned()) - MS_THROW_TYPE_ERROR("wrong bufferedAmountThreshold (not an unsigned number)"); - - this->bufferedAmountLowThreshold = jsonThresholdIt->get(); + this->bufferedAmountLowThreshold = body->threshold(); request->Accept(); @@ -208,12 +246,15 @@ namespace RTC // Trigger 'bufferedamountlow' now. if (this->bufferedAmount <= this->bufferedAmountLowThreshold) { - std::string data(R"({"bufferedAmount":)"); - - data.append(std::to_string(this->bufferedAmount)); - data.append("}"); - - this->shared->channelNotifier->Emit(this->id, "bufferedamountlow", data); + // Notify the Node DataConsumer. + auto bufferedAmountLowOffset = FBS::DataConsumer::CreateBufferedAmountLowNotification( + this->shared->channelNotifier->GetBufferBuilder(), this->bufferedAmount); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::DATACONSUMER_BUFFERED_AMOUNT_LOW, + FBS::Notification::Body::DataConsumer_BufferedAmountLowNotification, + bufferedAmountLowOffset); } // Force the trigger of 'bufferedamountlow' once there is less or same // buffered data than the given threshold. @@ -225,20 +266,7 @@ namespace RTC break; } - default: - { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); - } - } - } - - void DataConsumer::HandleRequest(PayloadChannel::PayloadChannelRequest* request) - { - MS_TRACE(); - - switch (request->methodId) - { - case PayloadChannel::PayloadChannelRequest::MethodId::DATA_CONSUMER_SEND: + case Channel::ChannelRequest::Method::DATACONSUMER_SEND: { if (this->GetType() != RTC::DataConsumer::Type::SCTP) { @@ -250,49 +278,70 @@ namespace RTC MS_THROW_ERROR("no SCTP association present"); } - int ppid; - - // This may throw. - // NOTE: If this throws we have to catch the error and throw a MediaSoupError - // intead, otherwise the process would crash. - try - { - ppid = std::stoi(request->data); - } - catch (const std::exception& error) - { - MS_THROW_TYPE_ERROR("invalid PPID value: %s", error.what()); - } - - const auto* msg = request->payload; - auto len = request->payloadLen; + const auto* body = request->data->body_as(); + const uint8_t* data = body->data()->Data(); + size_t len = body->data()->size(); if (len > this->maxMessageSize) { MS_THROW_TYPE_ERROR( "given message exceeds maxMessageSize value [maxMessageSize:%zu, len:%zu]", - len, - this->maxMessageSize); + this->maxMessageSize, + len); } const auto* cb = new onQueuedCallback( [&request](bool queued, bool sctpSendBufferFull) { if (queued) + { request->Accept(); + } else - request->Error( - sctpSendBufferFull == true ? "sctpsendbufferfull" : "message send failed"); + { + request->Error(sctpSendBufferFull ? "sctpsendbufferfull" : "message send failed"); + } }); - SendMessage(ppid, msg, len, cb); + static std::vector EmptySubchannels; + + SendMessage(data, len, body->ppid(), EmptySubchannels, std::nullopt, cb); + + break; + } + + case Channel::ChannelRequest::Method::DATACONSUMER_SET_SUBCHANNELS: + { + const auto* body = request->data->body_as(); + + this->subchannels.clear(); + + for (const auto subchannel : *body->subchannels()) + { + this->subchannels.insert(subchannel); + } + + std::vector subchannels; + + subchannels.reserve(this->subchannels.size()); + + for (auto subchannel : this->subchannels) + { + subchannels.emplace_back(subchannel); + } + + // Create response. + auto responseOffset = FBS::DataConsumer::CreateSetSubchannelsResponseDirect( + request->GetBufferBuilder(), std::addressof(subchannels)); + + request->Accept(FBS::Response::Body::DataConsumer_SetSubchannelsResponse, responseOffset); break; } default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } @@ -315,6 +364,40 @@ namespace RTC MS_DEBUG_DEV("Transport disconnected [dataConsumerId:%s]", this->id.c_str()); } + void DataConsumer::DataProducerPaused() + { + MS_TRACE(); + + if (this->dataProducerPaused) + { + return; + } + + this->dataProducerPaused = true; + + MS_DEBUG_DEV("DataProducer paused [dataConsumerId:%s]", this->id.c_str()); + + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::DATACONSUMER_DATAPRODUCER_PAUSE); + } + + void DataConsumer::DataProducerResumed() + { + MS_TRACE(); + + if (!this->dataProducerPaused) + { + return; + } + + this->dataProducerPaused = false; + + MS_DEBUG_DEV("DataProducer resumed [dataConsumerId:%s]", this->id.c_str()); + + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::DATACONSUMER_DATAPRODUCER_RESUME); + } + void DataConsumer::SctpAssociationConnected() { MS_TRACE(); @@ -351,12 +434,14 @@ namespace RTC this->forceTriggerBufferedAmountLow = false; // Notify the Node DataConsumer. - std::string data(R"({"bufferedAmount":)"); - - data.append(std::to_string(this->bufferedAmount)); - data.append("}"); - - this->shared->channelNotifier->Emit(this->id, "bufferedamountlow", data); + auto bufferedAmountLowOffset = FBS::DataConsumer::CreateBufferedAmountLowNotification( + this->shared->channelNotifier->GetBufferBuilder(), this->bufferedAmount); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::DATACONSUMER_BUFFERED_AMOUNT_LOW, + FBS::Notification::Body::DataConsumer_BufferedAmountLowNotification, + bufferedAmountLowOffset); } } @@ -364,7 +449,8 @@ namespace RTC { MS_TRACE(); - this->shared->channelNotifier->Emit(this->id, "sctpsendbufferfull"); + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::DATACONSUMER_SCTP_SENDBUFFER_FULL); } // The caller (Router) is supposed to proceed with the deletion of this DataConsumer @@ -377,17 +463,57 @@ namespace RTC MS_DEBUG_DEV("DataProducer closed [dataConsumerId:%s]", this->id.c_str()); - this->shared->channelNotifier->Emit(this->id, "dataproducerclose"); + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::DATACONSUMER_DATAPRODUCER_CLOSE); this->listener->OnDataConsumerDataProducerClosed(this); } - void DataConsumer::SendMessage(uint32_t ppid, const uint8_t* msg, size_t len, onQueuedCallback* cb) + void DataConsumer::SendMessage( + const uint8_t* msg, + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel, + onQueuedCallback* cb) { MS_TRACE(); if (!IsActive()) + { + return; + } + + // If a required subchannel is given, verify that this data consumer is + // subscribed to it. + if ( + requiredSubchannel.has_value() && + this->subchannels.find(requiredSubchannel.value()) == this->subchannels.end()) + { return; + } + + // If subchannels are given, verify that this data consumer is subscribed + // to at least one of them. + if (subchannels.size() > 0) + { + bool subchannelMatched{ false }; + + for (const auto subchannel : subchannels) + { + if (this->subchannels.find(subchannel) != this->subchannels.end()) + { + subchannelMatched = true; + + break; + } + } + + if (!subchannelMatched) + { + return; + } + } if (len > this->maxMessageSize) { @@ -403,6 +529,6 @@ namespace RTC this->messagesSent++; this->bytesSent += len; - this->listener->OnDataConsumerSendMessage(this, ppid, msg, len, cb); + this->listener->OnDataConsumerSendMessage(this, msg, len, ppid, cb); } } // namespace RTC diff --git a/worker/src/RTC/DataProducer.cpp b/worker/src/RTC/DataProducer.cpp index f0888c83ae..34c9efc525 100644 --- a/worker/src/RTC/DataProducer.cpp +++ b/worker/src/RTC/DataProducer.cpp @@ -7,6 +7,7 @@ #include "MediaSoupErrors.hpp" #include "Utils.hpp" #include +#include namespace RTC { @@ -17,56 +18,56 @@ namespace RTC const std::string& id, size_t maxMessageSize, RTC::DataProducer::Listener* listener, - json& data) + const FBS::Transport::ProduceDataRequest* data) : id(id), shared(shared), maxMessageSize(maxMessageSize), listener(listener) { MS_TRACE(); - auto jsonTypeIt = data.find("type"); - auto jsonSctpStreamParametersIt = data.find("sctpStreamParameters"); - auto jsonLabelIt = data.find("label"); - auto jsonProtocolIt = data.find("protocol"); - - if (jsonTypeIt == data.end() || !jsonTypeIt->is_string()) - MS_THROW_TYPE_ERROR("missing type"); + switch (data->type()) + { + case FBS::DataProducer::Type::SCTP: + { + this->type = DataProducer::Type::SCTP; - this->typeString = jsonTypeIt->get(); + break; + } + case FBS::DataProducer::Type::DIRECT: + { + this->type = DataProducer::Type::DIRECT; - if (this->typeString == "sctp") - this->type = DataProducer::Type::SCTP; - else if (this->typeString == "direct") - this->type = DataProducer::Type::DIRECT; - else - MS_THROW_TYPE_ERROR("invalid type"); + break; + } + } if (this->type == DataProducer::Type::SCTP) { - // clang-format off - if ( - jsonSctpStreamParametersIt == data.end() || - !jsonSctpStreamParametersIt->is_object() - ) - // clang-format on + if (!flatbuffers::IsFieldPresent( + data, FBS::Transport::ProduceDataRequest::VT_SCTPSTREAMPARAMETERS)) { MS_THROW_TYPE_ERROR("missing sctpStreamParameters"); } // This may throw. - this->sctpStreamParameters = RTC::SctpStreamParameters(*jsonSctpStreamParametersIt); + this->sctpStreamParameters = RTC::SctpStreamParameters(data->sctpStreamParameters()); } - if (jsonLabelIt != data.end() && jsonLabelIt->is_string()) - this->label = jsonLabelIt->get(); + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ProduceDataRequest::VT_LABEL)) + { + this->label = data->label()->str(); + } + + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ProduceDataRequest::VT_PROTOCOL)) + { + this->protocol = data->protocol()->str(); + } - if (jsonProtocolIt != data.end() && jsonProtocolIt->is_string()) - this->protocol = jsonProtocolIt->get(); + this->paused = data->paused(); // NOTE: This may throw. this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } DataProducer::~DataProducer() @@ -76,124 +77,160 @@ namespace RTC this->shared->channelMessageRegistrator->UnregisterHandler(this->id); } - void DataProducer::FillJson(json& jsonObject) const + flatbuffers::Offset DataProducer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add type. - jsonObject["type"] = this->typeString; + flatbuffers::Offset sctpStreamParametersOffset; // Add sctpStreamParameters. if (this->type == DataProducer::Type::SCTP) { - this->sctpStreamParameters.FillJson(jsonObject["sctpStreamParameters"]); + sctpStreamParametersOffset = this->sctpStreamParameters.FillBuffer(builder); } - // Add label. - jsonObject["label"] = this->label; - - // Add protocol. - jsonObject["protocol"] = this->protocol; + return FBS::DataProducer::CreateDumpResponseDirect( + builder, + this->id.c_str(), + this->type == DataProducer::Type::SCTP ? FBS::DataProducer::Type::SCTP + : FBS::DataProducer::Type::DIRECT, + sctpStreamParametersOffset, + this->label.c_str(), + this->protocol.c_str(), + this->paused); } - void DataProducer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset DataProducer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonArray.emplace_back(json::value_t::object); - auto& jsonObject = jsonArray[0]; + return FBS::DataProducer::CreateGetStatsResponseDirect( + builder, + // timestamp. + DepLibUV::GetTimeMs(), + // label. + this->label.c_str(), + // protocol. + this->protocol.c_str(), + // messagesReceived. + this->messagesReceived, + // bytesReceived. + this->bytesReceived); + } - // Add type. - jsonObject["type"] = "data-producer"; + void DataProducer::HandleRequest(Channel::ChannelRequest* request) + { + MS_TRACE(); - // Add timestamp. - jsonObject["timestamp"] = DepLibUV::GetTimeMs(); + switch (request->method) + { + case Channel::ChannelRequest::Method::DATAPRODUCER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - // Add label. - jsonObject["label"] = this->label; + request->Accept(FBS::Response::Body::DataProducer_DumpResponse, dumpOffset); - // Add protocol. - jsonObject["protocol"] = this->protocol; + break; + } - // Add messagesReceived. - jsonObject["messagesReceived"] = this->messagesReceived; + case Channel::ChannelRequest::Method::DATAPRODUCER_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); - // Add bytesReceived. - jsonObject["bytesReceived"] = this->bytesReceived; - } + request->Accept(FBS::Response::Body::DataProducer_GetStatsResponse, responseOffset); - void DataProducer::HandleRequest(Channel::ChannelRequest* request) - { - MS_TRACE(); + break; + } - switch (request->methodId) - { - case Channel::ChannelRequest::MethodId::DATA_PRODUCER_DUMP: + case Channel::ChannelRequest::Method::DATAPRODUCER_PAUSE: { - json data = json::object(); + if (this->paused) + { + request->Accept(); + + break; + } + + this->paused = true; - FillJson(data); + MS_DEBUG_DEV("DataProducer paused [dataProducerId:%s]", this->id.c_str()); - request->Accept(data); + this->listener->OnDataProducerPaused(this); + + request->Accept(); break; } - case Channel::ChannelRequest::MethodId::DATA_PRODUCER_GET_STATS: + case Channel::ChannelRequest::Method::DATAPRODUCER_RESUME: { - json data = json::array(); + if (!this->paused) + { + request->Accept(); + + break; + } + + this->paused = false; - FillJsonStats(data); + MS_DEBUG_DEV("DataProducer resumed [dataProducerId:%s]", this->id.c_str()); - request->Accept(data); + this->listener->OnDataProducerResumed(this); + + request->Accept(); break; } default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } - void DataProducer::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void DataProducer::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - switch (notification->eventId) + switch (notification->event) { - case PayloadChannel::PayloadChannelNotification::EventId::DATA_PRODUCER_SEND: + case Channel::ChannelNotification::Event::DATAPRODUCER_SEND: { - int ppid; + const auto* body = notification->data->body_as(); + const uint8_t* data = body->data()->Data(); + size_t len = body->data()->size(); - // This may throw. - // NOTE: If this throws we have to catch the error and throw a MediaSoupError - // intead, otherwise the process would crash. - try + if (len > this->maxMessageSize) { - ppid = std::stoi(notification->data); + MS_THROW_TYPE_ERROR( + "given message exceeds maxMessageSize value [maxMessageSize:%zu, len:%zu]", + this->maxMessageSize, + len); } - catch (const std::exception& error) + + std::vector subchannels; + + if (flatbuffers::IsFieldPresent(body, FBS::DataProducer::SendNotification::VT_SUBCHANNELS)) { - MS_THROW_TYPE_ERROR("invalid PPID value: %s", error.what()); + subchannels.reserve(body->subchannels()->size()); + + for (const auto subchannel : *body->subchannels()) + { + subchannels.emplace_back(subchannel); + } } - const auto* msg = notification->payload; - auto len = notification->payloadLen; + std::optional requiredSubchannel{ std::nullopt }; - if (len > this->maxMessageSize) + if (body->requiredSubchannel().has_value()) { - MS_THROW_TYPE_ERROR( - "given message exceeds maxMessageSize value [maxMessageSize:%zu, len:%zu]", - len, - this->maxMessageSize); + requiredSubchannel = body->requiredSubchannel().value(); } - this->ReceiveMessage(ppid, msg, len); + ReceiveMessage(data, len, body->ppid(), subchannels, requiredSubchannel); // Increase receive transmission. this->listener->OnDataProducerReceiveData(this, len); @@ -203,18 +240,30 @@ namespace RTC default: { - MS_ERROR("unknown event '%s'", notification->event.c_str()); + MS_ERROR("unknown event '%s'", notification->eventCStr); } } } - void DataProducer::ReceiveMessage(uint32_t ppid, const uint8_t* msg, size_t len) + void DataProducer::ReceiveMessage( + const uint8_t* msg, + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel) { MS_TRACE(); this->messagesReceived++; this->bytesReceived += len; - this->listener->OnDataProducerMessageReceived(this, ppid, msg, len); + // If paused stop here. + if (this->paused) + { + return; + } + + this->listener->OnDataProducerMessageReceived( + this, msg, len, ppid, subchannels, requiredSubchannel); } } // namespace RTC diff --git a/worker/src/RTC/DirectTransport.cpp b/worker/src/RTC/DirectTransport.cpp index 903881170b..d11d5a3acd 100644 --- a/worker/src/RTC/DirectTransport.cpp +++ b/worker/src/RTC/DirectTransport.cpp @@ -11,8 +11,11 @@ namespace RTC // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) DirectTransport::DirectTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data) - : RTC::Transport::Transport(shared, id, listener, data) + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::DirectTransport::DirectTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()) { MS_TRACE(); @@ -20,8 +23,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } DirectTransport::~DirectTransport() @@ -35,57 +37,80 @@ namespace RTC this->shared->channelMessageRegistrator->UnregisterHandler(this->id); } - void DirectTransport::FillJson(json& jsonObject) const + flatbuffers::Offset DirectTransport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { - MS_TRACE(); + // Add base transport dump. + auto base = Transport::FillBuffer(builder); - // Call the parent method. - RTC::Transport::FillJson(jsonObject); + return FBS::DirectTransport::CreateDumpResponse(builder, base); } - void DirectTransport::FillJsonStats(json& jsonArray) + flatbuffers::Offset DirectTransport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJsonStats(jsonArray); - - auto& jsonObject = jsonArray[0]; + // Base Transport stats. + auto base = Transport::FillBufferStats(builder); - // Add type. - jsonObject["type"] = "direct-transport"; + return FBS::DirectTransport::CreateGetStatsResponse(builder, base); } void DirectTransport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - // Pass it to the parent class. - RTC::Transport::HandleRequest(request); + switch (request->method) + { + case Channel::ChannelRequest::Method::TRANSPORT_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::DirectTransport_GetStatsResponse, responseOffset); + + break; + } + + case Channel::ChannelRequest::Method::TRANSPORT_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::DirectTransport_DumpResponse, dumpOffset); + + break; + } + + default: + { + // Pass it to the parent class. + RTC::Transport::HandleRequest(request); + } + } } - void DirectTransport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void DirectTransport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - switch (notification->eventId) + switch (notification->event) { - case PayloadChannel::PayloadChannelNotification::EventId::TRANSPORT_SEND_RTCP: + case Channel::ChannelNotification::Event::TRANSPORT_SEND_RTCP: { - const auto* data = notification->payload; - auto len = notification->payloadLen; + const auto* body = notification->data->body_as(); + auto len = body->data()->size(); // Increase receive transmission. RTC::Transport::DataReceived(len); if (len > RTC::MtuSize + 100) { - MS_WARN_TAG(rtp, "given RTCP packet exceeds maximum size [len:%zu]", len); + MS_WARN_TAG(rtp, "given RTCP packet exceeds maximum size [len:%i]", len); return; } - RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, len); + RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(body->data()->data(), len); if (!packet) { @@ -125,11 +150,17 @@ namespace RTC return; } - const uint8_t* data = packet->GetData(); - const size_t len = packet->GetSize(); + const auto data = this->shared->channelNotifier->GetBufferBuilder().CreateVector( + packet->GetData(), packet->GetSize()); - // Notify the Node DirectTransport. - this->shared->payloadChannelNotifier->Emit(consumer->id, "rtp", data, len); + auto notification = + FBS::Consumer::CreateRtpNotification(this->shared->channelNotifier->GetBufferBuilder(), data); + + this->shared->channelNotifier->Emit( + consumer->id, + FBS::Notification::Event::CONSUMER_RTP, + FBS::Notification::Body::Consumer_RtpNotification, + notification); if (cb) { @@ -138,21 +169,28 @@ namespace RTC } // Increase send transmission. - RTC::Transport::DataSent(len); + RTC::Transport::DataSent(packet->GetSize()); } void DirectTransport::SendRtcpPacket(RTC::RTCP::Packet* packet) { MS_TRACE(); - const uint8_t* data = packet->GetData(); - const size_t len = packet->GetSize(); - // Notify the Node DirectTransport. - this->shared->payloadChannelNotifier->Emit(this->id, "rtcp", data, len); + const auto data = this->shared->channelNotifier->GetBufferBuilder().CreateVector( + packet->GetData(), packet->GetSize()); + + auto notification = FBS::DirectTransport::CreateRtcpNotification( + this->shared->channelNotifier->GetBufferBuilder(), data); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::DIRECTTRANSPORT_RTCP, + FBS::Notification::Body::DirectTransport_RtcpNotification, + notification); // Increase send transmission. - RTC::Transport::DataSent(len); + RTC::Transport::DataSent(packet->GetSize()); } void DirectTransport::SendRtcpCompoundPacket(RTC::RTCP::CompoundPacket* packet) @@ -161,27 +199,35 @@ namespace RTC packet->Serialize(RTC::RTCP::Buffer); - const uint8_t* data = packet->GetData(); - const size_t len = packet->GetSize(); + const auto data = this->shared->channelNotifier->GetBufferBuilder().CreateVector( + packet->GetData(), packet->GetSize()); - // Notify the Node DirectTransport. - this->shared->payloadChannelNotifier->Emit(this->id, "rtcp", data, len); + auto notification = FBS::DirectTransport::CreateRtcpNotification( + this->shared->channelNotifier->GetBufferBuilder(), data); - // Increase send transmission. - RTC::Transport::DataSent(len); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::DIRECTTRANSPORT_RTCP, + FBS::Notification::Body::DirectTransport_RtcpNotification, + notification); } void DirectTransport::SendMessage( - RTC::DataConsumer* dataConsumer, uint32_t ppid, const uint8_t* msg, size_t len, onQueuedCallback* cb) + RTC::DataConsumer* dataConsumer, const uint8_t* msg, size_t len, uint32_t ppid, onQueuedCallback* cb) { MS_TRACE(); // Notify the Node DirectTransport. - json data = json::object(); + auto data = this->shared->channelNotifier->GetBufferBuilder().CreateVector(msg, len); - data["ppid"] = ppid; + auto notification = FBS::DataConsumer::CreateMessageNotification( + this->shared->channelNotifier->GetBufferBuilder(), ppid, data); - this->shared->payloadChannelNotifier->Emit(dataConsumer->id, "message", data, msg, len); + this->shared->channelNotifier->Emit( + dataConsumer->id, + FBS::Notification::Event::DATACONSUMER_MESSAGE, + FBS::Notification::Body::DataConsumer_MessageNotification, + notification); // Increase send transmission. RTC::Transport::DataSent(len); diff --git a/worker/src/RTC/DtlsTransport.cpp b/worker/src/RTC/DtlsTransport.cpp index d639f64767..adada495d3 100644 --- a/worker/src/RTC/DtlsTransport.cpp +++ b/worker/src/RTC/DtlsTransport.cpp @@ -16,7 +16,9 @@ do \ { \ if (ERR_peek_error() == 0) \ + { \ MS_ERROR("OpenSSL error [desc:'%s']", desc); \ + } \ else \ { \ int64_t err; \ @@ -46,11 +48,42 @@ inline static void onSslInfo(const SSL* ssl, int where, int ret) inline static unsigned int onSslDtlsTimer(SSL* /*ssl*/, unsigned int timerUs) { if (timerUs == 0) + { return 100000; + } else if (timerUs >= 4000000) + { return 4000000; + } else + { return 2 * timerUs; + } +} + +inline static long onSslBioOut( + BIO* bio, + int operationType, + const char* argp, + size_t len, + int /*argi*/, + long /*argl*/, + int ret, + size_t* /*processed*/) +{ + long resultOfcallback = (operationType == BIO_CB_RETURN) ? static_cast(ret) : 1; + + if (operationType == BIO_CB_WRITE && argp && len > 0) + { + MS_DEBUG_DEV("%zu bytes of DTLS data ready to be sent", len); + + RTC::DtlsTransport* dtlsTransport = + reinterpret_cast(BIO_get_callback_arg(bio)); + + dtlsTransport->SendDtlsData(reinterpret_cast(argp), len); + } + + return resultOfcallback; } namespace RTC @@ -142,11 +175,156 @@ namespace RTC MS_TRACE(); if (DtlsTransport::privateKey) + { EVP_PKEY_free(DtlsTransport::privateKey); + } + if (DtlsTransport::certificate) + { X509_free(DtlsTransport::certificate); + } + if (DtlsTransport::sslCtx) + { SSL_CTX_free(DtlsTransport::sslCtx); + } + } + + DtlsTransport::Role DtlsTransport::RoleFromFbs(FBS::WebRtcTransport::DtlsRole role) + { + switch (role) + { + case FBS::WebRtcTransport::DtlsRole::AUTO: + { + return DtlsTransport::Role::AUTO; + } + + case FBS::WebRtcTransport::DtlsRole::CLIENT: + { + return DtlsTransport::Role::CLIENT; + } + + case FBS::WebRtcTransport::DtlsRole::SERVER: + { + return DtlsTransport::Role::SERVER; + } + } + } + + FBS::WebRtcTransport::DtlsRole DtlsTransport::RoleToFbs(DtlsTransport::Role role) + { + switch (role) + { + case DtlsTransport::Role::AUTO: + { + return FBS::WebRtcTransport::DtlsRole::AUTO; + } + + case DtlsTransport::Role::CLIENT: + { + return FBS::WebRtcTransport::DtlsRole::CLIENT; + } + + case DtlsTransport::Role::SERVER: + { + return FBS::WebRtcTransport::DtlsRole::SERVER; + } + } + } + + FBS::WebRtcTransport::DtlsState DtlsTransport::StateToFbs(DtlsTransport::DtlsState state) + { + switch (state) + { + case DtlsTransport::DtlsState::NEW: + { + return FBS::WebRtcTransport::DtlsState::NEW; + } + + case DtlsTransport::DtlsState::CONNECTING: + { + return FBS::WebRtcTransport::DtlsState::CONNECTING; + } + + case DtlsTransport::DtlsState::CONNECTED: + { + return FBS::WebRtcTransport::DtlsState::CONNECTED; + } + + case DtlsTransport::DtlsState::FAILED: + { + return FBS::WebRtcTransport::DtlsState::FAILED; + } + + case DtlsTransport::DtlsState::CLOSED: + { + return FBS::WebRtcTransport::DtlsState::CLOSED; + } + } + } + + DtlsTransport::FingerprintAlgorithm DtlsTransport::AlgorithmFromFbs( + FBS::WebRtcTransport::FingerprintAlgorithm algorithm) + { + switch (algorithm) + { + case FBS::WebRtcTransport::FingerprintAlgorithm::SHA1: + { + return DtlsTransport::FingerprintAlgorithm::SHA1; + } + + case FBS::WebRtcTransport::FingerprintAlgorithm::SHA224: + { + return DtlsTransport::FingerprintAlgorithm::SHA224; + } + + case FBS::WebRtcTransport::FingerprintAlgorithm::SHA256: + { + return DtlsTransport::FingerprintAlgorithm::SHA256; + } + + case FBS::WebRtcTransport::FingerprintAlgorithm::SHA384: + { + return DtlsTransport::FingerprintAlgorithm::SHA384; + } + + case FBS::WebRtcTransport::FingerprintAlgorithm::SHA512: + { + return DtlsTransport::FingerprintAlgorithm::SHA512; + } + } + } + + FBS::WebRtcTransport::FingerprintAlgorithm DtlsTransport::AlgorithmToFbs( + DtlsTransport::FingerprintAlgorithm algorithm) + { + switch (algorithm) + { + case DtlsTransport::FingerprintAlgorithm::SHA1: + { + return FBS::WebRtcTransport::FingerprintAlgorithm::SHA1; + } + + case DtlsTransport::FingerprintAlgorithm::SHA224: + { + return FBS::WebRtcTransport::FingerprintAlgorithm::SHA224; + } + + case DtlsTransport::FingerprintAlgorithm::SHA256: + { + return FBS::WebRtcTransport::FingerprintAlgorithm::SHA256; + } + + case DtlsTransport::FingerprintAlgorithm::SHA384: + { + return FBS::WebRtcTransport::FingerprintAlgorithm::SHA384; + } + + case DtlsTransport::FingerprintAlgorithm::SHA512: + { + return FBS::WebRtcTransport::FingerprintAlgorithm::SHA512; + } + } } void DtlsTransport::GenerateCertificateAndPrivateKey() @@ -240,10 +418,14 @@ namespace RTC error: if (DtlsTransport::privateKey) + { EVP_PKEY_free(DtlsTransport::privateKey); + } if (DtlsTransport::certificate) + { X509_free(DtlsTransport::certificate); + } MS_THROW_ERROR("DTLS certificate and private key generation failed"); } @@ -395,7 +577,9 @@ namespace RTC ++it) { if (it != DtlsTransport::srtpCryptoSuites.begin()) + { dtlsSrtpCryptoSuites += ":"; + } SrtpCryptoSuiteMapEntry* cryptoSuiteEntry = std::addressof(*it); dtlsSrtpCryptoSuites += cryptoSuiteEntry->name; @@ -445,27 +629,39 @@ namespace RTC switch (algorithm) { case FingerprintAlgorithm::SHA1: + { hashFunction = EVP_sha1(); break; + } case FingerprintAlgorithm::SHA224: + { hashFunction = EVP_sha224(); break; + } case FingerprintAlgorithm::SHA256: + { hashFunction = EVP_sha256(); break; + } case FingerprintAlgorithm::SHA384: + { hashFunction = EVP_sha384(); break; + } case FingerprintAlgorithm::SHA512: + { hashFunction = EVP_sha512(); break; + } default: + { MS_THROW_ERROR("unknown algorithm"); + } } ret = X509_digest(DtlsTransport::certificate, hashFunction, binaryFingerprint, &size); @@ -488,7 +684,7 @@ namespace RTC // Store it in the vector. DtlsTransport::Fingerprint fingerprint; - fingerprint.algorithm = DtlsTransport::GetFingerprintAlgorithm(algorithmString); + fingerprint.algorithm = algorithm; fingerprint.value = hexFingerprint; DtlsTransport::localFingerprints.push_back(fingerprint); @@ -538,6 +734,8 @@ namespace RTC goto error; } + BIO_set_callback_ex(this->sslBioToNetwork, onSslBioOut); + BIO_set_callback_arg(this->sslBioToNetwork, reinterpret_cast(this)); SSL_set_bio(this->ssl, this->sslBioFromNetwork, this->sslBioToNetwork); // Set the MTU so that we don't send packets that are too large with no fragmentation. @@ -548,7 +746,7 @@ namespace RTC DTLS_set_timer_cb(this->ssl, onSslDtlsTimer); // Set the DTLS timer. - this->timer = new Timer(this); + this->timer = new TimerHandle(this); return; @@ -557,13 +755,19 @@ namespace RTC // NOTE: At this point SSL_set_bio() was not called so we must free BIOs as // well. if (this->sslBioFromNetwork) + { BIO_free(this->sslBioFromNetwork); + } if (this->sslBioToNetwork) + { BIO_free(this->sslBioToNetwork); + } if (this->ssl) + { SSL_free(this->ssl); + } // NOTE: If this is not catched by the caller the program will abort, but // this should never happen. @@ -578,7 +782,6 @@ namespace RTC { // Send close alert to the peer. SSL_shutdown(this->ssl); - SendPendingOutgoingDtlsData(); } if (this->ssl) @@ -604,32 +807,54 @@ namespace RTC switch (this->state) { case DtlsState::CONNECTING: + { state = "connecting"; break; + } + case DtlsState::CONNECTED: + { state = "connected"; break; + } + case DtlsState::FAILED: + { state = "failed"; break; + } + case DtlsState::CLOSED: + { state = "closed"; break; + } + default:; } - switch (this->localRole) + if (this->localRole.has_value()) { - case Role::AUTO: - role = "auto"; - break; - case Role::SERVER: - role = "server"; - break; - case Role::CLIENT: - role = "client"; - break; - default:; + switch (this->localRole.value()) + { + case Role::AUTO: + { + role = "auto"; + break; + } + + case Role::SERVER: + { + role = "server"; + break; + } + + case Role::CLIENT: + { + role = "client"; + break; + } + } } MS_DUMP(""); @@ -647,9 +872,7 @@ namespace RTC localRole == Role::CLIENT || localRole == Role::SERVER, "local DTLS role must be 'client' or 'server'"); - const Role previousLocalRole = this->localRole; - - if (localRole == previousLocalRole) + if (this->localRole.has_value() && localRole == this->localRole.value()) { MS_ERROR("same local DTLS role provided, doing nothing"); @@ -657,7 +880,9 @@ namespace RTC } // If the previous local DTLS role was 'client' or 'server' do reset. - if (previousLocalRole == Role::CLIENT || previousLocalRole == Role::SERVER) + if ( + this->localRole.has_value() && + (this->localRole.value() == Role::CLIENT || this->localRole.value() == Role::SERVER)) { MS_DEBUG_TAG(dtls, "resetting DTLS due to local role change"); @@ -671,7 +896,7 @@ namespace RTC this->state = DtlsState::CONNECTING; this->listener->OnDtlsTransportConnecting(this); - switch (this->localRole) + switch (this->localRole.value()) { case Role::CLIENT: { @@ -679,7 +904,6 @@ namespace RTC SSL_set_connect_state(this->ssl); SSL_do_handshake(this->ssl); - SendPendingOutgoingDtlsData(); SetTimeout(); break; @@ -706,9 +930,6 @@ namespace RTC { MS_TRACE(); - MS_ASSERT( - fingerprint.algorithm != FingerprintAlgorithm::NONE, "no fingerprint algorithm provided"); - this->remoteFingerprint = fingerprint; // The remote fingerpring may have been set after DTLS handshake was done, @@ -753,16 +974,17 @@ namespace RTC // Must call SSL_read() to process received DTLS data. read = SSL_read(this->ssl, static_cast(DtlsTransport::sslReadBuffer), SslReadBufferSize); - // Send data if it's ready. - SendPendingOutgoingDtlsData(); - // Check SSL status and return if it is bad/closed. if (!CheckStatus(read)) + { return; + } // Set/update the DTLS timeout. if (!SetTimeout()) + { return; + } // Application data received. Notify to the listener. if (read > 0) @@ -809,16 +1031,23 @@ namespace RTC LOG_OPENSSL_ERROR("SSL_write() failed"); if (!CheckStatus(written)) + { return; + } } else if (written != static_cast(len)) { MS_WARN_TAG( dtls, "OpenSSL SSL_write() wrote less (%d bytes) than given data (%zu bytes)", written, len); } + } + + void DtlsTransport::SendDtlsData(const uint8_t* data, size_t len) + { + MS_TRACE(); - // Send data. - SendPendingOutgoingDtlsData(); + // Notify the listener. + this->listener->OnDtlsTransportSendData(this, data, len); } void DtlsTransport::Reset() @@ -828,19 +1057,20 @@ namespace RTC int ret; if (!IsRunning()) + { return; + } MS_WARN_TAG(dtls, "resetting DTLS transport"); // Stop the DTLS timer. this->timer->Stop(); - // We need to reset the SSL instance so we need to "shutdown" it, but we - // don't want to send a Close Alert to the peer, so just don't call - // SendPendingOutgoingDTLSData(). + // NOTE: We need to reset the SSL instance so we need to "shutdown" it, but we + // don't want to send a Close Alert to the peer. However this is gonna happen. SSL_shutdown(this->ssl); - this->localRole = Role::NONE; + this->localRole.reset(); this->state = DtlsState::NEW; this->handshakeDone = false; this->handshakeDoneNow = false; @@ -852,7 +1082,9 @@ namespace RTC ret = SSL_clear(this->ssl); if (ret == 0) + { ERR_clear_error(); + } } inline bool DtlsTransport::CheckStatus(int returnCode) @@ -867,40 +1099,60 @@ namespace RTC switch (err) { case SSL_ERROR_NONE: + { break; + } case SSL_ERROR_SSL: + { LOG_OPENSSL_ERROR("SSL status: SSL_ERROR_SSL"); break; + } case SSL_ERROR_WANT_READ: + { break; + } case SSL_ERROR_WANT_WRITE: + { MS_WARN_TAG(dtls, "SSL status: SSL_ERROR_WANT_WRITE"); break; + } case SSL_ERROR_WANT_X509_LOOKUP: + { MS_DEBUG_TAG(dtls, "SSL status: SSL_ERROR_WANT_X509_LOOKUP"); break; + } case SSL_ERROR_SYSCALL: + { LOG_OPENSSL_ERROR("SSL status: SSL_ERROR_SYSCALL"); break; + } case SSL_ERROR_ZERO_RETURN: + { break; + } case SSL_ERROR_WANT_CONNECT: + { MS_WARN_TAG(dtls, "SSL status: SSL_ERROR_WANT_CONNECT"); break; + } case SSL_ERROR_WANT_ACCEPT: + { MS_WARN_TAG(dtls, "SSL status: SSL_ERROR_WANT_ACCEPT"); break; + } default: + { MS_WARN_TAG(dtls, "SSL status: unknown error"); + } } // Check if the handshake (or re-handshake) has been done right now. @@ -913,8 +1165,10 @@ namespace RTC this->timer->Stop(); // Process the handshake just once (ignore if DTLS renegotiation). - if (!wasHandshakeDone && this->remoteFingerprint.algorithm != FingerprintAlgorithm::NONE) + if (!wasHandshakeDone && this->remoteFingerprint.has_value()) + { return ProcessHandshake(); + } return true; } @@ -950,32 +1204,6 @@ namespace RTC } } - inline void DtlsTransport::SendPendingOutgoingDtlsData() - { - MS_TRACE(); - - if (BIO_eof(this->sslBioToNetwork)) - return; - - int64_t read; - char* data{ nullptr }; - - read = BIO_get_mem_data(this->sslBioToNetwork, &data); // NOLINT - - if (read <= 0) - return; - - MS_DEBUG_DEV("%" PRIu64 " bytes of DTLS data ready to sent to the peer", read); - - // Notify the listener. - this->listener->OnDtlsTransportSendData( - this, reinterpret_cast(data), static_cast(read)); - - // Clear the BIO buffer. - // NOTE: the (void) avoids the -Wunused-value warning. - (void)BIO_reset(this->sslBioToNetwork); - } - inline bool DtlsTransport::SetTimeout() { MS_TRACE(); @@ -1031,8 +1259,6 @@ namespace RTC MS_TRACE(); MS_ASSERT(this->handshakeDone, "handshake not done yet"); - MS_ASSERT( - this->remoteFingerprint.algorithm != FingerprintAlgorithm::NONE, "remote fingerprint not set"); // Validate the remote fingerprint. if (!CheckRemoteFingerprint()) @@ -1047,12 +1273,12 @@ namespace RTC } // Get the negotiated SRTP crypto suite. - RTC::SrtpSession::CryptoSuite srtpCryptoSuite = GetNegotiatedSrtpCryptoSuite(); + auto srtpCryptoSuite = GetNegotiatedSrtpCryptoSuite(); - if (srtpCryptoSuite != RTC::SrtpSession::CryptoSuite::NONE) + if (srtpCryptoSuite) { // Extract the SRTP keys (will notify the listener with them). - ExtractSrtpKeys(srtpCryptoSuite); + ExtractSrtpKeys(srtpCryptoSuite.value()); return true; } @@ -1074,8 +1300,7 @@ namespace RTC { MS_TRACE(); - MS_ASSERT( - this->remoteFingerprint.algorithm != FingerprintAlgorithm::NONE, "remote fingerprint not set"); + MS_ASSERT(this->remoteFingerprint.has_value(), "remote fingerprint not set"); X509* certificate; uint8_t binaryFingerprint[EVP_MAX_MD_SIZE]; @@ -1093,30 +1318,37 @@ namespace RTC return false; } - switch (this->remoteFingerprint.algorithm) + switch (this->remoteFingerprint->algorithm) { case FingerprintAlgorithm::SHA1: + { hashFunction = EVP_sha1(); break; + } case FingerprintAlgorithm::SHA224: + { hashFunction = EVP_sha224(); break; + } case FingerprintAlgorithm::SHA256: + { hashFunction = EVP_sha256(); break; + } case FingerprintAlgorithm::SHA384: + { hashFunction = EVP_sha384(); break; + } case FingerprintAlgorithm::SHA512: + { hashFunction = EVP_sha512(); break; - - default: - MS_ABORT("unknown algorithm"); + } } // Compare the remote fingerprint with the value given via signaling. @@ -1138,13 +1370,13 @@ namespace RTC } hexFingerprint[(size * 3) - 1] = '\0'; - if (this->remoteFingerprint.value != hexFingerprint) + if (this->remoteFingerprint->value != hexFingerprint) { MS_WARN_TAG( dtls, "fingerprint in the remote certificate (%s) does not match the announced one (%s)", hexFingerprint, - this->remoteFingerprint.value.c_str()); + this->remoteFingerprint->value.c_str()); X509_free(certificate); @@ -1233,11 +1465,6 @@ namespace RTC break; } - - default: - { - MS_ABORT("unknown SRTP crypto suite"); - } } auto* srtpMaterial = new uint8_t[srtpMasterLength * 2]; @@ -1253,8 +1480,9 @@ namespace RTC this->ssl, srtpMaterial, srtpMasterLength * 2, "EXTRACTOR-dtls_srtp", 19, nullptr, 0, 0); MS_ASSERT(ret != 0, "SSL_export_keying_material() failed"); + MS_ASSERT(this->localRole.has_value(), "no DTLS role set"); - switch (this->localRole) + switch (this->localRole.value()) { case Role::SERVER: { @@ -1305,18 +1533,20 @@ namespace RTC delete[] srtpRemoteMasterKey; } - inline RTC::SrtpSession::CryptoSuite DtlsTransport::GetNegotiatedSrtpCryptoSuite() + inline std::optional DtlsTransport::GetNegotiatedSrtpCryptoSuite() { MS_TRACE(); - RTC::SrtpSession::CryptoSuite negotiatedSrtpCryptoSuite = RTC::SrtpSession::CryptoSuite::NONE; + std::optional negotiatedSrtpCryptoSuite; // Ensure that the SRTP crypto suite has been negotiated. // NOTE: This is a OpenSSL type. SRTP_PROTECTION_PROFILE* sslSrtpCryptoSuite = SSL_get_selected_srtp_profile(this->ssl); if (!sslSrtpCryptoSuite) + { return negotiatedSrtpCryptoSuite; + } // Get the negotiated SRTP crypto suite. for (auto& srtpCryptoSuite : DtlsTransport::srtpCryptoSuites) @@ -1332,8 +1562,7 @@ namespace RTC } MS_ASSERT( - negotiatedSrtpCryptoSuite != RTC::SrtpSession::CryptoSuite::NONE, - "chosen SRTP crypto suite is not an available one"); + negotiatedSrtpCryptoSuite.has_value(), "chosen SRTP crypto suite is not an available one"); return negotiatedSrtpCryptoSuite; } @@ -1346,11 +1575,17 @@ namespace RTC const char* role; if ((w & SSL_ST_CONNECT) != 0) + { role = "client"; + } else if ((w & SSL_ST_ACCEPT) != 0) + { role = "server"; + } else + { role = "undefined"; + } if ((where & SSL_CB_LOOP) != 0) { @@ -1363,15 +1598,21 @@ namespace RTC switch (*SSL_alert_type_string(ret)) { case 'W': + { alertType = "warning"; break; + } case 'F': + { alertType = "fatal"; break; + } default: + { alertType = "undefined"; + } } if ((where & SSL_CB_READ) != 0) @@ -1390,9 +1631,13 @@ namespace RTC else if ((where & SSL_CB_EXIT) != 0) { if (ret == 0) + { MS_DEBUG_TAG(dtls, "[role:%s, failed:'%s']", role, SSL_state_string_long(this->ssl)); + } else if (ret < 0) + { MS_DEBUG_TAG(dtls, "role: %s, waiting:'%s']", role, SSL_state_string_long(this->ssl)); + } } else if ((where & SSL_CB_HANDSHAKE_START) != 0) { @@ -1409,7 +1654,7 @@ namespace RTC // receipt of a close alert does not work (the flag is set after this callback). } - inline void DtlsTransport::OnTimer(Timer* /*timer*/) + inline void DtlsTransport::OnTimer(TimerHandle* /*timer*/) { MS_TRACE(); @@ -1429,9 +1674,6 @@ namespace RTC if (ret == 1) { - // If required, send DTLS data. - SendPendingOutgoingDtlsData(); - // Set the DTLS timer again. SetTimeout(); } diff --git a/worker/src/RTC/IceCandidate.cpp b/worker/src/RTC/IceCandidate.cpp index 4d756c3a64..d3e23ee978 100644 --- a/worker/src/RTC/IceCandidate.cpp +++ b/worker/src/RTC/IceCandidate.cpp @@ -6,53 +6,78 @@ namespace RTC { - /* Instance methods. */ + /* Class methods. */ - void IceCandidate::FillJson(json& jsonObject) const + IceCandidate::CandidateType IceCandidate::CandidateTypeFromFbs( + FBS::WebRtcTransport::IceCandidateType type) { - MS_TRACE(); - - // Add foundation. - jsonObject["foundation"] = this->foundation; - - // Add priority. - jsonObject["priority"] = this->priority; - - // Add ip. - jsonObject["ip"] = this->ip; - - // Add protocol. - switch (this->protocol) + switch (type) { - case Protocol::UDP: - jsonObject["protocol"] = "udp"; - break; + case FBS::WebRtcTransport::IceCandidateType::HOST: + return IceCandidate::CandidateType::HOST; + } + } - case Protocol::TCP: - jsonObject["protocol"] = "tcp"; - break; + FBS::WebRtcTransport::IceCandidateType IceCandidate::CandidateTypeToFbs(IceCandidate::CandidateType type) + { + switch (type) + { + case IceCandidate::CandidateType::HOST: + return FBS::WebRtcTransport::IceCandidateType::HOST; } + } - // Add port. - jsonObject["port"] = this->port; + IceCandidate::TcpCandidateType IceCandidate::TcpCandidateTypeFromFbs( + FBS::WebRtcTransport::IceCandidateTcpType type) + { + switch (type) + { + case FBS::WebRtcTransport::IceCandidateTcpType::PASSIVE: + return IceCandidate::TcpCandidateType::PASSIVE; + } + } - // Add type. - switch (this->type) + FBS::WebRtcTransport::IceCandidateTcpType IceCandidate::TcpCandidateTypeToFbs( + IceCandidate::TcpCandidateType type) + { + switch (type) { - case CandidateType::HOST: - jsonObject["type"] = "host"; - break; + case IceCandidate::TcpCandidateType::PASSIVE: + return FBS::WebRtcTransport::IceCandidateTcpType::PASSIVE; } + } + + /* Instance methods. */ + + flatbuffers::Offset IceCandidate::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const + { + MS_TRACE(); + + auto protocol = TransportTuple::ProtocolToFbs(this->protocol); + auto type = CandidateTypeToFbs(this->type); + flatbuffers::Optional tcpType; - // Add tcpType. if (this->protocol == Protocol::TCP) { - switch (this->tcpType) - { - case TcpCandidateType::PASSIVE: - jsonObject["tcpType"] = "passive"; - break; - } + tcpType.emplace(TcpCandidateTypeToFbs(this->tcpType)); } + + return FBS::WebRtcTransport::CreateIceCandidateDirect( + builder, + // foundation. + this->foundation.c_str(), + // priority. + this->priority, + // ip. + this->ip.c_str(), + // protocol. + protocol, + // port. + this->port, + // type. + type, + // tcpType. + tcpType); } } // namespace RTC diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index 4cf1a6a924..aac5716186 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -14,6 +14,43 @@ namespace RTC thread_local static uint8_t StunSerializeBuffer[StunSerializeBufferSize]; static constexpr size_t MaxTuples{ 8 }; + /* Class methods. */ + IceServer::IceState IceStateFromFbs(FBS::WebRtcTransport::IceState state) + { + switch (state) + { + case FBS::WebRtcTransport::IceState::NEW: + return IceServer::IceState::NEW; + + case FBS::WebRtcTransport::IceState::CONNECTED: + return IceServer::IceState::CONNECTED; + + case FBS::WebRtcTransport::IceState::COMPLETED: + return IceServer::IceState::COMPLETED; + + case FBS::WebRtcTransport::IceState::DISCONNECTED: + return IceServer::IceState::DISCONNECTED; + } + } + + FBS::WebRtcTransport::IceState IceServer::IceStateToFbs(IceServer::IceState state) + { + switch (state) + { + case IceServer::IceState::NEW: + return FBS::WebRtcTransport::IceState::NEW; + + case IceServer::IceState::CONNECTED: + return FBS::WebRtcTransport::IceState::CONNECTED; + + case IceServer::IceState::COMPLETED: + return FBS::WebRtcTransport::IceState::COMPLETED; + + case IceServer::IceState::DISCONNECTED: + return FBS::WebRtcTransport::IceState::DISCONNECTED; + } + } + /* Instance methods. */ IceServer::IceServer(Listener* listener, const std::string& usernameFragment, const std::string& password) diff --git a/worker/src/RTC/KeyFrameRequestManager.cpp b/worker/src/RTC/KeyFrameRequestManager.cpp index aae45b0f70..f3b1e7ed67 100644 --- a/worker/src/RTC/KeyFrameRequestManager.cpp +++ b/worker/src/RTC/KeyFrameRequestManager.cpp @@ -13,7 +13,7 @@ RTC::PendingKeyFrameInfo::PendingKeyFrameInfo(PendingKeyFrameInfo::Listener* lis { MS_TRACE(); - this->timer = new Timer(this); + this->timer = new TimerHandle(this); this->timer->Start(KeyFrameRetransmissionWaitTime); } @@ -25,12 +25,14 @@ RTC::PendingKeyFrameInfo::~PendingKeyFrameInfo() delete this->timer; } -inline void RTC::PendingKeyFrameInfo::OnTimer(Timer* timer) +inline void RTC::PendingKeyFrameInfo::OnTimer(TimerHandle* timer) { MS_TRACE(); if (timer == this->timer) + { this->listener->OnKeyFrameRequestTimeout(this); + } } /* KeyFrameRequestDelayer methods. */ @@ -41,7 +43,7 @@ RTC::KeyFrameRequestDelayer::KeyFrameRequestDelayer( { MS_TRACE(); - this->timer = new Timer(this); + this->timer = new TimerHandle(this); this->timer->Start(delay); } @@ -53,12 +55,14 @@ RTC::KeyFrameRequestDelayer::~KeyFrameRequestDelayer() delete this->timer; } -inline void RTC::KeyFrameRequestDelayer::OnTimer(Timer* timer) +inline void RTC::KeyFrameRequestDelayer::OnTimer(TimerHandle* timer) { MS_TRACE(); if (timer == this->timer) + { this->listener->OnKeyFrameDelayTimeout(this); + } } /* KeyFrameRequestManager methods. */ @@ -185,7 +189,9 @@ void RTC::KeyFrameRequestManager::KeyFrameReceived(uint32_t ssrc) // There is no pending key frame for the given ssrc. if (it == this->mapSsrcPendingKeyFrameInfo.end()) + { return; + } auto* pendingKeyFrameInfo = it->second; diff --git a/worker/src/RTC/NackGenerator.cpp b/worker/src/RTC/NackGenerator.cpp index 289d6dd3df..7eb168df40 100644 --- a/worker/src/RTC/NackGenerator.cpp +++ b/worker/src/RTC/NackGenerator.cpp @@ -26,7 +26,7 @@ namespace RTC MS_TRACE(); // Set the timer. - this->timer = new Timer(this); + this->timer = new TimerHandle(this); } NackGenerator::~NackGenerator() @@ -372,7 +372,7 @@ namespace RTC } } - inline void NackGenerator::OnTimer(Timer* /*timer*/) + inline void NackGenerator::OnTimer(TimerHandle* /*timer*/) { MS_TRACE(); diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index 9078dc83ea..3af878f6db 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -1,11 +1,12 @@ +#include "FBS/consumer.h" #define MS_CLASS "RTC::PipeConsumer" // #define MS_LOG_DEV_LEVEL 3 -#include "RTC/PipeConsumer.hpp" #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "RTC/Codecs/Tools.hpp" +#include "RTC/PipeConsumer.hpp" namespace RTC { @@ -16,7 +17,7 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data) + const FBS::Transport::ConsumeRequest* data) : RTC::Consumer::Consumer(shared, id, producerId, listener, data, RTC::RtpParameters::Type::PIPE) { MS_TRACE(); @@ -37,8 +38,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } PipeConsumer::~PipeConsumer() @@ -56,61 +56,72 @@ namespace RTC this->mapSsrcRtpStream.clear(); } - void PipeConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset PipeConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Call the parent method. - RTC::Consumer::FillJson(jsonObject); + auto base = RTC::Consumer::FillBuffer(builder); // Add rtpStreams. - jsonObject["rtpStreams"] = json::array(); - auto jsonRtpStreamsIt = jsonObject.find("rtpStreams"); + std::vector> rtpStreams; + rtpStreams.reserve(this->rtpStreams.size()); - for (auto* rtpStream : this->rtpStreams) + for (const auto* rtpStream : this->rtpStreams) { - jsonRtpStreamsIt->emplace_back(json::value_t::object); + rtpStreams.emplace_back(rtpStream->FillBuffer(builder)); + } - auto& jsonEntry = (*jsonRtpStreamsIt)[jsonRtpStreamsIt->size() - 1]; + auto dump = FBS::Consumer::CreateConsumerDumpDirect(builder, base, &rtpStreams); - rtpStream->FillJson(jsonEntry); - } + return FBS::Consumer::CreateDumpResponse(builder, dump); } - void PipeConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset PipeConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + rtpStreams.reserve(this->rtpStreams.size()); + // Add stats of our send streams. for (auto* rtpStream : this->rtpStreams) { - jsonArray.emplace_back(json::value_t::object); - - auto& jsonEntry = jsonArray[jsonArray.size() - 1]; - - rtpStream->FillJsonStats(jsonEntry); + rtpStreams.emplace_back(rtpStream->FillBufferStats(builder)); } + + return FBS::Consumer::CreateGetStatsResponseDirect(builder, &rtpStreams); } - void PipeConsumer::FillJsonScore(json& jsonObject) const + flatbuffers::Offset PipeConsumer::FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); MS_ASSERT(this->producerRtpStreamScores, "producerRtpStreamScores not set"); // NOTE: Hardcoded values in PipeTransport. - jsonObject["score"] = 10; - jsonObject["producerScore"] = 10; - jsonObject["producerScores"] = *this->producerRtpStreamScores; + return FBS::Consumer::CreateConsumerScoreDirect(builder, 10, 10, this->producerRtpStreamScores); } void PipeConsumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME: + case Channel::ChannelRequest::Method::CONSUMER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::Consumer_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) RequestKeyFrame(); @@ -120,11 +131,14 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS: + case Channel::ChannelRequest::Method::CONSUMER_SET_PREFERRED_LAYERS: { - // Do nothing. + // Accept with empty preferred layers object. - request->Accept(); + auto responseOffset = + FBS::Consumer::CreateSetPreferredLayersResponse(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::Consumer_SetPreferredLayersResponse, responseOffset); break; } diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index d46624a649..9c42fd9e33 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -15,7 +15,6 @@ namespace RTC RTC::SrtpSession::CryptoSuite PipeTransport::srtpCryptoSuite{ RTC::SrtpSession::CryptoSuite::AEAD_AES_256_GCM }; - std::string PipeTransport::srtpCryptoSuiteString{ "AEAD_AES_256_GCM" }; // MAster length of AEAD_AES_256_GCM. size_t PipeTransport::srtpMasterLength{ 44 }; @@ -23,65 +22,51 @@ namespace RTC // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) PipeTransport::PipeTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data) - : RTC::Transport::Transport(shared, id, listener, data) + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::PipeTransport::PipeTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()) { MS_TRACE(); - auto jsonListenIpIt = data.find("listenIp"); - - if (jsonListenIpIt == data.end()) - MS_THROW_TYPE_ERROR("missing listenIp"); - else if (!jsonListenIpIt->is_object()) - MS_THROW_TYPE_ERROR("wrong listenIp (not an object)"); - - auto jsonIpIt = jsonListenIpIt->find("ip"); - - if (jsonIpIt == jsonListenIpIt->end()) - MS_THROW_TYPE_ERROR("missing listenIp.ip"); - else if (!jsonIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.ip (not an string)"); + if (options->listenInfo()->protocol() != FBS::Transport::Protocol::UDP) + { + MS_THROW_TYPE_ERROR("unsupported listen protocol"); + } - this->listenIp.ip.assign(jsonIpIt->get()); + this->listenInfo.ip.assign(options->listenInfo()->ip()->str()); // This may throw. - Utils::IP::NormalizeIp(this->listenIp.ip); + Utils::IP::NormalizeIp(this->listenInfo.ip); - auto jsonAnnouncedIpIt = jsonListenIpIt->find("announcedIp"); - - if (jsonAnnouncedIpIt != jsonListenIpIt->end()) + if (flatbuffers::IsFieldPresent(options->listenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) { - if (!jsonAnnouncedIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.announcedIp (not an string"); + this->listenInfo.announcedIp.assign(options->listenInfo()->announcedIp()->str()); + } - this->listenIp.announcedIp.assign(jsonAnnouncedIpIt->get()); + if (flatbuffers::IsFieldPresent(options->listenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) + { + this->listenInfo.announcedIp.assign(options->listenInfo()->announcedIp()->str()); } - uint16_t port{ 0 }; - auto jsonPortIt = data.find("port"); + this->listenInfo.port = options->listenInfo()->port(); - if (jsonPortIt != data.end()) + if (flatbuffers::IsFieldPresent( + options->listenInfo(), FBS::Transport::ListenInfo::VT_SENDBUFFERSIZE)) { - if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) - MS_THROW_TYPE_ERROR("wrong port (not a positive number)"); - - port = jsonPortIt->get(); + this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); } - auto jsonEnableRtxIt = data.find("enableRtx"); - - if (jsonEnableRtxIt != data.end() && jsonEnableRtxIt->is_boolean()) - this->rtx = jsonEnableRtxIt->get(); + if (flatbuffers::IsFieldPresent( + options->listenInfo(), FBS::Transport::ListenInfo::VT_RECVBUFFERSIZE)) + { + this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); + } - auto jsonEnableSrtpIt = data.find("enableSrtp"); + this->rtx = options->enableRtx(); - // clang-format off - if ( - jsonEnableSrtpIt != data.end() && - jsonEnableSrtpIt->is_boolean() && - jsonEnableSrtpIt->get() - ) - // clang-format on + if (options->enableSrtp()) { this->srtpKey = Utils::Crypto::GetRandomString(PipeTransport::srtpMasterLength); this->srtpKeyBase64 = Utils::String::Base64Encode(this->srtpKey); @@ -90,17 +75,38 @@ namespace RTC try { // This may throw. - if (port != 0) - this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip, port); + if (this->listenInfo.port != 0) + { + this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.port); + } else - this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip); + { + this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip); + } + + if (this->listenInfo.sendBufferSize != 0) + { + // NOTE: This may throw. + this->udpSocket->SetSendBufferSize(this->listenInfo.sendBufferSize); + } + + if (this->listenInfo.recvBufferSize != 0) + { + // NOTE: This may throw. + this->udpSocket->SetRecvBufferSize(this->listenInfo.recvBufferSize); + } + + MS_DEBUG_TAG( + info, + "UDP socket buffer sizes [send:%" PRIu32 ", recv:%" PRIu32 "]", + udpSocket->GetSendBufferSize(), + udpSocket->GetRecvBufferSize()); // NOTE: This may throw. this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } catch (const MediaSoupError& error) { @@ -136,85 +142,127 @@ namespace RTC this->srtpRecvSession = nullptr; } - void PipeTransport::FillJson(json& jsonObject) const + flatbuffers::Offset PipeTransport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJson(jsonObject); - // Add tuple. + flatbuffers::Offset tuple; + if (this->tuple) { - this->tuple->FillJson(jsonObject["tuple"]); + tuple = this->tuple->FillBuffer(builder); } else { - jsonObject["tuple"] = json::object(); - auto jsonTupleIt = jsonObject.find("tuple"); + std::string localIp; - if (this->listenIp.announcedIp.empty()) - (*jsonTupleIt)["localIp"] = this->udpSocket->GetLocalIp(); + if (this->listenInfo.announcedIp.empty()) + { + localIp = this->udpSocket->GetLocalIp(); + } else - (*jsonTupleIt)["localIp"] = this->listenIp.announcedIp; + { + localIp = this->listenInfo.announcedIp; + } - (*jsonTupleIt)["localPort"] = this->udpSocket->GetLocalPort(); - (*jsonTupleIt)["protocol"] = "udp"; + tuple = FBS::Transport::CreateTupleDirect( + builder, + localIp.c_str(), + this->udpSocket->GetLocalPort(), + nullptr, + 0, + FBS::Transport::Protocol::UDP); } - // Add rtx. - jsonObject["rtx"] = this->rtx; - // Add srtpParameters. + flatbuffers::Offset srtpParameters; + if (HasSrtp()) { - jsonObject["srtpParameters"] = json::object(); - auto jsonSrtpParametersIt = jsonObject.find("srtpParameters"); - - (*jsonSrtpParametersIt)["cryptoSuite"] = PipeTransport::srtpCryptoSuiteString; - (*jsonSrtpParametersIt)["keyBase64"] = this->srtpKeyBase64; + srtpParameters = FBS::SrtpParameters::CreateSrtpParametersDirect( + builder, + SrtpSession::CryptoSuiteToFbs(PipeTransport::srtpCryptoSuite), + this->srtpKeyBase64.c_str()); } + + // Add base transport dump. + auto base = Transport::FillBuffer(builder); + + return FBS::PipeTransport::CreateDumpResponse(builder, base, tuple, this->rtx, srtpParameters); } - void PipeTransport::FillJsonStats(json& jsonArray) + flatbuffers::Offset PipeTransport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJsonStats(jsonArray); - - auto& jsonObject = jsonArray[0]; - - // Add type. - jsonObject["type"] = "pipe-transport"; + // Add tuple. + flatbuffers::Offset tuple; if (this->tuple) { - this->tuple->FillJson(jsonObject["tuple"]); + tuple = this->tuple->FillBuffer(builder); } else { - // Add tuple. - jsonObject["tuple"] = json::object(); - auto jsonTupleIt = jsonObject.find("tuple"); + std::string localIp; - if (this->listenIp.announcedIp.empty()) - (*jsonTupleIt)["localIp"] = this->udpSocket->GetLocalIp(); + if (this->listenInfo.announcedIp.empty()) + { + localIp = this->udpSocket->GetLocalIp(); + } else - (*jsonTupleIt)["localIp"] = this->listenIp.announcedIp; + { + localIp = this->listenInfo.announcedIp; + } - (*jsonTupleIt)["localPort"] = this->udpSocket->GetLocalPort(); - (*jsonTupleIt)["protocol"] = "udp"; + tuple = FBS::Transport::CreateTupleDirect( + builder, + // localIp. + localIp.c_str(), + // localPort, + this->udpSocket->GetLocalPort(), + // remoteIp. + nullptr, + // remotePort. + 0, + // protocol. + FBS::Transport::Protocol::UDP); } + + // Base Transport stats. + auto base = Transport::FillBufferStats(builder); + + return FBS::PipeTransport::CreateGetStatsResponse(builder, base, tuple); } void PipeTransport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::TRANSPORT_CONNECT: + case Channel::ChannelRequest::Method::TRANSPORT_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::PipeTransport_GetStatsResponse, responseOffset); + + break; + } + + case Channel::ChannelRequest::Method::TRANSPORT_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::PipeTransport_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::PIPETRANSPORT_CONNECT: { // Ensure this method is not called twice. if (this->tuple) @@ -226,56 +274,32 @@ namespace RTC uint16_t port{ 0u }; std::string srtpKeyBase64; - auto jsonSrtpParametersIt = request->data.find("srtpParameters"); + const auto* body = request->data->body_as(); - if (!HasSrtp() && jsonSrtpParametersIt != request->data.end()) + auto srtpParametersPresent = + flatbuffers::IsFieldPresent(body, FBS::PipeTransport::ConnectRequest::VT_SRTPPARAMETERS); + + if (!HasSrtp() && srtpParametersPresent) { MS_THROW_TYPE_ERROR("invalid srtpParameters (SRTP not enabled)"); } else if (HasSrtp()) { - // clang-format off - if ( - jsonSrtpParametersIt == request->data.end() || - !jsonSrtpParametersIt->is_object() - ) - // clang-format on + if (!srtpParametersPresent) { MS_THROW_TYPE_ERROR("missing srtpParameters (SRTP enabled)"); } - auto jsonCryptoSuiteIt = jsonSrtpParametersIt->find("cryptoSuite"); - - // clang-format off - if ( - jsonCryptoSuiteIt == jsonSrtpParametersIt->end() || - !jsonCryptoSuiteIt->is_string() - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing srtpParameters.cryptoSuite)"); - } + const auto* srtpParameters = body->srtpParameters(); // NOTE: We just use AEAD_AES_256_GCM as SRTP crypto suite in // PipeTransport. - if (jsonCryptoSuiteIt->get() != PipeTransport::srtpCryptoSuiteString) + if (srtpParameters->cryptoSuite() != FBS::SrtpParameters::SrtpCryptoSuite::AEAD_AES_256_GCM) { MS_THROW_TYPE_ERROR("invalid/unsupported srtpParameters.cryptoSuite"); } - auto jsonKeyBase64It = jsonSrtpParametersIt->find("keyBase64"); - - // clang-format off - if ( - jsonKeyBase64It == jsonSrtpParametersIt->end() || - !jsonKeyBase64It->is_string() - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing srtpParameters.keyBase64)"); - } - - srtpKeyBase64 = jsonKeyBase64It->get(); + srtpKeyBase64 = srtpParameters->keyBase64()->str(); size_t outLen; // This may throw. @@ -326,29 +350,20 @@ namespace RTC delete[] srtpRemoteKey; } - auto jsonIpIt = request->data.find("ip"); - - if (jsonIpIt == request->data.end() || !jsonIpIt->is_string()) + if (!flatbuffers::IsFieldPresent(body, FBS::PipeTransport::ConnectRequest::VT_IP)) MS_THROW_TYPE_ERROR("missing ip"); - ip = jsonIpIt->get(); + ip = body->ip()->str(); // This may throw. Utils::IP::NormalizeIp(ip); - auto jsonPortIt = request->data.find("port"); - - // clang-format off - if ( - jsonPortIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonPortIt) - ) - // clang-format on + if (!body->port().has_value()) { MS_THROW_TYPE_ERROR("missing port"); } - port = jsonPortIt->get(); + port = body->port().value(); int err; @@ -390,8 +405,10 @@ namespace RTC this->tuple = new RTC::TransportTuple( this->udpSocket, reinterpret_cast(&this->remoteAddrStorage)); - if (!this->listenIp.announcedIp.empty()) - this->tuple->SetLocalAnnouncedIp(this->listenIp.announcedIp); + if (!this->listenInfo.announcedIp.empty()) + { + this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + } } catch (const MediaSoupError& error) { @@ -407,12 +424,12 @@ namespace RTC throw; } - // Tell the caller about the selected local DTLS role. - json data = json::object(); + auto tupleOffset = this->tuple->FillBuffer(request->GetBufferBuilder()); - this->tuple->FillJson(data["tuple"]); + auto responseOffset = + FBS::PipeTransport::CreateConnectResponse(request->GetBufferBuilder(), tupleOffset); - request->Accept(data); + request->Accept(FBS::Response::Body::PipeTransport_ConnectResponse, responseOffset); // Assume we are connected (there is no much more we can do to know it) // and tell the parent class. @@ -429,7 +446,7 @@ namespace RTC } } - void PipeTransport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void PipeTransport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); @@ -530,11 +547,11 @@ namespace RTC } void PipeTransport::SendMessage( - RTC::DataConsumer* dataConsumer, uint32_t ppid, const uint8_t* msg, size_t len, onQueuedCallback* cb) + RTC::DataConsumer* dataConsumer, const uint8_t* msg, size_t len, uint32_t ppid, onQueuedCallback* cb) { MS_TRACE(); - this->sctpAssociation->SendSctpMessage(dataConsumer, ppid, msg, len, cb); + this->sctpAssociation->SendSctpMessage(dataConsumer, msg, len, ppid, cb); } void PipeTransport::SendSctpData(const uint8_t* data, size_t len) diff --git a/worker/src/RTC/PlainTransport.cpp b/worker/src/RTC/PlainTransport.cpp index 6a461dc78d..305e67516f 100644 --- a/worker/src/RTC/PlainTransport.cpp +++ b/worker/src/RTC/PlainTransport.cpp @@ -26,114 +26,100 @@ namespace RTC /* Class variables. */ - // clang-format off - absl::flat_hash_map PlainTransport::string2SrtpCryptoSuite = - { - { "AEAD_AES_256_GCM", RTC::SrtpSession::CryptoSuite::AEAD_AES_256_GCM }, - { "AEAD_AES_128_GCM", RTC::SrtpSession::CryptoSuite::AEAD_AES_128_GCM }, - { "AES_CM_128_HMAC_SHA1_80", RTC::SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_80 }, - { "AES_CM_128_HMAC_SHA1_32", RTC::SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_32 } - }; - absl::flat_hash_map PlainTransport::srtpCryptoSuite2String = - { - { RTC::SrtpSession::CryptoSuite::AEAD_AES_256_GCM, "AEAD_AES_256_GCM" }, - { RTC::SrtpSession::CryptoSuite::AEAD_AES_128_GCM, "AEAD_AES_128_GCM" }, - { RTC::SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_80, "AES_CM_128_HMAC_SHA1_80" }, - { RTC::SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_32, "AES_CM_128_HMAC_SHA1_32" } - }; - /* Instance methods. */ - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) - PlainTransport::PlainTransport(RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data) - : RTC::Transport::Transport(shared, id, listener, data) + PlainTransport::PlainTransport( + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::PlainTransport::PlainTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()) { MS_TRACE(); - auto jsonListenIpIt = data.find("listenIp"); - - if (jsonListenIpIt == data.end()) - MS_THROW_TYPE_ERROR("missing listenIp"); - else if (!jsonListenIpIt->is_object()) - MS_THROW_TYPE_ERROR("wrong listenIp (not an object)"); - - auto jsonIpIt = jsonListenIpIt->find("ip"); - - if (jsonIpIt == jsonListenIpIt->end()) - MS_THROW_TYPE_ERROR("missing listenIp.ip"); - else if (!jsonIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.ip (not an string)"); + if (options->listenInfo()->protocol() != FBS::Transport::Protocol::UDP) + { + MS_THROW_TYPE_ERROR("unsupported listen protocol"); + } - this->listenIp.ip.assign(jsonIpIt->get()); + this->listenInfo.ip.assign(options->listenInfo()->ip()->str()); // This may throw. - Utils::IP::NormalizeIp(this->listenIp.ip); + Utils::IP::NormalizeIp(this->listenInfo.ip); - auto jsonAnnouncedIpIt = jsonListenIpIt->find("announcedIp"); - - if (jsonAnnouncedIpIt != jsonListenIpIt->end()) + if (flatbuffers::IsFieldPresent(options->listenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) { - if (!jsonAnnouncedIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.announcedIp (not an string"); - - this->listenIp.announcedIp.assign(jsonAnnouncedIpIt->get()); + this->listenInfo.announcedIp.assign(options->listenInfo()->announcedIp()->str()); } - uint16_t port{ 0 }; - auto jsonPortIt = data.find("port"); + this->listenInfo.port = options->listenInfo()->port(); - if (jsonPortIt != data.end()) + if (flatbuffers::IsFieldPresent( + options->listenInfo(), FBS::Transport::ListenInfo::VT_SENDBUFFERSIZE)) { - if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) - MS_THROW_TYPE_ERROR("wrong port (not a positive number)"); - - port = jsonPortIt->get(); + this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); } - auto jsonRtcpMuxIt = data.find("rtcpMux"); - - if (jsonRtcpMuxIt != data.end()) + if (flatbuffers::IsFieldPresent( + options->listenInfo(), FBS::Transport::ListenInfo::VT_RECVBUFFERSIZE)) { - if (!jsonRtcpMuxIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong rtcpMux (not a boolean)"); - - this->rtcpMux = jsonRtcpMuxIt->get(); + this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); } - auto jsonComediaIt = data.find("comedia"); + this->rtcpMux = options->rtcpMux(); + this->comedia = options->comedia(); - if (jsonComediaIt != data.end()) + if (!this->rtcpMux) { - if (!jsonComediaIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong comedia (not a boolean)"); + if (flatbuffers::IsFieldPresent( + options, FBS::PlainTransport::PlainTransportOptions::VT_RTCPLISTENINFO)) + { + if (options->rtcpListenInfo()->protocol() != FBS::Transport::Protocol::UDP) + { + MS_THROW_TYPE_ERROR("unsupported RTCP listen protocol"); + } - this->comedia = jsonComediaIt->get(); - } + this->rtcpListenInfo.ip.assign(options->rtcpListenInfo()->ip()->str()); - auto jsonEnableSrtpIt = data.find("enableSrtp"); + // This may throw. + Utils::IP::NormalizeIp(this->rtcpListenInfo.ip); - // clang-format off - if ( - jsonEnableSrtpIt != data.end() && - jsonEnableSrtpIt->is_boolean() && - jsonEnableSrtpIt->get() - ) - // clang-format on - { - auto jsonSrtpCryptoSuiteIt = data.find("srtpCryptoSuite"); + if (flatbuffers::IsFieldPresent( + options->rtcpListenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) + { + this->rtcpListenInfo.announcedIp.assign(options->rtcpListenInfo()->announcedIp()->str()); + } - if (jsonSrtpCryptoSuiteIt == data.end() || !jsonSrtpCryptoSuiteIt->is_string()) - MS_THROW_TYPE_ERROR("missing srtpCryptoSuite)"); + this->rtcpListenInfo.port = options->rtcpListenInfo()->port(); - // Ensure it's a crypto suite supported by us. - auto it = - PlainTransport::string2SrtpCryptoSuite.find(jsonSrtpCryptoSuiteIt->get()); + if (flatbuffers::IsFieldPresent( + options->rtcpListenInfo(), FBS::Transport::ListenInfo::VT_SENDBUFFERSIZE)) + { + this->rtcpListenInfo.sendBufferSize = options->rtcpListenInfo()->sendBufferSize(); + } - if (it == PlainTransport::string2SrtpCryptoSuite.end()) - MS_THROW_TYPE_ERROR("invalid/unsupported srtpCryptoSuite"); + if (flatbuffers::IsFieldPresent( + options->rtcpListenInfo(), FBS::Transport::ListenInfo::VT_RECVBUFFERSIZE)) + { + this->rtcpListenInfo.recvBufferSize = options->rtcpListenInfo()->recvBufferSize(); + } + } + // If rtcpListenInfo is not given, just clone listenInfo. + else + { + this->rtcpListenInfo = this->listenInfo; + } + } + + if (options->enableSrtp()) + { + if (!options->srtpCryptoSuite().has_value()) + { + MS_THROW_TYPE_ERROR("missing srtpCryptoSuite"); + } // NOTE: The SRTP crypto suite may change later on connect(). - this->srtpCryptoSuite = it->second; + this->srtpCryptoSuite = SrtpSession::CryptoSuiteFromFbs(options->srtpCryptoSuite().value()); switch (this->srtpCryptoSuite) { @@ -172,23 +158,58 @@ namespace RTC try { // This may throw. - if (port != 0) - this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip, port); + if (this->listenInfo.port != 0) + { + this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.port); + } else - this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip); + { + this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip); + } + + if (this->listenInfo.sendBufferSize != 0) + { + // NOTE: This may throw. + this->udpSocket->SetSendBufferSize(this->listenInfo.sendBufferSize); + } + + if (this->listenInfo.recvBufferSize != 0) + { + // NOTE: This may throw. + this->udpSocket->SetRecvBufferSize(this->listenInfo.recvBufferSize); + } if (!this->rtcpMux) { // This may throw. - this->rtcpUdpSocket = new RTC::UdpSocket(this, this->listenIp.ip); + if (this->rtcpListenInfo.port != 0) + { + this->rtcpUdpSocket = + new RTC::UdpSocket(this, this->rtcpListenInfo.ip, this->rtcpListenInfo.port); + } + else + { + this->rtcpUdpSocket = new RTC::UdpSocket(this, this->rtcpListenInfo.ip); + } + + if (this->rtcpListenInfo.sendBufferSize != 0) + { + // NOTE: This may throw. + this->rtcpUdpSocket->SetSendBufferSize(this->rtcpListenInfo.sendBufferSize); + } + + if (this->rtcpListenInfo.recvBufferSize != 0) + { + // NOTE: This may throw. + this->rtcpUdpSocket->SetRecvBufferSize(this->rtcpListenInfo.recvBufferSize); + } } // NOTE: This may throw. this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } catch (const MediaSoupError& error) { @@ -231,126 +252,173 @@ namespace RTC this->srtpRecvSession = nullptr; } - void PlainTransport::FillJson(json& jsonObject) const + flatbuffers::Offset PlainTransport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJson(jsonObject); - - // Add rtcpMux. - jsonObject["rtcpMux"] = this->rtcpMux; - - // Add comedia. - jsonObject["comedia"] = this->comedia; - // Add tuple. + flatbuffers::Offset tuple; + if (this->tuple) { - this->tuple->FillJson(jsonObject["tuple"]); + tuple = this->tuple->FillBuffer(builder); } else { - jsonObject["tuple"] = json::object(); - auto jsonTupleIt = jsonObject.find("tuple"); + std::string localIp; - if (this->listenIp.announcedIp.empty()) - (*jsonTupleIt)["localIp"] = this->udpSocket->GetLocalIp(); + if (this->listenInfo.announcedIp.empty()) + { + localIp = this->udpSocket->GetLocalIp(); + } else - (*jsonTupleIt)["localIp"] = this->listenIp.announcedIp; + { + localIp = this->listenInfo.announcedIp; + } - (*jsonTupleIt)["localPort"] = this->udpSocket->GetLocalPort(); - (*jsonTupleIt)["protocol"] = "udp"; + tuple = FBS::Transport::CreateTupleDirect( + builder, + localIp.c_str(), + this->udpSocket->GetLocalPort(), + nullptr, + 0, + FBS::Transport::Protocol::UDP); } // Add rtcpTuple. + flatbuffers::Offset rtcpTuple; + if (!this->rtcpMux) { if (this->rtcpTuple) { - this->rtcpTuple->FillJson(jsonObject["rtcpTuple"]); + rtcpTuple = this->rtcpTuple->FillBuffer(builder); } else { - jsonObject["rtcpTuple"] = json::object(); - auto jsonRtcpTupleIt = jsonObject.find("rtcpTuple"); + std::string localIp; - if (this->listenIp.announcedIp.empty()) - (*jsonRtcpTupleIt)["localIp"] = this->rtcpUdpSocket->GetLocalIp(); + if (this->rtcpListenInfo.announcedIp.empty()) + { + localIp = this->rtcpUdpSocket->GetLocalIp(); + } else - (*jsonRtcpTupleIt)["localIp"] = this->listenIp.announcedIp; + { + localIp = this->rtcpListenInfo.announcedIp; + } - (*jsonRtcpTupleIt)["localPort"] = this->rtcpUdpSocket->GetLocalPort(); - (*jsonRtcpTupleIt)["protocol"] = "udp"; + rtcpTuple = FBS::Transport::CreateTupleDirect( + builder, + localIp.c_str(), + this->rtcpUdpSocket->GetLocalPort(), + nullptr, + 0, + FBS::Transport::Protocol::UDP); } } // Add srtpParameters. + flatbuffers::Offset srtpParameters; + if (HasSrtp()) { - jsonObject["srtpParameters"] = json::object(); - auto jsonSrtpParametersIt = jsonObject.find("srtpParameters"); - - (*jsonSrtpParametersIt)["cryptoSuite"] = - PlainTransport::srtpCryptoSuite2String[this->srtpCryptoSuite]; - (*jsonSrtpParametersIt)["keyBase64"] = this->srtpKeyBase64; + srtpParameters = FBS::SrtpParameters::CreateSrtpParametersDirect( + builder, SrtpSession::CryptoSuiteToFbs(this->srtpCryptoSuite), this->srtpKeyBase64.c_str()); } + + // Add base transport dump. + auto base = Transport::FillBuffer(builder); + + return FBS::PlainTransport::CreateDumpResponse( + builder, base, this->rtcpMux, this->comedia, tuple, rtcpTuple, srtpParameters); } - void PlainTransport::FillJsonStats(json& jsonArray) + flatbuffers::Offset PlainTransport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJsonStats(jsonArray); - - auto& jsonObject = jsonArray[0]; - - // Add type. - jsonObject["type"] = "plain-rtp-transport"; - - // Add rtcpMux. - jsonObject["rtcpMux"] = this->rtcpMux; - - // Add comedia. - jsonObject["comedia"] = this->comedia; + // Add tuple. + flatbuffers::Offset tuple; if (this->tuple) { - // Add tuple. - this->tuple->FillJson(jsonObject["tuple"]); + tuple = this->tuple->FillBuffer(builder); } else { - // Add tuple. - jsonObject["tuple"] = json::object(); - auto jsonTupleIt = jsonObject.find("tuple"); + std::string localIp; - if (this->listenIp.announcedIp.empty()) - (*jsonTupleIt)["localIp"] = this->udpSocket->GetLocalIp(); + if (this->listenInfo.announcedIp.empty()) + { + localIp = this->udpSocket->GetLocalIp(); + } else - (*jsonTupleIt)["localIp"] = this->listenIp.announcedIp; + { + localIp = this->listenInfo.announcedIp; + } - (*jsonTupleIt)["localPort"] = this->udpSocket->GetLocalPort(); - (*jsonTupleIt)["protocol"] = "udp"; + tuple = FBS::Transport::CreateTupleDirect( + builder, + // localIp. + localIp.c_str(), + // localPort, + this->udpSocket->GetLocalPort(), + // remoteIp. + nullptr, + // remotePort. + 0, + // protocol. + FBS::Transport::Protocol::UDP); } // Add rtcpTuple. + flatbuffers::Offset rtcpTuple; + if (!this->rtcpMux && this->rtcpTuple) - this->rtcpTuple->FillJson(jsonObject["rtcpTuple"]); + { + rtcpTuple = this->rtcpTuple->FillBuffer(builder); + } + + // Base Transport stats. + auto base = Transport::FillBufferStats(builder); + + return FBS::PlainTransport::CreateGetStatsResponse( + builder, base, this->rtcpMux, this->comedia, tuple, rtcpTuple); } void PlainTransport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::TRANSPORT_CONNECT: + case Channel::ChannelRequest::Method::TRANSPORT_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::PlainTransport_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::TRANSPORT_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::PlainTransport_GetStatsResponse, responseOffset); + + break; + } + + case Channel::ChannelRequest::Method::PLAINTRANSPORT_CONNECT: { // Ensure this method is not called twice. if (this->connectCalled) + { MS_THROW_ERROR("connect() already called"); + } try { @@ -359,46 +427,27 @@ namespace RTC uint16_t rtcpPort{ 0u }; std::string srtpKeyBase64; - auto jsonSrtpParametersIt = request->data.find("srtpParameters"); + const auto* body = request->data->body_as(); + + auto srtpParametersPresent = flatbuffers::IsFieldPresent( + body, FBS::PlainTransport::ConnectRequest::VT_SRTPPARAMETERS); - if (!HasSrtp() && jsonSrtpParametersIt != request->data.end()) + if (!HasSrtp() && srtpParametersPresent) { MS_THROW_TYPE_ERROR("invalid srtpParameters (SRTP not enabled)"); } else if (HasSrtp()) { - // clang-format off - if ( - jsonSrtpParametersIt == request->data.end() || - !jsonSrtpParametersIt->is_object() - ) - // clang-format on + if (!srtpParametersPresent) { MS_THROW_TYPE_ERROR("missing srtpParameters (SRTP enabled)"); } - auto jsonCryptoSuiteIt = jsonSrtpParametersIt->find("cryptoSuite"); - - // clang-format off - if ( - jsonCryptoSuiteIt == jsonSrtpParametersIt->end() || - !jsonCryptoSuiteIt->is_string() - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing srtpParameters.cryptoSuite)"); - } - - // Ensure it's a crypto suite supported by us. - auto it = - PlainTransport::string2SrtpCryptoSuite.find(jsonCryptoSuiteIt->get()); - - if (it == PlainTransport::string2SrtpCryptoSuite.end()) - MS_THROW_TYPE_ERROR("invalid/unsupported srtpParameters.cryptoSuite"); + const auto srtpParameters = body->srtpParameters(); // Update out SRTP crypto suite with the one used by the remote. auto previousSrtpCryptoSuite = this->srtpCryptoSuite; - this->srtpCryptoSuite = it->second; + this->srtpCryptoSuite = SrtpSession::CryptoSuiteFromFbs(srtpParameters->cryptoSuite()); switch (this->srtpCryptoSuite) { @@ -437,26 +486,16 @@ namespace RTC this->srtpKeyBase64 = Utils::String::Base64Encode(this->srtpKey); } - auto jsonKeyBase64It = jsonSrtpParametersIt->find("keyBase64"); - - // clang-format off - if ( - jsonKeyBase64It == jsonSrtpParametersIt->end() || - !jsonKeyBase64It->is_string() - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing srtpParameters.keyBase64)"); - } - - srtpKeyBase64 = jsonKeyBase64It->get(); + srtpKeyBase64 = srtpParameters->keyBase64()->str(); size_t outLen; // This may throw. auto* srtpKey = Utils::String::Base64Decode(srtpKeyBase64, outLen); if (outLen != this->srtpMasterLength) + { MS_THROW_TYPE_ERROR("invalid decoded SRTP key length"); + } auto* srtpLocalKey = new uint8_t[this->srtpMasterLength]; auto* srtpRemoteKey = new uint8_t[this->srtpMasterLength]; @@ -502,48 +541,38 @@ namespace RTC if (!this->comedia) { - auto jsonIpIt = request->data.find("ip"); - - if (jsonIpIt == request->data.end() || !jsonIpIt->is_string()) + if (!flatbuffers::IsFieldPresent(body, FBS::PlainTransport::ConnectRequest::VT_IP)) + { MS_THROW_TYPE_ERROR("missing ip"); + } - ip = jsonIpIt->get(); + ip = body->ip()->str(); // This may throw. Utils::IP::NormalizeIp(ip); - auto jsonPortIt = request->data.find("port"); - - // clang-format off - if ( - jsonPortIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonPortIt) - ) - // clang-format on + if (!body->port().has_value()) { MS_THROW_TYPE_ERROR("missing port"); } - port = jsonPortIt->get(); - - auto jsonRtcpPortIt = request->data.find("rtcpPort"); + port = body->port().value(); - // clang-format off - if ( - jsonRtcpPortIt != request->data.end() && - Utils::Json::IsPositiveInteger(*jsonRtcpPortIt) - ) - // clang-format on + if (body->rtcpPort().has_value()) { if (this->rtcpMux) + { MS_THROW_TYPE_ERROR("cannot set rtcpPort with rtcpMux enabled"); + } - rtcpPort = jsonRtcpPortIt->get(); + rtcpPort = body->rtcpPort().value(); } else { if (!this->rtcpMux) + { MS_THROW_TYPE_ERROR("missing rtcpPort (required with rtcpMux disabled)"); + } } int err; @@ -558,7 +587,9 @@ namespace RTC reinterpret_cast(&this->remoteAddrStorage)); if (err != 0) + { MS_THROW_ERROR("uv_ip4_addr() failed: %s", uv_strerror(err)); + } break; } @@ -571,7 +602,9 @@ namespace RTC reinterpret_cast(&this->remoteAddrStorage)); if (err != 0) + { MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); + } break; } @@ -586,8 +619,10 @@ namespace RTC this->tuple = new RTC::TransportTuple( this->udpSocket, reinterpret_cast(&this->remoteAddrStorage)); - if (!this->listenIp.announcedIp.empty()) - this->tuple->SetLocalAnnouncedIp(this->listenIp.announcedIp); + if (!this->listenInfo.announcedIp.empty()) + { + this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + } if (!this->rtcpMux) { @@ -601,7 +636,9 @@ namespace RTC reinterpret_cast(&this->rtcpRemoteAddrStorage)); if (err != 0) + { MS_THROW_ERROR("uv_ip4_addr() failed: %s", uv_strerror(err)); + } break; } @@ -614,7 +651,9 @@ namespace RTC reinterpret_cast(&this->rtcpRemoteAddrStorage)); if (err != 0) + { MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); + } break; } @@ -630,8 +669,10 @@ namespace RTC this->rtcpUdpSocket, reinterpret_cast(&this->rtcpRemoteAddrStorage)); - if (!this->listenIp.announcedIp.empty()) - this->rtcpTuple->SetLocalAnnouncedIp(this->listenIp.announcedIp); + if (!this->rtcpListenInfo.announcedIp.empty()) + { + this->rtcpTuple->SetLocalAnnouncedIp(this->rtcpListenInfo.announcedIp); + } } } } @@ -655,25 +696,32 @@ namespace RTC this->connectCalled = true; // Tell the caller about the selected local DTLS role. - json data = json::object(); + flatbuffers::Offset tupleOffset; + flatbuffers::Offset rtcpTupleOffset; + flatbuffers::Offset srtpParametersOffset; if (this->tuple) - this->tuple->FillJson(data["tuple"]); + { + tupleOffset = this->tuple->FillBuffer(request->GetBufferBuilder()); + } if (!this->rtcpMux && this->rtcpTuple) - this->rtcpTuple->FillJson(data["rtcpTuple"]); + { + rtcpTupleOffset = this->rtcpTuple->FillBuffer(request->GetBufferBuilder()); + } if (HasSrtp()) { - data["srtpParameters"] = json::object(); - auto jsonSrtpParametersIt = data.find("srtpParameters"); - - (*jsonSrtpParametersIt)["cryptoSuite"] = - PlainTransport::srtpCryptoSuite2String[this->srtpCryptoSuite]; - (*jsonSrtpParametersIt)["keyBase64"] = this->srtpKeyBase64; + srtpParametersOffset = FBS::SrtpParameters::CreateSrtpParametersDirect( + request->GetBufferBuilder(), + SrtpSession::CryptoSuiteToFbs(this->srtpCryptoSuite), + this->srtpKeyBase64.c_str()); } - request->Accept(data); + auto responseOffset = FBS::PlainTransport::CreateConnectResponse( + request->GetBufferBuilder(), tupleOffset, rtcpTupleOffset, srtpParametersOffset); + + request->Accept(FBS::Response::Body::PlainTransport_ConnectResponse, responseOffset); // Assume we are connected (there is no much more we can do to know it) // and tell the parent class. @@ -690,7 +738,7 @@ namespace RTC } } - void PlainTransport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void PlainTransport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); @@ -756,20 +804,28 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } const uint8_t* data = packet->GetData(); auto intLen = static_cast(packet->GetSize()); if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &intLen)) + { return; + } auto len = static_cast(intLen); if (this->rtcpMux) + { this->tuple->Send(data, len); + } else if (this->rtcpTuple) + { this->rtcpTuple->Send(data, len); + } // Increase send transmission. RTC::Transport::DataSent(len); @@ -780,7 +836,9 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } packet->Serialize(RTC::RTCP::Buffer); @@ -788,25 +846,31 @@ namespace RTC auto intLen = static_cast(packet->GetSize()); if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &intLen)) + { return; + } auto len = static_cast(intLen); if (this->rtcpMux) + { this->tuple->Send(data, len); + } else if (this->rtcpTuple) + { this->rtcpTuple->Send(data, len); + } // Increase send transmission. RTC::Transport::DataSent(len); } void PlainTransport::SendMessage( - RTC::DataConsumer* dataConsumer, uint32_t ppid, const uint8_t* msg, size_t len, onQueuedCallback* cb) + RTC::DataConsumer* dataConsumer, const uint8_t* msg, size_t len, uint32_t ppid, onQueuedCallback* cb) { MS_TRACE(); - this->sctpAssociation->SendSctpMessage(dataConsumer, ppid, msg, len, cb); + this->sctpAssociation->SendSctpMessage(dataConsumer, msg, len, ppid, cb); } void PlainTransport::SendSctpData(const uint8_t* data, size_t len) @@ -814,7 +878,9 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } this->tuple->Send(data, len); @@ -876,7 +942,9 @@ namespace RTC MS_TRACE(); if (HasSrtp() && !IsSrtpReady()) + { return; + } // Decrypt the SRTP packet. auto intLen = static_cast(len); @@ -934,18 +1002,16 @@ namespace RTC this->tuple = new RTC::TransportTuple(tuple); - if (!this->listenIp.announcedIp.empty()) - this->tuple->SetLocalAnnouncedIp(this->listenIp.announcedIp); + if (!this->listenInfo.announcedIp.empty()) + { + this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + } // If not yet connected do it now. if (!wasConnected) { // Notify the Node PlainTransport. - json data = json::object(); - - this->tuple->FillJson(data["tuple"]); - - this->shared->channelNotifier->Emit(this->id, "tuple", data); + EmitTuple(); RTC::Transport::Connected(); } @@ -974,7 +1040,9 @@ namespace RTC MS_TRACE(); if (HasSrtp() && !IsSrtpReady()) + { return; + } // Decrypt the SRTCP packet. auto intLen = static_cast(len); @@ -1001,18 +1069,16 @@ namespace RTC this->tuple = new RTC::TransportTuple(tuple); - if (!this->listenIp.announcedIp.empty()) - this->tuple->SetLocalAnnouncedIp(this->listenIp.announcedIp); + if (!this->listenInfo.announcedIp.empty()) + { + this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + } // If not yet connected do it now. if (!wasConnected) { // Notify the Node PlainTransport. - json data = json::object(); - - this->tuple->FillJson(data["tuple"]); - - this->shared->channelNotifier->Emit(this->id, "tuple", data); + EmitTuple(); RTC::Transport::Connected(); } @@ -1032,15 +1098,13 @@ namespace RTC this->rtcpTuple = new RTC::TransportTuple(tuple); - if (!this->listenIp.announcedIp.empty()) - this->rtcpTuple->SetLocalAnnouncedIp(this->listenIp.announcedIp); + if (!this->rtcpListenInfo.announcedIp.empty()) + { + this->rtcpTuple->SetLocalAnnouncedIp(this->rtcpListenInfo.announcedIp); + } // Notify the Node PlainTransport. - json data = json::object(); - - this->rtcpTuple->FillJson(data["rtcpTuple"]); - - this->shared->channelNotifier->Emit(this->id, "rtcptuple", data); + EmitRtcpTuple(); } // If RTCP-mux verify that the packet's tuple matches our RTP tuple. else if (this->rtcpMux && !this->tuple->Compare(tuple)) @@ -1091,18 +1155,16 @@ namespace RTC this->tuple = new RTC::TransportTuple(tuple); - if (!this->listenIp.announcedIp.empty()) - this->tuple->SetLocalAnnouncedIp(this->listenIp.announcedIp); + if (!this->listenInfo.announcedIp.empty()) + { + this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + } // If not yet connected do it now. if (!wasConnected) { // Notify the Node PlainTransport. - json data = json::object(); - - this->tuple->FillJson(data["tuple"]); - - this->shared->channelNotifier->Emit(this->id, "tuple", data); + EmitTuple(); RTC::Transport::Connected(); } @@ -1120,6 +1182,32 @@ namespace RTC RTC::Transport::ReceiveSctpData(data, len); } + inline void PlainTransport::EmitTuple() const + { + auto tuple = this->tuple->FillBuffer(this->shared->channelNotifier->GetBufferBuilder()); + auto notification = FBS::PlainTransport::CreateTupleNotification( + this->shared->channelNotifier->GetBufferBuilder(), tuple); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PLAINTRANSPORT_TUPLE, + FBS::Notification::Body::PlainTransport_TupleNotification, + notification); + } + + inline void PlainTransport::EmitRtcpTuple() const + { + auto rtcpTuple = this->rtcpTuple->FillBuffer(this->shared->channelNotifier->GetBufferBuilder()); + auto notification = FBS::PlainTransport::CreateRtcpTupleNotification( + this->shared->channelNotifier->GetBufferBuilder(), rtcpTuple); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PLAINTRANSPORT_RTCP_TUPLE, + FBS::Notification::Body::PlainTransport_RtcpTupleNotification, + notification); + } + inline void PlainTransport::OnUdpSocketPacketReceived( RTC::UdpSocket* socket, const uint8_t* data, size_t len, const struct sockaddr* remoteAddr) { diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index 368bbee096..5b0023ca58 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -652,55 +652,4 @@ namespace RTC return emptyPorts; } - - void PortManager::FillJson(json& jsonObject) - { - MS_TRACE(); - - // Add udp. - jsonObject["udp"] = json::object(); - auto jsonUdpIt = jsonObject.find("udp"); - - for (auto& kv : PortManager::mapUdpIpPorts) - { - const auto& ip = kv.first; - auto& ports = kv.second; - - (*jsonUdpIt)[ip] = json::array(); - auto jsonIpIt = jsonUdpIt->find(ip); - - for (size_t i{ 0 }; i < ports.size(); ++i) - { - if (!ports[i]) - continue; - - auto port = static_cast(i + Settings::configuration.rtcMinPort); - - jsonIpIt->push_back(port); - } - } - - // Add tcp. - jsonObject["tcp"] = json::object(); - auto jsonTcpIt = jsonObject.find("tcp"); - - for (auto& kv : PortManager::mapTcpIpPorts) - { - const auto& ip = kv.first; - auto& ports = kv.second; - - (*jsonTcpIt)[ip] = json::array(); - auto jsonIpIt = jsonTcpIt->find(ip); - - for (size_t i{ 0 }; i < ports.size(); ++i) - { - if (!ports[i]) - continue; - - auto port = static_cast(i + Settings::configuration.rtcMinPort); - - jsonIpIt->emplace_back(port); - } - } - } } // namespace RTC diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index c4d542d4e9..6c5f7a8951 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -28,38 +28,29 @@ namespace RTC /* Instance methods. */ Producer::Producer( - RTC::Shared* shared, const std::string& id, RTC::Producer::Listener* listener, json& data) + RTC::Shared* shared, + const std::string& id, + RTC::Producer::Listener* listener, + const FBS::Transport::ProduceRequest* data) : id(id), shared(shared), listener(listener) { MS_TRACE(); - auto jsonKindIt = data.find("kind"); - - if (jsonKindIt == data.end() || !jsonKindIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing kind"); - } - // This may throw. - this->kind = RTC::Media::GetKind(jsonKindIt->get()); + this->kind = RTC::Media::Kind(data->kind()); - if (this->kind == RTC::Media::Kind::ALL) - { - MS_THROW_TYPE_ERROR("invalid empty kind"); - } + // This may throw. + this->rtpParameters = RTC::RtpParameters(data->rtpParameters()); - auto jsonRtpParametersIt = data.find("rtpParameters"); + // Evaluate type. + auto type = RTC::RtpParameters::GetType(this->rtpParameters); - if (jsonRtpParametersIt == data.end() || !jsonRtpParametersIt->is_object()) + if (!type.has_value()) { - MS_THROW_TYPE_ERROR("missing rtpParameters"); + MS_THROW_TYPE_ERROR("invalid RTP parameters"); } - // This may throw. - this->rtpParameters = RTC::RtpParameters(*jsonRtpParametersIt); - - // Evaluate type. - this->type = RTC::RtpParameters::GetType(this->rtpParameters); + this->type = type.value(); // Reserve a slot in rtpStreamByEncodingIdx and rtpStreamsScores vectors // for each RTP stream. @@ -77,102 +68,34 @@ namespace RTC RTC::RtpParameters::GetTypeString(this->type).c_str()); } - auto jsonRtpMappingIt = data.find("rtpMapping"); - - if (jsonRtpMappingIt == data.end() || !jsonRtpMappingIt->is_object()) - { - MS_THROW_TYPE_ERROR("missing rtpMapping"); - } - - auto jsonCodecsIt = jsonRtpMappingIt->find("codecs"); - - if (jsonCodecsIt == jsonRtpMappingIt->end() || !jsonCodecsIt->is_array()) - { - MS_THROW_TYPE_ERROR("missing rtpMapping.codecs"); - } - - for (auto& codec : *jsonCodecsIt) + for (const auto& codec : *data->rtpMapping()->codecs()) { - if (!codec.is_object()) - { - MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.codecs (not an object)"); - } - - auto jsonPayloadTypeIt = codec.find("payloadType"); - - // clang-format off - if ( - jsonPayloadTypeIt == codec.end() || - !Utils::Json::IsPositiveInteger(*jsonPayloadTypeIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.codecs (missing payloadType)"); - } - - auto jsonMappedPayloadTypeIt = codec.find("mappedPayloadType"); - - // clang-format off - if ( - jsonMappedPayloadTypeIt == codec.end() || - !Utils::Json::IsPositiveInteger(*jsonMappedPayloadTypeIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.codecs (missing mappedPayloadType)"); - } - - this->rtpMapping.codecs[jsonPayloadTypeIt->get()] = - jsonMappedPayloadTypeIt->get(); + this->rtpMapping.codecs[codec->payloadType()] = codec->mappedPayloadType(); } - auto jsonEncodingsIt = jsonRtpMappingIt->find("encodings"); - - if (jsonEncodingsIt == jsonRtpMappingIt->end() || !jsonEncodingsIt->is_array()) - { - MS_THROW_TYPE_ERROR("missing rtpMapping.encodings"); - } + const auto* encodings = data->rtpMapping()->encodings(); - this->rtpMapping.encodings.reserve(jsonEncodingsIt->size()); + this->rtpMapping.encodings.reserve(encodings->size()); - for (auto& encoding : *jsonEncodingsIt) + for (const auto& encoding : *encodings) { - if (!encoding.is_object()) - { - MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.encodings"); - } - this->rtpMapping.encodings.emplace_back(); auto& encodingMapping = this->rtpMapping.encodings.back(); // ssrc is optional. - auto jsonSsrcIt = encoding.find("ssrc"); - - // clang-format off - if ( - jsonSsrcIt != encoding.end() && - Utils::Json::IsPositiveInteger(*jsonSsrcIt) - ) - // clang-format on + if (encoding->ssrc().has_value()) { - encodingMapping.ssrc = jsonSsrcIt->get(); + encodingMapping.ssrc = encoding->ssrc().value(); } // rid is optional. - auto jsonRidIt = encoding.find("rid"); - - if (jsonRidIt != encoding.end() && jsonRidIt->is_string()) - { - encodingMapping.rid = jsonRidIt->get(); - } - // However ssrc or rid must be present (if more than 1 encoding). // clang-format off if ( - jsonEncodingsIt->size() > 1 && - jsonSsrcIt == encoding.end() && - jsonRidIt == encoding.end() + encodings->size() > 1 && + !encoding->ssrc().has_value() && + !flatbuffers::IsFieldPresent(encoding, FBS::RtpParameters::EncodingMapping::VT_RID) ) // clang-format on { @@ -183,9 +106,9 @@ namespace RTC // clang-format off if ( this->rtpParameters.mid.empty() && - jsonEncodingsIt->size() == 1 && - jsonSsrcIt == encoding.end() && - jsonRidIt == encoding.end() + encodings->size() == 1 && + !encoding->ssrc().has_value() && + !flatbuffers::IsFieldPresent(encoding, FBS::RtpParameters::EncodingMapping::VT_RID) ) // clang-format on { @@ -194,27 +117,15 @@ namespace RTC } // mappedSsrc is mandatory. - auto jsonMappedSsrcIt = encoding.find("mappedSsrc"); - - // clang-format off - if ( - jsonMappedSsrcIt == encoding.end() || - !Utils::Json::IsPositiveInteger(*jsonMappedSsrcIt) - ) - // clang-format on + if (!encoding->mappedSsrc()) { MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.encodings (missing mappedSsrc)"); } - encodingMapping.mappedSsrc = jsonMappedSsrcIt->get(); + encodingMapping.mappedSsrc = encoding->mappedSsrc(); } - auto jsonPausedIt = data.find("paused"); - - if (jsonPausedIt != data.end() && jsonPausedIt->is_boolean()) - { - this->paused = jsonPausedIt->get(); - } + this->paused = data->paused(); // The number of encodings in rtpParameters must match the number of encodings // in rtpMapping. @@ -291,25 +202,18 @@ namespace RTC // Set the RTCP report generation interval. if (this->kind == RTC::Media::Kind::AUDIO) + { this->maxRtcpInterval = RTC::RTCP::MaxAudioIntervalMs; + } else + { this->maxRtcpInterval = RTC::RTCP::MaxVideoIntervalMs; + } // Create a KeyFrameRequestManager. if (this->kind == RTC::Media::Kind::VIDEO) { - auto jsonKeyFrameRequestDelayIt = data.find("keyFrameRequestDelay"); - uint32_t keyFrameRequestDelay = 0u; - - // clang-format off - if ( - jsonKeyFrameRequestDelayIt != data.end() && - jsonKeyFrameRequestDelayIt->is_number_integer() - ) - // clang-format on - { - keyFrameRequestDelay = jsonKeyFrameRequestDelayIt->get(); - } + auto keyFrameRequestDelay = data->keyFrameRequestDelay(); this->keyFrameRequestManager = new RTC::KeyFrameRequestManager(this, keyFrameRequestDelay); } @@ -318,8 +222,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } Producer::~Producer() @@ -347,171 +250,141 @@ namespace RTC delete this->keyFrameRequestManager; } - void Producer::FillJson(json& jsonObject) const + flatbuffers::Offset Producer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add kind. - jsonObject["kind"] = RTC::Media::GetString(this->kind); - // Add rtpParameters. - this->rtpParameters.FillJson(jsonObject["rtpParameters"]); - - // Add type. - jsonObject["type"] = RTC::RtpParameters::GetTypeString(this->type); - - // Add rtpMapping. - jsonObject["rtpMapping"] = json::object(); - auto jsonRtpMappingIt = jsonObject.find("rtpMapping"); + auto rtpParameters = this->rtpParameters.FillBuffer(builder); // Add rtpMapping.codecs. - { - (*jsonRtpMappingIt)["codecs"] = json::array(); - auto jsonCodecsIt = jsonRtpMappingIt->find("codecs"); - size_t idx{ 0 }; - - for (const auto& kv : this->rtpMapping.codecs) - { - jsonCodecsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonCodecsIt)[idx]; - auto payloadType = kv.first; - auto mappedPayloadType = kv.second; - - jsonEntry["payloadType"] = payloadType; - jsonEntry["mappedPayloadType"] = mappedPayloadType; + std::vector> codecs; - ++idx; - } + for (const auto& kv : this->rtpMapping.codecs) + { + codecs.emplace_back(FBS::RtpParameters::CreateCodecMapping(builder, kv.first, kv.second)); } // Add rtpMapping.encodings. - { - (*jsonRtpMappingIt)["encodings"] = json::array(); - auto jsonEncodingsIt = jsonRtpMappingIt->find("encodings"); + std::vector> encodings; + encodings.reserve(this->rtpMapping.encodings.size()); - for (size_t i{ 0 }; i < this->rtpMapping.encodings.size(); ++i) - { - jsonEncodingsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonEncodingsIt)[i]; - const auto& encodingMapping = this->rtpMapping.encodings[i]; - - if (!encodingMapping.rid.empty()) - jsonEntry["rid"] = encodingMapping.rid; - else - jsonEntry["rid"] = nullptr; - - if (encodingMapping.ssrc != 0u) - jsonEntry["ssrc"] = encodingMapping.ssrc; - else - jsonEntry["ssrc"] = nullptr; - - jsonEntry["mappedSsrc"] = encodingMapping.mappedSsrc; - } + for (const auto& encodingMapping : this->rtpMapping.encodings) + { + encodings.emplace_back(FBS::RtpParameters::CreateEncodingMappingDirect( + builder, + encodingMapping.rid.c_str(), + encodingMapping.ssrc != 0u ? flatbuffers::Optional(encodingMapping.ssrc) + : flatbuffers::nullopt, + nullptr, /* capability mode. NOTE: Present in NODE*/ + encodingMapping.mappedSsrc)); } + // Build rtpMapping. + auto rtpMapping = FBS::RtpParameters::CreateRtpMappingDirect(builder, &codecs, &encodings); + // Add rtpStreams. - jsonObject["rtpStreams"] = json::array(); - auto jsonRtpStreamsIt = jsonObject.find("rtpStreams"); + std::vector> rtpStreams; - for (auto* rtpStream : this->rtpStreamByEncodingIdx) + for (const auto* rtpStream : this->rtpStreamByEncodingIdx) { if (!rtpStream) + { continue; + } - jsonRtpStreamsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonRtpStreamsIt)[jsonRtpStreamsIt->size() - 1]; - - rtpStream->FillJson(jsonEntry); + rtpStreams.emplace_back(rtpStream->FillBuffer(builder)); } - // Add paused. - jsonObject["paused"] = this->paused; - // Add traceEventTypes. - std::vector traceEventTypes; - std::ostringstream traceEventTypesStream; + std::vector traceEventTypes; if (this->traceEventTypes.rtp) - traceEventTypes.emplace_back("rtp"); + { + traceEventTypes.emplace_back(FBS::Producer::TraceEventType::RTP); + } if (this->traceEventTypes.keyframe) - traceEventTypes.emplace_back("keyframe"); + { + traceEventTypes.emplace_back(FBS::Producer::TraceEventType::KEYFRAME); + } if (this->traceEventTypes.nack) - traceEventTypes.emplace_back("nack"); + { + traceEventTypes.emplace_back(FBS::Producer::TraceEventType::NACK); + } if (this->traceEventTypes.pli) - traceEventTypes.emplace_back("pli"); + { + traceEventTypes.emplace_back(FBS::Producer::TraceEventType::PLI); + } if (this->traceEventTypes.fir) - traceEventTypes.emplace_back("fir"); - - if (!traceEventTypes.empty()) { - std::copy( - traceEventTypes.begin(), - traceEventTypes.end() - 1, - std::ostream_iterator(traceEventTypesStream, ",")); - traceEventTypesStream << traceEventTypes.back(); + traceEventTypes.emplace_back(FBS::Producer::TraceEventType::FIR); } - jsonObject["traceEventTypes"] = traceEventTypesStream.str(); + return FBS::Producer::CreateDumpResponseDirect( + builder, + this->id.c_str(), + this->kind == RTC::Media::Kind::AUDIO ? FBS::RtpParameters::MediaKind::AUDIO + : FBS::RtpParameters::MediaKind::VIDEO, + RTC::RtpParameters::TypeToFbs(this->type), + rtpParameters, + rtpMapping, + &rtpStreams, + &traceEventTypes, + this->paused); } - void Producer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset Producer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + for (auto* rtpStream : this->rtpStreamByEncodingIdx) { if (!rtpStream) + { continue; + } - jsonArray.emplace_back(json::value_t::object); - - auto& jsonEntry = jsonArray[jsonArray.size() - 1]; - - rtpStream->FillJsonStats(jsonEntry); + rtpStreams.emplace_back(rtpStream->FillBufferStats(builder)); } + + return FBS::Producer::CreateGetStatsResponseDirect(builder, &rtpStreams); } void Producer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::PRODUCER_DUMP: + case Channel::ChannelRequest::Method::PRODUCER_DUMP: { - json data = json::object(); - - FillJson(data); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::Producer_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::PRODUCER_GET_STATS: + case Channel::ChannelRequest::Method::PRODUCER_GET_STATS: { - json data = json::array(); + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); - FillJsonStats(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::Producer_GetStatsResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::PRODUCER_PAUSE: + case Channel::ChannelRequest::Method::PRODUCER_PAUSE: { if (this->paused) { request->Accept(); - return; + break; } // Pause all streams. @@ -533,13 +406,13 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::PRODUCER_RESUME: + case Channel::ChannelRequest::Method::PRODUCER_RESUME: { if (!this->paused) { request->Accept(); - return; + break; } // Resume all streams. @@ -574,34 +447,48 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::PRODUCER_ENABLE_TRACE_EVENT: + case Channel::ChannelRequest::Method::PRODUCER_ENABLE_TRACE_EVENT: { - auto jsonTypesIt = request->data.find("types"); - - // Disable all if no entries. - if (jsonTypesIt == request->data.end() || !jsonTypesIt->is_array()) - MS_THROW_TYPE_ERROR("wrong types (not an array)"); + const auto* body = request->data->body_as(); // Reset traceEventTypes. struct TraceEventTypes newTraceEventTypes; - for (const auto& type : *jsonTypesIt) + for (const auto& type : *body->events()) { - if (!type.is_string()) - MS_THROW_TYPE_ERROR("wrong type (not a string)"); - - const std::string typeStr = type.get(); - - if (typeStr == "rtp") - newTraceEventTypes.rtp = true; - else if (typeStr == "keyframe") - newTraceEventTypes.keyframe = true; - else if (typeStr == "nack") - newTraceEventTypes.nack = true; - else if (typeStr == "pli") - newTraceEventTypes.pli = true; - else if (typeStr == "fir") - newTraceEventTypes.fir = true; + switch (type) + { + case FBS::Producer::TraceEventType::KEYFRAME: + { + newTraceEventTypes.keyframe = true; + + break; + } + case FBS::Producer::TraceEventType::FIR: + { + newTraceEventTypes.fir = true; + + break; + } + case FBS::Producer::TraceEventType::NACK: + { + newTraceEventTypes.nack = true; + + break; + } + case FBS::Producer::TraceEventType::PLI: + { + newTraceEventTypes.pli = true; + + break; + } + case FBS::Producer::TraceEventType::RTP: + { + newTraceEventTypes.rtp = true; + + break; + } + } } this->traceEventTypes = newTraceEventTypes; @@ -613,38 +500,41 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } - void Producer::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void Producer::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - switch (notification->eventId) + switch (notification->event) { - case PayloadChannel::PayloadChannelNotification::EventId::PRODUCER_SEND: + case Channel::ChannelNotification::Event::PRODUCER_SEND: { - const auto* data = notification->payload; - auto len = notification->payloadLen; + const auto* body = notification->data->body_as(); + auto len = body->data()->size(); // Increase receive transmission. this->listener->OnProducerReceiveData(this, len); if (len > RTC::MtuSize + 100) { - MS_WARN_TAG(rtp, "given RTP packet exceeds maximum size [len:%zu]", len); + MS_WARN_TAG(rtp, "given RTP packet exceeds maximum size [len:%i]", len); break; } - // If this is the first time to receive a RTP packet then allocate the receiving buffer now. + // If this is the first time to receive a RTP packet then allocate the + // receiving buffer now. if (!Producer::buffer) + { Producer::buffer = new uint8_t[RTC::MtuSize + 100]; + } // Copy the received packet into this buffer so it can be expanded later. - std::memcpy(Producer::buffer, data, static_cast(len)); + std::memcpy(Producer::buffer, body->data()->data(), static_cast(len)); RTC::RtpPacket* packet = RTC::RtpPacket::Parse(Producer::buffer, len); @@ -663,7 +553,7 @@ namespace RTC default: { - MS_ERROR("unknown event '%s'", notification->event.c_str()); + MS_ERROR("unknown event '%s'", notification->eventCStr); } } } @@ -707,7 +597,9 @@ namespace RTC { // May have to announce a new RTP stream to the listener. if (this->mapSsrcRtpStream.size() > numRtpStreamsBefore) + { NotifyNewRtpStream(rtpStream); + } packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_DISCARDED); @@ -744,7 +636,9 @@ namespace RTC // Tell the keyFrameRequestManager. if (this->keyFrameRequestManager) + { this->keyFrameRequestManager->KeyFrameReceived(packet->GetSsrc()); + } } // May have to announce a new RTP stream to the listener. @@ -753,7 +647,9 @@ namespace RTC // Request a key frame for this stream since we may have lost the first packets // (do not do it if this is a key frame). if (this->keyFrameRequestManager && !this->paused && !packet->IsKeyFrame()) + { this->keyFrameRequestManager->ForceKeyFrameNeeded(packet->GetSsrc()); + } // Update current packet. this->currentRtpPacket = packet; @@ -766,14 +662,18 @@ namespace RTC // If paused stop here. if (this->paused) + { return result; + } // May emit 'trace' event. EmitTraceEventRtpAndKeyFrameTypes(packet, isRtx); // Mangle the packet before providing the listener with it. if (!MangleRtpPacket(packet, rtpStream)) + { return ReceiveRtpPacketResult::DISCARDED; + } // Post-process the packet. PostProcessRtpPacket(packet); @@ -839,7 +739,9 @@ namespace RTC MS_TRACE(); if (static_cast((nowMs - this->lastRtcpSentTime) * 1.15) < this->maxRtcpInterval) + { return true; + } std::vector receiverReports; RTCP::ReceiverReferenceTime* receiverReferenceTimeReport{ nullptr }; @@ -854,7 +756,9 @@ namespace RTC auto* rtxReport = rtpStream->GetRtxRtcpReceiverReport(); if (rtxReport) + { receiverReports.push_back(rtxReport); + } } // Add a receiver reference time report if no present in the packet. @@ -869,7 +773,9 @@ namespace RTC // RTCP Compound packet buffer cannot hold the data. if (!packet->Add(receiverReports, receiverReferenceTimeReport)) + { return false; + } this->lastRtcpSentTime = nowMs; @@ -881,7 +787,9 @@ namespace RTC MS_TRACE(); if (!this->keyFrameRequestManager || this->paused) + { return; + } auto it = this->mapMappedSsrcSsrc.find(mappedSsrc); @@ -1005,7 +913,9 @@ namespace RTC auto& encoding = this->rtpParameters.encodings[i]; if (encoding.rid != rid) + { continue; + } const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); @@ -1242,7 +1152,9 @@ namespace RTC // If the Producer is paused tell it to the new RtpStreamRecv. if (this->paused) + { rtpStream->Pause(); + } // Emit the first score event right now. EmitScore(); @@ -1307,7 +1219,9 @@ namespace RTC // This happens just once. if (extensions.capacity() != 24) + { extensions.reserve(24); + } extensions.clear(); @@ -1505,13 +1419,17 @@ namespace RTC this->videoOrientation.flip = flip; this->videoOrientation.rotation = rotation; - json data = json::object(); - - data["camera"] = this->videoOrientation.camera; - data["flip"] = this->videoOrientation.flip; - data["rotation"] = this->videoOrientation.rotation; - - this->shared->channelNotifier->Emit(this->id, "videoorientationchange", data); + auto notification = FBS::Producer::CreateVideoOrientationChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), + this->videoOrientation.camera, + this->videoOrientation.flip, + this->videoOrientation.rotation); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PRODUCER_VIDEO_ORIENTATION_CHANGE, + FBS::Notification::Body::Producer_VideoOrientationChangeNotification, + notification); } } } @@ -1521,27 +1439,31 @@ namespace RTC { MS_TRACE(); - json data = json::array(); + std::vector> scores; - for (auto* rtpStream : this->rtpStreamByEncodingIdx) + for (const auto* rtpStream : this->rtpStreamByEncodingIdx) { if (!rtpStream) + { continue; + } - data.emplace_back(json::value_t::object); - - auto& jsonEntry = data[data.size() - 1]; - - jsonEntry["encodingIdx"] = rtpStream->GetEncodingIdx(); - jsonEntry["ssrc"] = rtpStream->GetSsrc(); - - if (!rtpStream->GetRid().empty()) - jsonEntry["rid"] = rtpStream->GetRid(); - - jsonEntry["score"] = rtpStream->GetScore(); + scores.emplace_back(FBS::Producer::CreateScoreDirect( + this->shared->channelNotifier->GetBufferBuilder(), + rtpStream->GetEncodingIdx(), + rtpStream->GetSsrc(), + !rtpStream->GetRid().empty() ? rtpStream->GetRid().c_str() : nullptr, + rtpStream->GetScore())); } - this->shared->channelNotifier->Emit(this->id, "score", data); + auto notification = FBS::Producer::CreateScoreNotificationDirect( + this->shared->channelNotifier->GetBufferBuilder(), &scores); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PRODUCER_SCORE, + FBS::Notification::Body::Producer_ScoreNotification, + notification); } inline void Producer::EmitTraceEventRtpAndKeyFrameTypes(RTC::RtpPacket* packet, bool isRtx) const @@ -1550,33 +1472,35 @@ namespace RTC if (this->traceEventTypes.keyframe && packet->IsKeyFrame()) { - json data = json::object(); - - data["type"] = "keyframe"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - - packet->FillJson(data["info"]); - - if (isRtx) - data["info"]["isRtx"] = true; - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto rtpPacketDump = packet->FillBuffer(this->shared->channelNotifier->GetBufferBuilder()); + auto traceInfo = FBS::Producer::CreateKeyFrameTraceInfo( + this->shared->channelNotifier->GetBufferBuilder(), rtpPacketDump, isRtx); + + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceEventType::KEYFRAME, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_IN, + FBS::Producer::TraceInfo::KeyFrameTraceInfo, + traceInfo.Union()); + + EmitTraceEvent(notification); } else if (this->traceEventTypes.rtp) { - json data = json::object(); - - data["type"] = "rtp"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - - packet->FillJson(data["info"]); - - if (isRtx) - data["info"]["isRtx"] = true; - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto rtpPacketDump = packet->FillBuffer(this->shared->channelNotifier->GetBufferBuilder()); + auto traceInfo = FBS::Producer::CreateRtpTraceInfo( + this->shared->channelNotifier->GetBufferBuilder(), rtpPacketDump, isRtx); + + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceEventType::RTP, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_IN, + FBS::Producer::TraceInfo::RtpTraceInfo, + traceInfo.Union()); + + EmitTraceEvent(notification); } } @@ -1585,16 +1509,22 @@ namespace RTC MS_TRACE(); if (!this->traceEventTypes.pli) + { return; + } - json data = json::object(); + auto traceInfo = + FBS::Producer::CreatePliTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), ssrc); - data["type"] = "pli"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - data["info"]["ssrc"] = ssrc; + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceEventType::PLI, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_OUT, + FBS::Producer::TraceInfo::PliTraceInfo, + traceInfo.Union()); - this->shared->channelNotifier->Emit(this->id, "trace", data); + EmitTraceEvent(notification); } inline void Producer::EmitTraceEventFirType(uint32_t ssrc) const @@ -1602,16 +1532,22 @@ namespace RTC MS_TRACE(); if (!this->traceEventTypes.fir) + { return; + } - json data = json::object(); + auto traceInfo = + FBS::Producer::CreateFirTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), ssrc); - data["type"] = "fir"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - data["info"]["ssrc"] = ssrc; + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceEventType::FIR, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_OUT, + FBS::Producer::TraceInfo::FirTraceInfo, + traceInfo.Union()); - this->shared->channelNotifier->Emit(this->id, "trace", data); + EmitTraceEvent(notification); } inline void Producer::EmitTraceEventNackType() const @@ -1619,16 +1555,29 @@ namespace RTC MS_TRACE(); if (!this->traceEventTypes.nack) + { return; + } - json data = json::object(); + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceEventType::NACK, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_OUT); - data["type"] = "nack"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - data["info"] = json::object(); + EmitTraceEvent(notification); + } - this->shared->channelNotifier->Emit(this->id, "trace", data); + inline void Producer::EmitTraceEvent( + flatbuffers::Offset& notification) const + { + MS_TRACE(); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PRODUCER_TRACE, + FBS::Notification::Body::Producer_TraceNotification, + notification); } inline void Producer::OnRtpStreamScore(RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index 61b46a6dd8..33e543909b 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -25,8 +25,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*ChannelNotificationHandler*/ nullptr); } Router::~Router() @@ -63,227 +62,198 @@ namespace RTC this->mapDataProducers.clear(); } - void Router::FillJson(json& jsonObject) const + flatbuffers::Offset Router::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - // Add transportIds. - jsonObject["transportIds"] = json::array(); - auto jsonTransportIdsIt = jsonObject.find("transportIds"); + std::vector> transportIds; + transportIds.reserve(this->mapTransports.size()); for (const auto& kv : this->mapTransports) { const auto& transportId = kv.first; - jsonTransportIdsIt->emplace_back(transportId); + transportIds.push_back(builder.CreateString(transportId)); } // Add rtpObserverIds. - jsonObject["rtpObserverIds"] = json::array(); - auto jsonRtpObserverIdsIt = jsonObject.find("rtpObserverIds"); + std::vector> rtpObserverIds; + rtpObserverIds.reserve(this->mapRtpObservers.size()); for (const auto& kv : this->mapRtpObservers) { const auto& rtpObserverId = kv.first; - jsonRtpObserverIdsIt->emplace_back(rtpObserverId); + rtpObserverIds.push_back(builder.CreateString(rtpObserverId)); } // Add mapProducerIdConsumerIds. - jsonObject["mapProducerIdConsumerIds"] = json::object(); - auto jsonMapProducerConsumersIt = jsonObject.find("mapProducerIdConsumerIds"); + std::vector> mapProducerIdConsumerIds; + mapProducerIdConsumerIds.reserve(this->mapProducerConsumers.size()); for (const auto& kv : this->mapProducerConsumers) { auto* producer = kv.first; const auto& consumers = kv.second; - (*jsonMapProducerConsumersIt)[producer->id] = json::array(); - auto jsonProducerIdIt = jsonMapProducerConsumersIt->find(producer->id); + std::vector> consumerIds; + consumerIds.reserve(consumers.size()); for (auto* consumer : consumers) { - jsonProducerIdIt->emplace_back(consumer->id); + consumerIds.emplace_back(builder.CreateString(consumer->id)); } + + mapProducerIdConsumerIds.emplace_back( + FBS::Common::CreateStringStringArrayDirect(builder, producer->id.c_str(), &consumerIds)); } // Add mapConsumerIdProducerId. - jsonObject["mapConsumerIdProducerId"] = json::object(); - auto jsonMapConsumerProducerIt = jsonObject.find("mapConsumerIdProducerId"); + std::vector> mapConsumerIdProducerId; + mapConsumerIdProducerId.reserve(this->mapConsumerProducer.size()); for (const auto& kv : this->mapConsumerProducer) { auto* consumer = kv.first; auto* producer = kv.second; - (*jsonMapConsumerProducerIt)[consumer->id] = producer->id; + mapConsumerIdProducerId.emplace_back( + FBS::Common::CreateStringStringDirect(builder, consumer->id.c_str(), producer->id.c_str())); } // Add mapProducerIdObserverIds. - jsonObject["mapProducerIdObserverIds"] = json::object(); - auto jsonMapProducerRtpObserversIt = jsonObject.find("mapProducerIdObserverIds"); + std::vector> mapProducerIdObserverIds; + mapProducerIdObserverIds.reserve(this->mapProducerRtpObservers.size()); for (const auto& kv : this->mapProducerRtpObservers) { auto* producer = kv.first; const auto& rtpObservers = kv.second; - (*jsonMapProducerRtpObserversIt)[producer->id] = json::array(); - auto jsonProducerIdIt = jsonMapProducerRtpObserversIt->find(producer->id); + std::vector> observerIds; + observerIds.reserve(rtpObservers.size()); for (auto* rtpObserver : rtpObservers) { - jsonProducerIdIt->emplace_back(rtpObserver->id); + observerIds.emplace_back(builder.CreateString(rtpObserver->id)); } + + mapProducerIdObserverIds.emplace_back( + FBS::Common::CreateStringStringArrayDirect(builder, producer->id.c_str(), &observerIds)); } // Add mapDataProducerIdDataConsumerIds. - jsonObject["mapDataProducerIdDataConsumerIds"] = json::object(); - auto jsonMapDataProducerDataConsumersIt = jsonObject.find("mapDataProducerIdDataConsumerIds"); + std::vector> mapDataProducerIdDataConsumerIds; + mapDataProducerIdDataConsumerIds.reserve(this->mapDataProducerDataConsumers.size()); for (const auto& kv : this->mapDataProducerDataConsumers) { auto* dataProducer = kv.first; const auto& dataConsumers = kv.second; - (*jsonMapDataProducerDataConsumersIt)[dataProducer->id] = json::array(); - auto jsonDataProducerIdIt = jsonMapDataProducerDataConsumersIt->find(dataProducer->id); + std::vector> dataConsumerIds; + dataConsumerIds.reserve(dataConsumers.size()); for (auto* dataConsumer : dataConsumers) { - jsonDataProducerIdIt->emplace_back(dataConsumer->id); + dataConsumerIds.emplace_back(builder.CreateString(dataConsumer->id)); } + + mapDataProducerIdDataConsumerIds.emplace_back(FBS::Common::CreateStringStringArrayDirect( + builder, dataProducer->id.c_str(), &dataConsumerIds)); } // Add mapDataConsumerIdDataProducerId. - jsonObject["mapDataConsumerIdDataProducerId"] = json::object(); - auto jsonMapDataConsumerDataProducerIt = jsonObject.find("mapDataConsumerIdDataProducerId"); + std::vector> mapDataConsumerIdDataProducerId; + mapDataConsumerIdDataProducerId.reserve(this->mapDataConsumerDataProducer.size()); for (const auto& kv : this->mapDataConsumerDataProducer) { auto* dataConsumer = kv.first; auto* dataProducer = kv.second; - (*jsonMapDataConsumerDataProducerIt)[dataConsumer->id] = dataProducer->id; + mapDataConsumerIdDataProducerId.emplace_back(FBS::Common::CreateStringStringDirect( + builder, dataConsumer->id.c_str(), dataProducer->id.c_str())); } + + return FBS::Router::CreateDumpResponseDirect( + builder, + this->id.c_str(), + &transportIds, + &rtpObserverIds, + &mapProducerIdConsumerIds, + &mapConsumerIdProducerId, + &mapProducerIdObserverIds, + &mapDataProducerIdDataConsumerIds, + &mapDataConsumerIdDataProducerId); } void Router::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::ROUTER_DUMP: + case Channel::ChannelRequest::Method::ROUTER_DUMP: { - json data = json::object(); - - FillJson(data); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::Router_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CREATE_WEBRTCTRANSPORT: { - std::string transportId; + const auto* body = request->data->body_as(); + + auto transportId = body->transportId()->str(); // This may throw. - SetNewTransportIdFromData(request->data, transportId); + CheckNoTransport(transportId); // This may throw. auto* webRtcTransport = - new RTC::WebRtcTransport(this->shared, transportId, this, request->data); + new RTC::WebRtcTransport(this->shared, transportId, this, body->options()); // Insert into the map. this->mapTransports[transportId] = webRtcTransport; MS_DEBUG_DEV("WebRtcTransport created [transportId:%s]", transportId.c_str()); - json data = json::object(); + auto dumpOffset = webRtcTransport->FillBuffer(request->GetBufferBuilder()); - webRtcTransport->FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::WebRtcTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER: + case Channel::ChannelRequest::Method::ROUTER_CREATE_WEBRTCTRANSPORT_WITH_SERVER: { - std::string transportId; + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); // This may throw. - SetNewTransportIdFromData(request->data, transportId); - - auto jsonWebRtcServerIdIt = request->data.find("webRtcServerId"); + CheckNoTransport(transportId); - if (jsonWebRtcServerIdIt == request->data.end() || !jsonWebRtcServerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing webRtcServerId"); - } + const auto* options = body->options(); + const auto* listenInfo = options->listen_as(); - std::string webRtcServerId = jsonWebRtcServerIdIt->get(); + auto webRtcServerId = listenInfo->webRtcServerId()->str(); auto* webRtcServer = this->listener->OnRouterNeedWebRtcServer(this, webRtcServerId); if (!webRtcServer) MS_THROW_ERROR("wrong webRtcServerId (no associated WebRtcServer found)"); - bool enableUdp{ true }; - auto jsonEnableUdpIt = request->data.find("enableUdp"); - - if (jsonEnableUdpIt != request->data.end()) - { - if (!jsonEnableUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableUdp (not a boolean)"); - - enableUdp = jsonEnableUdpIt->get(); - } - - bool enableTcp{ false }; - auto jsonEnableTcpIt = request->data.find("enableTcp"); - - if (jsonEnableTcpIt != request->data.end()) - { - if (!jsonEnableTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableTcp (not a boolean)"); - - enableTcp = jsonEnableTcpIt->get(); - } - - bool preferUdp{ false }; - auto jsonPreferUdpIt = request->data.find("preferUdp"); - - if (jsonPreferUdpIt != request->data.end()) - { - if (!jsonPreferUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferUdp (not a boolean)"); - - preferUdp = jsonPreferUdpIt->get(); - } - - bool preferTcp{ false }; - auto jsonPreferTcpIt = request->data.find("preferTcp"); - - if (jsonPreferTcpIt != request->data.end()) - { - if (!jsonPreferTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferTcp (not a boolean)"); - - preferTcp = jsonPreferTcpIt->get(); - } - - auto iceCandidates = - webRtcServer->GetIceCandidates(enableUdp, enableTcp, preferUdp, preferTcp); + auto iceCandidates = webRtcServer->GetIceCandidates( + options->enableUdp(), options->enableTcp(), options->preferUdp(), options->preferTcp()); // This may throw. auto* webRtcTransport = new RTC::WebRtcTransport( - this->shared, transportId, this, webRtcServer, iceCandidates, request->data); + this->shared, transportId, this, webRtcServer, iceCandidates, options); // Insert into the map. this->mapTransports[transportId] = webRtcTransport; @@ -291,95 +261,92 @@ namespace RTC MS_DEBUG_DEV( "WebRtcTransport with WebRtcServer created [transportId:%s]", transportId.c_str()); - json data = json::object(); + auto dumpOffset = webRtcTransport->FillBuffer(request->GetBufferBuilder()); - webRtcTransport->FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::WebRtcTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_PLAIN_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CREATE_PLAINTRANSPORT: { - std::string transportId; + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); - // This may throw - SetNewTransportIdFromData(request->data, transportId); + // This may throw. + CheckNoTransport(transportId); auto* plainTransport = - new RTC::PlainTransport(this->shared, transportId, this, request->data); + new RTC::PlainTransport(this->shared, transportId, this, body->options()); // Insert into the map. this->mapTransports[transportId] = plainTransport; MS_DEBUG_DEV("PlainTransport created [transportId:%s]", transportId.c_str()); - json data = json::object(); - - plainTransport->FillJson(data); + auto dumpOffset = plainTransport->FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::PlainTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_PIPE_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CREATE_PIPETRANSPORT: { - std::string transportId; + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); - // This may throw - SetNewTransportIdFromData(request->data, transportId); + // This may throw. + CheckNoTransport(transportId); - auto* pipeTransport = new RTC::PipeTransport(this->shared, transportId, this, request->data); + auto* pipeTransport = + new RTC::PipeTransport(this->shared, transportId, this, body->options()); // Insert into the map. this->mapTransports[transportId] = pipeTransport; MS_DEBUG_DEV("PipeTransport created [transportId:%s]", transportId.c_str()); - json data = json::object(); - - pipeTransport->FillJson(data); + auto dumpOffset = pipeTransport->FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::PipeTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_DIRECT_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CREATE_DIRECTTRANSPORT: { - std::string transportId; + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); - // This may throw - SetNewTransportIdFromData(request->data, transportId); + // This may throw. + CheckNoTransport(transportId); auto* directTransport = - new RTC::DirectTransport(this->shared, transportId, this, request->data); + new RTC::DirectTransport(this->shared, transportId, this, body->options()); // Insert into the map. this->mapTransports[transportId] = directTransport; MS_DEBUG_DEV("DirectTransport created [transportId:%s]", transportId.c_str()); - json data = json::object(); + auto dumpOffset = directTransport->FillBuffer(request->GetBufferBuilder()); - directTransport->FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::DirectTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER: + case Channel::ChannelRequest::Method::ROUTER_CREATE_ACTIVESPEAKEROBSERVER: { - std::string rtpObserverId; + const auto* body = request->data->body_as(); + auto rtpObserverId = body->rtpObserverId()->str(); // This may throw. - SetNewRtpObserverIdFromData(request->data, rtpObserverId); + CheckNoRtpObserver(rtpObserverId); auto* activeSpeakerObserver = - new RTC::ActiveSpeakerObserver(this->shared, rtpObserverId, this, request->data); + new RTC::ActiveSpeakerObserver(this->shared, rtpObserverId, this, body->options()); // Insert into the map. this->mapRtpObservers[rtpObserverId] = activeSpeakerObserver; @@ -391,15 +358,16 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_AUDIO_LEVEL_OBSERVER: + case Channel::ChannelRequest::Method::ROUTER_CREATE_AUDIOLEVELOBSERVER: { - std::string rtpObserverId; + const auto* body = request->data->body_as(); + auto rtpObserverId = body->rtpObserverId()->str(); - // This may throw - SetNewRtpObserverIdFromData(request->data, rtpObserverId); + // This may throw. + CheckNoRtpObserver(rtpObserverId); auto* audioLevelObserver = - new RTC::AudioLevelObserver(this->shared, rtpObserverId, this, request->data); + new RTC::AudioLevelObserver(this->shared, rtpObserverId, this, body->options()); // Insert into the map. this->mapRtpObservers[rtpObserverId] = audioLevelObserver; @@ -411,10 +379,13 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::ROUTER_CLOSE_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CLOSE_TRANSPORT: { + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); + // This may throw. - RTC::Transport* transport = GetTransportFromData(request->data); + RTC::Transport* transport = GetTransportById(transportId); // Tell the Transport to close all its Producers and Consumers so it will // notify us about their closures. @@ -433,10 +404,13 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::ROUTER_CLOSE_RTP_OBSERVER: + case Channel::ChannelRequest::Method::ROUTER_CLOSE_RTPOBSERVER: { + const auto* body = request->data->body_as(); + auto rtpObserverId = body->rtpObserverId()->str(); + // This may throw. - RTC::RtpObserver* rtpObserver = GetRtpObserverFromData(request->data); + RTC::RtpObserver* rtpObserver = GetRtpObserverById(rtpObserverId); // Remove it from the map. this->mapRtpObservers.erase(rtpObserver->id); @@ -461,89 +435,45 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", Channel::ChannelRequest::method2String[request->method]); } } } - void Router::SetNewTransportIdFromData(json& data, std::string& transportId) const + void Router::CheckNoTransport(const std::string& transportId) const { - MS_TRACE(); - - auto jsonTransportIdIt = data.find("transportId"); - - if (jsonTransportIdIt == data.end() || !jsonTransportIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing transportId"); - } - - transportId.assign(jsonTransportIdIt->get()); - if (this->mapTransports.find(transportId) != this->mapTransports.end()) - { - MS_THROW_ERROR("a Transport with same transportId already exists"); - } + MS_THROW_ERROR("a Transport with same id already exists"); } - RTC::Transport* Router::GetTransportFromData(json& data) const + void Router::CheckNoRtpObserver(const std::string& rtpObserverId) const { - MS_TRACE(); - - auto jsonTransportIdIt = data.find("transportId"); - - if (jsonTransportIdIt == data.end() || !jsonTransportIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing transportId"); - } - - auto it = this->mapTransports.find(jsonTransportIdIt->get()); - - if (it == this->mapTransports.end()) - MS_THROW_ERROR("Transport not found"); - - RTC::Transport* transport = it->second; - - return transport; + if (this->mapRtpObservers.find(rtpObserverId) != this->mapRtpObservers.end()) + MS_THROW_ERROR("an RtpObserver with same id already exists"); } - void Router::SetNewRtpObserverIdFromData(json& data, std::string& rtpObserverId) const + RTC::Transport* Router::GetTransportById(const std::string& transportId) const { MS_TRACE(); - auto jsonRtpObserverIdIt = data.find("rtpObserverId"); - - if (jsonRtpObserverIdIt == data.end() || !jsonRtpObserverIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing rtpObserverId"); - } + auto it = this->mapTransports.find(transportId); - rtpObserverId.assign(jsonRtpObserverIdIt->get()); + if (this->mapTransports.find(transportId) == this->mapTransports.end()) + MS_THROW_ERROR("Transport not found"); - if (this->mapRtpObservers.find(rtpObserverId) != this->mapRtpObservers.end()) - { - MS_THROW_ERROR("an RtpObserver with same rtpObserverId already exists"); - } + return it->second; } - RTC::RtpObserver* Router::GetRtpObserverFromData(json& data) const + RTC::RtpObserver* Router::GetRtpObserverById(const std::string& rtpObserverId) const { MS_TRACE(); - auto jsonRtpObserverIdIt = data.find("rtpObserverId"); + auto it = this->mapRtpObservers.find(rtpObserverId); - if (jsonRtpObserverIdIt == data.end() || !jsonRtpObserverIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing rtpObserverId"); - } - - auto it = this->mapRtpObservers.find(jsonRtpObserverIdIt->get()); - - if (it == this->mapRtpObservers.end()) + if (this->mapRtpObservers.find(rtpObserverId) == this->mapRtpObservers.end()) MS_THROW_ERROR("RtpObserver not found"); - RTC::RtpObserver* rtpObserver = it->second; - - return rtpObserver; + return it->second; } inline void Router::OnTransportNewProducer(RTC::Transport* /*transport*/, RTC::Producer* producer) @@ -762,7 +692,7 @@ namespace RTC } inline void Router::OnTransportNewConsumer( - RTC::Transport* /*transport*/, RTC::Consumer* consumer, std::string& producerId) + RTC::Transport* /*transport*/, RTC::Consumer* consumer, const std::string& producerId) { MS_TRACE(); @@ -783,7 +713,9 @@ namespace RTC // Update the Consumer status based on the Producer status. if (producer->IsPaused()) + { consumer->ProducerPaused(); + } // Insert the Consumer in the maps. auto& consumers = mapProducerConsumersIt->second; @@ -923,20 +855,48 @@ namespace RTC this->mapDataProducerDataConsumers.erase(mapDataProducerDataConsumersIt); } + inline void Router::OnTransportDataProducerPaused( + RTC::Transport* /*transport*/, RTC::DataProducer* dataProducer) + { + MS_TRACE(); + + auto& dataConsumers = this->mapDataProducerDataConsumers.at(dataProducer); + + for (auto* dataConsumer : dataConsumers) + { + dataConsumer->DataProducerPaused(); + } + } + + inline void Router::OnTransportDataProducerResumed( + RTC::Transport* /*transport*/, RTC::DataProducer* dataProducer) + { + MS_TRACE(); + + auto& dataConsumers = this->mapDataProducerDataConsumers.at(dataProducer); + + for (auto* dataConsumer : dataConsumers) + { + dataConsumer->DataProducerResumed(); + } + } + inline void Router::OnTransportDataProducerMessageReceived( RTC::Transport* /*transport*/, RTC::DataProducer* dataProducer, - uint32_t ppid, const uint8_t* msg, - size_t len) + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel) { MS_TRACE(); auto& dataConsumers = this->mapDataProducerDataConsumers.at(dataProducer); - for (auto* consumer : dataConsumers) + for (auto* dataConsumer : dataConsumers) { - consumer->SendMessage(ppid, msg, len); + dataConsumer->SendMessage(msg, len, ppid, subchannels, requiredSubchannel); } } @@ -948,7 +908,9 @@ namespace RTC auto mapDataProducersIt = this->mapDataProducers.find(dataProducerId); if (mapDataProducersIt == this->mapDataProducers.end()) + { MS_THROW_ERROR("DataProducer not found [dataProducerId:%s]", dataProducerId.c_str()); + } auto* dataProducer = mapDataProducersIt->second; auto mapDataProducerDataConsumersIt = this->mapDataProducerDataConsumers.find(dataProducer); @@ -960,6 +922,12 @@ namespace RTC this->mapDataConsumerDataProducer.find(dataConsumer) == this->mapDataConsumerDataProducer.end(), "DataConsumer already present in mapDataConsumerDataProducer"); + // Update the DataConsumer status based on the DataProducer status. + if (dataProducer->IsPaused()) + { + dataConsumer->DataProducerPaused(); + } + // Insert the DataConsumer in the maps. auto& dataConsumers = mapDataProducerDataConsumersIt->second; diff --git a/worker/src/RTC/RtpDictionaries/Media.cpp b/worker/src/RTC/RtpDictionaries/Media.cpp deleted file mode 100644 index 35a780546d..0000000000 --- a/worker/src/RTC/RtpDictionaries/Media.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#define MS_CLASS "RTC::Media" -// #define MS_LOG_DEV_LEVEL 3 - -#include "Logger.hpp" -#include "MediaSoupErrors.hpp" -#include "Utils.hpp" -#include "RTC/RtpDictionaries.hpp" - -namespace RTC -{ - /* Class variables. */ - - // clang-format off - absl::flat_hash_map Media::string2Kind = - { - { "", Media::Kind::ALL }, - { "audio", Media::Kind::AUDIO }, - { "video", Media::Kind::VIDEO } - }; - absl::flat_hash_map Media::kind2String = - { - { Media::Kind::ALL, "" }, - { Media::Kind::AUDIO, "audio" }, - { Media::Kind::VIDEO, "video" } - }; - // clang-format on - - /* Class methods. */ - - Media::Kind Media::GetKind(std::string& str) - { - MS_TRACE(); - - // Force lowcase kind. - Utils::String::ToLowerCase(str); - - auto it = Media::string2Kind.find(str); - - if (it == Media::string2Kind.end()) - MS_THROW_TYPE_ERROR("invalid media kind [kind:%s]", str.c_str()); - - return it->second; - } - - Media::Kind Media::GetKind(std::string&& str) - { - MS_TRACE(); - - // Force lowcase kind. - Utils::String::ToLowerCase(str); - - auto it = Media::string2Kind.find(str); - - if (it == Media::string2Kind.end()) - MS_THROW_TYPE_ERROR("invalid media kind [kind:%s]", str.c_str()); - - return it->second; - } - - const std::string& Media::GetString(Media::Kind kind) - { - MS_TRACE(); - - return Media::kind2String.at(kind); - } -} // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/Parameters.cpp b/worker/src/RTC/RtpDictionaries/Parameters.cpp index c51b8c9b9f..c6ce8df665 100644 --- a/worker/src/RTC/RtpDictionaries/Parameters.cpp +++ b/worker/src/RTC/RtpDictionaries/Parameters.cpp @@ -8,104 +8,121 @@ namespace RTC { /* Instance methods. */ - void Parameters::FillJson(json& jsonObject) const + std::vector> Parameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Force it to be an object even if no key/values are added below. - jsonObject = json::object(); + std::vector> parameters; - for (auto& kv : this->mapKeyValues) + for (const auto& kv : this->mapKeyValues) { - auto& key = kv.first; - auto& value = kv.second; + const auto& key = kv.first; + const auto& value = kv.second; + + flatbuffers::Offset parameter; switch (value.type) { case Value::Type::BOOLEAN: - jsonObject[key] = value.booleanValue; + { + auto valueOffset = FBS::RtpParameters::CreateBoolean(builder, value.booleanValue); + + parameter = FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::Boolean, valueOffset.Union()); + break; + } case Value::Type::INTEGER: - jsonObject[key] = value.integerValue; + { + auto valueOffset = FBS::RtpParameters::CreateInteger32(builder, value.integerValue); + + parameters.emplace_back(FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::Integer32, valueOffset.Union())); + break; + } case Value::Type::DOUBLE: - jsonObject[key] = value.doubleValue; + { + auto valueOffset = FBS::RtpParameters::CreateDouble(builder, value.doubleValue); + + parameters.emplace_back(FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::Double, valueOffset.Union())); + break; + } case Value::Type::STRING: - jsonObject[key] = value.stringValue; + { + auto valueOffset = + FBS::RtpParameters::CreateStringDirect(builder, value.stringValue.c_str()); + + parameters.emplace_back(FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::String, valueOffset.Union())); + break; + } case Value::Type::ARRAY_OF_INTEGERS: - jsonObject[key] = value.arrayOfIntegers; + { + auto valueOffset = + FBS::RtpParameters::CreateInteger32ArrayDirect(builder, &value.arrayOfIntegers); + + parameters.emplace_back(FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::Integer32Array, valueOffset.Union())); + break; + } } } + + return parameters; } - void Parameters::Set(json& data) + void Parameters::Set(const flatbuffers::Vector>* data) { MS_TRACE(); - MS_ASSERT(data.is_object(), "data is not an object"); - - for (json::iterator it = data.begin(); it != data.end(); ++it) + for (const auto* parameter : *data) { - const std::string& key = it.key(); - auto& value = it.value(); + const auto key = parameter->name()->str(); - switch (value.type()) + switch (parameter->value_type()) { - case json::value_t::boolean: + case FBS::RtpParameters::Value::Boolean: { - this->mapKeyValues.emplace(key, Value(value.get())); + this->mapKeyValues.emplace( + key, Value((parameter->value_as_Boolean()->value() == 0) ? false : true)); break; } - case json::value_t::number_integer: - case json::value_t::number_unsigned: + case FBS::RtpParameters::Value::Integer32: { - this->mapKeyValues.emplace(key, Value(value.get())); + this->mapKeyValues.emplace(key, Value(parameter->value_as_Integer32()->value())); break; } - case json::value_t::number_float: + case FBS::RtpParameters::Value::Double: { - this->mapKeyValues.emplace(key, Value(value.get())); + this->mapKeyValues.emplace(key, Value(parameter->value_as_Double()->value())); break; } - case json::value_t::string: + case FBS::RtpParameters::Value::String: { - this->mapKeyValues.emplace(key, Value(value.get())); + this->mapKeyValues.emplace(key, Value(parameter->value_as_String()->value()->str())); break; } - case json::value_t::array: + case FBS::RtpParameters::Value::Integer32Array: { - std::vector arrayOfIntegers; - bool isValid = true; - - for (auto& entry : value) - { - if (!entry.is_number_integer()) - { - isValid = false; - - break; - } - - arrayOfIntegers.emplace_back(entry.get()); - } - - if (!arrayOfIntegers.empty() && isValid) - this->mapKeyValues.emplace(key, Value(arrayOfIntegers)); + this->mapKeyValues.emplace(key, Value(parameter->value_as_Integer32Array()->value())); break; } @@ -124,7 +141,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::BOOLEAN; } @@ -138,7 +155,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::INTEGER; } @@ -152,7 +169,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::INTEGER && value.integerValue >= 0; } @@ -166,7 +183,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::DOUBLE; } @@ -180,7 +197,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::STRING; } @@ -194,7 +211,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::ARRAY_OF_INTEGERS; } @@ -208,8 +225,8 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; - auto& array = value.arrayOfIntegers; + const auto& value = it->second; + const auto& array = value.arrayOfIntegers; return std::find(array.begin(), array.end(), integer) != array.end(); } @@ -222,7 +239,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.booleanValue; } @@ -235,7 +252,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.integerValue; } @@ -248,7 +265,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.doubleValue; } @@ -261,7 +278,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.stringValue; } @@ -274,7 +291,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.arrayOfIntegers; } diff --git a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp index 4c0f90f054..1b735e9c8d 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp @@ -9,36 +9,20 @@ namespace RTC { /* Instance methods. */ - RtcpFeedback::RtcpFeedback(json& data) + RtcpFeedback::RtcpFeedback(const FBS::RtpParameters::RtcpFeedback* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonTypeIt = data.find("type"); - auto jsonParameterIt = data.find("parameter"); - - // type is mandatory. - if (jsonTypeIt == data.end() || !jsonTypeIt->is_string()) - MS_THROW_TYPE_ERROR("missing type"); - - this->type = jsonTypeIt->get(); - - // parameter is optional. - if (jsonParameterIt != data.end() && jsonParameterIt->is_string()) - this->parameter = jsonParameterIt->get(); + this->type = data->type()->str(); + this->parameter = data->parameter()->str(); } - void RtcpFeedback::FillJson(json& jsonObject) const + flatbuffers::Offset RtcpFeedback::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add type. - jsonObject["type"] = this->type; - - // Add parameter (optional). - if (this->parameter.length() > 0) - jsonObject["parameter"] = this->parameter; + return FBS::RtpParameters::CreateRtcpFeedbackDirect( + builder, this->type.c_str(), this->parameter.empty() ? nullptr : this->parameter.c_str()); } } // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp index fe77eeebd1..c98713a9f9 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp @@ -10,50 +10,24 @@ namespace RTC { /* Instance methods. */ - RtcpParameters::RtcpParameters(json& data) + RtcpParameters::RtcpParameters(const FBS::RtpParameters::RtcpParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonCnameIt = data.find("cname"); - auto jsonSsrcIt = data.find("ssrc"); - auto jsonRedicedSizeIt = data.find("reducedSize"); - // cname is optional. - if (jsonCnameIt != data.end() && jsonCnameIt->is_string()) - this->cname = jsonCnameIt->get(); - - // ssrc is optional. - // clang-format off - if ( - jsonSsrcIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonSsrcIt) - ) - // clang-format on - { - this->ssrc = jsonSsrcIt->get(); - } + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtcpParameters::VT_CNAME)) + this->cname = data->cname()->str(); - // reducedSize is optional. - if (jsonRedicedSizeIt != data.end() && jsonRedicedSizeIt->is_boolean()) - this->reducedSize = jsonRedicedSizeIt->get(); + // reducedSize is optional, default value is true. + this->reducedSize = data->reducedSize(); } - void RtcpParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtcpParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add cname. - if (!this->cname.empty()) - jsonObject["cname"] = this->cname; - - // Add ssrc. - if (this->ssrc != 0u) - jsonObject["ssrc"] = this->ssrc; - - // Add reducedSize. - jsonObject["reducedSize"] = this->reducedSize; + return FBS::RtpParameters::CreateRtcpParametersDirect( + builder, this->cname.c_str(), this->reducedSize); } } // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpCodecMimeType.cpp b/worker/src/RTC/RtpDictionaries/RtpCodecMimeType.cpp index 3b5874ef78..b49f42844f 100644 --- a/worker/src/RTC/RtpDictionaries/RtpCodecMimeType.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpCodecMimeType.cpp @@ -128,9 +128,6 @@ namespace RTC { MS_TRACE(); - MS_ASSERT(this->type != Type::UNSET, "type unset"); - MS_ASSERT(this->subtype != Subtype::UNSET, "subtype unset"); - // Set mimeType. this->mimeType = RtpCodecMimeType::type2String[this->type] + "/" + RtpCodecMimeType::subtype2String[this->subtype]; diff --git a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp index caab4b63ce..92655338ef 100644 --- a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp @@ -10,77 +10,37 @@ namespace RTC { /* Instance methods. */ - RtpCodecParameters::RtpCodecParameters(json& data) + RtpCodecParameters::RtpCodecParameters(const FBS::RtpParameters::RtpCodecParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonMimeTypeIt = data.find("mimeType"); - auto jsonPayloadTypeIt = data.find("payloadType"); - auto jsonClockRateIt = data.find("clockRate"); - auto jsonChannelsIt = data.find("channels"); - auto jsonParametersIt = data.find("parameters"); - auto jsonRtcpFeedbackIt = data.find("rtcpFeedback"); - - // mimeType is mandatory. - if (jsonMimeTypeIt == data.end() || !jsonMimeTypeIt->is_string()) - MS_THROW_TYPE_ERROR("missing mimeType"); - // Set MIME field. // This may throw. - this->mimeType.SetMimeType(jsonMimeTypeIt->get()); - - // payloadType is mandatory. - // clang-format off - if ( - jsonPayloadTypeIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonPayloadTypeIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing payloadType"); - } - - this->payloadType = jsonPayloadTypeIt->get(); + this->mimeType.SetMimeType(data->mimeType()->str()); - // clockRate is mandatory. - // clang-format off - if ( - jsonClockRateIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonClockRateIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing clockRate"); - } + // payloadType. + this->payloadType = data->payloadType(); - this->clockRate = jsonClockRateIt->get(); + // clockRate. + this->clockRate = data->clockRate(); // channels is optional. - // clang-format off - if ( - jsonChannelsIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonChannelsIt) - ) - // clang-format on + if (data->channels().has_value()) { - this->channels = jsonChannelsIt->get(); + this->channels = data->channels().value(); } // parameters is optional. - if (jsonParametersIt != data.end() && jsonParametersIt->is_object()) - this->parameters.Set(*jsonParametersIt); + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpCodecParameters::VT_PARAMETERS)) + this->parameters.Set(data->parameters()); // rtcpFeedback is optional. - if (jsonRtcpFeedbackIt != data.end() && jsonRtcpFeedbackIt->is_array()) + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpCodecParameters::VT_RTCPFEEDBACK)) { - this->rtcpFeedback.reserve(jsonRtcpFeedbackIt->size()); + this->rtcpFeedback.reserve(data->rtcpFeedback()->size()); - for (auto& entry : *jsonRtcpFeedbackIt) + for (const auto* entry : *data->rtcpFeedback()) { - // This may throw due the constructor of RTC::RtcpFeedback. this->rtcpFeedback.emplace_back(entry); } } @@ -89,39 +49,29 @@ namespace RTC CheckCodec(); } - void RtpCodecParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpCodecParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add mimeType. - jsonObject["mimeType"] = this->mimeType.ToString(); + auto parameters = this->parameters.FillBuffer(builder); - // Add payloadType. - jsonObject["payloadType"] = this->payloadType; + std::vector> rtcpFeedback; + rtcpFeedback.reserve(this->rtcpFeedback.size()); - // Add clockRate. - jsonObject["clockRate"] = this->clockRate; - - // Add channels. - if (this->channels > 1) - jsonObject["channels"] = this->channels; - - // Add parameters. - this->parameters.FillJson(jsonObject["parameters"]); - - // Add rtcpFeedback. - jsonObject["rtcpFeedback"] = json::array(); - auto jsonRtcpFeedbackIt = jsonObject.find("rtcpFeedback"); - - for (size_t i{ 0 }; i < this->rtcpFeedback.size(); ++i) + for (const auto& fb : this->rtcpFeedback) { - jsonRtcpFeedbackIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonRtcpFeedbackIt)[i]; - auto& fb = this->rtcpFeedback[i]; - - fb.FillJson(jsonEntry); + rtcpFeedback.emplace_back(fb.FillBuffer(builder)); } + + return FBS::RtpParameters::CreateRtpCodecParametersDirect( + builder, + this->mimeType.ToString().c_str(), + this->payloadType, + this->clockRate, + this->channels > 1 ? flatbuffers::Optional(this->channels) : flatbuffers::nullopt, + ¶meters, + &rtcpFeedback); } inline void RtpCodecParameters::CheckCodec() diff --git a/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp index 6c745802bd..e046c350e6 100644 --- a/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp @@ -12,80 +12,44 @@ namespace RTC { /* Instance methods. */ - RtpEncodingParameters::RtpEncodingParameters(json& data) + RtpEncodingParameters::RtpEncodingParameters(const FBS::RtpParameters::RtpEncodingParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonSsrcIt = data.find("ssrc"); - auto jsonRidIt = data.find("rid"); - auto jsonCodecPayloadTypeIt = data.find("codecPayloadType"); - auto jsonRtxIt = data.find("rtx"); - auto jsonMaxBitrateIt = data.find("maxBitrate"); - auto jsonMaxFramerateIt = data.find("maxFramerate"); - auto jsonDtxIt = data.find("dtx"); - auto jsonScalabilityModeIt = data.find("scalabilityMode"); - // ssrc is optional. - // clang-format off - if ( - jsonSsrcIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonSsrcIt) - ) - // clang-format on - { - this->ssrc = jsonSsrcIt->get(); - } + if (data->ssrc().has_value()) + this->ssrc = data->ssrc().value(); // rid is optional. - if (jsonRidIt != data.end() && jsonRidIt->is_string()) - this->rid = jsonRidIt->get(); + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpEncodingParameters::VT_RID)) + this->rid = data->rid()->str(); // codecPayloadType is optional. - // clang-format off - if ( - jsonCodecPayloadTypeIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonCodecPayloadTypeIt) - ) - // clang-format on + if (data->codecPayloadType().has_value()) { - this->codecPayloadType = jsonCodecPayloadTypeIt->get(); + this->codecPayloadType = data->codecPayloadType().value(); this->hasCodecPayloadType = true; } // rtx is optional. - // This may throw. - if (jsonRtxIt != data.end() && jsonRtxIt->is_object()) + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpEncodingParameters::VT_RTX)) { - this->rtx = RtpRtxParameters(*jsonRtxIt); + this->rtx = RtpRtxParameters(data->rtx()); this->hasRtx = true; } // maxBitrate is optional. - // clang-format off - if ( - jsonMaxBitrateIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonMaxBitrateIt) - ) - // clang-format on - { - this->maxBitrate = jsonMaxBitrateIt->get(); - } - - // maxFramerate is optional. - if (jsonMaxFramerateIt != data.end() && jsonMaxFramerateIt->is_number()) - this->maxFramerate = jsonMaxFramerateIt->get(); + if (data->maxBitrate().has_value()) + this->maxBitrate = data->maxBitrate().value(); - // dtx is optional. - if (jsonDtxIt != data.end() && jsonDtxIt->is_boolean()) - this->dtx = jsonDtxIt->get(); + // dtx is optional, default is false. + this->dtx = data->dtx(); // scalabilityMode is optional. - if (jsonScalabilityModeIt != data.end() && jsonScalabilityModeIt->is_string()) + if (flatbuffers::IsFieldPresent( + data, FBS::RtpParameters::RtpEncodingParameters::VT_SCALABILITYMODE)) { - std::string scalabilityMode = jsonScalabilityModeIt->get(); + const std::string scalabilityMode = data->scalabilityMode()->str(); static const std::regex ScalabilityModeRegex( "^[LS]([1-9]\\d{0,1})T([1-9]\\d{0,1})(_KEY)?.*", std::regex_constants::ECMAScript); @@ -112,48 +76,19 @@ namespace RTC } } - void RtpEncodingParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpEncodingParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Force it to be an object even if no key/values are added below. - jsonObject = json::object(); - - // Add ssrc. - if (this->ssrc != 0u) - jsonObject["ssrc"] = this->ssrc; - - // Add rid. - if (!this->rid.empty()) - jsonObject["rid"] = this->rid; - - // Add codecPayloadType. - if (this->hasCodecPayloadType) - jsonObject["codecPayloadType"] = this->codecPayloadType; - - // Add rtx. - if (this->hasRtx) - this->rtx.FillJson(jsonObject["rtx"]); - - // Add maxBitrate. - if (this->maxBitrate != 0u) - jsonObject["maxBitrate"] = this->maxBitrate; - - // Add maxFramerate. - if (this->maxFramerate > 0) - jsonObject["maxFramerate"] = this->maxFramerate; - - // Add dtx. - if (this->dtx) - jsonObject["dtx"] = this->dtx; - - // Add scalabilityMode. - if (!this->scalabilityMode.empty()) - { - jsonObject["scalabilityMode"] = this->scalabilityMode; - jsonObject["spatialLayers"] = this->spatialLayers; - jsonObject["temporalLayers"] = this->temporalLayers; - jsonObject["ksvc"] = this->ksvc; - } + return FBS::RtpParameters::CreateRtpEncodingParametersDirect( + builder, + this->ssrc != 0u ? flatbuffers::Optional(this->ssrc) : flatbuffers::nullopt, + this->rid.size() > 0 ? this->rid.c_str() : nullptr, + this->hasCodecPayloadType ? flatbuffers::Optional(this->codecPayloadType) + : flatbuffers::nullopt, + this->hasRtx ? this->rtx.FillBuffer(builder) : 0u, + this->dtx, + this->scalabilityMode.c_str()); } } // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp index bb762881bc..3810a759d0 100644 --- a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp @@ -10,63 +10,39 @@ namespace RTC { /* Instance methods. */ - RtpHeaderExtensionParameters::RtpHeaderExtensionParameters(json& data) + RtpHeaderExtensionParameters::RtpHeaderExtensionParameters( + const FBS::RtpParameters::RtpHeaderExtensionParameters* const data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonUriIt = data.find("uri"); - auto jsonIdIt = data.find("id"); - auto jsonEncryptIt = data.find("encrypt"); - auto jsonParametersIt = data.find("parameters"); - - // uri is mandatory. - if (jsonUriIt == data.end() || !jsonUriIt->is_string()) - MS_THROW_TYPE_ERROR("missing uri"); - - this->uri = jsonUriIt->get(); - - if (this->uri.empty()) - MS_THROW_TYPE_ERROR("empty uri"); - // Get the type. - this->type = RTC::RtpHeaderExtensionUri::GetType(this->uri); - - // id is mandatory. - if (jsonIdIt == data.end() || !Utils::Json::IsPositiveInteger(*jsonIdIt)) - MS_THROW_TYPE_ERROR("missing id"); + this->type = RTC::RtpHeaderExtensionUri::TypeFromFbs(data->uri()); - this->id = jsonIdIt->get(); + this->id = data->id(); // Don't allow id 0. if (this->id == 0u) MS_THROW_TYPE_ERROR("invalid id 0"); - // encrypt is optional. - if (jsonEncryptIt != data.end() && jsonEncryptIt->is_boolean()) - this->encrypt = jsonEncryptIt->get(); + // encrypt is false by default. + this->encrypt = data->encrypt(); // parameters is optional. - if (jsonParametersIt != data.end() && jsonParametersIt->is_object()) - this->parameters.Set(*jsonParametersIt); + if (flatbuffers::IsFieldPresent( + data, FBS::RtpParameters::RtpHeaderExtensionParameters::VT_PARAMETERS)) + { + this->parameters.Set(data->parameters()); + } } - void RtpHeaderExtensionParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpHeaderExtensionParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add uri. - jsonObject["uri"] = this->uri; - - // Add id. - jsonObject["id"] = this->id; - - // Add encrypt. - jsonObject["encrypt"] = this->encrypt; + auto parameters = this->parameters.FillBuffer(builder); - // Add parameters. - this->parameters.FillJson(jsonObject["parameters"]); + return FBS::RtpParameters::CreateRtpHeaderExtensionParametersDirect( + builder, RTC::RtpHeaderExtensionUri::TypeToFbs(this->type), this->id, this->encrypt, ¶meters); } } // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp index e4e11e67fe..e5125ea90c 100644 --- a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp @@ -7,40 +7,66 @@ namespace RTC { - /* Class variables. */ - - // clang-format off - absl::flat_hash_map RtpHeaderExtensionUri::string2Type = - { - { "urn:ietf:params:rtp-hdrext:sdes:mid", RtpHeaderExtensionUri::Type::MID }, - { "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id", RtpHeaderExtensionUri::Type::RTP_STREAM_ID }, - { "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id", RtpHeaderExtensionUri::Type::REPAIRED_RTP_STREAM_ID }, - { "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time", RtpHeaderExtensionUri::Type::ABS_SEND_TIME }, - { "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01", RtpHeaderExtensionUri::Type::TRANSPORT_WIDE_CC_01 }, - // NOTE: Remove this once framemarking draft becomes RFC. - { "http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07", RtpHeaderExtensionUri::Type::FRAME_MARKING_07 }, - { "urn:ietf:params:rtp-hdrext:framemarking", RtpHeaderExtensionUri::Type::FRAME_MARKING }, - { "urn:ietf:params:rtp-hdrext:ssrc-audio-level", RtpHeaderExtensionUri::Type::SSRC_AUDIO_LEVEL }, - { "urn:3gpp:video-orientation", RtpHeaderExtensionUri::Type::VIDEO_ORIENTATION }, - { "urn:ietf:params:rtp-hdrext:toffset", RtpHeaderExtensionUri::Type::TOFFSET }, - { "http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time", RtpHeaderExtensionUri::Type::ABS_CAPTURE_TIME }, - }; - // clang-format on - /* Class methods. */ - RtpHeaderExtensionUri::Type RtpHeaderExtensionUri::GetType(std::string& uri) + RtpHeaderExtensionUri::Type RtpHeaderExtensionUri::TypeFromFbs( + FBS::RtpParameters::RtpHeaderExtensionUri uri) { - MS_TRACE(); - - // Force lowcase names. - Utils::String::ToLowerCase(uri); - - auto it = RtpHeaderExtensionUri::string2Type.find(uri); - - if (it != RtpHeaderExtensionUri::string2Type.end()) - return it->second; + switch (uri) + { + case FBS::RtpParameters::RtpHeaderExtensionUri::Mid: + return RtpHeaderExtensionUri::Type::MID; + case FBS::RtpParameters::RtpHeaderExtensionUri::RtpStreamId: + return RtpHeaderExtensionUri::Type::RTP_STREAM_ID; + case FBS::RtpParameters::RtpHeaderExtensionUri::RepairRtpStreamId: + return RtpHeaderExtensionUri::Type::REPAIRED_RTP_STREAM_ID; + case FBS::RtpParameters::RtpHeaderExtensionUri::FrameMarkingDraft07: + return RtpHeaderExtensionUri::Type::FRAME_MARKING_07; + case FBS::RtpParameters::RtpHeaderExtensionUri::FrameMarking: + return RtpHeaderExtensionUri::Type::FRAME_MARKING; + case FBS::RtpParameters::RtpHeaderExtensionUri::AudioLevel: + return RtpHeaderExtensionUri::Type::SSRC_AUDIO_LEVEL; + case FBS::RtpParameters::RtpHeaderExtensionUri::VideoOrientation: + return RtpHeaderExtensionUri::Type::VIDEO_ORIENTATION; + case FBS::RtpParameters::RtpHeaderExtensionUri::TimeOffset: + return RtpHeaderExtensionUri::Type::TOFFSET; + case FBS::RtpParameters::RtpHeaderExtensionUri::TransportWideCcDraft01: + return RtpHeaderExtensionUri::Type::TRANSPORT_WIDE_CC_01; + case FBS::RtpParameters::RtpHeaderExtensionUri::AbsSendTime: + return RtpHeaderExtensionUri::Type::ABS_SEND_TIME; + case FBS::RtpParameters::RtpHeaderExtensionUri::AbsCaptureTime: + return RtpHeaderExtensionUri::Type::ABS_CAPTURE_TIME; + } + } - return RtpHeaderExtensionUri::Type::UNKNOWN; + FBS::RtpParameters::RtpHeaderExtensionUri RtpHeaderExtensionUri::TypeToFbs( + RtpHeaderExtensionUri::Type uri) + { + switch (uri) + { + case RtpHeaderExtensionUri::Type::MID: + return FBS::RtpParameters::RtpHeaderExtensionUri::Mid; + case RtpHeaderExtensionUri::Type::RTP_STREAM_ID: + return FBS::RtpParameters::RtpHeaderExtensionUri::RtpStreamId; + case RtpHeaderExtensionUri::Type::REPAIRED_RTP_STREAM_ID: + return FBS::RtpParameters::RtpHeaderExtensionUri::RepairRtpStreamId; + case RtpHeaderExtensionUri::Type::ABS_SEND_TIME: + return FBS::RtpParameters::RtpHeaderExtensionUri::AbsSendTime; + case RtpHeaderExtensionUri::Type::TRANSPORT_WIDE_CC_01: + return FBS::RtpParameters::RtpHeaderExtensionUri::TransportWideCcDraft01; + case RtpHeaderExtensionUri::Type::FRAME_MARKING_07: + return FBS::RtpParameters::RtpHeaderExtensionUri::FrameMarkingDraft07; + case RtpHeaderExtensionUri::Type::FRAME_MARKING: + return FBS::RtpParameters::RtpHeaderExtensionUri::FrameMarking; + case RtpHeaderExtensionUri::Type::SSRC_AUDIO_LEVEL: + return FBS::RtpParameters::RtpHeaderExtensionUri::AudioLevel; + case RtpHeaderExtensionUri::Type::VIDEO_ORIENTATION: + return FBS::RtpParameters::RtpHeaderExtensionUri::VideoOrientation; + case RtpHeaderExtensionUri::Type::TOFFSET: + return FBS::RtpParameters::RtpHeaderExtensionUri::TimeOffset; + case RtpHeaderExtensionUri::Type::ABS_CAPTURE_TIME: + return FBS::RtpParameters::RtpHeaderExtensionUri::AbsCaptureTime; + } } + } // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpParameters.cpp index 2a0010affa..df62479110 100644 --- a/worker/src/RTC/RtpDictionaries/RtpParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpParameters.cpp @@ -11,34 +11,25 @@ namespace RTC { /* Class variables. */ - // clang-format off - absl::flat_hash_map RtpParameters::string2Type = - { - { "none", RtpParameters::Type::NONE }, - { "simple", RtpParameters::Type::SIMPLE }, - { "simulcast", RtpParameters::Type::SIMULCAST }, - { "svc", RtpParameters::Type::SVC }, - { "pipe", RtpParameters::Type::PIPE } - }; - absl::flat_hash_map RtpParameters::type2String = - { - { RtpParameters::Type::NONE, "none" }, - { RtpParameters::Type::SIMPLE, "simple" }, + absl::flat_hash_map RtpParameters::type2String = { + { RtpParameters::Type::SIMPLE, "simple" }, { RtpParameters::Type::SIMULCAST, "simulcast" }, - { RtpParameters::Type::SVC, "svc" }, - { RtpParameters::Type::PIPE, "pipe" } + { RtpParameters::Type::SVC, "svc" }, + { RtpParameters::Type::PIPE, "pipe" } }; // clang-format on /* Class methods. */ - RtpParameters::Type RtpParameters::GetType(const RtpParameters& rtpParameters) + std::optional RtpParameters::GetType(const RtpParameters& rtpParameters) { MS_TRACE(); + std::optional type; + if (rtpParameters.encodings.size() == 1) { - auto& encoding = rtpParameters.encodings[0]; + const auto& encoding = rtpParameters.encodings[0]; const auto* mediaCodec = rtpParameters.GetCodecForEncoding(const_cast(encoding)); @@ -46,93 +37,69 @@ namespace RTC { if (RTC::Codecs::Tools::IsValidTypeForCodec(RtpParameters::Type::SVC, mediaCodec->mimeType)) { - return RtpParameters::Type::SVC; + type.emplace(RtpParameters::Type::SVC); } else if (RTC::Codecs::Tools::IsValidTypeForCodec( RtpParameters::Type::SIMULCAST, mediaCodec->mimeType)) { - return RtpParameters::Type::SIMULCAST; - } - else - { - return RtpParameters::Type::NONE; + type.emplace(RtpParameters::Type::SIMULCAST); } } else { - return RtpParameters::Type::SIMPLE; + type.emplace(RtpParameters::Type::SIMPLE); } } else if (rtpParameters.encodings.size() > 1) { - return RtpParameters::Type::SIMULCAST; + type.emplace(RtpParameters::Type::SIMULCAST); } - return RtpParameters::Type::NONE; + return type; } - RtpParameters::Type RtpParameters::GetType(std::string& str) - { - MS_TRACE(); - - auto it = RtpParameters::string2Type.find(str); - - if (it == RtpParameters::string2Type.end()) - MS_THROW_TYPE_ERROR("invalid RtpParameters type [type:%s]", str.c_str()); - - return it->second; - } - - RtpParameters::Type RtpParameters::GetType(std::string&& str) + std::string& RtpParameters::GetTypeString(RtpParameters::Type type) { MS_TRACE(); - auto it = RtpParameters::string2Type.find(str); - - if (it == RtpParameters::string2Type.end()) - MS_THROW_TYPE_ERROR("invalid RtpParameters type [type:%s]", str.c_str()); - - return it->second; + return RtpParameters::type2String.at(type); } - std::string& RtpParameters::GetTypeString(RtpParameters::Type type) + FBS::RtpParameters::Type RtpParameters::TypeToFbs(RtpParameters::Type type) { MS_TRACE(); - return RtpParameters::type2String.at(type); + switch (type) + { + case Type::SIMPLE: + return FBS::RtpParameters::Type::SIMPLE; + case Type::SIMULCAST: + return FBS::RtpParameters::Type::SIMULCAST; + case Type::SVC: + return FBS::RtpParameters::Type::SVC; + case Type::PIPE: + return FBS::RtpParameters::Type::PIPE; + } } /* Instance methods. */ - RtpParameters::RtpParameters(json& data) + RtpParameters::RtpParameters(const FBS::RtpParameters::RtpParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonMidIt = data.find("mid"); - auto jsonCodecsIt = data.find("codecs"); - auto jsonEncodingsIt = data.find("encodings"); - auto jsonHeaderExtensionsIt = data.find("headerExtensions"); - auto jsonRtcpIt = data.find("rtcp"); - // mid is optional. - if (jsonMidIt != data.end() && jsonMidIt->is_string()) + if (data->mid()) { - this->mid = jsonMidIt->get(); + this->mid = data->mid()->str(); if (this->mid.empty()) MS_THROW_TYPE_ERROR("empty mid"); } - // codecs is mandatory. - if (jsonCodecsIt == data.end() || !jsonCodecsIt->is_array()) - MS_THROW_TYPE_ERROR("missing codecs"); - - this->codecs.reserve(jsonCodecsIt->size()); + this->codecs.reserve(data->codecs()->size()); - for (auto& entry : *jsonCodecsIt) + for (const auto* entry : *data->codecs()) { // This may throw due the constructor of RTC::RtpCodecParameters. this->codecs.emplace_back(entry); @@ -141,13 +108,9 @@ namespace RTC if (this->codecs.empty()) MS_THROW_TYPE_ERROR("empty codecs"); - // encodings is mandatory. - if (jsonEncodingsIt == data.end() || !jsonEncodingsIt->is_array()) - MS_THROW_TYPE_ERROR("missing encodings"); + this->encodings.reserve(data->encodings()->size()); - this->encodings.reserve(jsonEncodingsIt->size()); - - for (auto& entry : *jsonEncodingsIt) + for (const auto* entry : *data->encodings()) { // This may throw due the constructor of RTC::RtpEncodingParameters. this->encodings.emplace_back(entry); @@ -156,86 +119,61 @@ namespace RTC if (this->encodings.empty()) MS_THROW_TYPE_ERROR("empty encodings"); - // headerExtensions is optional. - if (jsonHeaderExtensionsIt != data.end() && jsonHeaderExtensionsIt->is_array()) - { - this->headerExtensions.reserve(jsonHeaderExtensionsIt->size()); - - for (auto& entry : *jsonHeaderExtensionsIt) - { - // This may throw due the constructor of RTC::RtpHeaderExtensionParameters. - this->headerExtensions.emplace_back(entry); - } - } + this->headerExtensions.reserve(data->headerExtensions()->size()); - // rtcp is optional. - if (jsonRtcpIt != data.end() && jsonRtcpIt->is_object()) + for (const auto* entry : *data->headerExtensions()) { - // This may throw. - this->rtcp = RTC::RtcpParameters(*jsonRtcpIt); - this->hasRtcp = true; + // This may throw due the constructor of RTC::RtpHeaderExtensionParameters. + this->headerExtensions.emplace_back(entry); } + // This may throw. + this->rtcp = RTC::RtcpParameters(data->rtcp()); + // Validate RTP parameters. ValidateCodecs(); ValidateEncodings(); } - void RtpParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add mid. - if (!this->mid.empty()) - jsonObject["mid"] = this->mid; - // Add codecs. - jsonObject["codecs"] = json::array(); - auto jsonCodecsIt = jsonObject.find("codecs"); + std::vector> codecs; + codecs.reserve(this->codecs.size()); - for (size_t i{ 0 }; i < this->codecs.size(); ++i) + for (const auto& codec : this->codecs) { - jsonCodecsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonCodecsIt)[i]; - auto& codec = this->codecs[i]; - - codec.FillJson(jsonEntry); + codecs.emplace_back(codec.FillBuffer(builder)); } // Add encodings. - jsonObject["encodings"] = json::array(); - auto jsonEncodingsIt = jsonObject.find("encodings"); + std::vector> encodings; + encodings.reserve(this->encodings.size()); - for (size_t i{ 0 }; i < this->encodings.size(); ++i) + for (const auto& encoding : this->encodings) { - jsonEncodingsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonEncodingsIt)[i]; - auto& encoding = this->encodings[i]; - - encoding.FillJson(jsonEntry); + encodings.emplace_back(encoding.FillBuffer(builder)); } // Add headerExtensions. - jsonObject["headerExtensions"] = json::array(); - auto jsonHeaderExtensionsIt = jsonObject.find("headerExtensions"); + std::vector> headerExtensions; + headerExtensions.reserve(this->headerExtensions.size()); - for (size_t i{ 0 }; i < this->headerExtensions.size(); ++i) + for (const auto& headerExtension : this->headerExtensions) { - jsonHeaderExtensionsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonHeaderExtensionsIt)[i]; - auto& headerExtension = this->headerExtensions[i]; - - headerExtension.FillJson(jsonEntry); + headerExtensions.emplace_back(headerExtension.FillBuffer(builder)); } // Add rtcp. - if (this->hasRtcp) - this->rtcp.FillJson(jsonObject["rtcp"]); - else - jsonObject["rtcp"] = json::object(); + flatbuffers::Offset rtcp; + + rtcp = this->rtcp.FillBuffer(builder); + + return FBS::RtpParameters::CreateRtpParametersDirect( + builder, mid.c_str(), &codecs, &headerExtensions, &encodings, rtcp); } const RTC::RtpCodecParameters* RtpParameters::GetCodecForEncoding(RtpEncodingParameters& encoding) const @@ -247,7 +185,7 @@ namespace RTC for (; it != this->codecs.end(); ++it) { - auto& codec = *it; + const auto& codec = *it; if (codec.payloadType == payloadType) return std::addressof(codec); diff --git a/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp index eaf8726395..41272388b1 100644 --- a/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp @@ -10,36 +10,18 @@ namespace RTC { /* Instance methods. */ - RtpRtxParameters::RtpRtxParameters(json& data) + RtpRtxParameters::RtpRtxParameters(const FBS::RtpParameters::Rtx* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonSsrcIt = data.find("ssrc"); - - // ssrc is optional. - // clang-format off - if ( - jsonSsrcIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonSsrcIt) - ) - // clang-format on - { - this->ssrc = jsonSsrcIt->get(); - } + this->ssrc = data->ssrc(); } - void RtpRtxParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpRtxParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Force it to be an object even if no key/values are added below. - jsonObject = json::object(); - - // Add ssrc (optional). - if (this->ssrc != 0u) - jsonObject["ssrc"] = this->ssrc; + return FBS::RtpParameters::CreateRtx(builder, this->ssrc); } } // namespace RTC diff --git a/worker/src/RTC/RtpListener.cpp b/worker/src/RTC/RtpListener.cpp index 5c21c60cf9..e8a4e43e24 100644 --- a/worker/src/RTC/RtpListener.cpp +++ b/worker/src/RTC/RtpListener.cpp @@ -10,44 +10,48 @@ namespace RTC { /* Instance methods. */ - void RtpListener::FillJson(json& jsonObject) const + flatbuffers::Offset RtpListener::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonObject["ssrcTable"] = json::object(); - jsonObject["midTable"] = json::object(); - jsonObject["ridTable"] = json::object(); - - auto jsonSsrcTableIt = jsonObject.find("ssrcTable"); - auto jsonMidTableIt = jsonObject.find("midTable"); - auto jsonRidTableIt = jsonObject.find("ridTable"); - // Add ssrcTable. + std::vector> ssrcTable; + for (const auto& kv : this->ssrcTable) { auto ssrc = kv.first; auto* producer = kv.second; - (*jsonSsrcTableIt)[std::to_string(ssrc)] = producer->id; + ssrcTable.emplace_back( + FBS::Common::CreateUint32StringDirect(builder, ssrc, producer->id.c_str())); } // Add midTable. + std::vector> midTable; + for (const auto& kv : this->midTable) { const auto& mid = kv.first; auto* producer = kv.second; - (*jsonMidTableIt)[mid] = producer->id; + midTable.emplace_back( + FBS::Common::CreateStringStringDirect(builder, mid.c_str(), producer->id.c_str())); } // Add ridTable. + std::vector> ridTable; + for (const auto& kv : this->ridTable) { const auto& rid = kv.first; auto* producer = kv.second; - (*jsonRidTableIt)[rid] = producer->id; + ridTable.emplace_back( + FBS::Common::CreateStringStringDirect(builder, rid.c_str(), producer->id.c_str())); } + + return FBS::Transport::CreateRtpListenerDirect(builder, &ssrcTable, &midTable, &ridTable); } void RtpListener::AddProducer(RTC::Producer* producer) diff --git a/worker/src/RTC/RtpObserver.cpp b/worker/src/RTC/RtpObserver.cpp index e57dfe542b..203ee99cea 100644 --- a/worker/src/RTC/RtpObserver.cpp +++ b/worker/src/RTC/RtpObserver.cpp @@ -24,9 +24,9 @@ namespace RTC { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::RTP_OBSERVER_PAUSE: + case Channel::ChannelRequest::Method::RTPOBSERVER_PAUSE: { this->Pause(); @@ -35,7 +35,7 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::RTP_OBSERVER_RESUME: + case Channel::ChannelRequest::Method::RTPOBSERVER_RESUME: { this->Resume(); @@ -44,10 +44,11 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::RTP_OBSERVER_ADD_PRODUCER: + case Channel::ChannelRequest::Method::RTPOBSERVER_ADD_PRODUCER: { - // This may throw. - auto producerId = GetProducerIdFromData(request->data); + const auto* body = request->data->body_as(); + auto producerId = body->producerId()->str(); + RTC::Producer* producer = this->listener->RtpObserverGetProducer(this, producerId); this->AddProducer(producer); @@ -59,10 +60,11 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::RTP_OBSERVER_REMOVE_PRODUCER: + case Channel::ChannelRequest::Method::RTPOBSERVER_REMOVE_PRODUCER: { - // This may throw. - auto producerId = GetProducerIdFromData(request->data); + const auto* body = request->data->body_as(); + auto producerId = body->producerId()->str(); + RTC::Producer* producer = this->listener->RtpObserverGetProducer(this, producerId); this->RemoveProducer(producer); @@ -77,7 +79,7 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } @@ -105,16 +107,4 @@ namespace RTC Resumed(); } - - std::string RtpObserver::GetProducerIdFromData(json& data) const - { - MS_TRACE(); - - auto jsonRouterIdIt = data.find("producerId"); - - if (jsonRouterIdIt == data.end() || !jsonRouterIdIt->is_string()) - MS_THROW_ERROR("missing data.producerId"); - - return jsonRouterIdIt->get(); - } } // namespace RTC diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index 368115abed..dae9b41e10 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -317,63 +317,60 @@ namespace RTC MS_DUMP("
"); } - void RtpPacket::FillJson(json& jsonObject) const + flatbuffers::Offset RtpPacket::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { - MS_TRACE(); - - // Add payloadType. - jsonObject["payloadType"] = GetPayloadType(); - - // Add sequenceNumber. - jsonObject["sequenceNumber"] = GetSequenceNumber(); - - // Add timestamp. - jsonObject["timestamp"] = GetTimestamp(); - - // Add marker. - jsonObject["marker"] = HasMarker(); - - // Add ssrc. - jsonObject["ssrc"] = GetSsrc(); - - // Add isKeyFrame. - jsonObject["isKeyFrame"] = IsKeyFrame(); - - // Add size. - jsonObject["size"] = GetSize(); - - // Add payloadSize. - jsonObject["payloadSize"] = GetPayloadLength(); - - // Add spatialLayer. - jsonObject["spatialLayer"] = GetSpatialLayer(); - - // Add temporalLayer. - jsonObject["temporalLayer"] = GetTemporalLayer(); - // Add mid. std::string mid; - if (this->midExtensionId != 0u && ReadMid(mid)) - jsonObject["mid"] = mid; + if (this->midExtensionId != 0u) + { + ReadMid(mid); + } // Add rid. std::string rid; - if (this->ridExtensionId != 0u && ReadRid(rid)) - jsonObject["rid"] = rid; + if (this->ridExtensionId != 0u) + { + ReadRid(rid); + } // Add rrid. std::string rrid; - if (this->rridExtensionId != 0u && ReadRid(rrid)) - jsonObject["rrid"] = rrid; + if (this->rridExtensionId != 0u) + { + ReadRid(rrid); + } // Add wideSequenceNumber. uint16_t wideSequenceNumber; + bool wideSequenceNumberSet = false; - if (this->transportWideCc01ExtensionId != 0u && ReadTransportWideCc01(wideSequenceNumber)) - jsonObject["wideSequenceNumber"] = wideSequenceNumber; + if (this->transportWideCc01ExtensionId != 0u) + { + wideSequenceNumberSet = true; + ReadTransportWideCc01(wideSequenceNumber); + } + + return FBS::RtpPacket::CreateDumpDirect( + builder, + this->GetPayloadType(), + this->GetSequenceNumber(), + this->GetTimestamp(), + this->HasMarker(), + this->GetSsrc(), + this->IsKeyFrame(), + this->GetSize(), + this->GetPayloadLength(), + this->GetSpatialLayer(), + this->GetTemporalLayer(), + mid.empty() ? nullptr : mid.c_str(), + rid.empty() ? nullptr : rid.c_str(), + rrid.empty() ? nullptr : rrid.c_str(), + wideSequenceNumberSet ? flatbuffers::Optional(wideSequenceNumber) + : flatbuffers::nullopt); } void RtpPacket::SetExtensions(uint8_t type, const std::vector& extensions) diff --git a/worker/src/RTC/RtpStream.cpp b/worker/src/RTC/RtpStream.cpp index 8503025f31..45add75d99 100644 --- a/worker/src/RTC/RtpStream.cpp +++ b/worker/src/RTC/RtpStream.cpp @@ -31,53 +31,57 @@ namespace RTC this->rtxStream = nullptr; } - void RtpStream::FillJson(json& jsonObject) const + flatbuffers::Offset RtpStream::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Add params. - this->params.FillJson(jsonObject["params"]); - - // Add score. - jsonObject["score"] = this->score; + auto params = this->params.FillBuffer(builder); // Add rtxStream. + flatbuffers::Offset rtxStream; + if (HasRtx()) - this->rtxStream->FillJson(jsonObject["rtxStream"]); + rtxStream = this->rtxStream->FillBuffer(builder); + + return FBS::RtpStream::CreateDump(builder, params, this->score, rtxStream); } - void RtpStream::FillJsonStats(json& jsonObject) + flatbuffers::Offset RtpStream::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); const uint64_t nowMs = DepLibUV::GetTimeMs(); - - jsonObject["timestamp"] = nowMs; - jsonObject["ssrc"] = this->params.ssrc; - jsonObject["kind"] = RtpCodecMimeType::type2String[this->params.mimeType.type]; - jsonObject["mimeType"] = this->params.mimeType.ToString(); - jsonObject["packetsLost"] = this->packetsLost; - jsonObject["fractionLost"] = this->fractionLost; - jsonObject["packetsDiscarded"] = this->packetsDiscarded; - jsonObject["packetsRetransmitted"] = this->packetsRetransmitted; - jsonObject["packetsRepaired"] = this->packetsRepaired; - jsonObject["nackCount"] = this->nackCount; - jsonObject["nackPacketCount"] = this->nackPacketCount; - jsonObject["pliCount"] = this->pliCount; - jsonObject["firCount"] = this->firCount; - jsonObject["score"] = this->score; - - if (!this->params.rid.empty()) - jsonObject["rid"] = this->params.rid; - - if (this->params.rtxSsrc) - jsonObject["rtxSsrc"] = this->params.rtxSsrc; - - if (this->rtxStream) - jsonObject["rtxPacketsDiscarded"] = this->rtxStream->GetPacketsDiscarded(); - - if (this->rtt > 0.0f) - jsonObject["roundTripTime"] = this->rtt; + const auto mediaKind = this->params.mimeType.type == RTC::RtpCodecMimeType::Type::AUDIO + ? FBS::RtpParameters::MediaKind::AUDIO + : FBS::RtpParameters::MediaKind::VIDEO; + + auto baseStats = FBS::RtpStream::CreateBaseStatsDirect( + builder, + nowMs, + this->params.ssrc, + mediaKind, + this->params.mimeType.ToString().c_str(), + this->packetsLost, + this->fractionLost, + this->packetsDiscarded, + this->packetsRetransmitted, + this->packetsRepaired, + this->nackCount, + this->nackPacketCount, + this->pliCount, + this->firCount, + this->score, + !this->params.rid.empty() ? this->params.rid.c_str() : nullptr, + this->params.rtxSsrc ? flatbuffers::Optional(this->params.rtxSsrc) + : flatbuffers::nullopt, + this->rtxStream ? this->rtxStream->GetPacketsDiscarded() : 0, + this->rtt > 0.0f ? this->rtt : 0); + + return FBS::RtpStream::CreateStats( + builder, FBS::RtpStream::StatsData::BaseStats, baseStats.Union()); } void RtpStream::SetRtx(uint8_t payloadType, uint32_t ssrc) @@ -338,33 +342,28 @@ namespace RTC this->badSeq = RtpSeqMod + 1; // So seq == badSeq is false. } - void RtpStream::Params::FillJson(json& jsonObject) const + flatbuffers::Offset RtpStream::Params::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonObject["encodingIdx"] = this->encodingIdx; - jsonObject["ssrc"] = this->ssrc; - jsonObject["payloadType"] = this->payloadType; - jsonObject["mimeType"] = this->mimeType.ToString(); - jsonObject["clockRate"] = this->clockRate; - - if (!this->rid.empty()) - jsonObject["rid"] = this->rid; - - jsonObject["cname"] = this->cname; - - if (this->rtxSsrc != 0) - { - jsonObject["rtxSsrc"] = this->rtxSsrc; - jsonObject["rtxPayloadType"] = this->rtxPayloadType; - } - - jsonObject["useNack"] = this->useNack; - jsonObject["usePli"] = this->usePli; - jsonObject["useFir"] = this->useFir; - jsonObject["useInBandFec"] = this->useInBandFec; - jsonObject["useDtx"] = this->useDtx; - jsonObject["spatialLayers"] = this->spatialLayers; - jsonObject["temporalLayers"] = this->temporalLayers; + return FBS::RtpStream::CreateParamsDirect( + builder, + this->encodingIdx, + this->ssrc, + this->payloadType, + this->mimeType.ToString().c_str(), + this->clockRate, + this->rid.c_str(), + this->cname.c_str(), + this->rtxSsrc != 0 ? flatbuffers::Optional(this->rtxSsrc) : flatbuffers::nullopt, + this->rtxSsrc != 0 ? flatbuffers::Optional(this->rtxPayloadType) : flatbuffers::nullopt, + this->useNack, + this->usePli, + this->useFir, + this->useInBandFec, + this->useDtx, + this->spatialLayers, + this->temporalLayers); } } // namespace RTC diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index b4b8fc2c0f..fd55c94618 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -158,9 +158,9 @@ namespace RTC size_t packetCount{ 0u }; - for (auto& spatialLayerCounter : this->spatialLayerCounters) + for (const auto& spatialLayerCounter : this->spatialLayerCounters) { - for (auto& temporalLayerCounter : spatialLayerCounter) + for (const auto& temporalLayerCounter : spatialLayerCounter) { packetCount += temporalLayerCounter.GetPacketCount(); } @@ -211,7 +211,7 @@ namespace RTC { // Run the RTP inactivity periodic timer (use a different timeout if DTX is // enabled). - this->inactivityCheckPeriodicTimer = new Timer(this); + this->inactivityCheckPeriodicTimer = new TimerHandle(this); this->inactivityCheckPeriodicTimer->Start( this->params.useDtx ? InactivityCheckIntervalWithDtx : InactivityCheckInterval); @@ -227,34 +227,41 @@ namespace RTC this->inactivityCheckPeriodicTimer = nullptr; } - void RtpStreamRecv::FillJsonStats(json& jsonObject) + flatbuffers::Offset RtpStreamRecv::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); const uint64_t nowMs = DepLibUV::GetTimeMs(); - RTC::RtpStream::FillJsonStats(jsonObject); + auto baseStats = RTC::RtpStream::FillBufferStats(builder); - jsonObject["type"] = "inbound-rtp"; - jsonObject["jitter"] = static_cast(this->jitter); - jsonObject["packetCount"] = this->transmissionCounter.GetPacketCount(); - jsonObject["byteCount"] = this->transmissionCounter.GetBytes(); - jsonObject["bitrate"] = this->transmissionCounter.GetBitrate(nowMs); + std::vector> bitrateByLayer; if (GetSpatialLayers() > 1 || GetTemporalLayers() > 1) { - jsonObject["bitrateByLayer"] = json::object(); - auto jsonBitrateByLayerIt = jsonObject.find("bitrateByLayer"); - for (uint8_t sIdx = 0; sIdx < GetSpatialLayers(); ++sIdx) { for (uint8_t tIdx = 0; tIdx < GetTemporalLayers(); ++tIdx) { - (*jsonBitrateByLayerIt)[std::to_string(sIdx) + "." + std::to_string(tIdx)] = - GetBitrate(nowMs, sIdx, tIdx); + auto layer = std::to_string(sIdx) + "." + std::to_string(tIdx); + + bitrateByLayer.emplace_back(FBS::RtpStream::CreateBitrateByLayerDirect( + builder, layer.c_str(), GetBitrate(nowMs, sIdx, tIdx))); } } } + + auto stats = FBS::RtpStream::CreateRecvStatsDirect( + builder, + baseStats, + static_cast(this->jitter), + this->transmissionCounter.GetPacketCount(), + this->transmissionCounter.GetBytes(), + this->transmissionCounter.GetBitrate(nowMs), + &bitrateByLayer); + + return FBS::RtpStream::CreateStats(builder, FBS::RtpStream::StatsData::RecvStats, stats.Union()); } bool RtpStreamRecv::ReceivePacket(RTC::RtpPacket* packet) @@ -846,7 +853,7 @@ namespace RTC // Nothing to do. } - inline void RtpStreamRecv::OnTimer(Timer* timer) + inline void RtpStreamRecv::OnTimer(TimerHandle* timer) { MS_TRACE(); diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index ebc8780d58..a76ce3fce4 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -51,11 +51,6 @@ namespace RTC break; } - - default: - { - MS_ABORT("codec mimeType not set"); - } } this->retransmissionBuffer = new RTC::RtpRetransmissionBuffer( @@ -72,18 +67,22 @@ namespace RTC this->retransmissionBuffer = nullptr; } - void RtpStreamSend::FillJsonStats(json& jsonObject) + flatbuffers::Offset RtpStreamSend::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); const uint64_t nowMs = DepLibUV::GetTimeMs(); - RTC::RtpStream::FillJsonStats(jsonObject); + auto baseStats = RTC::RtpStream::FillBufferStats(builder); + auto stats = FBS::RtpStream::CreateSendStats( + builder, + baseStats, + this->transmissionCounter.GetPacketCount(), + this->transmissionCounter.GetBytes(), + this->transmissionCounter.GetBitrate(nowMs)); - jsonObject["type"] = "outbound-rtp"; - jsonObject["packetCount"] = this->transmissionCounter.GetPacketCount(); - jsonObject["byteCount"] = this->transmissionCounter.GetBytes(); - jsonObject["bitrate"] = this->transmissionCounter.GetBitrate(nowMs); + return FBS::RtpStream::CreateStats(builder, FBS::RtpStream::StatsData::SendStats, stats.Union()); } void RtpStreamSend::SetRtx(uint8_t payloadType, uint32_t ssrc) diff --git a/worker/src/RTC/RtxStream.cpp b/worker/src/RTC/RtxStream.cpp index 44b5c3bc12..6f900906f4 100644 --- a/worker/src/RTC/RtxStream.cpp +++ b/worker/src/RTC/RtxStream.cpp @@ -28,12 +28,15 @@ namespace RTC MS_TRACE(); } - void RtxStream::FillJson(json& jsonObject) const + flatbuffers::Offset RtxStream::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Add params. - this->params.FillJson(jsonObject["params"]); + auto params = this->params.FillBuffer(builder); + + return FBS::RtxStream::CreateRtxDump(builder, params); } bool RtxStream::ReceivePacket(RTC::RtpPacket* packet) @@ -231,18 +234,18 @@ namespace RTC this->badSeq = RtpSeqMod + 1; // So seq == badSeq is false. } - void RtxStream::Params::FillJson(json& jsonObject) const + flatbuffers::Offset RtxStream::Params::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonObject["ssrc"] = this->ssrc; - jsonObject["payloadType"] = this->payloadType; - jsonObject["mimeType"] = this->mimeType.ToString(); - jsonObject["clockRate"] = this->clockRate; - - if (!this->rrid.empty()) - jsonObject["rrid"] = this->rrid; - - jsonObject["cname"] = this->cname; + return FBS::RtxStream::CreateParamsDirect( + builder, + this->ssrc, + this->payloadType, + this->mimeType.ToString().c_str(), + this->clockRate, + this->rrid.c_str(), + this->cname.c_str()); } } // namespace RTC diff --git a/worker/src/RTC/SctpAssociation.cpp b/worker/src/RTC/SctpAssociation.cpp index 8a5b6c2df6..13922f00c8 100644 --- a/worker/src/RTC/SctpAssociation.cpp +++ b/worker/src/RTC/SctpAssociation.cpp @@ -341,30 +341,27 @@ namespace RTC } } - void SctpAssociation::FillJson(json& jsonObject) const + flatbuffers::Offset SctpAssociation::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add port (always 5000). - jsonObject["port"] = 5000; - - // Add OS. - jsonObject["OS"] = this->os; - - // Add MIS. - jsonObject["MIS"] = this->mis; - - // Add maxMessageSize. - jsonObject["maxMessageSize"] = this->maxSctpMessageSize; - - // Add sendBufferSize. - jsonObject["sendBufferSize"] = this->sctpSendBufferSize; - - // Add sctpBufferedAmountLowThreshold. - jsonObject["sctpBufferedAmount"] = this->sctpBufferedAmount; - - // Add isDataChannel. - jsonObject["isDataChannel"] = this->isDataChannel; + return FBS::SctpParameters::CreateSctpParameters( + builder, + // Add port (always 5000). + 5000, + // Add OS. + this->os, + // Add MIS. + this->mis, + // Add maxMessageSize. + this->maxSctpMessageSize, + // Add sendBufferSize. + this->sctpSendBufferSize, + // Add sctpBufferedAmountLowThreshold. + this->sctpBufferedAmount, + // Add isDataChannel. + this->isDataChannel); } void SctpAssociation::ProcessSctpData(const uint8_t* data, size_t len) @@ -379,7 +376,7 @@ namespace RTC } void SctpAssociation::SendSctpMessage( - RTC::DataConsumer* dataConsumer, uint32_t ppid, const uint8_t* msg, size_t len, onQueuedCallback* cb) + RTC::DataConsumer* dataConsumer, const uint8_t* msg, size_t len, uint32_t ppid, onQueuedCallback* cb) { MS_TRACE(); @@ -691,7 +688,7 @@ namespace RTC { MS_DEBUG_DEV("directly notifying listener [eor:1, buffer len:0]"); - this->listener->OnSctpAssociationMessageReceived(this, streamId, ppid, data, len); + this->listener->OnSctpAssociationMessageReceived(this, streamId, data, len, ppid); } // If end of message and there is buffered data, append data and notify buffer. else if (eor && this->messageBufferLen != 0) @@ -702,7 +699,7 @@ namespace RTC MS_DEBUG_DEV("notifying listener [eor:1, buffer len:%zu]", this->messageBufferLen); this->listener->OnSctpAssociationMessageReceived( - this, streamId, ppid, this->messageBuffer, this->messageBufferLen); + this, streamId, this->messageBuffer, this->messageBufferLen, ppid); this->messageBufferLen = 0; } diff --git a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp index 5a6e4156c5..1634783876 100644 --- a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp +++ b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp @@ -10,23 +10,11 @@ namespace RTC { /* Instance methods. */ - SctpStreamParameters::SctpStreamParameters(json& data) + SctpStreamParameters::SctpStreamParameters(const FBS::SctpParameters::SctpStreamParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonStreamIdIt = data.find("streamId"); - auto jsonOrderedIdIt = data.find("ordered"); - auto jsonMaxPacketLifeTimeIt = data.find("maxPacketLifeTime"); - auto jsonMaxRetransmitsIt = data.find("maxRetransmits"); - - // streamId is mandatory. - if (jsonStreamIdIt == data.end() || !Utils::Json::IsPositiveInteger(*jsonStreamIdIt)) - MS_THROW_TYPE_ERROR("missing streamId"); - - this->streamId = jsonStreamIdIt->get(); + this->streamId = data->streamId(); if (this->streamId > 65534) MS_THROW_TYPE_ERROR("streamId must not be greater than 65534"); @@ -34,32 +22,22 @@ namespace RTC // ordered is optional. bool orderedGiven = false; - if (jsonOrderedIdIt != data.end() && jsonOrderedIdIt->is_boolean()) + if (data->ordered().has_value()) { orderedGiven = true; - this->ordered = jsonOrderedIdIt->get(); + this->ordered = data->ordered().value(); } // maxPacketLifeTime is optional. - // clang-format off - if ( - jsonMaxPacketLifeTimeIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonMaxPacketLifeTimeIt) - ) - // clang-format on + if (data->maxPacketLifeTime().has_value()) { - this->maxPacketLifeTime = jsonMaxPacketLifeTimeIt->get(); + this->maxPacketLifeTime = data->maxPacketLifeTime().value(); } // maxRetransmits is optional. - // clang-format off - if ( - jsonMaxRetransmitsIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonMaxRetransmitsIt) - ) - // clang-format on + if (data->maxRetransmits().has_value()) { - this->maxRetransmits = jsonMaxRetransmitsIt->get(); + this->maxRetransmits = data->maxRetransmits().value(); } if (this->maxPacketLifeTime && this->maxRetransmits) @@ -81,22 +59,18 @@ namespace RTC } } - void SctpStreamParameters::FillJson(json& jsonObject) const + flatbuffers::Offset SctpStreamParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add streamId. - jsonObject["streamId"] = this->streamId; - - // Add ordered. - jsonObject["ordered"] = this->ordered; - - // Add maxPacketLifeTime. - if (this->maxPacketLifeTime) - jsonObject["maxPacketLifeTime"] = this->maxPacketLifeTime; - - // Add maxRetransmits. - if (this->maxRetransmits) - jsonObject["maxRetransmits"] = this->maxRetransmits; + return FBS::SctpParameters::CreateSctpStreamParameters( + builder, + this->streamId, + this->ordered, + this->maxPacketLifeTime ? flatbuffers::Optional(this->maxPacketLifeTime) + : flatbuffers::nullopt, + this->maxRetransmits ? flatbuffers::Optional(this->maxRetransmits) + : flatbuffers::nullopt); } } // namespace RTC diff --git a/worker/src/RTC/SctpListener.cpp b/worker/src/RTC/SctpListener.cpp index 64300c6c0a..3daf7aa76f 100644 --- a/worker/src/RTC/SctpListener.cpp +++ b/worker/src/RTC/SctpListener.cpp @@ -10,22 +10,24 @@ namespace RTC { /* Instance methods. */ - void SctpListener::FillJson(json& jsonObject) const + flatbuffers::Offset SctpListener::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonObject["streamIdTable"] = json::object(); - - auto jsonStreamIdTableIt = jsonObject.find("streamIdTable"); - // Add streamIdTable. + std::vector> streamIdTable; + for (const auto& kv : this->streamIdTable) { auto streamId = kv.first; auto* dataProducer = kv.second; - (*jsonStreamIdTableIt)[std::to_string(streamId)] = dataProducer->id; + streamIdTable.emplace_back( + FBS::Common::CreateUint16StringDirect(builder, streamId, dataProducer->id.c_str())); } + + return FBS::Transport::CreateSctpListenerDirect(builder, &streamIdTable); } void SctpListener::AddDataProducer(RTC::DataProducer* dataProducer) diff --git a/worker/src/RTC/Shared.cpp b/worker/src/RTC/Shared.cpp index e984862df0..037eca59c8 100644 --- a/worker/src/RTC/Shared.cpp +++ b/worker/src/RTC/Shared.cpp @@ -7,11 +7,8 @@ namespace RTC { Shared::Shared( - ChannelMessageRegistrator* channelMessageRegistrator, - Channel::ChannelNotifier* channelNotifier, - PayloadChannel::PayloadChannelNotifier* payloadChannelNotifier) - : channelMessageRegistrator(channelMessageRegistrator), channelNotifier(channelNotifier), - payloadChannelNotifier(payloadChannelNotifier) + ChannelMessageRegistrator* channelMessageRegistrator, Channel::ChannelNotifier* channelNotifier) + : channelMessageRegistrator(channelMessageRegistrator), channelNotifier(channelNotifier) { MS_TRACE(); } @@ -22,6 +19,5 @@ namespace RTC delete this->channelMessageRegistrator; delete this->channelNotifier; - delete this->payloadChannelNotifier; } } // namespace RTC diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index 44463793c0..9f05f36dfe 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -1,11 +1,12 @@ +#include "FBS/consumer.h" #define MS_CLASS "RTC::SimpleConsumer" // #define MS_LOG_DEV_LEVEL 3 -#include "RTC/SimpleConsumer.hpp" #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "RTC/Codecs/Tools.hpp" +#include "RTC/SimpleConsumer.hpp" namespace RTC { @@ -16,7 +17,7 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data) + const FBS::Transport::ConsumeRequest* data) : RTC::Consumer::Consumer(shared, id, producerId, listener, data, RTC::RtpParameters::Type::SIMPLE) { MS_TRACE(); @@ -44,22 +45,15 @@ namespace RTC this->encodingContext.reset( RTC::Codecs::Tools::GetEncodingContext(mediaCodec->mimeType, params)); - auto jsonIgnoreDtx = data.find("ignoreDtx"); - - if (jsonIgnoreDtx != data.end() && jsonIgnoreDtx->is_boolean()) - { - auto ignoreDtx = jsonIgnoreDtx->get(); - - this->encodingContext->SetIgnoreDtx(ignoreDtx); - } + // ignoreDtx is set to false by default. + this->encodingContext->SetIgnoreDtx(data->ignoreDtx()); } // NOTE: This may throw. this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } SimpleConsumer::~SimpleConsumer() @@ -71,56 +65,73 @@ namespace RTC delete this->rtpStream; } - void SimpleConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset SimpleConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Call the parent method. - RTC::Consumer::FillJson(jsonObject); - + auto base = RTC::Consumer::FillBuffer(builder); // Add rtpStream. - this->rtpStream->FillJson(jsonObject["rtpStream"]); + std::vector> rtpStreams; + rtpStreams.emplace_back(this->rtpStream->FillBuffer(builder)); + + auto dump = FBS::Consumer::CreateConsumerDumpDirect(builder, base, &rtpStreams); + + return FBS::Consumer::CreateDumpResponse(builder, dump); } - void SimpleConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset SimpleConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + // Add stats of our send stream. - jsonArray.emplace_back(json::value_t::object); - this->rtpStream->FillJsonStats(jsonArray[0]); + rtpStreams.emplace_back(this->rtpStream->FillBufferStats(builder)); // Add stats of our recv stream. if (this->producerRtpStream) { - jsonArray.emplace_back(json::value_t::object); - this->producerRtpStream->FillJsonStats(jsonArray[1]); + rtpStreams.emplace_back(this->producerRtpStream->FillBufferStats(builder)); } + + return FBS::Consumer::CreateGetStatsResponseDirect(builder, &rtpStreams); } - void SimpleConsumer::FillJsonScore(json& jsonObject) const + flatbuffers::Offset SimpleConsumer::FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); MS_ASSERT(this->producerRtpStreamScores, "producerRtpStreamScores not set"); - jsonObject["score"] = this->rtpStream->GetScore(); + uint8_t producerScore{ 0 }; if (this->producerRtpStream) - jsonObject["producerScore"] = this->producerRtpStream->GetScore(); - else - jsonObject["producerScore"] = 0; + producerScore = this->producerRtpStream->GetScore(); - jsonObject["producerScores"] = *this->producerRtpStreamScores; + return FBS::Consumer::CreateConsumerScoreDirect( + builder, this->rtpStream->GetScore(), producerScore, this->producerRtpStreamScores); } void SimpleConsumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME: + case Channel::ChannelRequest::Method::CONSUMER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::Consumer_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) RequestKeyFrame(); @@ -130,11 +141,14 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS: + case Channel::ChannelRequest::Method::CONSUMER_SET_PREFERRED_LAYERS: { - // Do nothing. + // Accept with empty preferred layers object. - request->Accept(); + auto responseOffset = + FBS::Consumer::CreateSetPreferredLayersResponse(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::Consumer_SetPreferredLayersResponse, responseOffset); break; } @@ -636,11 +650,16 @@ namespace RTC { MS_TRACE(); - json data = json::object(); + auto scoreOffset = FillBufferScore(this->shared->channelNotifier->GetBufferBuilder()); - FillJsonScore(data); + auto notificationOffset = FBS::Consumer::CreateScoreNotification( + this->shared->channelNotifier->GetBufferBuilder(), scoreOffset); - this->shared->channelNotifier->Emit(this->id, "score", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_SCORE, + FBS::Notification::Body::Consumer_ScoreNotification, + notificationOffset); } inline void SimpleConsumer::OnRtpStreamScore( diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index a26f6bb2b9..20378a69a3 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -1,4 +1,3 @@ - #define MS_CLASS "RTC::SimulcastConsumer" // #define MS_LOG_DEV_LEVEL 3 @@ -25,7 +24,7 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data) + const FBS::Transport::ConsumeRequest* data) : RTC::Consumer::Consumer( shared, id, producerId, listener, data, RTC::RtpParameters::Type::SIMULCAST) { @@ -44,8 +43,6 @@ namespace RTC MS_THROW_TYPE_ERROR("encoding.spatialLayers does not match number of consumableRtpEncodings"); } - auto jsonPreferredLayersIt = data.find("preferredLayers"); - // Fill mapMappedSsrcSpatialLayer. for (size_t idx{ 0u }; idx < this->consumableRtpEncodings.size(); ++idx) { @@ -55,34 +52,18 @@ namespace RTC } // Set preferredLayers (if given). - if (jsonPreferredLayersIt != data.end() && jsonPreferredLayersIt->is_object()) + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeRequest::VT_PREFERREDLAYERS)) { - auto jsonSpatialLayerIt = jsonPreferredLayersIt->find("spatialLayer"); - auto jsonTemporalLayerIt = jsonPreferredLayersIt->find("temporalLayer"); + const auto* preferredLayers = data->preferredLayers(); - // clang-format off - if ( - jsonSpatialLayerIt == jsonPreferredLayersIt->end() || - !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing preferredLayers.spatialLayer"); - } - - this->preferredSpatialLayer = jsonSpatialLayerIt->get(); + this->preferredSpatialLayer = preferredLayers->spatialLayer(); if (this->preferredSpatialLayer > encoding.spatialLayers - 1) this->preferredSpatialLayer = encoding.spatialLayers - 1; - // clang-format off - if ( - jsonTemporalLayerIt != jsonPreferredLayersIt->end() && - Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) - ) - // clang-format on + if (preferredLayers->temporalLayer().has_value()) { - this->preferredTemporalLayer = jsonTemporalLayerIt->get(); + this->preferredTemporalLayer = preferredLayers->temporalLayer().value(); if (this->preferredTemporalLayer > encoding.temporalLayers - 1) this->preferredTemporalLayer = encoding.temporalLayers - 1; @@ -130,8 +111,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelRequestHandler*/ nullptr); } SimulcastConsumer::~SimulcastConsumer() @@ -143,54 +123,54 @@ namespace RTC delete this->rtpStream; } - void SimulcastConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset SimulcastConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Call the parent method. - RTC::Consumer::FillJson(jsonObject); - + auto base = RTC::Consumer::FillBuffer(builder); // Add rtpStream. - this->rtpStream->FillJson(jsonObject["rtpStream"]); - - // Add preferredSpatialLayer. - jsonObject["preferredSpatialLayer"] = this->preferredSpatialLayer; - - // Add targetSpatialLayer. - jsonObject["targetSpatialLayer"] = this->targetSpatialLayer; - - // Add currentSpatialLayer. - jsonObject["currentSpatialLayer"] = this->currentSpatialLayer; - - // Add preferredTemporalLayer. - jsonObject["preferredTemporalLayer"] = this->preferredTemporalLayer; - - // Add targetTemporalLayer. - jsonObject["targetTemporalLayer"] = this->targetTemporalLayer; + std::vector> rtpStreams; + rtpStreams.emplace_back(this->rtpStream->FillBuffer(builder)); + + auto dump = FBS::Consumer::CreateConsumerDumpDirect( + builder, + base, + &rtpStreams, + this->preferredSpatialLayer, + this->targetSpatialLayer, + this->currentSpatialLayer, + this->preferredTemporalLayer, + this->targetTemporalLayer, + this->encodingContext->GetCurrentTemporalLayer()); - // Add currentTemporalLayer. - jsonObject["currentTemporalLayer"] = this->encodingContext->GetCurrentTemporalLayer(); + return FBS::Consumer::CreateDumpResponse(builder, dump); } - void SimulcastConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset SimulcastConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + // Add stats of our send stream. - jsonArray.emplace_back(json::value_t::object); - this->rtpStream->FillJsonStats(jsonArray[0]); + rtpStreams.emplace_back(this->rtpStream->FillBufferStats(builder)); - // Add stats of our recv stream. auto* producerCurrentRtpStream = GetProducerCurrentRtpStream(); + // Add stats of our recv stream. if (producerCurrentRtpStream) { - jsonArray.emplace_back(json::value_t::object); - producerCurrentRtpStream->FillJsonStats(jsonArray[1]); + rtpStreams.emplace_back(producerCurrentRtpStream->FillBufferStats(builder)); } + + return FBS::Consumer::CreateGetStatsResponseDirect(builder, &rtpStreams); } - void SimulcastConsumer::FillJsonScore(json& jsonObject) const + flatbuffers::Offset SimulcastConsumer::FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); @@ -198,23 +178,33 @@ namespace RTC auto* producerCurrentRtpStream = GetProducerCurrentRtpStream(); - jsonObject["score"] = this->rtpStream->GetScore(); + uint8_t producerScore{ 0 }; if (producerCurrentRtpStream) - jsonObject["producerScore"] = producerCurrentRtpStream->GetScore(); + producerScore = producerCurrentRtpStream->GetScore(); else - jsonObject["producerScore"] = 0; + producerScore = 0; - jsonObject["producerScores"] = *this->producerRtpStreamScores; + return FBS::Consumer::CreateConsumerScoreDirect( + builder, this->rtpStream->GetScore(), producerScore, this->producerRtpStreamScores); } void SimulcastConsumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME: + case Channel::ChannelRequest::Method::CONSUMER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::Consumer_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) RequestKeyFrames(); @@ -224,39 +214,24 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS: + case Channel::ChannelRequest::Method::CONSUMER_SET_PREFERRED_LAYERS: { auto previousPreferredSpatialLayer = this->preferredSpatialLayer; auto previousPreferredTemporalLayer = this->preferredTemporalLayer; - auto jsonSpatialLayerIt = request->data.find("spatialLayer"); - auto jsonTemporalLayerIt = request->data.find("temporalLayer"); + const auto* body = request->data->body_as(); + const auto* preferredLayers = body->preferredLayers(); // Spatial layer. - // clang-format off - if ( - jsonSpatialLayerIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing spatialLayer"); - } - - this->preferredSpatialLayer = jsonSpatialLayerIt->get(); + this->preferredSpatialLayer = preferredLayers->spatialLayer(); if (this->preferredSpatialLayer > this->rtpStream->GetSpatialLayers() - 1) this->preferredSpatialLayer = this->rtpStream->GetSpatialLayers() - 1; // preferredTemporaLayer is optional. - // clang-format off - if ( - jsonTemporalLayerIt != request->data.end() && - Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) - ) - // clang-format on + if (preferredLayers->temporalLayer().has_value()) { - this->preferredTemporalLayer = jsonTemporalLayerIt->get(); + this->preferredTemporalLayer = preferredLayers->temporalLayer().value(); if (this->preferredTemporalLayer > this->rtpStream->GetTemporalLayers() - 1) this->preferredTemporalLayer = this->rtpStream->GetTemporalLayers() - 1; @@ -272,12 +247,13 @@ namespace RTC this->preferredTemporalLayer, this->id.c_str()); - json data = json::object(); - - data["spatialLayer"] = this->preferredSpatialLayer; - data["temporalLayer"] = this->preferredTemporalLayer; + const flatbuffers::Optional preferredTemporalLayer{ this->preferredTemporalLayer }; + auto preferredLayersOffset = FBS::Consumer::CreateConsumerLayers( + request->GetBufferBuilder(), this->preferredSpatialLayer, preferredTemporalLayer); + auto responseOffset = FBS::Consumer::CreateSetPreferredLayersResponse( + request->GetBufferBuilder(), preferredLayersOffset); - request->Accept(data); + request->Accept(FBS::Response::Body::Consumer_SetPreferredLayersResponse, responseOffset); // clang-format off if ( @@ -1507,11 +1483,16 @@ namespace RTC { MS_TRACE(); - json data = json::object(); + auto scoreOffset = FillBufferScore(this->shared->channelNotifier->GetBufferBuilder()); - FillJsonScore(data); + auto notificationOffset = FBS::Consumer::CreateScoreNotification( + this->shared->channelNotifier->GetBufferBuilder(), scoreOffset); - this->shared->channelNotifier->Emit(this->id, "score", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_SCORE, + FBS::Notification::Body::Consumer_ScoreNotification, + notificationOffset); } inline void SimulcastConsumer::EmitLayersChange() const @@ -1524,19 +1505,24 @@ namespace RTC this->encodingContext->GetCurrentTemporalLayer(), this->id.c_str()); - json data = json::object(); + flatbuffers::Offset layersOffset; if (this->currentSpatialLayer >= 0) { - data["spatialLayer"] = this->currentSpatialLayer; - data["temporalLayer"] = this->encodingContext->GetCurrentTemporalLayer(); - } - else - { - data = nullptr; + layersOffset = FBS::Consumer::CreateConsumerLayers( + this->shared->channelNotifier->GetBufferBuilder(), + this->currentSpatialLayer, + this->encodingContext->GetCurrentTemporalLayer()); } - this->shared->channelNotifier->Emit(this->id, "layerschange", data); + auto notificationOffset = FBS::Consumer::CreateLayersChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), layersOffset); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_LAYERS_CHANGE, + FBS::Notification::Body::Consumer_LayersChangeNotification, + notificationOffset); } inline RTC::RtpStreamRecv* SimulcastConsumer::GetProducerCurrentRtpStream() const diff --git a/worker/src/RTC/SrtpSession.cpp b/worker/src/RTC/SrtpSession.cpp index 97051e0cfd..ee400c07eb 100644 --- a/worker/src/RTC/SrtpSession.cpp +++ b/worker/src/RTC/SrtpSession.cpp @@ -28,6 +28,42 @@ namespace RTC } } + FBS::SrtpParameters::SrtpCryptoSuite SrtpSession::CryptoSuiteToFbs(CryptoSuite cryptoSuite) + { + switch (cryptoSuite) + { + case SrtpSession::CryptoSuite::AEAD_AES_256_GCM: + return FBS::SrtpParameters::SrtpCryptoSuite::AEAD_AES_256_GCM; + + case SrtpSession::CryptoSuite::AEAD_AES_128_GCM: + return FBS::SrtpParameters::SrtpCryptoSuite::AEAD_AES_128_GCM; + + case SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_80: + return FBS::SrtpParameters::SrtpCryptoSuite::AES_CM_128_HMAC_SHA1_80; + + case SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_32: + return FBS::SrtpParameters::SrtpCryptoSuite::AES_CM_128_HMAC_SHA1_32; + } + } + + SrtpSession::CryptoSuite SrtpSession::CryptoSuiteFromFbs(FBS::SrtpParameters::SrtpCryptoSuite cryptoSuite) + { + switch (cryptoSuite) + { + case FBS::SrtpParameters::SrtpCryptoSuite::AEAD_AES_256_GCM: + return SrtpSession::CryptoSuite::AEAD_AES_256_GCM; + + case FBS::SrtpParameters::SrtpCryptoSuite::AEAD_AES_128_GCM: + return SrtpSession::CryptoSuite::AEAD_AES_128_GCM; + + case FBS::SrtpParameters::SrtpCryptoSuite::AES_CM_128_HMAC_SHA1_80: + return SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_80; + + case FBS::SrtpParameters::SrtpCryptoSuite::AES_CM_128_HMAC_SHA1_32: + return SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_32; + } + } + void SrtpSession::OnSrtpEvent(srtp_event_data_t* data) { MS_TRACE(); diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index aadf4f8b63..9b3a18101e 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -22,7 +22,7 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data) + const FBS::Transport::ConsumeRequest* data) : RTC::Consumer::Consumer(shared, id, producerId, listener, data, RTC::RtpParameters::Type::SVC) { MS_TRACE(); @@ -37,38 +37,17 @@ namespace RTC if (encoding.spatialLayers < 2u && encoding.temporalLayers < 2u) MS_THROW_TYPE_ERROR("invalid number of layers"); - auto jsonPreferredLayersIt = data.find("preferredLayers"); - // Set preferredLayers (if given). - if (jsonPreferredLayersIt != data.end() && jsonPreferredLayersIt->is_object()) + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeRequest::VT_PREFERREDLAYERS)) { - auto jsonSpatialLayerIt = jsonPreferredLayersIt->find("spatialLayer"); - auto jsonTemporalLayerIt = jsonPreferredLayersIt->find("temporalLayer"); - - // clang-format off - if ( - jsonSpatialLayerIt == jsonPreferredLayersIt->end() || - !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing preferredLayers.spatialLayer"); - } - - this->preferredSpatialLayer = jsonSpatialLayerIt->get(); + this->preferredSpatialLayer = data->preferredLayers()->spatialLayer(); if (this->preferredSpatialLayer > encoding.spatialLayers - 1) this->preferredSpatialLayer = encoding.spatialLayers - 1; - // clang-format off - if ( - jsonTemporalLayerIt != jsonPreferredLayersIt->end() && - Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) - ) - // clang-format on + if (flatbuffers::IsFieldPresent( + data->preferredLayers(), FBS::Consumer::ConsumerLayers::VT_TEMPORALLAYER)) { - this->preferredTemporalLayer = jsonTemporalLayerIt->get(); - if (this->preferredTemporalLayer > encoding.temporalLayers - 1) this->preferredTemporalLayer = encoding.temporalLayers - 1; } @@ -110,8 +89,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } SvcConsumer::~SvcConsumer() @@ -123,74 +101,84 @@ namespace RTC delete this->rtpStream; } - void SvcConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset SvcConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Call the parent method. - RTC::Consumer::FillJson(jsonObject); - + auto base = RTC::Consumer::FillBuffer(builder); // Add rtpStream. - this->rtpStream->FillJson(jsonObject["rtpStream"]); - - // Add preferredSpatialLayer. - jsonObject["preferredSpatialLayer"] = this->preferredSpatialLayer; - - // Add targetSpatialLayer. - jsonObject["targetSpatialLayer"] = this->encodingContext->GetTargetSpatialLayer(); - - // Add currentSpatialLayer. - jsonObject["currentSpatialLayer"] = this->encodingContext->GetCurrentSpatialLayer(); - - // Add preferredTemporalLayer. - jsonObject["preferredTemporalLayer"] = this->preferredTemporalLayer; - - // Add targetTemporalLayer. - jsonObject["targetTemporalLayer"] = this->encodingContext->GetTargetTemporalLayer(); + std::vector> rtpStreams; + rtpStreams.emplace_back(this->rtpStream->FillBuffer(builder)); + + auto dump = FBS::Consumer::CreateConsumerDumpDirect( + builder, + base, + &rtpStreams, + this->preferredSpatialLayer, + this->encodingContext->GetTargetSpatialLayer(), + this->encodingContext->GetCurrentSpatialLayer(), + this->preferredTemporalLayer, + this->encodingContext->GetTargetTemporalLayer(), + this->encodingContext->GetCurrentTemporalLayer()); - // Add currentTemporalLayer. - jsonObject["currentTemporalLayer"] = this->encodingContext->GetCurrentTemporalLayer(); + return FBS::Consumer::CreateDumpResponse(builder, dump); } - void SvcConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset SvcConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + // Add stats of our send stream. - jsonArray.emplace_back(json::value_t::object); - this->rtpStream->FillJsonStats(jsonArray[0]); + rtpStreams.emplace_back(this->rtpStream->FillBufferStats(builder)); // Add stats of our recv stream. if (this->producerRtpStream) { - jsonArray.emplace_back(json::value_t::object); - this->producerRtpStream->FillJsonStats(jsonArray[1]); + rtpStreams.emplace_back(producerRtpStream->FillBufferStats(builder)); } + + return FBS::Consumer::CreateGetStatsResponseDirect(builder, &rtpStreams); } - void SvcConsumer::FillJsonScore(json& jsonObject) const + flatbuffers::Offset SvcConsumer::FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); MS_ASSERT(this->producerRtpStreamScores, "producerRtpStreamScores not set"); - jsonObject["score"] = this->rtpStream->GetScore(); + uint8_t producerScore{ 0 }; if (this->producerRtpStream) - jsonObject["producerScore"] = this->producerRtpStream->GetScore(); + producerScore = this->producerRtpStream->GetScore(); else - jsonObject["producerScore"] = 0; + producerScore = 0; - jsonObject["producerScores"] = *this->producerRtpStreamScores; + return FBS::Consumer::CreateConsumerScoreDirect( + builder, this->rtpStream->GetScore(), producerScore, this->producerRtpStreamScores); } void SvcConsumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME: + case Channel::ChannelRequest::Method::CONSUMER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::Consumer_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) RequestKeyFrame(); @@ -200,39 +188,24 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS: + case Channel::ChannelRequest::Method::CONSUMER_SET_PREFERRED_LAYERS: { auto previousPreferredSpatialLayer = this->preferredSpatialLayer; auto previousPreferredTemporalLayer = this->preferredTemporalLayer; - auto jsonSpatialLayerIt = request->data.find("spatialLayer"); - auto jsonTemporalLayerIt = request->data.find("temporalLayer"); + const auto* body = request->data->body_as(); + const auto* preferredLayers = body->preferredLayers(); // Spatial layer. - // clang-format off - if ( - jsonSpatialLayerIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing spatialLayer"); - } - - this->preferredSpatialLayer = jsonSpatialLayerIt->get(); + this->preferredSpatialLayer = preferredLayers->spatialLayer(); if (this->preferredSpatialLayer > this->rtpStream->GetSpatialLayers() - 1) this->preferredSpatialLayer = this->rtpStream->GetSpatialLayers() - 1; // preferredTemporaLayer is optional. - // clang-format off - if ( - jsonTemporalLayerIt != request->data.end() && - Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) - ) - // clang-format on + if (preferredLayers->temporalLayer().has_value()) { - this->preferredTemporalLayer = jsonTemporalLayerIt->get(); + this->preferredTemporalLayer = preferredLayers->temporalLayer().value(); if (this->preferredTemporalLayer > this->rtpStream->GetTemporalLayers() - 1) this->preferredTemporalLayer = this->rtpStream->GetTemporalLayers() - 1; @@ -248,12 +221,13 @@ namespace RTC this->preferredTemporalLayer, this->id.c_str()); - json data = json::object(); - - data["spatialLayer"] = this->preferredSpatialLayer; - data["temporalLayer"] = this->preferredTemporalLayer; + const flatbuffers::Optional preferredTemporalLayer{ this->preferredTemporalLayer }; + auto preferredLayersOffset = FBS::Consumer::CreateConsumerLayers( + request->GetBufferBuilder(), this->preferredSpatialLayer, preferredTemporalLayer); + auto responseOffset = FBS::Consumer::CreateSetPreferredLayersResponse( + request->GetBufferBuilder(), preferredLayersOffset); - request->Accept(data); + request->Accept(FBS::Response::Body::Consumer_SetPreferredLayersResponse, responseOffset); // clang-format off if ( @@ -1139,11 +1113,16 @@ namespace RTC { MS_TRACE(); - json data = json::object(); + auto scoreOffset = FillBufferScore(this->shared->channelNotifier->GetBufferBuilder()); - FillJsonScore(data); + auto notificationOffset = FBS::Consumer::CreateScoreNotification( + this->shared->channelNotifier->GetBufferBuilder(), scoreOffset); - this->shared->channelNotifier->Emit(this->id, "score", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_SCORE, + FBS::Notification::Body::Consumer_ScoreNotification, + notificationOffset); } inline void SvcConsumer::EmitLayersChange() const @@ -1156,19 +1135,24 @@ namespace RTC this->encodingContext->GetCurrentTemporalLayer(), this->id.c_str()); - json data = json::object(); + flatbuffers::Offset layersOffset; if (this->encodingContext->GetCurrentSpatialLayer() >= 0) { - data["spatialLayer"] = this->encodingContext->GetCurrentSpatialLayer(); - data["temporalLayer"] = this->encodingContext->GetCurrentTemporalLayer(); - } - else - { - data = nullptr; + layersOffset = FBS::Consumer::CreateConsumerLayers( + this->shared->channelNotifier->GetBufferBuilder(), + this->encodingContext->GetCurrentSpatialLayer(), + this->encodingContext->GetCurrentTemporalLayer()); } - this->shared->channelNotifier->Emit(this->id, "layerschange", data); + auto notificationOffset = FBS::Consumer::CreateLayersChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), layersOffset); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_LAYERS_CHANGE, + FBS::Notification::Body::Consumer_LayersChangeNotification, + notificationOffset); } inline void SvcConsumer::OnRtpStreamScore( diff --git a/worker/src/RTC/TcpConnection.cpp b/worker/src/RTC/TcpConnection.cpp index b13cfd430c..143447367f 100644 --- a/worker/src/RTC/TcpConnection.cpp +++ b/worker/src/RTC/TcpConnection.cpp @@ -16,7 +16,7 @@ namespace RTC /* Instance methods. */ TcpConnection::TcpConnection(Listener* listener, size_t bufferSize) - : ::TcpConnectionHandler::TcpConnectionHandler(bufferSize), listener(listener) + : ::TcpConnectionHandle::TcpConnectionHandle(bufferSize), listener(listener) { MS_TRACE(); } @@ -154,7 +154,7 @@ namespace RTC } } - void TcpConnection::Send(const uint8_t* data, size_t len, ::TcpConnectionHandler::onSendCallback* cb) + void TcpConnection::Send(const uint8_t* data, size_t len, ::TcpConnectionHandle::onSendCallback* cb) { MS_TRACE(); @@ -163,6 +163,6 @@ namespace RTC uint8_t frameLen[2]; Utils::Byte::Set2Bytes(frameLen, 0, len); - ::TcpConnectionHandler::Write(frameLen, 2, data, len, cb); + ::TcpConnectionHandle::Write(frameLen, 2, data, len, cb); } } // namespace RTC diff --git a/worker/src/RTC/TcpServer.cpp b/worker/src/RTC/TcpServer.cpp index 3d502c9d69..ddd1d2da82 100644 --- a/worker/src/RTC/TcpServer.cpp +++ b/worker/src/RTC/TcpServer.cpp @@ -12,7 +12,7 @@ namespace RTC TcpServer::TcpServer(Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip) : // This may throw. - ::TcpServerHandler::TcpServerHandler(RTC::PortManager::BindTcp(ip)), listener(listener), + ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip)), listener(listener), connListener(connListener) { MS_TRACE(); @@ -21,7 +21,7 @@ namespace RTC TcpServer::TcpServer( Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, uint16_t port) : // This may throw. - ::TcpServerHandler::TcpServerHandler(RTC::PortManager::BindTcp(ip, port)), listener(listener), + ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, port)), listener(listener), connListener(connListener), fixedPort(true) { MS_TRACE(); @@ -48,7 +48,7 @@ namespace RTC AcceptTcpConnection(connection); } - void TcpServer::UserOnTcpConnectionClosed(::TcpConnectionHandler* connection) + void TcpServer::UserOnTcpConnectionClosed(::TcpConnectionHandle* connection) { MS_TRACE(); diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index a99915b71c..e4c39263ff 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -1,10 +1,11 @@ +#include "flatbuffers/stl_emulation.h" #define MS_CLASS "RTC::Transport" // #define MS_LOG_DEV_LEVEL 3 -#include "RTC/Transport.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" +#include "FBS/transport.h" #include "RTC/BweType.hpp" #include "RTC/PipeConsumer.hpp" #include "RTC/RTCP/FeedbackPs.hpp" @@ -18,6 +19,7 @@ #include "RTC/SimpleConsumer.hpp" #include "RTC/SimulcastConsumer.hpp" #include "RTC/SvcConsumer.hpp" +#include "RTC/Transport.hpp" #include // webrtc::RtpPacketSendInfo #include // std::ostream_iterator #include // std::multimap @@ -30,152 +32,81 @@ namespace RTC /* Instance methods. */ - Transport::Transport(RTC::Shared* shared, const std::string& id, Listener* listener, json& data) + Transport::Transport( + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::Transport::Options* options) : id(id), shared(shared), listener(listener), recvRtxTransmission(1000u), sendRtxTransmission(1000u), sendProbationTransmission(100u) { MS_TRACE(); - auto jsonDirectIt = data.find("direct"); - - // clang-format off - if ( - jsonDirectIt != data.end() && - jsonDirectIt->is_boolean() && - jsonDirectIt->get() - ) - // clang-format on + if (options->direct()) { this->direct = true; - auto jsonMaxMessageSizeIt = data.find("maxMessageSize"); - - // maxMessageSize is mandatory for direct Transports. - // clang-format off - if ( - jsonMaxMessageSizeIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonMaxMessageSizeIt) - ) - // clang-format on + if (options->maxMessageSize().has_value()) { - MS_THROW_TYPE_ERROR("wrong maxMessageSize (not a number)"); + this->maxMessageSize = options->maxMessageSize().value(); } - - this->maxMessageSize = jsonMaxMessageSizeIt->get(); } - auto jsonInitialAvailableOutgoingBitrateIt = data.find("initialAvailableOutgoingBitrate"); - - if (jsonInitialAvailableOutgoingBitrateIt != data.end()) + if (options->initialAvailableOutgoingBitrate().has_value()) { - if (!Utils::Json::IsPositiveInteger(*jsonInitialAvailableOutgoingBitrateIt)) - { - MS_THROW_TYPE_ERROR("wrong initialAvailableOutgoingBitrate (not a number)"); - } - - this->initialAvailableOutgoingBitrate = jsonInitialAvailableOutgoingBitrateIt->get(); + this->initialAvailableOutgoingBitrate = options->initialAvailableOutgoingBitrate().value(); } - auto jsonEnableSctpIt = data.find("enableSctp"); - - // clang-format off - if ( - jsonEnableSctpIt != data.end() && - jsonEnableSctpIt->is_boolean() && - jsonEnableSctpIt->get() - ) - // clang-format on + if (options->enableSctp()) { if (this->direct) { MS_THROW_TYPE_ERROR("cannot enable SCTP in a direct Transport"); } - auto jsonNumSctpStreamsIt = data.find("numSctpStreams"); - auto jsonMaxSctpMessageSizeIt = data.find("maxSctpMessageSize"); - auto jsonSctpSendBufferSizeIt = data.find("sctpSendBufferSize"); - auto jsonIsDataChannelIt = data.find("isDataChannel"); - // numSctpStreams is mandatory. - // clang-format off - if ( - jsonNumSctpStreamsIt == data.end() || - !jsonNumSctpStreamsIt->is_object() - ) - // clang-format on + if (!flatbuffers::IsFieldPresent(options, FBS::Transport::Options::VT_NUMSCTPSTREAMS)) { - MS_THROW_TYPE_ERROR("wrong numSctpStreams (not an object)"); + MS_THROW_TYPE_ERROR("numSctpStreams missing"); } - auto jsonOSIt = jsonNumSctpStreamsIt->find("OS"); - auto jsonMISIt = jsonNumSctpStreamsIt->find("MIS"); - - // numSctpStreams.OS and numSctpStreams.MIS are mandatory. - // clang-format off - if ( - jsonOSIt == jsonNumSctpStreamsIt->end() || - !Utils::Json::IsPositiveInteger(*jsonOSIt) || - jsonMISIt == jsonNumSctpStreamsIt->end() || - !Utils::Json::IsPositiveInteger(*jsonMISIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("wrong numSctpStreams.OS and/or numSctpStreams.MIS (not a number)"); - } - - auto os = jsonOSIt->get(); - auto mis = jsonMISIt->get(); - // maxSctpMessageSize is mandatory. - // clang-format off - if ( - jsonMaxSctpMessageSizeIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonMaxSctpMessageSizeIt) - ) - // clang-format on + if (!flatbuffers::IsFieldPresent(options, FBS::Transport::Options::VT_MAXSCTPMESSAGESIZE)) { - MS_THROW_TYPE_ERROR("wrong maxSctpMessageSize (not a number)"); + MS_THROW_TYPE_ERROR("maxSctpMessageSize missing"); } - this->maxMessageSize = jsonMaxSctpMessageSizeIt->get(); + this->maxMessageSize = options->maxSctpMessageSize(); size_t sctpSendBufferSize; // sctpSendBufferSize is optional. - if (jsonSctpSendBufferSizeIt != data.end()) + if (flatbuffers::IsFieldPresent(options, FBS::Transport::Options::VT_SCTPSENDBUFFERSIZE)) { - if (!Utils::Json::IsPositiveInteger(*jsonSctpSendBufferSizeIt)) - { - MS_THROW_TYPE_ERROR("wrong sctpSendBufferSize (not a number)"); - } - - sctpSendBufferSize = jsonSctpSendBufferSizeIt->get(); - - if (sctpSendBufferSize > MaxSctpSendBufferSize) + if (options->sctpSendBufferSize() > MaxSctpSendBufferSize) { MS_THROW_TYPE_ERROR("wrong sctpSendBufferSize (maximum value exceeded)"); } + + sctpSendBufferSize = options->sctpSendBufferSize(); } else { sctpSendBufferSize = DefaultSctpSendBufferSize; } - // isDataChannel is optional. - bool isDataChannel{ false }; - - if (jsonIsDataChannelIt != data.end() && jsonIsDataChannelIt->is_boolean()) - { - isDataChannel = jsonIsDataChannelIt->get(); - } - // This may throw. this->sctpAssociation = new RTC::SctpAssociation( - this, os, mis, this->maxMessageSize, sctpSendBufferSize, isDataChannel); + this, + options->numSctpStreams()->os(), + options->numSctpStreams()->mis(), + this->maxMessageSize, + sctpSendBufferSize, + options->isDataChannel()); } // Create the RTCP timer. - this->rtcpTimer = new Timer(this); + this->rtcpTimer = new TimerHandle(this); } Transport::~Transport() @@ -300,189 +231,171 @@ namespace RTC this->listener->OnTransportListenServerClosed(this); } - void Transport::FillJson(json& jsonObject) const + flatbuffers::Offset Transport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add direct. - jsonObject["direct"] = this->direct; - // Add producerIds. - jsonObject["producerIds"] = json::array(); - auto jsonProducerIdsIt = jsonObject.find("producerIds"); + std::vector> producerIds; for (const auto& kv : this->mapProducers) { const auto& producerId = kv.first; - jsonProducerIdsIt->emplace_back(producerId); + producerIds.emplace_back(builder.CreateString(producerId)); } // Add consumerIds. - jsonObject["consumerIds"] = json::array(); - auto jsonConsumerIdsIt = jsonObject.find("consumerIds"); + std::vector> consumerIds; for (const auto& kv : this->mapConsumers) { const auto& consumerId = kv.first; - jsonConsumerIdsIt->emplace_back(consumerId); + consumerIds.emplace_back(builder.CreateString(consumerId)); } // Add mapSsrcConsumerId. - jsonObject["mapSsrcConsumerId"] = json::object(); - auto jsonMapSsrcConsumerId = jsonObject.find("mapSsrcConsumerId"); + std::vector> mapSsrcConsumerId; for (const auto& kv : this->mapSsrcConsumer) { auto ssrc = kv.first; auto* consumer = kv.second; - (*jsonMapSsrcConsumerId)[std::to_string(ssrc)] = consumer->id; + mapSsrcConsumerId.emplace_back( + FBS::Common::CreateUint32StringDirect(builder, ssrc, consumer->id.c_str())); } // Add mapRtxSsrcConsumerId. - jsonObject["mapRtxSsrcConsumerId"] = json::object(); - auto jsonMapRtxSsrcConsumerId = jsonObject.find("mapRtxSsrcConsumerId"); + std::vector> mapRtxSsrcConsumerId; for (const auto& kv : this->mapRtxSsrcConsumer) { auto ssrc = kv.first; auto* consumer = kv.second; - (*jsonMapRtxSsrcConsumerId)[std::to_string(ssrc)] = consumer->id; + mapRtxSsrcConsumerId.emplace_back( + FBS::Common::CreateUint32StringDirect(builder, ssrc, consumer->id.c_str())); } // Add dataProducerIds. - jsonObject["dataProducerIds"] = json::array(); - auto jsonDataProducerIdsIt = jsonObject.find("dataProducerIds"); + std::vector> dataProducerIds; for (const auto& kv : this->mapDataProducers) { const auto& dataProducerId = kv.first; - jsonDataProducerIdsIt->emplace_back(dataProducerId); + dataProducerIds.emplace_back(builder.CreateString(dataProducerId)); } // Add dataConsumerIds. - jsonObject["dataConsumerIds"] = json::array(); - auto jsonDataConsumerIdsIt = jsonObject.find("dataConsumerIds"); + std::vector> dataConsumerIds; for (const auto& kv : this->mapDataConsumers) { const auto& dataConsumerId = kv.first; - jsonDataConsumerIdsIt->emplace_back(dataConsumerId); + dataConsumerIds.emplace_back(builder.CreateString(dataConsumerId)); } // Add headerExtensionIds. - jsonObject["recvRtpHeaderExtensions"] = json::object(); - auto jsonRtpHeaderExtensionsIt = jsonObject.find("recvRtpHeaderExtensions"); - - if (this->recvRtpHeaderExtensionIds.mid != 0u) - { - (*jsonRtpHeaderExtensionsIt)["mid"] = this->recvRtpHeaderExtensionIds.mid; - } - - if (this->recvRtpHeaderExtensionIds.rid != 0u) - { - (*jsonRtpHeaderExtensionsIt)["rid"] = this->recvRtpHeaderExtensionIds.rid; - } - - if (this->recvRtpHeaderExtensionIds.rrid != 0u) - { - (*jsonRtpHeaderExtensionsIt)["rrid"] = this->recvRtpHeaderExtensionIds.rrid; - } - - if (this->recvRtpHeaderExtensionIds.absSendTime != 0u) - { - (*jsonRtpHeaderExtensionsIt)["absSendTime"] = this->recvRtpHeaderExtensionIds.absSendTime; - } - - if (this->recvRtpHeaderExtensionIds.transportWideCc01 != 0u) - { - (*jsonRtpHeaderExtensionsIt)["transportWideCc01"] = - this->recvRtpHeaderExtensionIds.transportWideCc01; - } - - // Add rtpListener. - this->rtpListener.FillJson(jsonObject["rtpListener"]); - - // Add maxMessageSize. - jsonObject["maxMessageSize"] = this->maxMessageSize; + auto recvRtpHeaderExtensions = FBS::Transport::CreateRecvRtpHeaderExtensions( + builder, + this->recvRtpHeaderExtensionIds.mid != 0u + ? flatbuffers::Optional(this->recvRtpHeaderExtensionIds.mid) + : flatbuffers::nullopt, + this->recvRtpHeaderExtensionIds.rid != 0u + ? flatbuffers::Optional(this->recvRtpHeaderExtensionIds.rid) + : flatbuffers::nullopt, + this->recvRtpHeaderExtensionIds.rrid != 0u + ? flatbuffers::Optional(this->recvRtpHeaderExtensionIds.rrid) + : flatbuffers::nullopt, + this->recvRtpHeaderExtensionIds.absSendTime != 0u + ? flatbuffers::Optional(this->recvRtpHeaderExtensionIds.absSendTime) + : flatbuffers::nullopt, + this->recvRtpHeaderExtensionIds.transportWideCc01 != 0u + ? flatbuffers::Optional(this->recvRtpHeaderExtensionIds.transportWideCc01) + : flatbuffers::nullopt); + + auto rtpListenerOffset = this->rtpListener.FillBuffer(builder); + + // Add sctpParameters. + flatbuffers::Offset sctpParameters; + // Add sctpState. + FBS::SctpAssociation::SctpState sctpState; + // Add sctpListener. + flatbuffers::Offset sctpListener; if (this->sctpAssociation) { // Add sctpParameters. - this->sctpAssociation->FillJson(jsonObject["sctpParameters"]); + sctpParameters = this->sctpAssociation->FillBuffer(builder); - // Add sctpState. switch (this->sctpAssociation->GetState()) { case RTC::SctpAssociation::SctpState::NEW: - jsonObject["sctpState"] = "new"; + sctpState = FBS::SctpAssociation::SctpState::NEW; break; case RTC::SctpAssociation::SctpState::CONNECTING: - jsonObject["sctpState"] = "connecting"; + sctpState = FBS::SctpAssociation::SctpState::CONNECTING; break; case RTC::SctpAssociation::SctpState::CONNECTED: - jsonObject["sctpState"] = "connected"; + sctpState = FBS::SctpAssociation::SctpState::CONNECTED; break; case RTC::SctpAssociation::SctpState::FAILED: - jsonObject["sctpState"] = "failed"; + sctpState = FBS::SctpAssociation::SctpState::FAILED; break; case RTC::SctpAssociation::SctpState::CLOSED: - jsonObject["sctpState"] = "closed"; + sctpState = FBS::SctpAssociation::SctpState::CLOSED; break; } - // Add sctpListener. - this->sctpListener.FillJson(jsonObject["sctpListener"]); + sctpListener = this->sctpListener.FillBuffer(builder); } // Add traceEventTypes. - std::vector traceEventTypes; - std::ostringstream traceEventTypesStream; + std::vector traceEventTypes; if (this->traceEventTypes.probation) { - traceEventTypes.emplace_back("probation"); + traceEventTypes.emplace_back(FBS::Transport::TraceEventType::PROBATION); } - if (this->traceEventTypes.bwe) { - traceEventTypes.emplace_back("bwe"); - } - - if (!traceEventTypes.empty()) - { - std::copy( - traceEventTypes.begin(), - traceEventTypes.end() - 1, - std::ostream_iterator(traceEventTypesStream, ",")); - traceEventTypesStream << traceEventTypes.back(); - } - - jsonObject["traceEventTypes"] = traceEventTypesStream.str(); + traceEventTypes.emplace_back(FBS::Transport::TraceEventType::BWE); + } + + return FBS::Transport::CreateDumpDirect( + builder, + this->id.c_str(), + this->direct, + &producerIds, + &consumerIds, + &mapSsrcConsumerId, + &mapRtxSsrcConsumerId, + &dataProducerIds, + &dataConsumerIds, + recvRtpHeaderExtensions, + rtpListenerOffset, + this->maxMessageSize, + sctpParameters, + this->sctpAssociation ? flatbuffers::Optional(sctpState) + : flatbuffers::nullopt, + sctpListener, + &traceEventTypes); } - void Transport::FillJsonStats(json& jsonArray) + flatbuffers::Offset Transport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); auto nowMs = DepLibUV::GetTimeMs(); - jsonArray.emplace_back(json::value_t::object); - auto& jsonObject = jsonArray[0]; - - // Add transportId. - jsonObject["transportId"] = this->id; - - // Add timestamp. - jsonObject["timestamp"] = nowMs; + // Add sctpState. + FBS::SctpAssociation::SctpState sctpState; if (this->sctpAssociation) { @@ -490,139 +403,94 @@ namespace RTC switch (this->sctpAssociation->GetState()) { case RTC::SctpAssociation::SctpState::NEW: - jsonObject["sctpState"] = "new"; + sctpState = FBS::SctpAssociation::SctpState::NEW; break; case RTC::SctpAssociation::SctpState::CONNECTING: - jsonObject["sctpState"] = "connecting"; + sctpState = FBS::SctpAssociation::SctpState::CONNECTING; break; case RTC::SctpAssociation::SctpState::CONNECTED: - jsonObject["sctpState"] = "connected"; + sctpState = FBS::SctpAssociation::SctpState::CONNECTED; break; case RTC::SctpAssociation::SctpState::FAILED: - jsonObject["sctpState"] = "failed"; + sctpState = FBS::SctpAssociation::SctpState::FAILED; break; case RTC::SctpAssociation::SctpState::CLOSED: - jsonObject["sctpState"] = "closed"; + sctpState = FBS::SctpAssociation::SctpState::CLOSED; break; } } - // Add bytesReceived. - jsonObject["bytesReceived"] = this->recvTransmission.GetBytes(); - - // Add recvBitrate. - jsonObject["recvBitrate"] = this->recvTransmission.GetRate(nowMs); - - // Add bytesSent. - jsonObject["bytesSent"] = this->sendTransmission.GetBytes(); - - // Add sendBitrate. - jsonObject["sendBitrate"] = this->sendTransmission.GetRate(nowMs); - - // Add rtpBytesReceived. - jsonObject["rtpBytesReceived"] = this->recvRtpTransmission.GetBytes(); - - // Add rtpRecvBitrate. - jsonObject["rtpRecvBitrate"] = this->recvRtpTransmission.GetBitrate(nowMs); - - // Add rtpBytesSent. - jsonObject["rtpBytesSent"] = this->sendRtpTransmission.GetBytes(); - - // Add rtpSendBitrate. - jsonObject["rtpSendBitrate"] = this->sendRtpTransmission.GetBitrate(nowMs); - - // Add rtxBytesReceived. - jsonObject["rtxBytesReceived"] = this->recvRtxTransmission.GetBytes(); - - // Add rtxRecvBitrate. - jsonObject["rtxRecvBitrate"] = this->recvRtxTransmission.GetBitrate(nowMs); - - // Add rtxBytesSent. - jsonObject["rtxBytesSent"] = this->sendRtxTransmission.GetBytes(); - - // Add rtxSendBitrate. - jsonObject["rtxSendBitrate"] = this->sendRtxTransmission.GetBitrate(nowMs); - - // Add probationBytesSent. - jsonObject["probationBytesSent"] = this->sendProbationTransmission.GetBytes(); - - // Add probationSendBitrate. - jsonObject["probationSendBitrate"] = this->sendProbationTransmission.GetBitrate(nowMs); - - // Add availableOutgoingBitrate. - if (this->tccClient) - { - jsonObject["availableOutgoingBitrate"] = this->tccClient->GetAvailableBitrate(); - } - - // Add availableIncomingBitrate. - if (this->tccServer && this->tccServer->GetAvailableBitrate() != 0u) - { - jsonObject["availableIncomingBitrate"] = this->tccServer->GetAvailableBitrate(); - } - - // Add maxIncomingBitrate. - if (this->maxIncomingBitrate != 0u) - { - jsonObject["maxIncomingBitrate"] = this->maxIncomingBitrate; - } - - // Add packetLossReceived. - if (this->tccServer) - { - jsonObject["rtpPacketLossReceived"] = this->tccServer->GetPacketLoss(); - } - - // Add packetLossSent. - if (this->tccClient) - { - jsonObject["rtpPacketLossSent"] = this->tccClient->GetPacketLoss(); - } + return FBS::Transport::CreateStatsDirect( + builder, + // transportId. + this->id.c_str(), + // timestamp. + nowMs, + // sctpState. + this->sctpAssociation ? flatbuffers::Optional(sctpState) + : flatbuffers::nullopt, + // bytesReceived. + this->recvTransmission.GetBytes(), + // recvBitrate. + this->recvTransmission.GetRate(nowMs), + // bytesSent. + this->sendTransmission.GetBytes(), + // sendBitrate. + this->sendTransmission.GetRate(nowMs), + // rtpBytesReceived. + this->recvRtpTransmission.GetBytes(), + // rtpRecvBitrate. + this->recvRtpTransmission.GetBitrate(nowMs), + // rtpBytesSent. + this->sendRtpTransmission.GetBytes(), + // rtpSendBitrate. + this->sendRtpTransmission.GetBitrate(nowMs), + // rtxBytesReceived. + this->recvRtxTransmission.GetBytes(), + // rtxRecvBitrate. + this->recvRtxTransmission.GetBitrate(nowMs), + // rtxBytesSent. + this->sendRtxTransmission.GetBytes(), + // rtxSendBitrate. + this->sendRtxTransmission.GetBitrate(nowMs), + // probationBytesSent. + this->sendProbationTransmission.GetBytes(), + // probationSendBitrate. + this->sendProbationTransmission.GetBitrate(nowMs), + // availableOutgoingBitrate. + this->tccClient ? flatbuffers::Optional(this->tccClient->GetAvailableBitrate()) + : flatbuffers::nullopt, + // availableIncomingBitrate. + this->tccServer ? flatbuffers::Optional(this->tccServer->GetAvailableBitrate()) + : flatbuffers::nullopt, + // maxIncomingBitrate. + this->maxIncomingBitrate ? flatbuffers::Optional(this->maxIncomingBitrate) + : flatbuffers::nullopt, + // maxOutgoingBitrate. + this->maxOutgoingBitrate ? flatbuffers::Optional(this->maxOutgoingBitrate) + : flatbuffers::nullopt, + // minOutgoingBitrate. + this->minOutgoingBitrate ? flatbuffers::Optional(this->minOutgoingBitrate) + : flatbuffers::nullopt, + // packetLossReceived. + this->tccServer ? flatbuffers::Optional(this->tccServer->GetPacketLoss()) + : flatbuffers::nullopt, + // packetLossSent. + this->tccClient ? flatbuffers::Optional(this->tccClient->GetPacketLoss()) + : flatbuffers::nullopt); } void Transport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::TRANSPORT_DUMP: - { - json data = json::object(); - - FillJson(data); - - request->Accept(data); - - break; - } - - case Channel::ChannelRequest::MethodId::TRANSPORT_GET_STATS: + case Channel::ChannelRequest::Method::TRANSPORT_SET_MAX_INCOMING_BITRATE: { - json data = json::array(); - - FillJsonStats(data); - - request->Accept(data); - - break; - } + const auto* body = request->data->body_as(); - case Channel::ChannelRequest::MethodId::TRANSPORT_SET_MAX_INCOMING_BITRATE: - { - auto jsonBitrateIt = request->data.find("bitrate"); - - // clang-format off - if ( - jsonBitrateIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonBitrateIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing bitrate"); - } - - this->maxIncomingBitrate = jsonBitrateIt->get(); + this->maxIncomingBitrate = body->maxIncomingBitrate(); MS_DEBUG_TAG(bwe, "maximum incoming bitrate set to %" PRIu32, this->maxIncomingBitrate); @@ -636,21 +504,10 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_SET_MAX_OUTGOING_BITRATE: + case Channel::ChannelRequest::Method::TRANSPORT_SET_MAX_OUTGOING_BITRATE: { - auto jsonBitrateIt = request->data.find("bitrate"); - - // clang-format off - if ( - jsonBitrateIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonBitrateIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing bitrate"); - } - - const uint32_t bitrate = jsonBitrateIt->get(); + const auto* body = request->data->body_as(); + const uint32_t bitrate = body->maxOutgoingBitrate(); if (bitrate > 0u && bitrate < RTC::TransportCongestionControlMinOutgoingBitrate) { @@ -686,21 +543,10 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_SET_MIN_OUTGOING_BITRATE: + case Channel::ChannelRequest::Method::TRANSPORT_SET_MIN_OUTGOING_BITRATE: { - auto jsonBitrateIt = request->data.find("bitrate"); - - // clang-format off - if ( - jsonBitrateIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonBitrateIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing bitrate"); - } - - const uint32_t bitrate = jsonBitrateIt->get(); + const auto* body = request->data->body_as(); + const uint32_t bitrate = body->minOutgoingBitrate(); if (bitrate > 0u && bitrate < RTC::TransportCongestionControlMinOutgoingBitrate) { @@ -736,15 +582,18 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_PRODUCE: + case Channel::ChannelRequest::Method::TRANSPORT_PRODUCE: { - std::string producerId; + const auto* body = request->data->body_as(); + auto producerId = body->producerId()->str(); - // This may throw. - SetNewProducerIdFromData(request->data, producerId); + if (this->mapProducers.find(producerId) != this->mapProducers.end()) + { + MS_THROW_ERROR("a Producer with same producerId already exists"); + } // This may throw. - auto* producer = new RTC::Producer(this->shared, producerId, this, request->data); + auto* producer = new RTC::Producer(this->shared, producerId, this, body); // Insert the Producer into the RtpListener. // This may throw. If so, delete the Producer and throw. @@ -812,11 +661,10 @@ namespace RTC } // Create status response. - json data = json::object(); - - data["type"] = RTC::RtpParameters::GetTypeString(producer->GetType()); + auto responseOffset = FBS::Transport::CreateProduceResponse( + request->GetBufferBuilder(), FBS::RtpParameters::Type(producer->GetType())); - request->Accept(data); + request->Accept(FBS::Response::Body::Transport_ProduceResponse, responseOffset); // Check if TransportCongestionControlServer or REMB server must be // created. @@ -898,48 +746,27 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CONSUME: + case Channel::ChannelRequest::Method::TRANSPORT_CONSUME: { - auto jsonProducerIdIt = request->data.find("producerId"); - - if (jsonProducerIdIt == request->data.end() || !jsonProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing producerId"); - } - - std::string producerId = jsonProducerIdIt->get(); - std::string consumerId; - - // This may throw. - SetNewConsumerIdFromData(request->data, consumerId); - - // Get type. - auto jsonTypeIt = request->data.find("type"); + const auto* body = request->data->body_as(); + const std::string producerId = body->producerId()->str(); + const std::string consumerId = body->consumerId()->str(); - if (jsonTypeIt == request->data.end() || !jsonTypeIt->is_string()) + if (this->mapConsumers.find(consumerId) != this->mapConsumers.end()) { - MS_THROW_TYPE_ERROR("missing type"); + MS_THROW_ERROR("a Consumer with same consumerId already exists"); } - // This may throw. - auto type = RTC::RtpParameters::GetType(jsonTypeIt->get()); + auto type = RTC::RtpParameters::Type(body->type()); RTC::Consumer* consumer{ nullptr }; switch (type) { - case RTC::RtpParameters::Type::NONE: - { - MS_THROW_TYPE_ERROR("invalid type 'none'"); - - break; - } - case RTC::RtpParameters::Type::SIMPLE: { // This may throw. - consumer = - new RTC::SimpleConsumer(this->shared, consumerId, producerId, this, request->data); + consumer = new RTC::SimpleConsumer(this->shared, consumerId, producerId, this, body); break; } @@ -947,8 +774,7 @@ namespace RTC case RTC::RtpParameters::Type::SIMULCAST: { // This may throw. - consumer = - new RTC::SimulcastConsumer(this->shared, consumerId, producerId, this, request->data); + consumer = new RTC::SimulcastConsumer(this->shared, consumerId, producerId, this, body); break; } @@ -956,8 +782,7 @@ namespace RTC case RTC::RtpParameters::Type::SVC: { // This may throw. - consumer = - new RTC::SvcConsumer(this->shared, consumerId, producerId, this, request->data); + consumer = new RTC::SvcConsumer(this->shared, consumerId, producerId, this, body); break; } @@ -965,8 +790,7 @@ namespace RTC case RTC::RtpParameters::Type::PIPE: { // This may throw. - consumer = - new RTC::PipeConsumer(this->shared, consumerId, producerId, this, request->data); + consumer = new RTC::PipeConsumer(this->shared, consumerId, producerId, this, body); break; } @@ -1001,23 +825,25 @@ namespace RTC MS_DEBUG_DEV( "Consumer created [consumerId:%s, producerId:%s]", consumerId.c_str(), producerId.c_str()); - // Create status response. - json data = json::object(); - - data["paused"] = consumer->IsPaused(); - data["producerPaused"] = consumer->IsProducerPaused(); - - consumer->FillJsonScore(data["score"]); - + flatbuffers::Offset preferredLayersOffset; auto preferredLayers = consumer->GetPreferredLayers(); if (preferredLayers.spatial > -1 && preferredLayers.temporal > -1) { - data["preferredLayers"]["spatialLayer"] = preferredLayers.spatial; - data["preferredLayers"]["temporalLayer"] = preferredLayers.temporal; + const flatbuffers::Optional preferredTemporalLayer{ preferredLayers.temporal }; + preferredLayersOffset = FBS::Consumer::CreateConsumerLayers( + request->GetBufferBuilder(), preferredLayers.spatial, preferredTemporalLayer); } - request->Accept(data); + auto scoreOffset = consumer->FillBufferScore(request->GetBufferBuilder()); + auto responseOffset = FBS::Transport::CreateConsumeResponse( + request->GetBufferBuilder(), + consumer->IsPaused(), + consumer->IsProducerPaused(), + scoreOffset, + preferredLayersOffset); + + request->Accept(FBS::Response::Body::Transport_ConsumeResponse, responseOffset); // Check if Transport Congestion Control client must be created. const auto& rtpHeaderExtensionIds = consumer->GetRtpHeaderExtensionIds(); @@ -1035,19 +861,19 @@ namespace RTC // - there is "transport-cc" in codecs RTCP feedback. // // clang-format off - if ( - consumer->GetKind() == RTC::Media::Kind::VIDEO && - rtpHeaderExtensionIds.transportWideCc01 != 0u && - std::any_of( - codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) - { - return std::any_of( - codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + if ( + consumer->GetKind() == RTC::Media::Kind::VIDEO && + rtpHeaderExtensionIds.transportWideCc01 != 0u && + std::any_of( + codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) { - return fb.type == "transport-cc"; - }); - }) - ) + return std::any_of( + codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + { + return fb.type == "transport-cc"; + }); + }) + ) // clang-format on { MS_DEBUG_TAG(bwe, "enabling TransportCongestionControlClient with transport-cc"); @@ -1061,19 +887,19 @@ namespace RTC // - there is "remb" in codecs RTCP feedback. // // clang-format off - else if ( - consumer->GetKind() == RTC::Media::Kind::VIDEO && - rtpHeaderExtensionIds.absSendTime != 0u && - std::any_of( - codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) - { - return std::any_of( - codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + else if ( + consumer->GetKind() == RTC::Media::Kind::VIDEO && + rtpHeaderExtensionIds.absSendTime != 0u && + std::any_of( + codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) { - return fb.type == "goog-remb"; - }); - }) - ) + return std::any_of( + codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + { + return fb.type == "goog-remb"; + }); + }) + ) // clang-format on { MS_DEBUG_TAG(bwe, "enabling TransportCongestionControlClient with REMB"); @@ -1121,20 +947,20 @@ namespace RTC // - there is "transport-cc" in codecs RTCP feedback. // // clang-format off - if ( - !this->senderBwe && - consumer->GetKind() == RTC::Media::Kind::VIDEO && - rtpHeaderExtensionIds.transportWideCc01 != 0u && - std::any_of( - codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) - { - return std::any_of( - codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + if ( + !this->senderBwe && + consumer->GetKind() == RTC::Media::Kind::VIDEO && + rtpHeaderExtensionIds.transportWideCc01 != 0u && + std::any_of( + codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) { - return fb.type == "transport-cc"; - }); - }) - ) + return std::any_of( + codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + { + return fb.type == "transport-cc"; + }); + }) + ) // clang-format on { MS_DEBUG_TAG(bwe, "enabling SenderBandwidthEstimator"); @@ -1172,7 +998,7 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_PRODUCE_DATA: + case Channel::ChannelRequest::Method::TRANSPORT_PRODUCE_DATA: { // Early check. The Transport must support SCTP or be direct. if (!this->sctpAssociation && !this->direct) @@ -1180,14 +1006,16 @@ namespace RTC MS_THROW_ERROR("SCTP not enabled and not a direct Transport"); } - std::string dataProducerId; + const auto* body = request->data->body_as(); + + auto dataProducerId = body->dataProducerId()->str(); // This may throw. - SetNewDataProducerIdFromData(request->data, dataProducerId); + CheckNoDataProducer(dataProducerId); // This may throw. - auto* dataProducer = new RTC::DataProducer( - this->shared, dataProducerId, this->maxMessageSize, this, request->data); + auto* dataProducer = + new RTC::DataProducer(this->shared, dataProducerId, this->maxMessageSize, this, body); // Verify the type of the DataProducer. switch (dataProducer->GetType()) @@ -1260,16 +1088,14 @@ namespace RTC MS_DEBUG_DEV("DataProducer created [dataProducerId:%s]", dataProducerId.c_str()); - json data = json::object(); - - dataProducer->FillJson(data); + auto dumpOffset = dataProducer->FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::DataProducer_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CONSUME_DATA: + case Channel::ChannelRequest::Method::TRANSPORT_CONSUME_DATA: { // Early check. The Transport must support SCTP or be direct. if (!this->sctpAssociation && !this->direct) @@ -1277,18 +1103,13 @@ namespace RTC MS_THROW_ERROR("SCTP not enabled and not a direct Transport"); } - auto jsonDataProducerIdIt = request->data.find("dataProducerId"); + const auto* body = request->data->body_as(); - if (jsonDataProducerIdIt == request->data.end() || !jsonDataProducerIdIt->is_string()) - { - MS_THROW_ERROR("missing dataProducerId"); - } - - std::string dataProducerId = jsonDataProducerIdIt->get(); - std::string dataConsumerId; + auto dataProducerId = body->dataProducerId()->str(); + auto dataConsumerId = body->dataConsumerId()->str(); // This may throw. - SetNewDataConsumerIdFromData(request->data, dataConsumerId); + CheckNoDataConsumer(dataConsumerId); // This may throw. auto* dataConsumer = new RTC::DataConsumer( @@ -1297,7 +1118,7 @@ namespace RTC dataProducerId, this->sctpAssociation, this, - request->data, + body, this->maxMessageSize); // Verify the type of the DataConsumer. @@ -1353,11 +1174,9 @@ namespace RTC dataConsumerId.c_str(), dataProducerId.c_str()); - json data = json::object(); - - dataConsumer->FillJson(data); + auto dumpOffset = dataConsumer->FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::DataConsumer_DumpResponse, dumpOffset); if (IsConnected()) { @@ -1378,35 +1197,30 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_ENABLE_TRACE_EVENT: + case Channel::ChannelRequest::Method::TRANSPORT_ENABLE_TRACE_EVENT: { - auto jsonTypesIt = request->data.find("types"); - - // Disable all if no entries. - if (jsonTypesIt == request->data.end() || !jsonTypesIt->is_array()) - { - MS_THROW_TYPE_ERROR("wrong types (not an array)"); - } + const auto* body = request->data->body_as(); // Reset traceEventTypes. struct TraceEventTypes newTraceEventTypes; - for (const auto& type : *jsonTypesIt) + for (const auto& type : *body->events()) { - if (!type.is_string()) + switch (type) { - MS_THROW_TYPE_ERROR("wrong type (not a string)"); - } + case FBS::Transport::TraceEventType::PROBATION: + { + newTraceEventTypes.probation = true; + + break; + } - const std::string typeStr = type.get(); + case FBS::Transport::TraceEventType::BWE: + { + newTraceEventTypes.bwe = true; - if (typeStr == "probation") - { - newTraceEventTypes.probation = true; - } - if (typeStr == "bwe") - { - newTraceEventTypes.bwe = true; + break; + } } } @@ -1417,10 +1231,12 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CLOSE_PRODUCER: + case Channel::ChannelRequest::Method::TRANSPORT_CLOSE_PRODUCER: { + const auto* body = request->data->body_as(); + // This may throw. - RTC::Producer* producer = GetProducerFromData(request->data); + RTC::Producer* producer = GetProducerById(body->producerId()->str()); // Remove it from the RtpListener. this->rtpListener.RemoveProducer(producer); @@ -1454,10 +1270,12 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CLOSE_CONSUMER: + case Channel::ChannelRequest::Method::TRANSPORT_CLOSE_CONSUMER: { + const auto* body = request->data->body_as(); + // This may throw. - RTC::Consumer* consumer = GetConsumerFromData(request->data); + RTC::Consumer* consumer = GetConsumerById(body->consumerId()->str()); // Remove it from the maps. this->mapConsumers.erase(consumer->id); @@ -1498,10 +1316,12 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CLOSE_DATA_PRODUCER: + case Channel::ChannelRequest::Method::TRANSPORT_CLOSE_DATAPRODUCER: { + const auto* body = request->data->body_as(); + // This may throw. - RTC::DataProducer* dataProducer = GetDataProducerFromData(request->data); + RTC::DataProducer* dataProducer = GetDataProducerById(body->dataProducerId()->str()); if (dataProducer->GetType() == RTC::DataProducer::Type::SCTP) { @@ -1531,10 +1351,12 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CLOSE_DATA_CONSUMER: + case Channel::ChannelRequest::Method::TRANSPORT_CLOSE_DATACONSUMER: { + const auto* body = request->data->body_as(); + // This may throw. - RTC::DataConsumer* dataConsumer = GetDataConsumerFromData(request->data); + RTC::DataConsumer* dataConsumer = GetDataConsumerById(body->dataConsumerId()->str()); // Remove it from the maps. this->mapDataConsumers.erase(dataConsumer->id); @@ -1560,33 +1382,30 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } - } - void Transport::HandleRequest(PayloadChannel::PayloadChannelRequest* request) - { - MS_TRACE(); + return; - switch (request->methodId) + switch (request->method) { default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_ERROR("unknown method"); } } } - void Transport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void Transport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - switch (notification->eventId) + switch (notification->event) { default: { - MS_ERROR("unknown event '%s'", notification->event.c_str()); + MS_ERROR("unknown event '%s'", notification->eventCStr); } } } @@ -1793,88 +1612,50 @@ namespace RTC this->sctpAssociation->ProcessSctpData(data, len); } - void Transport::SetNewProducerIdFromData(json& data, std::string& producerId) const + void Transport::CheckNoDataProducer(const std::string& dataProducerId) const { - MS_TRACE(); - - auto jsonProducerIdIt = data.find("producerId"); - - if (jsonProducerIdIt == data.end() || !jsonProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing producerId"); - } - - producerId.assign(jsonProducerIdIt->get()); - - if (this->mapProducers.find(producerId) != this->mapProducers.end()) + if (this->mapDataProducers.find(dataProducerId) != this->mapDataProducers.end()) { - MS_THROW_ERROR("a Producer with same producerId already exists"); + MS_THROW_ERROR("a DataProducer with same dataProducerId already exists"); } } - RTC::Producer* Transport::GetProducerFromData(json& data) const + void Transport::CheckNoDataConsumer(const std::string& dataConsumerId) const { MS_TRACE(); - auto jsonProducerIdIt = data.find("producerId"); - - if (jsonProducerIdIt == data.end() || !jsonProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing producerId"); - } - - auto it = this->mapProducers.find(jsonProducerIdIt->get()); - - if (it == this->mapProducers.end()) + if (this->mapDataConsumers.find(dataConsumerId) != this->mapDataConsumers.end()) { - MS_THROW_ERROR("Producer not found"); + MS_THROW_ERROR("a DataConsumer with same dataConsumerId already exists"); } - - RTC::Producer* producer = it->second; - - return producer; } - void Transport::SetNewConsumerIdFromData(json& data, std::string& consumerId) const + RTC::Producer* Transport::GetProducerById(const std::string& producerId) const { MS_TRACE(); - auto jsonConsumerIdIt = data.find("consumerId"); + auto it = this->mapProducers.find(producerId); - if (jsonConsumerIdIt == data.end() || !jsonConsumerIdIt->is_string()) + if (it == this->mapProducers.end()) { - MS_THROW_TYPE_ERROR("missing consumerId"); + MS_THROW_ERROR("Producer not found"); } - consumerId.assign(jsonConsumerIdIt->get()); - - if (this->mapConsumers.find(consumerId) != this->mapConsumers.end()) - { - MS_THROW_ERROR("a Consumer with same consumerId already exists"); - } + return it->second; } - RTC::Consumer* Transport::GetConsumerFromData(json& data) const + RTC::Consumer* Transport::GetConsumerById(const std::string& consumerId) const { MS_TRACE(); - auto jsonConsumerIdIt = data.find("consumerId"); - - if (jsonConsumerIdIt == data.end() || !jsonConsumerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing consumerId"); - } - - auto it = this->mapConsumers.find(jsonConsumerIdIt->get()); + auto it = this->mapConsumers.find(consumerId); if (it == this->mapConsumers.end()) { MS_THROW_ERROR("Consumer not found"); } - RTC::Consumer* consumer = it->second; - - return consumer; + return it->second; } inline RTC::Consumer* Transport::GetConsumerByMediaSsrc(uint32_t ssrc) const @@ -1909,88 +1690,32 @@ namespace RTC return consumer; } - void Transport::SetNewDataProducerIdFromData(json& data, std::string& dataProducerId) const - { - MS_TRACE(); - - auto jsonDataProducerIdIt = data.find("dataProducerId"); - - if (jsonDataProducerIdIt == data.end() || !jsonDataProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing dataProducerId"); - } - - dataProducerId.assign(jsonDataProducerIdIt->get()); - - if (this->mapDataProducers.find(dataProducerId) != this->mapDataProducers.end()) - { - MS_THROW_ERROR("a DataProducer with same dataProducerId already exists"); - } - } - - RTC::DataProducer* Transport::GetDataProducerFromData(json& data) const + RTC::DataProducer* Transport::GetDataProducerById(const std::string& dataProducerId) const { MS_TRACE(); - auto jsonDataProducerIdIt = data.find("dataProducerId"); - - if (jsonDataProducerIdIt == data.end() || !jsonDataProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing dataProducerId"); - } - - auto it = this->mapDataProducers.find(jsonDataProducerIdIt->get()); + auto it = this->mapDataProducers.find(dataProducerId); if (it == this->mapDataProducers.end()) { MS_THROW_ERROR("DataProducer not found"); } - RTC::DataProducer* dataProducer = it->second; - - return dataProducer; - } - - void Transport::SetNewDataConsumerIdFromData(json& data, std::string& dataConsumerId) const - { - MS_TRACE(); - - auto jsonDataConsumerIdIt = data.find("dataConsumerId"); - - if (jsonDataConsumerIdIt == data.end() || !jsonDataConsumerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing dataConsumerId"); - } - - dataConsumerId.assign(jsonDataConsumerIdIt->get()); - - if (this->mapDataConsumers.find(dataConsumerId) != this->mapDataConsumers.end()) - { - MS_THROW_ERROR("a DataConsumer with same dataConsumerId already exists"); - } + return it->second; } - RTC::DataConsumer* Transport::GetDataConsumerFromData(json& data) const + RTC::DataConsumer* Transport::GetDataConsumerById(const std::string& dataConsumerId) const { MS_TRACE(); - auto jsonDataConsumerIdIt = data.find("dataConsumerId"); - - if (jsonDataConsumerIdIt == data.end() || !jsonDataConsumerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing dataConsumerId"); - } - - auto it = this->mapDataConsumers.find(jsonDataConsumerIdIt->get()); + auto it = this->mapDataConsumers.find(dataConsumerId); if (it == this->mapDataConsumers.end()) { MS_THROW_ERROR("DataConsumer not found"); } - RTC::DataConsumer* dataConsumer = it->second; - - return dataConsumer; + return it->second; } void Transport::HandleRtcpPacket(RTC::RTCP::Packet* packet) @@ -2559,15 +2284,18 @@ namespace RTC return; } - json data = json::object(); - - data["type"] = "probation"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; + // TODO: Missing trace info (RTP packet dump). + auto notification = FBS::Transport::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Transport::TraceEventType::PROBATION, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_OUT); - packet->FillJson(data["info"]); - - this->shared->channelNotifier->Emit(this->id, "trace", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_TRACE, + FBS::Notification::Body::Transport_TraceNotification, + notification); } inline void Transport::EmitTraceEventBweType( @@ -2580,30 +2308,32 @@ namespace RTC return; } - json data = json::object(); - - data["type"] = "bwe"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - data["info"]["desiredBitrate"] = bitrates.desiredBitrate; - data["info"]["effectiveDesiredBitrate"] = bitrates.effectiveDesiredBitrate; - data["info"]["minBitrate"] = bitrates.minBitrate; - data["info"]["maxBitrate"] = bitrates.maxBitrate; - data["info"]["startBitrate"] = bitrates.startBitrate; - data["info"]["maxPaddingBitrate"] = bitrates.maxPaddingBitrate; - data["info"]["availableBitrate"] = bitrates.availableBitrate; - - switch (this->tccClient->GetBweType()) - { - case RTC::BweType::TRANSPORT_CC: - data["info"]["type"] = "transport-cc"; - break; - case RTC::BweType::REMB: - data["info"]["type"] = "remb"; - break; - } - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto traceInfo = FBS::Transport::CreateBweTraceInfo( + this->shared->channelNotifier->GetBufferBuilder(), + this->tccClient->GetBweType() == RTC::BweType::TRANSPORT_CC + ? FBS::Transport::BweType::TRANSPORT_CC + : FBS::Transport::BweType::REMB, + bitrates.desiredBitrate, + bitrates.effectiveDesiredBitrate, + bitrates.minBitrate, + bitrates.maxBitrate, + bitrates.startBitrate, + bitrates.maxPaddingBitrate, + bitrates.availableBitrate); + + auto notification = FBS::Transport::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Transport::TraceEventType::BWE, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_OUT, + FBS::Transport::TraceInfo::BweTraceInfo, + traceInfo.Union()); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_TRACE, + FBS::Notification::Body::Transport_TraceNotification, + notification); } inline void Transport::OnProducerPaused(RTC::Producer* producer) @@ -2926,19 +2656,39 @@ namespace RTC } inline void Transport::OnDataProducerMessageReceived( - RTC::DataProducer* dataProducer, uint32_t ppid, const uint8_t* msg, size_t len) + RTC::DataProducer* dataProducer, + const uint8_t* msg, + size_t len, + uint32_t ppid, + std::vector& subchannels, + std::optional requiredSubchannel) + { + MS_TRACE(); + + this->listener->OnTransportDataProducerMessageReceived( + this, dataProducer, msg, len, ppid, subchannels, requiredSubchannel); + } + + inline void Transport::OnDataProducerPaused(RTC::DataProducer* dataProducer) + { + MS_TRACE(); + + this->listener->OnTransportDataProducerPaused(this, dataProducer); + } + + inline void Transport::OnDataProducerResumed(RTC::DataProducer* dataProducer) { MS_TRACE(); - this->listener->OnTransportDataProducerMessageReceived(this, dataProducer, ppid, msg, len); + this->listener->OnTransportDataProducerResumed(this, dataProducer); } inline void Transport::OnDataConsumerSendMessage( - RTC::DataConsumer* dataConsumer, uint32_t ppid, const uint8_t* msg, size_t len, onQueuedCallback* cb) + RTC::DataConsumer* dataConsumer, const uint8_t* msg, size_t len, uint32_t ppid, onQueuedCallback* cb) { MS_TRACE(); - SendMessage(dataConsumer, ppid, msg, len, cb); + SendMessage(dataConsumer, msg, len, ppid, cb); } inline void Transport::OnDataConsumerDataProducerClosed(RTC::DataConsumer* dataConsumer) @@ -2966,11 +2716,14 @@ namespace RTC MS_TRACE(); // Notify the Node Transport. - json data = json::object(); - - data["sctpState"] = "connecting"; - - this->shared->channelNotifier->Emit(this->id, "sctpstatechange", data); + auto sctpStateChangeOffset = FBS::Transport::CreateSctpStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::SctpAssociation::SctpState::CONNECTING); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_SCTP_STATE_CHANGE, + FBS::Notification::Body::Transport_SctpStateChangeNotification, + sctpStateChangeOffset); } inline void Transport::OnSctpAssociationConnected(RTC::SctpAssociation* /*sctpAssociation*/) @@ -2989,11 +2742,14 @@ namespace RTC } // Notify the Node Transport. - json data = json::object(); - - data["sctpState"] = "connected"; - - this->shared->channelNotifier->Emit(this->id, "sctpstatechange", data); + auto sctpStateChangeOffset = FBS::Transport::CreateSctpStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::SctpAssociation::SctpState::CONNECTED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_SCTP_STATE_CHANGE, + FBS::Notification::Body::Transport_SctpStateChangeNotification, + sctpStateChangeOffset); } inline void Transport::OnSctpAssociationFailed(RTC::SctpAssociation* /*sctpAssociation*/) @@ -3012,11 +2768,14 @@ namespace RTC } // Notify the Node Transport. - json data = json::object(); - - data["sctpState"] = "failed"; - - this->shared->channelNotifier->Emit(this->id, "sctpstatechange", data); + auto sctpStateChangeOffset = FBS::Transport::CreateSctpStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::SctpAssociation::SctpState::FAILED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_SCTP_STATE_CHANGE, + FBS::Notification::Body::Transport_SctpStateChangeNotification, + sctpStateChangeOffset); } inline void Transport::OnSctpAssociationClosed(RTC::SctpAssociation* /*sctpAssociation*/) @@ -3035,11 +2794,14 @@ namespace RTC } // Notify the Node Transport. - json data = json::object(); - - data["sctpState"] = "closed"; - - this->shared->channelNotifier->Emit(this->id, "sctpstatechange", data); + auto sctpStateChangeOffset = FBS::Transport::CreateSctpStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::SctpAssociation::SctpState::CLOSED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_SCTP_STATE_CHANGE, + FBS::Notification::Body::Transport_SctpStateChangeNotification, + sctpStateChangeOffset); } inline void Transport::OnSctpAssociationSendData( @@ -3065,9 +2827,9 @@ namespace RTC inline void Transport::OnSctpAssociationMessageReceived( RTC::SctpAssociation* /*sctpAssociation*/, uint16_t streamId, - uint32_t ppid, const uint8_t* msg, - size_t len) + size_t len, + uint32_t ppid) { MS_TRACE(); @@ -3084,7 +2846,10 @@ namespace RTC // Pass the SCTP message to the corresponding DataProducer. try { - dataProducer->ReceiveMessage(ppid, msg, len); + static std::vector EmptySubchannels; + + dataProducer->ReceiveMessage( + msg, len, ppid, EmptySubchannels, /*requiredSubchannel*/ std::nullopt); } catch (std::exception& error) { @@ -3257,7 +3022,7 @@ namespace RTC } #endif - inline void Transport::OnTimer(Timer* timer) + inline void Transport::OnTimer(TimerHandle* timer) { MS_TRACE(); diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index 2a0d35badd..380fb34edb 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -73,7 +73,7 @@ namespace RTC // videos are muted or using screensharing with still images) this->rtpTransportControllerSend->EnablePeriodicAlrProbing(true); - this->processTimer = new Timer(this); + this->processTimer = new TimerHandle(this); // clang-format off this->processTimer->Start(std::min( @@ -556,7 +556,7 @@ namespace RTC return this->probationGenerator->GetNextPacket(size); } - void TransportCongestionControlClient::OnTimer(Timer* timer) + void TransportCongestionControlClient::OnTimer(TimerHandle* timer) { MS_TRACE(); diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index 8c7a016949..98ed26a575 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -38,7 +38,7 @@ namespace RTC this->transportCcFeedbackPacket->SetFeedbackPacketCount(this->transportCcFeedbackPacketCount); // Create the feedback send periodic timer. - this->transportCcFeedbackSendPeriodicTimer = new Timer(this); + this->transportCcFeedbackSendPeriodicTimer = new TimerHandle(this); break; } @@ -383,7 +383,7 @@ namespace RTC this->listener->OnTransportCongestionControlServerSendRtcpPacket(this, &packet); } - inline void TransportCongestionControlServer::OnTimer(Timer* timer) + inline void TransportCongestionControlServer::OnTimer(TimerHandle* timer) { MS_TRACE(); diff --git a/worker/src/RTC/TransportTuple.cpp b/worker/src/RTC/TransportTuple.cpp index ab8dce24b2..12f045e49c 100644 --- a/worker/src/RTC/TransportTuple.cpp +++ b/worker/src/RTC/TransportTuple.cpp @@ -7,46 +7,56 @@ namespace RTC { + /* Static methods. */ + + TransportTuple::Protocol TransportTuple::ProtocolFromFbs(FBS::Transport::Protocol protocol) + { + switch (protocol) + { + case FBS::Transport::Protocol::UDP: + return TransportTuple::Protocol::UDP; + + case FBS::Transport::Protocol::TCP: + return TransportTuple::Protocol::TCP; + } + } + + FBS::Transport::Protocol TransportTuple::ProtocolToFbs(TransportTuple::Protocol protocol) + { + switch (protocol) + { + case TransportTuple::Protocol::UDP: + return FBS::Transport::Protocol::UDP; + + case TransportTuple::Protocol::TCP: + return FBS::Transport::Protocol::TCP; + } + } + /* Instance methods. */ - void TransportTuple::FillJson(json& jsonObject) const + flatbuffers::Offset TransportTuple::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); int family; - std::string ip; - uint16_t port; + std::string localIp; + uint16_t localPort; - Utils::IP::GetAddressInfo(GetLocalAddress(), family, ip, port); + Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort); - // Add localIp. - if (this->localAnnouncedIp.empty()) - jsonObject["localIp"] = ip; - else - jsonObject["localIp"] = this->localAnnouncedIp; + localIp = this->localAnnouncedIp.empty() ? localIp : this->localAnnouncedIp; - // Add localPort. - jsonObject["localPort"] = port; + std::string remoteIp; + uint16_t remotePort; - Utils::IP::GetAddressInfo(GetRemoteAddress(), family, ip, port); + Utils::IP::GetAddressInfo(GetRemoteAddress(), family, remoteIp, remotePort); - // Add remoteIp. - jsonObject["remoteIp"] = ip; + auto protocol = TransportTuple::ProtocolToFbs(GetProtocol()); - // Add remotePort. - jsonObject["remotePort"] = port; - - // Add protocol. - switch (GetProtocol()) - { - case Protocol::UDP: - jsonObject["protocol"] = "udp"; - break; - - case Protocol::TCP: - jsonObject["protocol"] = "tcp"; - break; - } + return FBS::Transport::CreateTupleDirect( + builder, localIp.c_str(), localPort, remoteIp.c_str(), remotePort, protocol); } void TransportTuple::Dump() const diff --git a/worker/src/RTC/UdpSocket.cpp b/worker/src/RTC/UdpSocket.cpp index e750131f71..6c47ab4671 100644 --- a/worker/src/RTC/UdpSocket.cpp +++ b/worker/src/RTC/UdpSocket.cpp @@ -12,14 +12,14 @@ namespace RTC UdpSocket::UdpSocket(Listener* listener, std::string& ip) : // This may throw. - ::UdpSocketHandler::UdpSocketHandler(PortManager::BindUdp(ip)), listener(listener) + ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip)), listener(listener) { MS_TRACE(); } UdpSocket::UdpSocket(Listener* listener, std::string& ip, uint16_t port) : // This may throw. - ::UdpSocketHandler::UdpSocketHandler(PortManager::BindUdp(ip, port)), listener(listener), + ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip, port)), listener(listener), fixedPort(true) { MS_TRACE(); diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index fab070a96c..8fe9f760a3 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -27,113 +27,102 @@ namespace RTC /* Instance methods. */ - WebRtcServer::WebRtcServer(RTC::Shared* shared, const std::string& id, json& data) + WebRtcServer::WebRtcServer( + RTC::Shared* shared, + const std::string& id, + const flatbuffers::Vector>* listenInfos) : id(id), shared(shared) { MS_TRACE(); - auto jsonListenInfosIt = data.find("listenInfos"); - - if (jsonListenInfosIt == data.end()) - MS_THROW_TYPE_ERROR("missing listenInfos"); - else if (!jsonListenInfosIt->is_array()) - MS_THROW_TYPE_ERROR("wrong listenInfos (not an array)"); - else if (jsonListenInfosIt->empty()) + if (listenInfos->size() == 0) + { MS_THROW_TYPE_ERROR("wrong listenInfos (empty array)"); - else if (jsonListenInfosIt->size() > 8) + } + else if (listenInfos->size() > 8) + { MS_THROW_TYPE_ERROR("wrong listenInfos (too many entries)"); + } - std::vector listenInfos(jsonListenInfosIt->size()); - - for (size_t i{ 0 }; i < jsonListenInfosIt->size(); ++i) + try { - auto& jsonListenInfo = (*jsonListenInfosIt)[i]; - auto& listenInfo = listenInfos[i]; - - if (!jsonListenInfo.is_object()) - MS_THROW_TYPE_ERROR("wrong listenInfo (not an object)"); - - auto jsonProtocolIt = jsonListenInfo.find("protocol"); - - if (jsonProtocolIt == jsonListenInfo.end()) - MS_THROW_TYPE_ERROR("missing listenInfo.protocol"); - else if (!jsonProtocolIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenInfo.protocol (not an string"); - - std::string protocolStr = jsonProtocolIt->get(); - - Utils::String::ToLowerCase(protocolStr); - - if (protocolStr == "udp") - listenInfo.protocol = RTC::TransportTuple::Protocol::UDP; - else if (protocolStr == "tcp") - listenInfo.protocol = RTC::TransportTuple::Protocol::TCP; - else - MS_THROW_TYPE_ERROR("invalid listenInfo.protocol (must be 'udp' or 'tcp'"); - - auto jsonIpIt = jsonListenInfo.find("ip"); - - if (jsonIpIt == jsonListenInfo.end()) - MS_THROW_TYPE_ERROR("missing listenInfo.ip"); - else if (!jsonIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenInfo.ip (not an string"); - - listenInfo.ip.assign(jsonIpIt->get()); - - // This may throw. - Utils::IP::NormalizeIp(listenInfo.ip); - - auto jsonAnnouncedIpIt = jsonListenInfo.find("announcedIp"); - - if (jsonAnnouncedIpIt != jsonListenInfo.end()) + for (const auto* listenInfo : *listenInfos) { - if (!jsonAnnouncedIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenInfo.announcedIp (not an string)"); - - listenInfo.announcedIp.assign(jsonAnnouncedIpIt->get()); - } + auto ip = listenInfo->ip()->str(); - uint16_t port{ 0 }; - auto jsonPortIt = jsonListenInfo.find("port"); + // This may throw. + Utils::IP::NormalizeIp(ip); - if (jsonPortIt != jsonListenInfo.end()) - { - if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) - MS_THROW_TYPE_ERROR("wrong port (not a positive number)"); - - port = jsonPortIt->get(); - } + std::string announcedIp; - listenInfo.port = port; - } + if (flatbuffers::IsFieldPresent(listenInfo, FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) + { + announcedIp = listenInfo->announcedIp()->str(); + } - try - { - for (auto& listenInfo : listenInfos) - { - if (listenInfo.protocol == RTC::TransportTuple::Protocol::UDP) + if (listenInfo->protocol() == FBS::Transport::Protocol::UDP) { // This may throw. RTC::UdpSocket* udpSocket; - if (listenInfo.port != 0) - udpSocket = new RTC::UdpSocket(this, listenInfo.ip, listenInfo.port); + if (listenInfo->port() != 0) + { + udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port()); + } else - udpSocket = new RTC::UdpSocket(this, listenInfo.ip); - - this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, listenInfo.announcedIp); + { + udpSocket = new RTC::UdpSocket(this, ip); + } + + this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, announcedIp); + + if (listenInfo->sendBufferSize() != 0) + { + udpSocket->SetSendBufferSize(listenInfo->sendBufferSize()); + } + + if (listenInfo->recvBufferSize() != 0) + { + udpSocket->SetRecvBufferSize(listenInfo->recvBufferSize()); + } + + MS_DEBUG_TAG( + info, + "UDP socket send buffer size: %d, recv buffer size: %d", + udpSocket->GetSendBufferSize(), + udpSocket->GetRecvBufferSize()); } - else if (listenInfo.protocol == RTC::TransportTuple::Protocol::TCP) + else if (listenInfo->protocol() == FBS::Transport::Protocol::TCP) { // This may throw. RTC::TcpServer* tcpServer; - if (listenInfo.port != 0) - tcpServer = new RTC::TcpServer(this, this, listenInfo.ip, listenInfo.port); + if (listenInfo->port() != 0) + { + tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port()); + } else - tcpServer = new RTC::TcpServer(this, this, listenInfo.ip); - - this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, listenInfo.announcedIp); + { + tcpServer = new RTC::TcpServer(this, this, ip); + } + + this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, announcedIp); + + if (listenInfo->sendBufferSize() != 0) + { + tcpServer->SetSendBufferSize(listenInfo->sendBufferSize()); + } + + if (listenInfo->recvBufferSize() != 0) + { + tcpServer->SetRecvBufferSize(listenInfo->recvBufferSize()); + } + + MS_DEBUG_TAG( + info, + "TCP server send buffer size: %d, recv buffer size: %d", + tcpServer->GetSendBufferSize(), + tcpServer->GetRecvBufferSize()); } } @@ -141,8 +130,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } catch (const MediaSoupError& error) { @@ -185,126 +173,95 @@ namespace RTC this->webRtcTransports.clear(); } - void WebRtcServer::FillJson(json& jsonObject) const + flatbuffers::Offset WebRtcServer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - // Add udpSockets and tcpServers. - jsonObject["udpSockets"] = json::array(); - auto jsonUdpSocketsIt = jsonObject.find("udpSockets"); - jsonObject["tcpServers"] = json::array(); - auto jsonTcpServersIt = jsonObject.find("tcpServers"); + std::vector> udpSockets; + std::vector> tcpServers; - size_t udpSocketIdx{ 0 }; - size_t tcpServerIdx{ 0 }; - - for (auto& item : this->udpSocketOrTcpServers) + for (const auto& item : this->udpSocketOrTcpServers) { if (item.udpSocket) { - jsonUdpSocketsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonUdpSocketsIt)[udpSocketIdx]; - - jsonEntry["ip"] = item.udpSocket->GetLocalIp(); - jsonEntry["port"] = item.udpSocket->GetLocalPort(); - - ++udpSocketIdx; + udpSockets.emplace_back(FBS::WebRtcServer::CreateIpPortDirect( + builder, item.udpSocket->GetLocalIp().c_str(), item.udpSocket->GetLocalPort())); } else if (item.tcpServer) { - jsonTcpServersIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonTcpServersIt)[tcpServerIdx]; - - jsonEntry["ip"] = item.tcpServer->GetLocalIp(); - jsonEntry["port"] = item.tcpServer->GetLocalPort(); - - ++tcpServerIdx; + tcpServers.emplace_back(FBS::WebRtcServer::CreateIpPortDirect( + builder, item.tcpServer->GetLocalIp().c_str(), item.tcpServer->GetLocalPort())); } } // Add webRtcTransportIds. - jsonObject["webRtcTransportIds"] = json::array(); - auto jsonWebRtcTransportIdsIt = jsonObject.find("webRtcTransportIds"); + std::vector> webRtcTransportIds; for (auto* webRtcTransport : this->webRtcTransports) { - jsonWebRtcTransportIdsIt->emplace_back(webRtcTransport->id); + webRtcTransportIds.emplace_back(builder.CreateString(webRtcTransport->id)); } - size_t idx; - // Add localIceUsernameFragments. - jsonObject["localIceUsernameFragments"] = json::array(); - auto jsonLocalIceUsernamesIt = jsonObject.find("localIceUsernameFragments"); + std::vector> localIceUsernameFragments; - idx = 0; - for (auto& kv : this->mapLocalIceUsernameFragmentWebRtcTransport) + for (const auto& kv : this->mapLocalIceUsernameFragmentWebRtcTransport) { const auto& localIceUsernameFragment = kv.first; const auto* webRtcTransport = kv.second; - jsonLocalIceUsernamesIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonLocalIceUsernamesIt)[idx]; - - jsonEntry["localIceUsernameFragment"] = localIceUsernameFragment; - jsonEntry["webRtcTransportId"] = webRtcTransport->id; - - ++idx; + localIceUsernameFragments.emplace_back(FBS::WebRtcServer::CreateIceUserNameFragmentDirect( + builder, localIceUsernameFragment.c_str(), webRtcTransport->id.c_str())); } // Add tupleHashes. - jsonObject["tupleHashes"] = json::array(); - auto jsonTupleHashesIt = jsonObject.find("tupleHashes"); + std::vector> tupleHashes; - idx = 0; - for (auto& kv : this->mapTupleWebRtcTransport) + for (const auto& kv : this->mapTupleWebRtcTransport) { const auto& tupleHash = kv.first; const auto* webRtcTransport = kv.second; - jsonTupleHashesIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonTupleHashesIt)[idx]; - - jsonEntry["tupleHash"] = tupleHash; - jsonEntry["webRtcTransportId"] = webRtcTransport->id; - - ++idx; + tupleHashes.emplace_back( + FBS::WebRtcServer::CreateTupleHashDirect(builder, tupleHash, webRtcTransport->id.c_str())); } + + return FBS::WebRtcServer::CreateDumpResponseDirect( + builder, + this->id.c_str(), + &udpSockets, + &tcpServers, + &webRtcTransportIds, + &localIceUsernameFragments, + &tupleHashes); } void WebRtcServer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::WEBRTC_SERVER_DUMP: + case Channel::ChannelRequest::Method::WEBRTCSERVER_DUMP: { - json data = json::object(); - - FillJson(data); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::WebRtcServer_DumpResponse, dumpOffset); break; } default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } - std::vector WebRtcServer::GetIceCandidates( - bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp) + const std::vector WebRtcServer::GetIceCandidates( + bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp) const { MS_TRACE(); @@ -318,28 +275,42 @@ namespace RTC uint16_t iceLocalPreference = IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; if (preferUdp) + { iceLocalPreference += 1000; + } uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); if (item.announcedIp.empty()) + { iceCandidates.emplace_back(item.udpSocket, icePriority); + } else - iceCandidates.emplace_back(item.udpSocket, icePriority, item.announcedIp); + { + iceCandidates.emplace_back( + item.udpSocket, icePriority, const_cast(item.announcedIp)); + } } else if (item.tcpServer && enableTcp) { uint16_t iceLocalPreference = IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; if (preferTcp) + { iceLocalPreference += 1000; + } uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); if (item.announcedIp.empty()) + { iceCandidates.emplace_back(item.tcpServer, icePriority); + } else - iceCandidates.emplace_back(item.tcpServer, icePriority, item.announcedIp); + { + iceCandidates.emplace_back( + item.tcpServer, icePriority, const_cast(item.announcedIp)); + } } // Decrement initial ICE local preference for next IP. @@ -364,7 +335,9 @@ namespace RTC // If no colon is found just return the whole USERNAME attribute anyway. if (colonPos == std::string::npos) + { return username; + } return username.substr(0, colonPos); } @@ -551,7 +524,9 @@ namespace RTC auto it = this->mapTupleWebRtcTransport.find(tuple.hash); if (it == this->mapTupleWebRtcTransport.end()) + { return; + } auto* webRtcTransport = it->second; diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 4846006957..837066be13 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -5,6 +5,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" +#include "FBS/webRtcTransport.h" #include // std::pow() namespace RTC @@ -27,170 +28,127 @@ namespace RTC /* Instance methods. */ + /** + * This constructor is used when the WebRtcTransport doesn't use a WebRtcServer. + */ WebRtcTransport::WebRtcTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data) - : RTC::Transport::Transport(shared, id, listener, data) + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::WebRtcTransport::WebRtcTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()) { MS_TRACE(); - bool enableUdp{ true }; - auto jsonEnableUdpIt = data.find("enableUdp"); - - if (jsonEnableUdpIt != data.end()) - { - if (!jsonEnableUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableUdp (not a boolean)"); - - enableUdp = jsonEnableUdpIt->get(); - } - - bool enableTcp{ false }; - auto jsonEnableTcpIt = data.find("enableTcp"); - - if (jsonEnableTcpIt != data.end()) - { - if (!jsonEnableTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableTcp (not a boolean)"); - - enableTcp = jsonEnableTcpIt->get(); - } - - bool preferUdp{ false }; - auto jsonPreferUdpIt = data.find("preferUdp"); - - if (jsonPreferUdpIt != data.end()) - { - if (!jsonPreferUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferUdp (not a boolean)"); - - preferUdp = jsonPreferUdpIt->get(); - } - - bool preferTcp{ false }; - auto jsonPreferTcpIt = data.find("preferTcp"); - - if (jsonPreferTcpIt != data.end()) - { - if (!jsonPreferTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferTcp (not a boolean)"); - - preferTcp = jsonPreferTcpIt->get(); - } - - auto jsonListenIpsIt = data.find("listenIps"); - - if (jsonListenIpsIt == data.end()) - MS_THROW_TYPE_ERROR("missing listenIps"); - else if (!jsonListenIpsIt->is_array()) - MS_THROW_TYPE_ERROR("wrong listenIps (not an array)"); - else if (jsonListenIpsIt->empty()) - MS_THROW_TYPE_ERROR("wrong listenIps (empty array)"); - else if (jsonListenIpsIt->size() > 8) - MS_THROW_TYPE_ERROR("wrong listenIps (too many IPs)"); - - std::vector listenIps(jsonListenIpsIt->size()); - - for (size_t i{ 0 }; i < jsonListenIpsIt->size(); ++i) + try { - auto& jsonListenIp = (*jsonListenIpsIt)[i]; - auto& listenIp = listenIps[i]; - - if (!jsonListenIp.is_object()) - MS_THROW_TYPE_ERROR("wrong listenIp (not an object)"); - - auto jsonIpIt = jsonListenIp.find("ip"); - - if (jsonIpIt == jsonListenIp.end()) - MS_THROW_TYPE_ERROR("missing listenIp.ip"); - else if (!jsonIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.ip (not an string"); + const auto* listenIndividual = options->listen_as(); + const auto* listenInfos = listenIndividual->listenInfos(); + uint16_t iceLocalPreferenceDecrement{ 0u }; - listenIp.ip.assign(jsonIpIt->get()); + this->iceCandidates.reserve(listenInfos->size()); - // This may throw. - Utils::IP::NormalizeIp(listenIp.ip); - - auto jsonAnnouncedIpIt = jsonListenIp.find("announcedIp"); - - if (jsonAnnouncedIpIt != jsonListenIp.end()) + for (const auto* listenInfo : *listenInfos) { - if (!jsonAnnouncedIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.announcedIp (not an string)"); - - listenIp.announcedIp.assign(jsonAnnouncedIpIt->get()); - } - } + auto ip = listenInfo->ip()->str(); - uint16_t port{ 0 }; - auto jsonPortIt = data.find("port"); + // This may throw. + Utils::IP::NormalizeIp(ip); - if (jsonPortIt != data.end()) - { - if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) - MS_THROW_TYPE_ERROR("wrong port (not a positive number)"); + std::string announcedIp; - port = jsonPortIt->get(); - } - - try - { - uint16_t iceLocalPreferenceDecrement{ 0 }; - - if (enableUdp && enableTcp) - this->iceCandidates.reserve(2 * jsonListenIpsIt->size()); - else - this->iceCandidates.reserve(jsonListenIpsIt->size()); - - for (auto& listenIp : listenIps) - { - if (enableUdp) + if (flatbuffers::IsFieldPresent(listenInfo, FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) { - uint16_t iceLocalPreference = - IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; - - if (preferUdp) - iceLocalPreference += 1000; + announcedIp = listenInfo->announcedIp()->str(); + } - uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); + const uint16_t iceLocalPreference = + IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; + const uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); - // This may throw. + if (listenInfo->protocol() == FBS::Transport::Protocol::UDP) + { RTC::UdpSocket* udpSocket; - if (port != 0) - udpSocket = new RTC::UdpSocket(this, listenIp.ip, port); + + if (listenInfo->port() != 0) + { + udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port()); + } else - udpSocket = new RTC::UdpSocket(this, listenIp.ip); + { + udpSocket = new RTC::UdpSocket(this, ip); + } - this->udpSockets[udpSocket] = listenIp.announcedIp; + this->udpSockets[udpSocket] = announcedIp; - if (listenIp.announcedIp.empty()) + if (announcedIp.size() == 0) + { this->iceCandidates.emplace_back(udpSocket, icePriority); + } else - this->iceCandidates.emplace_back(udpSocket, icePriority, listenIp.announcedIp); - } - - if (enableTcp) - { - uint16_t iceLocalPreference = - IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; + { + this->iceCandidates.emplace_back(udpSocket, icePriority, announcedIp); + } - if (preferTcp) - iceLocalPreference += 1000; + if (listenInfo->sendBufferSize() != 0) + { + // NOTE: This may throw. + udpSocket->SetSendBufferSize(listenInfo->sendBufferSize()); + } - uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); + if (listenInfo->recvBufferSize() != 0) + { + // NOTE: This may throw. + udpSocket->SetRecvBufferSize(listenInfo->recvBufferSize()); + } - // This may throw. + MS_DEBUG_TAG( + info, + "UDP socket buffer sizes [send:%" PRIu32 ", recv:%" PRIu32 "]", + udpSocket->GetSendBufferSize(), + udpSocket->GetRecvBufferSize()); + } + else if (listenInfo->protocol() == FBS::Transport::Protocol::TCP) + { RTC::TcpServer* tcpServer; - if (port != 0) - tcpServer = new RTC::TcpServer(this, this, listenIp.ip, port); + + if (listenInfo->port() != 0) + { + tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port()); + } else - tcpServer = new RTC::TcpServer(this, this, listenIp.ip); + { + tcpServer = new RTC::TcpServer(this, this, ip); + } - this->tcpServers[tcpServer] = listenIp.announcedIp; + this->tcpServers[tcpServer] = announcedIp; - if (listenIp.announcedIp.empty()) + if (announcedIp.size() == 0) + { this->iceCandidates.emplace_back(tcpServer, icePriority); + } else - this->iceCandidates.emplace_back(tcpServer, icePriority, listenIp.announcedIp); + { + this->iceCandidates.emplace_back(tcpServer, icePriority, announcedIp); + } + + if (listenInfo->sendBufferSize() != 0) + { + // NOTE: This may throw. + tcpServer->SetSendBufferSize(listenInfo->sendBufferSize()); + } + + if (listenInfo->recvBufferSize() != 0) + { + // NOTE: This may throw. + tcpServer->SetRecvBufferSize(listenInfo->recvBufferSize()); + } + + MS_DEBUG_TAG( + info, + "TCP sockets buffer sizes [send:%" PRIu32 ", recv:%" PRIu32 "]", + tcpServer->GetSendBufferSize(), + tcpServer->GetRecvBufferSize()); } // Decrement initial ICE local preference for next IP. @@ -208,8 +166,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } catch (const MediaSoupError& error) { @@ -251,9 +208,9 @@ namespace RTC const std::string& id, RTC::Transport::Listener* listener, WebRtcTransportListener* webRtcTransportListener, - std::vector& iceCandidates, - json& data) - : RTC::Transport::Transport(shared, id, listener, data), + const std::vector& iceCandidates, + const FBS::WebRtcTransport::WebRtcTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()), webRtcTransportListener(webRtcTransportListener), iceCandidates(iceCandidates) { MS_TRACE(); @@ -277,8 +234,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } catch (const MediaSoupError& error) { @@ -290,8 +246,6 @@ namespace RTC delete this->iceServer; this->iceServer = nullptr; - this->iceCandidates.clear(); - throw; } } @@ -344,258 +298,151 @@ namespace RTC this->webRtcTransportListener->OnWebRtcTransportClosed(this); } - void WebRtcTransport::FillJson(json& jsonObject) const + flatbuffers::Offset WebRtcTransport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJson(jsonObject); - - // Add iceRole (we are always "controlled"). - jsonObject["iceRole"] = "controlled"; - // Add iceParameters. - jsonObject["iceParameters"] = json::object(); - auto jsonIceParametersIt = jsonObject.find("iceParameters"); - - (*jsonIceParametersIt)["usernameFragment"] = this->iceServer->GetUsernameFragment(); - (*jsonIceParametersIt)["password"] = this->iceServer->GetPassword(); - (*jsonIceParametersIt)["iceLite"] = true; + auto iceParameters = FBS::WebRtcTransport::CreateIceParametersDirect( + builder, + this->iceServer->GetUsernameFragment().c_str(), + this->iceServer->GetPassword().c_str(), + true); - // Add iceCandidates. - jsonObject["iceCandidates"] = json::array(); - auto jsonIceCandidatesIt = jsonObject.find("iceCandidates"); + std::vector> iceCandidates; + iceCandidates.reserve(this->iceCandidates.size()); - for (size_t i{ 0 }; i < this->iceCandidates.size(); ++i) + for (const auto& iceCandidate : this->iceCandidates) { - jsonIceCandidatesIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonIceCandidatesIt)[i]; - const auto& iceCandidate = this->iceCandidates[i]; - - iceCandidate.FillJson(jsonEntry); + iceCandidates.emplace_back(iceCandidate.FillBuffer(builder)); } // Add iceState. - switch (this->iceServer->GetState()) - { - case RTC::IceServer::IceState::NEW: - jsonObject["iceState"] = "new"; - break; - case RTC::IceServer::IceState::CONNECTED: - jsonObject["iceState"] = "connected"; - break; - case RTC::IceServer::IceState::COMPLETED: - jsonObject["iceState"] = "completed"; - break; - case RTC::IceServer::IceState::DISCONNECTED: - jsonObject["iceState"] = "disconnected"; - break; - } + auto iceState = RTC::IceServer::IceStateToFbs(this->iceServer->GetState()); // Add iceSelectedTuple. - if (this->iceServer->GetSelectedTuple()) - this->iceServer->GetSelectedTuple()->FillJson(jsonObject["iceSelectedTuple"]); + flatbuffers::Offset iceSelectedTuple; - // Add dtlsParameters. - jsonObject["dtlsParameters"] = json::object(); - auto jsonDtlsParametersIt = jsonObject.find("dtlsParameters"); + if (this->iceServer->GetSelectedTuple()) + iceSelectedTuple = this->iceServer->GetSelectedTuple()->FillBuffer(builder); // Add dtlsParameters.fingerprints. - (*jsonDtlsParametersIt)["fingerprints"] = json::array(); - auto jsonDtlsParametersFingerprintsIt = jsonDtlsParametersIt->find("fingerprints"); - auto& fingerprints = this->dtlsTransport->GetLocalFingerprints(); + std::vector> fingerprints; - for (size_t i{ 0 }; i < fingerprints.size(); ++i) + for (const auto& fingerprint : this->dtlsTransport->GetLocalFingerprints()) { - jsonDtlsParametersFingerprintsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonDtlsParametersFingerprintsIt)[i]; - auto& fingerprint = fingerprints[i]; + auto algorithm = DtlsTransport::AlgorithmToFbs(fingerprint.algorithm); + const auto& value = fingerprint.value; - jsonEntry["algorithm"] = - RTC::DtlsTransport::GetFingerprintAlgorithmString(fingerprint.algorithm); - jsonEntry["value"] = fingerprint.value; + fingerprints.emplace_back( + FBS::WebRtcTransport::CreateFingerprintDirect(builder, algorithm, value.c_str())); } // Add dtlsParameters.role. - switch (this->dtlsRole) - { - case RTC::DtlsTransport::Role::NONE: - (*jsonDtlsParametersIt)["role"] = "none"; - break; - case RTC::DtlsTransport::Role::AUTO: - (*jsonDtlsParametersIt)["role"] = "auto"; - break; - case RTC::DtlsTransport::Role::CLIENT: - (*jsonDtlsParametersIt)["role"] = "client"; - break; - case RTC::DtlsTransport::Role::SERVER: - (*jsonDtlsParametersIt)["role"] = "server"; - break; - } + auto dtlsRole = DtlsTransport::RoleToFbs(this->dtlsRole); + auto dtlsState = DtlsTransport::StateToFbs(this->dtlsTransport->GetState()); - // Add dtlsState. - switch (this->dtlsTransport->GetState()) - { - case RTC::DtlsTransport::DtlsState::NEW: - jsonObject["dtlsState"] = "new"; - break; - case RTC::DtlsTransport::DtlsState::CONNECTING: - jsonObject["dtlsState"] = "connecting"; - break; - case RTC::DtlsTransport::DtlsState::CONNECTED: - jsonObject["dtlsState"] = "connected"; - break; - case RTC::DtlsTransport::DtlsState::FAILED: - jsonObject["dtlsState"] = "failed"; - break; - case RTC::DtlsTransport::DtlsState::CLOSED: - jsonObject["dtlsState"] = "closed"; - break; - } + // Add base transport dump. + auto base = Transport::FillBuffer(builder); + // Add dtlsParameters. + auto dtlsParameters = + FBS::WebRtcTransport::CreateDtlsParametersDirect(builder, &fingerprints, dtlsRole); + + return FBS::WebRtcTransport::CreateDumpResponseDirect( + builder, + base, + FBS::WebRtcTransport::IceRole::CONTROLLED, + iceParameters, + &iceCandidates, + iceState, + iceSelectedTuple, + dtlsParameters, + dtlsState); } - void WebRtcTransport::FillJsonStats(json& jsonArray) + flatbuffers::Offset WebRtcTransport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJsonStats(jsonArray); - - auto& jsonObject = jsonArray[0]; + // Add iceState. + auto iceState = RTC::IceServer::IceStateToFbs(this->iceServer->GetState()); - // Add type. - jsonObject["type"] = "webrtc-transport"; + // Add iceSelectedTuple. + flatbuffers::Offset iceSelectedTuple; - // Add iceRole (we are always "controlled"). - jsonObject["iceRole"] = "controlled"; + if (this->iceServer->GetSelectedTuple()) + iceSelectedTuple = this->iceServer->GetSelectedTuple()->FillBuffer(builder); - // Add iceState. - switch (this->iceServer->GetState()) - { - case RTC::IceServer::IceState::NEW: - jsonObject["iceState"] = "new"; - break; - case RTC::IceServer::IceState::CONNECTED: - jsonObject["iceState"] = "connected"; - break; - case RTC::IceServer::IceState::COMPLETED: - jsonObject["iceState"] = "completed"; - break; - case RTC::IceServer::IceState::DISCONNECTED: - jsonObject["iceState"] = "disconnected"; - break; - } + auto dtlsState = DtlsTransport::StateToFbs(this->dtlsTransport->GetState()); - if (this->iceServer->GetSelectedTuple()) - { - // Add iceSelectedTuple. - this->iceServer->GetSelectedTuple()->FillJson(jsonObject["iceSelectedTuple"]); - } + // Base Transport stats. + auto base = Transport::FillBufferStats(builder); - // Add dtlsState. - switch (this->dtlsTransport->GetState()) - { - case RTC::DtlsTransport::DtlsState::NEW: - jsonObject["dtlsState"] = "new"; - break; - case RTC::DtlsTransport::DtlsState::CONNECTING: - jsonObject["dtlsState"] = "connecting"; - break; - case RTC::DtlsTransport::DtlsState::CONNECTED: - jsonObject["dtlsState"] = "connected"; - break; - case RTC::DtlsTransport::DtlsState::FAILED: - jsonObject["dtlsState"] = "failed"; - break; - case RTC::DtlsTransport::DtlsState::CLOSED: - jsonObject["dtlsState"] = "closed"; - break; - } + return FBS::WebRtcTransport::CreateGetStatsResponse( + builder, + base, + // iceRole (we are always "controlled"). + FBS::WebRtcTransport::IceRole::CONTROLLED, + iceState, + iceSelectedTuple, + dtlsState); } void WebRtcTransport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::TRANSPORT_CONNECT: + case Channel::ChannelRequest::Method::TRANSPORT_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::WebRtcTransport_GetStatsResponse, responseOffset); + + break; + } + + case Channel::ChannelRequest::Method::TRANSPORT_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::WebRtcTransport_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::WEBRTCTRANSPORT_CONNECT: { // Ensure this method is not called twice. if (this->connectCalled) MS_THROW_ERROR("connect() already called"); + const auto* body = request->data->body_as(); + const auto* dtlsParameters = body->dtlsParameters(); + RTC::DtlsTransport::Fingerprint dtlsRemoteFingerprint; RTC::DtlsTransport::Role dtlsRemoteRole; - auto jsonDtlsParametersIt = request->data.find("dtlsParameters"); - - if (jsonDtlsParametersIt == request->data.end() || !jsonDtlsParametersIt->is_object()) - MS_THROW_TYPE_ERROR("missing dtlsParameters"); - - auto jsonFingerprintsIt = jsonDtlsParametersIt->find("fingerprints"); - - if (jsonFingerprintsIt == jsonDtlsParametersIt->end() || !jsonFingerprintsIt->is_array()) - { - MS_THROW_TYPE_ERROR("missing dtlsParameters.fingerprints"); - } - else if (jsonFingerprintsIt->empty()) + if (dtlsParameters->fingerprints()->size() == 0) { MS_THROW_TYPE_ERROR("empty dtlsParameters.fingerprints array"); } // NOTE: Just take the first fingerprint. - for (auto& jsonFingerprint : *jsonFingerprintsIt) + for (const auto& fingerprint : *dtlsParameters->fingerprints()) { - if (!jsonFingerprint.is_object()) - MS_THROW_TYPE_ERROR("wrong entry in dtlsParameters.fingerprints (not an object)"); - - auto jsonAlgorithmIt = jsonFingerprint.find("algorithm"); + dtlsRemoteFingerprint.algorithm = DtlsTransport::AlgorithmFromFbs(fingerprint->algorithm()); - if (jsonAlgorithmIt == jsonFingerprint.end()) - MS_THROW_TYPE_ERROR("missing fingerprint.algorithm"); - else if (!jsonAlgorithmIt->is_string()) - MS_THROW_TYPE_ERROR("wrong fingerprint.algorithm (not a string)"); - - dtlsRemoteFingerprint.algorithm = - RTC::DtlsTransport::GetFingerprintAlgorithm(jsonAlgorithmIt->get()); - - if (dtlsRemoteFingerprint.algorithm == RTC::DtlsTransport::FingerprintAlgorithm::NONE) - { - MS_THROW_TYPE_ERROR("invalid fingerprint.algorithm value"); - } - - auto jsonValueIt = jsonFingerprint.find("value"); - - if (jsonValueIt == jsonFingerprint.end()) - MS_THROW_TYPE_ERROR("missing fingerprint.value"); - else if (!jsonValueIt->is_string()) - MS_THROW_TYPE_ERROR("wrong fingerprint.value (not a string)"); - - dtlsRemoteFingerprint.value = jsonValueIt->get(); + dtlsRemoteFingerprint.value = fingerprint->value()->str(); // Just use the first fingerprint. break; } - auto jsonRoleIt = jsonDtlsParametersIt->find("role"); - - if (jsonRoleIt != jsonDtlsParametersIt->end()) - { - if (!jsonRoleIt->is_string()) - MS_THROW_TYPE_ERROR("wrong dtlsParameters.role (not a string)"); - - dtlsRemoteRole = RTC::DtlsTransport::StringToRole(jsonRoleIt->get()); - - if (dtlsRemoteRole == RTC::DtlsTransport::Role::NONE) - MS_THROW_TYPE_ERROR("invalid dtlsParameters.role value"); - } - else - { - dtlsRemoteRole = RTC::DtlsTransport::Role::AUTO; - } + dtlsRemoteRole = RTC::DtlsTransport::RoleFromFbs(dtlsParameters->role()); // Set local DTLS role. switch (dtlsRemoteRole) @@ -614,10 +461,6 @@ namespace RTC break; } - case RTC::DtlsTransport::Role::NONE: - { - MS_THROW_TYPE_ERROR("invalid remote DTLS role"); - } } this->connectCalled = true; @@ -630,28 +473,17 @@ namespace RTC } // Tell the caller about the selected local DTLS role. - json data = json::object(); + auto dtlsLocalRole = DtlsTransport::RoleToFbs(this->dtlsRole); - switch (this->dtlsRole) - { - case RTC::DtlsTransport::Role::CLIENT: - data["dtlsLocalRole"] = "client"; - break; + auto responseOffset = + FBS::WebRtcTransport::CreateConnectResponse(request->GetBufferBuilder(), dtlsLocalRole); - case RTC::DtlsTransport::Role::SERVER: - data["dtlsLocalRole"] = "server"; - break; - - default: - MS_ABORT("invalid local DTLS role"); - } - - request->Accept(data); + request->Accept(FBS::Response::Body::WebRtcTransport_ConnectResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_RESTART_ICE: + case Channel::ChannelRequest::Method::TRANSPORT_RESTART_ICE: { const std::string usernameFragment = Utils::Crypto::GetRandomString(32); const std::string password = Utils::Crypto::GetRandomString(32); @@ -662,16 +494,14 @@ namespace RTC "WebRtcTransport ICE usernameFragment and password changed [id:%s]", this->id.c_str()); // Reply with the updated ICE local parameters. - json data = json::object(); - - data["iceParameters"] = json::object(); - auto jsonIceParametersIt = data.find("iceParameters"); + auto responseOffset = FBS::Transport::CreateRestartIceResponseDirect( + request->GetBufferBuilder(), + this->iceServer->GetUsernameFragment().c_str(), + this->iceServer->GetPassword().c_str(), + true /* iceLite */ + ); - (*jsonIceParametersIt)["usernameFragment"] = this->iceServer->GetUsernameFragment(); - (*jsonIceParametersIt)["password"] = this->iceServer->GetPassword(); - (*jsonIceParametersIt)["iceLite"] = true; - - request->Accept(data); + request->Accept(FBS::Response::Body::Transport_RestartIceResponse, responseOffset); break; } @@ -684,7 +514,7 @@ namespace RTC } } - void WebRtcTransport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void WebRtcTransport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); @@ -827,11 +657,6 @@ namespace RTC break; } - - case RTC::DtlsTransport::Role::NONE: - { - MS_ABORT("local DTLS role not set"); - } } } @@ -948,11 +773,11 @@ namespace RTC } void WebRtcTransport::SendMessage( - RTC::DataConsumer* dataConsumer, uint32_t ppid, const uint8_t* msg, size_t len, onQueuedCallback* cb) + RTC::DataConsumer* dataConsumer, const uint8_t* msg, size_t len, uint32_t ppid, onQueuedCallback* cb) { MS_TRACE(); - this->sctpAssociation->SendSctpMessage(dataConsumer, ppid, msg, len, cb); + this->sctpAssociation->SendSctpMessage(dataConsumer, msg, len, ppid, cb); } void WebRtcTransport::SendSctpData(const uint8_t* data, size_t len) @@ -1305,11 +1130,17 @@ namespace RTC MS_DEBUG_TAG(ice, "ICE selected tuple"); // Notify the Node WebRtcTransport. - json data = json::object(); + auto tuple = this->iceServer->GetSelectedTuple()->FillBuffer( + this->shared->channelNotifier->GetBufferBuilder()); - this->iceServer->GetSelectedTuple()->FillJson(data["iceSelectedTuple"]); + auto notification = FBS::WebRtcTransport::CreateIceSelectedTupleChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), tuple); - this->shared->channelNotifier->Emit(this->id, "iceselectedtuplechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, + FBS::Notification::Body::WebRtcTransport_IceSelectedTupleChangeNotification, + notification); } inline void WebRtcTransport::OnIceServerConnected(const RTC::IceServer* /*iceServer*/) @@ -1319,11 +1150,14 @@ namespace RTC MS_DEBUG_TAG(ice, "ICE connected"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["iceState"] = "connected"; + auto iceStateChangeOffset = FBS::WebRtcTransport::CreateIceStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::IceState::CONNECTED); - this->shared->channelNotifier->Emit(this->id, "icestatechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_ICE_STATE_CHANGE, + FBS::Notification::Body::WebRtcTransport_IceStateChangeNotification, + iceStateChangeOffset); // If ready, run the DTLS handler. MayRunDtlsTransport(); @@ -1342,11 +1176,14 @@ namespace RTC MS_DEBUG_TAG(ice, "ICE completed"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["iceState"] = "completed"; + auto iceStateChangeOffset = FBS::WebRtcTransport::CreateIceStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::IceState::COMPLETED); - this->shared->channelNotifier->Emit(this->id, "icestatechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_ICE_STATE_CHANGE, + FBS::Notification::Body::WebRtcTransport_IceStateChangeNotification, + iceStateChangeOffset); // If ready, run the DTLS handler. MayRunDtlsTransport(); @@ -1365,11 +1202,15 @@ namespace RTC MS_DEBUG_TAG(ice, "ICE disconnected"); // Notify the Node WebRtcTransport. - json data = json::object(); + auto iceStateChangeOffset = FBS::WebRtcTransport::CreateIceStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::WebRtcTransport::IceState::DISCONNECTED); - data["iceState"] = "disconnected"; - - this->shared->channelNotifier->Emit(this->id, "icestatechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_ICE_STATE_CHANGE, + FBS::Notification::Body::WebRtcTransport_IceStateChangeNotification, + iceStateChangeOffset); // If DTLS was already connected, notify the parent class. if (this->dtlsTransport->GetState() == RTC::DtlsTransport::DtlsState::CONNECTED) @@ -1385,11 +1226,14 @@ namespace RTC MS_DEBUG_TAG(dtls, "DTLS connecting"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["dtlsState"] = "connecting"; - - this->shared->channelNotifier->Emit(this->id, "dtlsstatechange", data); + auto dtlsStateChangeOffset = FBS::WebRtcTransport::CreateDtlsStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::DtlsState::CONNECTING); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + FBS::Notification::Body::WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeOffset); } inline void WebRtcTransport::OnDtlsTransportConnected( @@ -1428,12 +1272,16 @@ namespace RTC RTC::SrtpSession::Type::INBOUND, srtpCryptoSuite, srtpRemoteKey, srtpRemoteKeyLen); // Notify the Node WebRtcTransport. - json data = json::object(); + auto dtlsStateChangeOffset = FBS::WebRtcTransport::CreateDtlsStateChangeNotificationDirect( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::WebRtcTransport::DtlsState::CONNECTED, + remoteCert.c_str()); - data["dtlsState"] = "connected"; - data["dtlsRemoteCert"] = remoteCert; - - this->shared->channelNotifier->Emit(this->id, "dtlsstatechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + FBS::Notification::Body::WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeOffset); // Tell the parent class. RTC::Transport::Connected(); @@ -1454,11 +1302,14 @@ namespace RTC MS_WARN_TAG(dtls, "DTLS failed"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["dtlsState"] = "failed"; - - this->shared->channelNotifier->Emit(this->id, "dtlsstatechange", data); + auto dtlsStateChangeOffset = FBS::WebRtcTransport::CreateDtlsStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::DtlsState::FAILED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + FBS::Notification::Body::WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeOffset); } inline void WebRtcTransport::OnDtlsTransportClosed(const RTC::DtlsTransport* /*dtlsTransport*/) @@ -1468,11 +1319,14 @@ namespace RTC MS_WARN_TAG(dtls, "DTLS remotely closed"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["dtlsState"] = "closed"; - - this->shared->channelNotifier->Emit(this->id, "dtlsstatechange", data); + auto dtlsStateChangeOffset = FBS::WebRtcTransport::CreateDtlsStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::DtlsState::CLOSED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + FBS::Notification::Body::WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeOffset); // Tell the parent class. RTC::Transport::Disconnected(); diff --git a/worker/src/Settings.cpp b/worker/src/Settings.cpp index 786064d42d..41a91f1592 100644 --- a/worker/src/Settings.cpp +++ b/worker/src/Settings.cpp @@ -5,10 +5,10 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" +#include #include // isprint() #include // std::ostream_iterator #include -#include #include // std::ostringstream #include extern "C" @@ -263,31 +263,28 @@ void Settings::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::WORKER_UPDATE_SETTINGS: + case Channel::ChannelRequest::Method::WORKER_UPDATE_SETTINGS: { - auto jsonLogLevelIt = request->data.find("logLevel"); - auto jsonLogTagsIt = request->data.find("logTags"); + auto body = request->data->body_as(); - // Update logLevel if requested. - if (jsonLogLevelIt != request->data.end() && jsonLogLevelIt->is_string()) + if (flatbuffers::IsFieldPresent(body, FBS::Worker::UpdateSettingsRequest::VT_LOGLEVEL)) { - std::string logLevel = *jsonLogLevelIt; + auto logLevel = body->logLevel()->str(); // This may throw. Settings::SetLogLevel(logLevel); } // Update logTags if requested. - if (jsonLogTagsIt != request->data.end() && jsonLogTagsIt->is_array()) + if (flatbuffers::IsFieldPresent(body, FBS::Worker::UpdateSettingsRequest::VT_LOGTAGS)) { std::vector logTags; - for (const auto& logTag : *jsonLogTagsIt) + for (const auto& logTag : *body->logTags()) { - if (logTag.is_string()) - logTags.push_back(logTag); + logTags.push_back(logTag->str()); } Settings::SetLogTags(logTags); @@ -303,7 +300,7 @@ void Settings::HandleRequest(Channel::ChannelRequest* request) default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } diff --git a/worker/src/Utils/String.cpp b/worker/src/Utils/String.cpp index 0e5cdd2ede..04086187cb 100644 --- a/worker/src/Utils/String.cpp +++ b/worker/src/Utils/String.cpp @@ -170,43 +170,4 @@ namespace Utils return Base64Decode(data, str.size(), outLen); } - - std::vector Utils::String::Split(const std::string& str, char separator, size_t limit) - { - std::vector items; - size_t pos = 0; - - while (pos < str.length()) - { - auto found = str.find(separator, pos); - - std::string item; - if (found != std::string::npos) - { - item = str.substr(pos, found - pos); - items.push_back(item); - } - else - { - item = str.substr(pos, str.size()); - items.push_back(item); - - break; - } - - // Escape the separator character. - pos += item.length() + 1; - - // Limit reached, add the remaining buffer to the last item. - if (limit != 0 && items.size() >= limit) - { - item = str.substr(pos, str.size()); - items.push_back(item); - - break; - } - } - - return items; - } } // namespace Utils diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 9914efb9c2..46c63d4215 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -9,35 +9,31 @@ #include "MediaSoupErrors.hpp" #include "Settings.hpp" #include "Channel/ChannelNotifier.hpp" -#include "PayloadChannel/PayloadChannelNotifier.hpp" +#include "FBS/response.h" +#include "FBS/worker.h" /* Instance methods. */ -Worker::Worker(::Channel::ChannelSocket* channel, PayloadChannel::PayloadChannelSocket* payloadChannel) - : channel(channel), payloadChannel(payloadChannel) +Worker::Worker(::Channel::ChannelSocket* channel) : channel(channel) { MS_TRACE(); // Set us as Channel's listener. this->channel->SetListener(this); - // Set us as PayloadChannel's listener. - this->payloadChannel->SetListener(this); - - // Set the SignalHandler. - this->signalsHandler = new SignalsHandler(this); + // Set the SignalHandle. + this->signalHandle = new SignalHandle(this); // Set up the RTC::Shared singleton. this->shared = new RTC::Shared( /*channelMessageRegistrator*/ new ChannelMessageRegistrator(), - /*channelNotifier*/ new Channel::ChannelNotifier(this->channel), - /*payloadChannelNotifier*/ new PayloadChannel::PayloadChannelNotifier(this->payloadChannel)); + /*channelNotifier*/ new Channel::ChannelNotifier(this->channel)); #ifdef MS_EXECUTABLE { // Add signals to handle. - this->signalsHandler->AddSignal(SIGINT, "INT"); - this->signalsHandler->AddSignal(SIGTERM, "TERM"); + this->signalHandle->AddSignal(SIGINT, "INT"); + this->signalHandle->AddSignal(SIGTERM, "TERM"); } #endif @@ -45,7 +41,8 @@ Worker::Worker(::Channel::ChannelSocket* channel, PayloadChannel::PayloadChannel DepUsrSCTP::CreateChecker(); // Tell the Node process that we are running. - this->shared->channelNotifier->Emit(Logger::pid, "running"); + this->shared->channelNotifier->Emit( + std::to_string(Logger::pid), FBS::Notification::Event::WORKER_RUNNING); MS_DEBUG_DEV("starting libuv loop"); DepLibUV::RunLoop(); @@ -69,8 +66,8 @@ void Worker::Close() this->closed = true; - // Delete the SignalsHandler. - delete this->signalsHandler; + // Delete the SignalHandle. + delete this->signalHandle; // Delete all Routers. for (auto& kv : this->mapRouters) @@ -98,48 +95,41 @@ void Worker::Close() // Close the Channel. this->channel->Close(); - - // Close the PayloadChannel. - this->payloadChannel->Close(); } -void Worker::FillJson(json& jsonObject) const +flatbuffers::Offset Worker::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { - MS_TRACE(); - - // Add pid. - jsonObject["pid"] = Logger::pid; - // Add webRtcServerIds. - jsonObject["webRtcServerIds"] = json::array(); - auto jsonWebRtcServerIdsIt = jsonObject.find("webRtcServerIds"); + std::vector> webRtcServerIds; + webRtcServerIds.reserve(this->mapWebRtcServers.size()); for (const auto& kv : this->mapWebRtcServers) { const auto& webRtcServerId = kv.first; - jsonWebRtcServerIdsIt->emplace_back(webRtcServerId); + webRtcServerIds.push_back(builder.CreateString(webRtcServerId)); } // Add routerIds. - jsonObject["routerIds"] = json::array(); - auto jsonRouterIdsIt = jsonObject.find("routerIds"); + std::vector> routerIds; + routerIds.reserve(this->mapRouters.size()); for (const auto& kv : this->mapRouters) { const auto& routerId = kv.first; - jsonRouterIdsIt->emplace_back(routerId); + routerIds.push_back(builder.CreateString(routerId)); } - // Add channelMessageHandlers. - jsonObject["channelMessageHandlers"] = json::object(); - auto jsonChannelMessageHandlersIt = jsonObject.find("channelMessageHandlers"); + auto channelMessageHandlers = this->shared->channelMessageRegistrator->FillBuffer(builder); - this->shared->channelMessageRegistrator->FillJson(*jsonChannelMessageHandlersIt); + return FBS::Worker::CreateDumpResponseDirect( + builder, Logger::pid, &webRtcServerIds, &routerIds, channelMessageHandlers); } -void Worker::FillJsonResourceUsage(json& jsonObject) const +flatbuffers::Offset Worker::FillBufferResourceUsage( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); @@ -151,123 +141,85 @@ void Worker::FillJsonResourceUsage(json& jsonObject) const if (err != 0) MS_THROW_ERROR("uv_getrusagerequest() failed: %s", uv_strerror(err)); - // Add ru_utime (uv_timeval_t, user CPU time used, converted to ms). - jsonObject["ru_utime"] = - (uvRusage.ru_utime.tv_sec * static_cast(1000)) + (uvRusage.ru_utime.tv_usec / 1000); - - // Add ru_stime (uv_timeval_t, system CPU time used, converted to ms). - jsonObject["ru_stime"] = - (uvRusage.ru_stime.tv_sec * static_cast(1000)) + (uvRusage.ru_stime.tv_usec / 1000); + return FBS::Worker::CreateResourceUsageResponse( + builder, + // Add ru_utime (uv_timeval_t, user CPU time used, converted to ms). + (uvRusage.ru_utime.tv_sec * static_cast(1000)) + (uvRusage.ru_utime.tv_usec / 1000), + // Add ru_stime (uv_timeval_t, system CPU time used, converted to ms). + (uvRusage.ru_stime.tv_sec * static_cast(1000)) + (uvRusage.ru_stime.tv_usec / 1000), + // Add ru_maxrss (uint64_t, maximum resident set size). + uvRusage.ru_maxrss, - // Add ru_maxrss (uint64_t, maximum resident set size). - jsonObject["ru_maxrss"] = uvRusage.ru_maxrss; + // Add ru_ixrss (uint64_t, integral shared memory size). + uvRusage.ru_ixrss, - // Add ru_ixrss (uint64_t, integral shared memory size). - jsonObject["ru_ixrss"] = uvRusage.ru_ixrss; + // Add ru_idrss (uint64_t, integral unshared data size). + uvRusage.ru_idrss, - // Add ru_idrss (uint64_t, integral unshared data size). - jsonObject["ru_idrss"] = uvRusage.ru_idrss; + // Add ru_isrss (uint64_t, integral unshared stack size). + uvRusage.ru_isrss, - // Add ru_isrss (uint64_t, integral unshared stack size). - jsonObject["ru_isrss"] = uvRusage.ru_isrss; + // Add ru_minflt (uint64_t, page reclaims, soft page faults). + uvRusage.ru_minflt, - // Add ru_minflt (uint64_t, page reclaims, soft page faults). - jsonObject["ru_minflt"] = uvRusage.ru_minflt; + // Add ru_majflt (uint64_t, page faults, hard page faults). + uvRusage.ru_majflt, - // Add ru_majflt (uint64_t, page faults, hard page faults). - jsonObject["ru_majflt"] = uvRusage.ru_majflt; + // Add ru_nswap (uint64_t, swaps). + uvRusage.ru_nswap, - // Add ru_nswap (uint64_t, swaps). - jsonObject["ru_nswap"] = uvRusage.ru_nswap; + // Add ru_inblock (uint64_t, block input operations). + uvRusage.ru_inblock, - // Add ru_inblock (uint64_t, block input operations). - jsonObject["ru_inblock"] = uvRusage.ru_inblock; + // Add ru_oublock (uint64_t, block output operations). + uvRusage.ru_oublock, - // Add ru_oublock (uint64_t, block output operations). - jsonObject["ru_oublock"] = uvRusage.ru_oublock; + // Add ru_msgsnd (uint64_t, IPC messages sent). + uvRusage.ru_msgsnd, - // Add ru_msgsnd (uint64_t, IPC messages sent). - jsonObject["ru_msgsnd"] = uvRusage.ru_msgsnd; + // Add ru_msgrcv (uint64_t, IPC messages received). + uvRusage.ru_msgrcv, - // Add ru_msgrcv (uint64_t, IPC messages received). - jsonObject["ru_msgrcv"] = uvRusage.ru_msgrcv; - - // Add ru_nsignals (uint64_t, signals received). - jsonObject["ru_nsignals"] = uvRusage.ru_nsignals; - - // Add ru_nvcsw (uint64_t, voluntary context switches). - jsonObject["ru_nvcsw"] = uvRusage.ru_nvcsw; - - // Add ru_nivcsw (uint64_t, involuntary context switches). - jsonObject["ru_nivcsw"] = uvRusage.ru_nivcsw; + // Add ru_nsignals (uint64_t, signals received). + uvRusage.ru_nsignals, + // Add ru_nvcsw (uint64_t, voluntary context switches). + uvRusage.ru_nvcsw, + // Add ru_nivcsw (uint64_t, involuntary context switches). + uvRusage.ru_nivcsw); } -void Worker::SetNewWebRtcServerIdFromData(json& data, std::string& webRtcServerId) const +RTC::Router* Worker::GetRouter(const std::string& routerId) const { MS_TRACE(); - auto jsonWebRtcServerIdIt = data.find("webRtcServerId"); + auto it = this->mapRouters.find(routerId); - if (jsonWebRtcServerIdIt == data.end() || !jsonWebRtcServerIdIt->is_string()) - MS_THROW_ERROR("missing webRtcServerId"); - - webRtcServerId.assign(jsonWebRtcServerIdIt->get()); + if (it == this->mapRouters.end()) + MS_THROW_ERROR("Router not found"); - if (this->mapWebRtcServers.find(webRtcServerId) != this->mapWebRtcServers.end()) - MS_THROW_ERROR("a WebRtcServer with same webRtcServerId already exists"); + return it->second; } -RTC::WebRtcServer* Worker::GetWebRtcServerFromData(json& data) const +void Worker::CheckNoWebRtcServer(const std::string& webRtcServerId) const { - MS_TRACE(); - - auto jsonWebRtcServerIdIt = data.find("webRtcServerId"); - - if (jsonWebRtcServerIdIt == data.end() || !jsonWebRtcServerIdIt->is_string()) - MS_THROW_ERROR("missing handlerId.webRtcServerId"); - - auto it = this->mapWebRtcServers.find(jsonWebRtcServerIdIt->get()); - - if (it == this->mapWebRtcServers.end()) - MS_THROW_ERROR("WebRtcServer not found"); - - RTC::WebRtcServer* webRtcServer = it->second; - - return webRtcServer; + if (this->mapWebRtcServers.find(webRtcServerId) != this->mapWebRtcServers.end()) + MS_THROW_ERROR("a WebRtcServer with same webRtcServerId already exists"); } -void Worker::SetNewRouterIdFromData(json& data, std::string& routerId) const +void Worker::CheckNoRouter(const std::string& routerId) const { - MS_TRACE(); - - auto jsonRouterIdIt = data.find("routerId"); - - if (jsonRouterIdIt == data.end() || !jsonRouterIdIt->is_string()) - MS_THROW_ERROR("missing routerId"); - - routerId.assign(jsonRouterIdIt->get()); - if (this->mapRouters.find(routerId) != this->mapRouters.end()) MS_THROW_ERROR("a Router with same routerId already exists"); } -RTC::Router* Worker::GetRouterFromData(json& data) const +RTC::WebRtcServer* Worker::GetWebRtcServer(const std::string& webRtcServerId) const { - MS_TRACE(); - - auto jsonRouterIdIt = data.find("routerId"); - - if (jsonRouterIdIt == data.end() || !jsonRouterIdIt->is_string()) - MS_THROW_ERROR("missing routerId"); - - auto it = this->mapRouters.find(jsonRouterIdIt->get()); - - if (it == this->mapRouters.end()) - MS_THROW_ERROR("Router not found"); + auto it = this->mapWebRtcServers.find(webRtcServerId); - RTC::Router* router = it->second; + if (it == this->mapWebRtcServers.end()) + MS_THROW_ERROR("WebRtcServer not found"); - return router; + return it->second; } inline void Worker::HandleRequest(Channel::ChannelRequest* request) @@ -275,11 +227,11 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) MS_TRACE(); MS_DEBUG_DEV( - "Channel request received [method:%s, id:%" PRIu32 "]", request->method.c_str(), request->id); + "Channel request received [method:%s, id:%" PRIu32 "]", request->methodCStr, request->id); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::WORKER_CLOSE: + case Channel::ChannelRequest::Method::WORKER_CLOSE: { if (this->closed) return; @@ -291,44 +243,42 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) break; } - case Channel::ChannelRequest::MethodId::WORKER_DUMP: + case Channel::ChannelRequest::Method::WORKER_DUMP: { - json data = json::object(); - - FillJson(data); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::Worker_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::WORKER_GET_RESOURCE_USAGE: + case Channel::ChannelRequest::Method::WORKER_GET_RESOURCE_USAGE: { - json data = json::object(); - - FillJsonResourceUsage(data); + auto resourceUsageOffset = FillBufferResourceUsage(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::Worker_ResourceUsageResponse, resourceUsageOffset); break; } - case Channel::ChannelRequest::MethodId::WORKER_UPDATE_SETTINGS: + case Channel::ChannelRequest::Method::WORKER_UPDATE_SETTINGS: { Settings::HandleRequest(request); break; } - case Channel::ChannelRequest::MethodId::WORKER_CREATE_WEBRTC_SERVER: + case Channel::ChannelRequest::Method::WORKER_CREATE_WEBRTCSERVER: { try { - std::string webRtcServerId; + const auto body = request->data->body_as(); - SetNewWebRtcServerIdFromData(request->data, webRtcServerId); + std::string webRtcServerId = body->webRtcServerId()->str(); - auto* webRtcServer = new RTC::WebRtcServer(this->shared, webRtcServerId, request->data); + CheckNoWebRtcServer(webRtcServerId); + + auto* webRtcServer = new RTC::WebRtcServer(this->shared, webRtcServerId, body->listenInfos()); this->mapWebRtcServers[webRtcServerId] = webRtcServer; @@ -338,27 +288,31 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) } catch (const MediaSoupTypeError& error) { - MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->methodCStr); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } break; } - case Channel::ChannelRequest::MethodId::WORKER_WEBRTC_SERVER_CLOSE: + case Channel::ChannelRequest::Method::WORKER_WEBRTCSERVER_CLOSE: { RTC::WebRtcServer* webRtcServer{ nullptr }; + auto body = request->data->body_as(); + + auto webRtcServerId = body->webRtcServerId()->str(); + try { - webRtcServer = GetWebRtcServerFromData(request->data); + webRtcServer = GetWebRtcServer(webRtcServerId); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } // Remove it from the map and delete it. @@ -373,17 +327,19 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) break; } - case Channel::ChannelRequest::MethodId::WORKER_CREATE_ROUTER: + case Channel::ChannelRequest::Method::WORKER_CREATE_ROUTER: { - std::string routerId; + auto body = request->data->body_as(); + + auto routerId = body->routerId()->str(); try { - SetNewRouterIdFromData(request->data, routerId); + CheckNoRouter(routerId); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } auto* router = new RTC::Router(this->shared, routerId, this); @@ -397,17 +353,21 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) break; } - case Channel::ChannelRequest::MethodId::WORKER_CLOSE_ROUTER: + case Channel::ChannelRequest::Method::WORKER_CLOSE_ROUTER: { RTC::Router* router{ nullptr }; + auto body = request->data->body_as(); + + auto routerId = body->routerId()->str(); + try { - router = GetRouterFromData(request->data); + router = GetRouter(routerId); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } // Remove it from the map and delete it. @@ -439,11 +399,11 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) } catch (const MediaSoupTypeError& error) { - MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->methodCStr); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } break; @@ -451,96 +411,50 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) } } -inline void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) -{ - MS_TRACE_STD(); - - // Only needed for executable, library user can close channel earlier and it is fine. -#ifdef MS_EXECUTABLE - // If the pipe is remotely closed it may mean that mediasoup Node process - // abruptly died (SIGKILL?) so we must die. - MS_ERROR_STD("channel remotely closed, closing myself"); -#endif - - Close(); -} - -inline void Worker::HandleRequest(PayloadChannel::PayloadChannelRequest* request) +inline void Worker::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - MS_DEBUG_DEV( - "PayloadChannel request received [method:%s, id:%" PRIu32 "]", - request->method.c_str(), - request->id); + MS_DEBUG_DEV("Channel notification received [event:%s]", notification->eventCStr); try { auto* handler = - this->shared->channelMessageRegistrator->GetPayloadChannelRequestHandler(request->handlerId); - - if (handler == nullptr) - { - MS_THROW_ERROR( - "PayloadChannel request handler with ID %s not found", request->handlerId.c_str()); - } - - handler->HandleRequest(request); - } - catch (const MediaSoupTypeError& error) - { - MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->method.c_str()); - } - catch (const MediaSoupError& error) - { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); - } -} - -inline void Worker::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) -{ - MS_TRACE(); - - MS_DEBUG_DEV("PayloadChannel notification received [event:%s]", notification->event.c_str()); - - try - { - auto* handler = this->shared->channelMessageRegistrator->GetPayloadChannelNotificationHandler( - notification->handlerId); + this->shared->channelMessageRegistrator->GetChannelNotificationHandler(notification->handlerId); if (handler == nullptr) { MS_THROW_ERROR( - "PayloadChannel notification handler with ID %s not found", notification->handlerId.c_str()); + "Channel notification handler with ID %s not found", notification->handlerId.c_str()); } handler->HandleNotification(notification); } catch (const MediaSoupTypeError& error) { - MS_THROW_TYPE_ERROR("%s [event:%s]", error.what(), notification->event.c_str()); + MS_THROW_TYPE_ERROR("%s [event:%s]", error.what(), notification->eventCStr); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), notification->event.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), notification->eventCStr); } } -inline void Worker::OnPayloadChannelClosed(PayloadChannel::PayloadChannelSocket* /*payloadChannel*/) +inline void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) { - MS_TRACE(); + MS_TRACE_STD(); // Only needed for executable, library user can close channel earlier and it is fine. #ifdef MS_EXECUTABLE // If the pipe is remotely closed it may mean that mediasoup Node process // abruptly died (SIGKILL?) so we must die. - MS_ERROR_STD("payloadChannel remotely closed, closing myself"); + MS_ERROR_STD("channel remotely closed, closing myself"); #endif Close(); } -inline void Worker::OnSignal(SignalsHandler* /*signalsHandler*/, int signum) +inline void Worker::OnSignal(SignalHandle* /*signalHandle*/, int signum) { MS_TRACE(); diff --git a/worker/src/handles/SignalsHandler.cpp b/worker/src/handles/SignalHandle.cpp similarity index 77% rename from worker/src/handles/SignalsHandler.cpp rename to worker/src/handles/SignalHandle.cpp index 9d6ca8900e..0ceabc0b33 100644 --- a/worker/src/handles/SignalsHandler.cpp +++ b/worker/src/handles/SignalHandle.cpp @@ -1,7 +1,7 @@ -#define MS_CLASS "SignalsHandler" +#define MS_CLASS "SignalHandle" // #define MS_LOG_DEV_LEVEL 3 -#include "handles/SignalsHandler.hpp" +#include "handles/SignalHandle.hpp" #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" @@ -10,7 +10,7 @@ inline static void onSignal(uv_signal_t* handle, int signum) { - static_cast(handle->data)->OnUvSignal(signum); + static_cast(handle->data)->OnUvSignal(signum); } inline static void onCloseSignal(uv_handle_t* handle) @@ -20,25 +20,29 @@ inline static void onCloseSignal(uv_handle_t* handle) /* Instance methods. */ -SignalsHandler::SignalsHandler(Listener* listener) : listener(listener) +SignalHandle::SignalHandle(Listener* listener) : listener(listener) { MS_TRACE(); } -SignalsHandler::~SignalsHandler() +SignalHandle::~SignalHandle() { MS_TRACE(); if (!this->closed) + { Close(); + } } -void SignalsHandler::Close() +void SignalHandle::Close() { MS_TRACE(); if (this->closed) + { return; + } this->closed = true; @@ -48,12 +52,14 @@ void SignalsHandler::Close() } } -void SignalsHandler::AddSignal(int signum, const std::string& name) +void SignalHandle::AddSignal(int signum, const std::string& name) { MS_TRACE(); if (this->closed) + { MS_THROW_ERROR("closed"); + } int err; auto* uvHandle = new uv_signal_t; @@ -72,13 +78,15 @@ void SignalsHandler::AddSignal(int signum, const std::string& name) err = uv_signal_start(uvHandle, static_cast(onSignal), signum); if (err != 0) + { MS_THROW_ERROR("uv_signal_start() failed for signal %s: %s", name.c_str(), uv_strerror(err)); + } // Enter the UV handle into the vector. this->uvHandles.push_back(uvHandle); } -inline void SignalsHandler::OnUvSignal(int signum) +inline void SignalHandle::OnUvSignal(int signum) { MS_TRACE(); diff --git a/worker/src/handles/TcpConnectionHandler.cpp b/worker/src/handles/TcpConnectionHandle.cpp similarity index 87% rename from worker/src/handles/TcpConnectionHandler.cpp rename to worker/src/handles/TcpConnectionHandle.cpp index 253dc99c26..e6812b165b 100644 --- a/worker/src/handles/TcpConnectionHandler.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -1,7 +1,7 @@ -#define MS_CLASS "TcpConnectionHandler" +#define MS_CLASS "TcpConnectionHandle" // #define MS_LOG_DEV_LEVEL 3 -#include "handles/TcpConnectionHandler.hpp" +#include "handles/TcpConnectionHandle.hpp" #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" @@ -12,29 +12,35 @@ inline static void onAlloc(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf) { - auto* connection = static_cast(handle->data); + auto* connection = static_cast(handle->data); if (connection) + { connection->OnUvReadAlloc(suggestedSize, buf); + } } inline static void onRead(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { - auto* connection = static_cast(handle->data); + auto* connection = static_cast(handle->data); if (connection) + { connection->OnUvRead(nread, buf); + } } inline static void onWrite(uv_write_t* req, int status) { - auto* writeData = static_cast(req->data); + auto* writeData = static_cast(req->data); auto* handle = req->handle; - auto* connection = static_cast(handle->data); + auto* connection = static_cast(handle->data); auto* cb = writeData->cb; if (connection) + { connection->OnUvWrite(status, cb); + } // Delete the UvWriteData struct and the cb. delete writeData; @@ -65,7 +71,7 @@ inline static void onShutdown(uv_shutdown_t* req, int /*status*/) /* Instance methods. */ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -TcpConnectionHandler::TcpConnectionHandler(size_t bufferSize) : bufferSize(bufferSize) +TcpConnectionHandle::TcpConnectionHandle(size_t bufferSize) : bufferSize(bufferSize) { MS_TRACE(); @@ -75,35 +81,41 @@ TcpConnectionHandler::TcpConnectionHandler(size_t bufferSize) : bufferSize(buffe // NOTE: Don't allocate the buffer here. Instead wait for the first uv_alloc_cb(). } -TcpConnectionHandler::~TcpConnectionHandler() +TcpConnectionHandle::~TcpConnectionHandle() { MS_TRACE(); if (!this->closed) + { Close(); + } delete[] this->buffer; } -void TcpConnectionHandler::Close() +void TcpConnectionHandle::Close() { MS_TRACE(); if (this->closed) + { return; + } int err; this->closed = true; - // Tell the UV handle that the TcpConnectionHandler has been closed. + // Tell the UV handle that the TcpConnectionHandle has been closed. this->uvHandle->data = nullptr; // Don't read more. err = uv_read_stop(reinterpret_cast(this->uvHandle)); if (err != 0) + { MS_ABORT("uv_read_stop() failed: %s", uv_strerror(err)); + } // If there is no error and the peer didn't close its connection side then close gracefully. if (!this->hasError && !this->isClosedByPeer) @@ -116,7 +128,9 @@ void TcpConnectionHandler::Close() req, reinterpret_cast(this->uvHandle), static_cast(onShutdown)); if (err != 0) + { MS_ABORT("uv_shutdown() failed: %s", uv_strerror(err)); + } } // Otherwise directly close the socket. else @@ -125,18 +139,18 @@ void TcpConnectionHandler::Close() } } -void TcpConnectionHandler::Dump() const +void TcpConnectionHandle::Dump() const { - MS_DUMP(""); + MS_DUMP(""); MS_DUMP(" localIp : %s", this->localIp.c_str()); MS_DUMP(" localPort : %" PRIu16, static_cast(this->localPort)); MS_DUMP(" remoteIp : %s", this->peerIp.c_str()); MS_DUMP(" remotePort : %" PRIu16, static_cast(this->peerPort)); MS_DUMP(" closed : %s", !this->closed ? "open" : "closed"); - MS_DUMP(""); + MS_DUMP(""); } -void TcpConnectionHandler::Setup( +void TcpConnectionHandle::Setup( Listener* listener, struct sockaddr_storage* localAddr, const std::string& localIp, uint16_t localPort) { MS_TRACE(); @@ -161,12 +175,14 @@ void TcpConnectionHandler::Setup( this->localPort = localPort; } -void TcpConnectionHandler::Start() +void TcpConnectionHandle::Start() { MS_TRACE(); if (this->closed) + { return; + } int err = uv_read_start( reinterpret_cast(this->uvHandle), @@ -174,19 +190,23 @@ void TcpConnectionHandler::Start() static_cast(onRead)); if (err != 0) + { MS_THROW_ERROR("uv_read_start() failed: %s", uv_strerror(err)); + } // Get the peer address. if (!SetPeerAddress()) + { MS_THROW_ERROR("error setting peer IP and port"); + } } -void TcpConnectionHandler::Write( +void TcpConnectionHandle::Write( const uint8_t* data1, size_t len1, const uint8_t* data2, size_t len2, - TcpConnectionHandler::onSendCallback* cb) + TcpConnectionHandle::onSendCallback* cb) { MS_TRACE(); @@ -290,7 +310,9 @@ void TcpConnectionHandler::Write( MS_WARN_DEV("uv_write() failed: %s", uv_strerror(err)); if (cb) + { (*cb)(false); + } // Delete the UvWriteData struct (it will delete the store and cb too). delete writeData; @@ -302,7 +324,7 @@ void TcpConnectionHandler::Write( } } -void TcpConnectionHandler::ErrorReceiving() +void TcpConnectionHandle::ErrorReceiving() { MS_TRACE(); @@ -311,7 +333,7 @@ void TcpConnectionHandler::ErrorReceiving() this->listener->OnTcpConnectionClosed(this); } -bool TcpConnectionHandler::SetPeerAddress() +bool TcpConnectionHandle::SetPeerAddress() { MS_TRACE(); @@ -335,13 +357,15 @@ bool TcpConnectionHandler::SetPeerAddress() return true; } -inline void TcpConnectionHandler::OnUvReadAlloc(size_t /*suggestedSize*/, uv_buf_t* buf) +inline void TcpConnectionHandle::OnUvReadAlloc(size_t /*suggestedSize*/, uv_buf_t* buf) { MS_TRACE(); // If this is the first call to onUvReadAlloc() then allocate the receiving buffer now. if (!this->buffer) + { this->buffer = new uint8_t[this->bufferSize]; + } // Tell UV to write after the last data byte in the buffer. buf->base = reinterpret_cast(this->buffer + this->bufferDataLen); @@ -359,12 +383,14 @@ inline void TcpConnectionHandler::OnUvReadAlloc(size_t /*suggestedSize*/, uv_buf } } -inline void TcpConnectionHandler::OnUvRead(ssize_t nread, const uv_buf_t* /*buf*/) +inline void TcpConnectionHandle::OnUvRead(ssize_t nread, const uv_buf_t* /*buf*/) { MS_TRACE(); if (nread == 0) + { return; + } // Data received. if (nread > 0) @@ -406,7 +432,7 @@ inline void TcpConnectionHandler::OnUvRead(ssize_t nread, const uv_buf_t* /*buf* } } -inline void TcpConnectionHandler::OnUvWrite(int status, TcpConnectionHandler::onSendCallback* cb) +inline void TcpConnectionHandle::OnUvWrite(int status, TcpConnectionHandle::onSendCallback* cb) { MS_TRACE(); @@ -415,17 +441,23 @@ inline void TcpConnectionHandler::OnUvWrite(int status, TcpConnectionHandler::on if (status == 0) { if (cb) + { (*cb)(true); + } } else { if (status != UV_EPIPE && status != UV_ENOTCONN) + { this->hasError = true; + } MS_WARN_DEV("write error, closing the connection: %s", uv_strerror(status)); if (cb) + { (*cb)(false); + } Close(); diff --git a/worker/src/handles/TcpServerHandler.cpp b/worker/src/handles/TcpServerHandle.cpp similarity index 58% rename from worker/src/handles/TcpServerHandler.cpp rename to worker/src/handles/TcpServerHandle.cpp index 7b04ad1abc..fff1c9e3e2 100644 --- a/worker/src/handles/TcpServerHandler.cpp +++ b/worker/src/handles/TcpServerHandle.cpp @@ -1,7 +1,7 @@ -#define MS_CLASS "TcpServerHandler" +#define MS_CLASS "TcpServerHandle" // #define MS_LOG_DEV_LEVEL 3 -#include "handles/TcpServerHandler.hpp" +#include "handles/TcpServerHandle.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" @@ -14,10 +14,12 @@ static constexpr int ListenBacklog{ 512 }; inline static void onConnection(uv_stream_t* handle, int status) { - auto* server = static_cast(handle->data); + auto* server = static_cast(handle->data); if (server) + { server->OnUvConnection(status); + } } inline static void onCloseTcp(uv_handle_t* handle) @@ -28,7 +30,7 @@ inline static void onCloseTcp(uv_handle_t* handle) /* Instance methods. */ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -TcpServerHandler::TcpServerHandler(uv_tcp_t* uvHandle) : uvHandle(uvHandle) +TcpServerHandle::TcpServerHandle(uv_tcp_t* uvHandle) : uvHandle(uvHandle) { MS_TRACE(); @@ -57,24 +59,28 @@ TcpServerHandler::TcpServerHandler(uv_tcp_t* uvHandle) : uvHandle(uvHandle) } } -TcpServerHandler::~TcpServerHandler() +TcpServerHandle::~TcpServerHandle() { MS_TRACE(); if (!this->closed) + { Close(); + } } -void TcpServerHandler::Close() +void TcpServerHandle::Close() { MS_TRACE(); if (this->closed) + { return; + } this->closed = true; - // Tell the UV handle that the TcpServerHandler has been closed. + // Tell the UV handle that the TcpServerHandle has been closed. this->uvHandle->data = nullptr; MS_DEBUG_DEV("closing %zu active connections", this->connections.size()); @@ -87,23 +93,93 @@ void TcpServerHandler::Close() uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTcp)); } -void TcpServerHandler::Dump() const +void TcpServerHandle::Dump() const { - MS_DUMP(""); + MS_DUMP(""); MS_DUMP( " [TCP, local:%s :%" PRIu16 ", status:%s, connections:%zu]", this->localIp.c_str(), static_cast(this->localPort), (!this->closed) ? "open" : "closed", this->connections.size()); - MS_DUMP(""); + MS_DUMP(""); +} + +uint32_t TcpServerHandle::GetSendBufferSize() const +{ + MS_TRACE(); + + int size{ 0 }; + int err = uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + + if (err) + { + MS_THROW_ERROR("uv_send_buffer_size() failed: %s", uv_strerror(err)); + } + + return static_cast(size); +} + +void TcpServerHandle::SetSendBufferSize(uint32_t size) +{ + MS_TRACE(); + + auto size_int = static_cast(size); + + if (size_int <= 0) + { + MS_THROW_TYPE_ERROR("invalid size: %d", size_int); + } + + int err = + uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + + if (err) + { + MS_THROW_ERROR("uv_send_buffer_size() failed: %s", uv_strerror(err)); + } +} + +uint32_t TcpServerHandle::GetRecvBufferSize() const +{ + MS_TRACE(); + + int size{ 0 }; + int err = uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + + if (err) + { + MS_THROW_ERROR("uv_recv_buffer_size() failed: %s", uv_strerror(err)); + } + + return static_cast(size); +} + +void TcpServerHandle::SetRecvBufferSize(uint32_t size) +{ + MS_TRACE(); + + auto size_int = static_cast(size); + + if (size_int <= 0) + { + MS_THROW_TYPE_ERROR("invalid size: %d", size_int); + } + + int err = + uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + + if (err) + { + MS_THROW_ERROR("uv_recv_buffer_size() failed: %s", uv_strerror(err)); + } } -void TcpServerHandler::AcceptTcpConnection(TcpConnectionHandler* connection) +void TcpServerHandle::AcceptTcpConnection(TcpConnectionHandle* connection) { MS_TRACE(); - MS_ASSERT(connection != nullptr, "TcpConnectionHandler pointer was not allocated by the user"); + MS_ASSERT(connection != nullptr, "TcpConnectionHandle pointer was not allocated by the user"); try { @@ -122,7 +198,9 @@ void TcpServerHandler::AcceptTcpConnection(TcpConnectionHandler* connection) reinterpret_cast(connection->GetUvHandle())); if (err != 0) + { MS_ABORT("uv_accept() failed: %s", uv_strerror(err)); + } // Start receiving data. try @@ -141,7 +219,7 @@ void TcpServerHandler::AcceptTcpConnection(TcpConnectionHandler* connection) this->connections.insert(connection); } -bool TcpServerHandler::SetLocalAddress() +bool TcpServerHandle::SetLocalAddress() { MS_TRACE(); @@ -166,12 +244,14 @@ bool TcpServerHandler::SetLocalAddress() return true; } -inline void TcpServerHandler::OnUvConnection(int status) +inline void TcpServerHandle::OnUvConnection(int status) { MS_TRACE(); if (this->closed) + { return; + } if (status != 0) { @@ -184,13 +264,13 @@ inline void TcpServerHandler::OnUvConnection(int status) UserOnTcpConnectionAlloc(); } -inline void TcpServerHandler::OnTcpConnectionClosed(TcpConnectionHandler* connection) +inline void TcpServerHandle::OnTcpConnectionClosed(TcpConnectionHandle* connection) { MS_TRACE(); MS_DEBUG_DEV("TCP connection closed"); - // Remove the TcpConnectionHandler from the set. + // Remove the TcpConnectionHandle from the set. this->connections.erase(connection); // Notify the subclass. diff --git a/worker/src/handles/Timer.cpp b/worker/src/handles/TimerHandle.cpp similarity index 84% rename from worker/src/handles/Timer.cpp rename to worker/src/handles/TimerHandle.cpp index efc9133d33..1b85ce929c 100644 --- a/worker/src/handles/Timer.cpp +++ b/worker/src/handles/TimerHandle.cpp @@ -1,7 +1,7 @@ -#define MS_CLASS "Timer" +#define MS_CLASS "TimerHandle" // #define MS_LOG_DEV_LEVEL 3 -#include "handles/Timer.hpp" +#include "handles/TimerHandle.hpp" #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" @@ -10,7 +10,7 @@ inline static void onTimer(uv_timer_t* handle) { - static_cast(handle->data)->OnUvTimer(); + static_cast(handle->data)->OnUvTimer(); } inline static void onCloseTimer(uv_handle_t* handle) @@ -20,7 +20,7 @@ inline static void onCloseTimer(uv_handle_t* handle) /* Instance methods. */ -Timer::Timer(Listener* listener) : listener(listener) +TimerHandle::TimerHandle(Listener* listener) : listener(listener) { MS_TRACE(); @@ -38,7 +38,7 @@ Timer::Timer(Listener* listener) : listener(listener) } } -Timer::~Timer() +TimerHandle::~TimerHandle() { MS_TRACE(); @@ -48,7 +48,7 @@ Timer::~Timer() } } -void Timer::Close() +void TimerHandle::Close() { MS_TRACE(); @@ -62,7 +62,7 @@ void Timer::Close() uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTimer)); } -void Timer::Start(uint64_t timeout, uint64_t repeat) +void TimerHandle::Start(uint64_t timeout, uint64_t repeat) { MS_TRACE(); @@ -87,7 +87,7 @@ void Timer::Start(uint64_t timeout, uint64_t repeat) } } -void Timer::Stop() +void TimerHandle::Stop() { MS_TRACE(); @@ -104,7 +104,7 @@ void Timer::Stop() } } -void Timer::Reset() +void TimerHandle::Reset() { MS_TRACE(); @@ -132,7 +132,7 @@ void Timer::Reset() } } -void Timer::Restart() +void TimerHandle::Restart() { MS_TRACE(); @@ -155,7 +155,7 @@ void Timer::Restart() } } -inline void Timer::OnUvTimer() +inline void TimerHandle::OnUvTimer() { MS_TRACE(); diff --git a/worker/src/handles/UdpSocketHandler.cpp b/worker/src/handles/UdpSocketHandle.cpp similarity index 70% rename from worker/src/handles/UdpSocketHandler.cpp rename to worker/src/handles/UdpSocketHandle.cpp index 5bf4ba7cdf..092b0f041d 100644 --- a/worker/src/handles/UdpSocketHandler.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -1,7 +1,7 @@ -#define MS_CLASS "UdpSocketHandler" +#define MS_CLASS "UdpSocketHandle" // #define MS_LOG_DEV_LEVEL 3 -#include "handles/UdpSocketHandler.hpp" +#include "handles/UdpSocketHandle.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" @@ -16,30 +16,36 @@ thread_local static uint8_t ReadBuffer[ReadBufferSize]; inline static void onAlloc(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf) { - auto* socket = static_cast(handle->data); + auto* socket = static_cast(handle->data); if (socket) + { socket->OnUvRecvAlloc(suggestedSize, buf); + } } inline static void onRecv( uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned int flags) { - auto* socket = static_cast(handle->data); + auto* socket = static_cast(handle->data); if (socket) + { socket->OnUvRecv(nread, buf, addr, flags); + } } inline static void onSend(uv_udp_send_t* req, int status) { - auto* sendData = static_cast(req->data); + auto* sendData = static_cast(req->data); auto* handle = req->handle; - auto* socket = static_cast(handle->data); + auto* socket = static_cast(handle->data); auto* cb = sendData->cb; if (socket) + { socket->OnUvSend(status, cb); + } // Delete the UvSendData struct (it will delete the store and cb too). delete sendData; @@ -53,7 +59,7 @@ inline static void onCloseUdp(uv_handle_t* handle) /* Instance methods. */ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -UdpSocketHandler::UdpSocketHandler(uv_udp_t* uvHandle) : uvHandle(uvHandle) +UdpSocketHandle::UdpSocketHandle(uv_udp_t* uvHandle) : uvHandle(uvHandle) { MS_TRACE(); @@ -80,46 +86,52 @@ UdpSocketHandler::UdpSocketHandler(uv_udp_t* uvHandle) : uvHandle(uvHandle) } } -UdpSocketHandler::~UdpSocketHandler() +UdpSocketHandle::~UdpSocketHandle() { MS_TRACE(); if (!this->closed) + { Close(); + } } -void UdpSocketHandler::Close() +void UdpSocketHandle::Close() { MS_TRACE(); if (this->closed) + { return; + } this->closed = true; - // Tell the UV handle that the UdpSocketHandler has been closed. + // Tell the UV handle that the UdpSocketHandle has been closed. this->uvHandle->data = nullptr; // Don't read more. const int err = uv_udp_recv_stop(this->uvHandle); if (err != 0) + { MS_ABORT("uv_udp_recv_stop() failed: %s", uv_strerror(err)); + } uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseUdp)); } -void UdpSocketHandler::Dump() const +void UdpSocketHandle::Dump() const { - MS_DUMP(""); + MS_DUMP(""); MS_DUMP(" localIp : %s", this->localIp.c_str()); MS_DUMP(" localPort : %" PRIu16, static_cast(this->localPort)); MS_DUMP(" closed : %s", !this->closed ? "open" : "closed"); - MS_DUMP(""); + MS_DUMP(""); } -void UdpSocketHandler::Send( - const uint8_t* data, size_t len, const struct sockaddr* addr, UdpSocketHandler::onSendCallback* cb) +void UdpSocketHandle::Send( + const uint8_t* data, size_t len, const struct sockaddr* addr, UdpSocketHandle::onSendCallback* cb) { MS_TRACE(); @@ -204,7 +216,9 @@ void UdpSocketHandler::Send( MS_WARN_DEV("uv_udp_send() failed: %s", uv_strerror(err)); if (cb) + { (*cb)(false); + } // Delete the UvSendData struct (it will delete the store and cb too). delete sendData; @@ -216,7 +230,77 @@ void UdpSocketHandler::Send( } } -bool UdpSocketHandler::SetLocalAddress() +uint32_t UdpSocketHandle::GetSendBufferSize() const +{ + MS_TRACE(); + + int size{ 0 }; + int err = uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + + if (err) + { + MS_THROW_ERROR("uv_send_buffer_size() failed: %s", uv_strerror(err)); + } + + return static_cast(size); +} + +void UdpSocketHandle::SetSendBufferSize(uint32_t size) +{ + MS_TRACE(); + + auto size_int = static_cast(size); + + if (size_int <= 0) + { + MS_THROW_TYPE_ERROR("invalid size: %d", size_int); + } + + int err = + uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + + if (err) + { + MS_THROW_ERROR("uv_send_buffer_size() failed: %s", uv_strerror(err)); + } +} + +uint32_t UdpSocketHandle::GetRecvBufferSize() const +{ + MS_TRACE(); + + int size{ 0 }; + int err = uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + + if (err) + { + MS_THROW_ERROR("uv_recv_buffer_size() failed: %s", uv_strerror(err)); + } + + return static_cast(size); +} + +void UdpSocketHandle::SetRecvBufferSize(uint32_t size) +{ + MS_TRACE(); + + auto size_int = static_cast(size); + + if (size_int <= 0) + { + MS_THROW_TYPE_ERROR("invalid size: %d", size_int); + } + + int err = + uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + + if (err) + { + MS_THROW_ERROR("uv_recv_buffer_size() failed: %s", uv_strerror(err)); + } +} + +bool UdpSocketHandle::SetLocalAddress() { MS_TRACE(); @@ -241,7 +325,7 @@ bool UdpSocketHandler::SetLocalAddress() return true; } -inline void UdpSocketHandler::OnUvRecvAlloc(size_t /*suggestedSize*/, uv_buf_t* buf) +inline void UdpSocketHandle::OnUvRecvAlloc(size_t /*suggestedSize*/, uv_buf_t* buf) { MS_TRACE(); @@ -251,14 +335,16 @@ inline void UdpSocketHandler::OnUvRecvAlloc(size_t /*suggestedSize*/, uv_buf_t* buf->len = ReadBufferSize; } -inline void UdpSocketHandler::OnUvRecv( +inline void UdpSocketHandle::OnUvRecv( ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned int flags) { MS_TRACE(); // NOTE: Ignore if there is nothing to read or if it was an empty datagram. if (nread == 0) + { return; + } // Check flags. if ((flags & UV_UDP_PARTIAL) != 0u) @@ -284,7 +370,7 @@ inline void UdpSocketHandler::OnUvRecv( } } -inline void UdpSocketHandler::OnUvSend(int status, UdpSocketHandler::onSendCallback* cb) +inline void UdpSocketHandle::OnUvSend(int status, UdpSocketHandle::onSendCallback* cb) { MS_TRACE(); @@ -293,7 +379,9 @@ inline void UdpSocketHandler::OnUvSend(int status, UdpSocketHandler::onSendCallb if (status == 0) { if (cb) + { (*cb)(true); + } } else { @@ -302,6 +390,8 @@ inline void UdpSocketHandler::OnUvSend(int status, UdpSocketHandler::onSendCallb #endif if (cb) + { (*cb)(false); + } } } diff --git a/worker/src/handles/UnixStreamSocket.cpp b/worker/src/handles/UnixStreamSocketHandle.cpp similarity index 69% rename from worker/src/handles/UnixStreamSocket.cpp rename to worker/src/handles/UnixStreamSocketHandle.cpp index 8d8037d3ea..15afe5ead8 100644 --- a/worker/src/handles/UnixStreamSocket.cpp +++ b/worker/src/handles/UnixStreamSocketHandle.cpp @@ -3,10 +3,10 @@ * Channel. */ -#define MS_CLASS "UnixStreamSocket" +#define MS_CLASS "UnixStreamSocketHandle" // #define MS_LOG_DEV_LEVEL 3 -#include "handles/UnixStreamSocket.hpp" +#include "handles/UnixStreamSocketHandle.hpp" #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" @@ -16,29 +16,35 @@ inline static void onAlloc(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf) { - auto* socket = static_cast(handle->data); + auto* socket = static_cast(handle->data); if (socket) + { socket->OnUvReadAlloc(suggestedSize, buf); + } } inline static void onRead(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { - auto* socket = static_cast(handle->data); + auto* socket = static_cast(handle->data); if (socket) + { socket->OnUvRead(nread, buf); + } } inline static void onWrite(uv_write_t* req, int status) { - auto* writeData = static_cast(req->data); + auto* writeData = static_cast(req->data); auto* handle = req->handle; - auto* socket = static_cast(handle->data); + auto* socket = static_cast(handle->data); - // Just notify the UnixStreamSocket when error. + // Just notify the UnixStreamSocketHandle when error. if (socket && status != 0) + { socket->OnUvWriteError(status); + } // Delete the UvWriteData struct. delete writeData; @@ -68,7 +74,8 @@ inline static void onShutdown(uv_shutdown_t* req, int /*status*/) /* Instance methods. */ -UnixStreamSocket::UnixStreamSocket(int fd, size_t bufferSize, UnixStreamSocket::Role role) +UnixStreamSocketHandle::UnixStreamSocketHandle( + int fd, size_t bufferSize, UnixStreamSocketHandle::Role role) : bufferSize(bufferSize), role(role) { MS_TRACE_STD(); @@ -97,7 +104,7 @@ UnixStreamSocket::UnixStreamSocket(int fd, size_t bufferSize, UnixStreamSocket:: MS_THROW_ERROR_STD("uv_pipe_open() failed: %s", uv_strerror(err)); } - if (this->role == UnixStreamSocket::Role::CONSUMER) + if (this->role == UnixStreamSocketHandle::Role::CONSUMER) { // Start reading. err = uv_read_start( @@ -116,41 +123,47 @@ UnixStreamSocket::UnixStreamSocket(int fd, size_t bufferSize, UnixStreamSocket:: // NOTE: Don't allocate the buffer here. Instead wait for the first uv_alloc_cb(). } -UnixStreamSocket::~UnixStreamSocket() +UnixStreamSocketHandle::~UnixStreamSocketHandle() { MS_TRACE_STD(); delete[] this->buffer; if (!this->closed) + { Close(); + } } -void UnixStreamSocket::Close() +void UnixStreamSocketHandle::Close() { MS_TRACE_STD(); if (this->closed) + { return; + } int err; this->closed = true; - // Tell the UV handle that the UnixStreamSocket has been closed. + // Tell the UV handle that the UnixStreamSocketHandle has been closed. this->uvHandle->data = nullptr; - if (this->role == UnixStreamSocket::Role::CONSUMER) + if (this->role == UnixStreamSocketHandle::Role::CONSUMER) { // Don't read more. err = uv_read_stop(reinterpret_cast(this->uvHandle)); if (err != 0) + { MS_ABORT("uv_read_stop() failed: %s", uv_strerror(err)); + } } // If there is no error and the peer didn't close its pipe side then close gracefully. - if (this->role == UnixStreamSocket::Role::PRODUCER && !this->hasError && !this->isClosedByPeer) + if (this->role == UnixStreamSocketHandle::Role::PRODUCER && !this->hasError && !this->isClosedByPeer) { // Use uv_shutdown() so pending data to be written will be sent to the peer before closing. auto* req = new uv_shutdown_t; @@ -159,7 +172,9 @@ void UnixStreamSocket::Close() req, reinterpret_cast(this->uvHandle), static_cast(onShutdown)); if (err != 0) + { MS_ABORT("uv_shutdown() failed: %s", uv_strerror(err)); + } } // Otherwise directly close the socket. else @@ -168,15 +183,19 @@ void UnixStreamSocket::Close() } } -void UnixStreamSocket::Write(const uint8_t* data, size_t len) +void UnixStreamSocketHandle::Write(const uint8_t* data, size_t len) { MS_TRACE_STD(); if (this->closed) + { return; + } if (len == 0) + { return; + } // First try uv_try_write(). In case it can not directly send all the given data // then build a uv_req_t and use uv_write(). @@ -228,13 +247,85 @@ void UnixStreamSocket::Write(const uint8_t* data, size_t len) } } -inline void UnixStreamSocket::OnUvReadAlloc(size_t /*suggestedSize*/, uv_buf_t* buf) +uint32_t UnixStreamSocketHandle::GetSendBufferSize() const +{ + MS_TRACE(); + + int size{ 0 }; + int err = uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + + if (err) + { + MS_THROW_ERROR_STD("uv_send_buffer_size() failed: %s", uv_strerror(err)); + } + + return static_cast(size); +} + +void UnixStreamSocketHandle::SetSendBufferSize(uint32_t size) +{ + MS_TRACE(); + + auto size_int = static_cast(size); + + if (size_int <= 0) + { + MS_THROW_TYPE_ERROR_STD("invalid size: %d", size_int); + } + + int err = + uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + + if (err) + { + MS_THROW_ERROR_STD("uv_send_buffer_size() failed: %s", uv_strerror(err)); + } +} + +uint32_t UnixStreamSocketHandle::GetRecvBufferSize() const +{ + MS_TRACE(); + + int size{ 0 }; + int err = uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + + if (err) + { + MS_THROW_ERROR_STD("uv_recv_buffer_size() failed: %s", uv_strerror(err)); + } + + return static_cast(size); +} + +void UnixStreamSocketHandle::SetRecvBufferSize(uint32_t size) +{ + MS_TRACE(); + + auto size_int = static_cast(size); + + if (size_int <= 0) + { + MS_THROW_TYPE_ERROR_STD("invalid size: %d", size_int); + } + + int err = + uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + + if (err) + { + MS_THROW_ERROR_STD("uv_recv_buffer_size() failed: %s", uv_strerror(err)); + } +} + +inline void UnixStreamSocketHandle::OnUvReadAlloc(size_t /*suggestedSize*/, uv_buf_t* buf) { MS_TRACE_STD(); // If this is the first call to onUvReadAlloc() then allocate the receiving buffer now. if (!this->buffer) + { this->buffer = new uint8_t[this->bufferSize]; + } // Tell UV to write after the last data byte in the buffer. buf->base = reinterpret_cast(this->buffer + this->bufferDataLen); @@ -252,12 +343,14 @@ inline void UnixStreamSocket::OnUvReadAlloc(size_t /*suggestedSize*/, uv_buf_t* } } -inline void UnixStreamSocket::OnUvRead(ssize_t nread, const uv_buf_t* /*buf*/) +inline void UnixStreamSocketHandle::OnUvRead(ssize_t nread, const uv_buf_t* /*buf*/) { MS_TRACE_STD(); if (nread == 0) + { return; + } // Data received. if (nread > 0) @@ -294,12 +387,14 @@ inline void UnixStreamSocket::OnUvRead(ssize_t nread, const uv_buf_t* /*buf*/) } } -inline void UnixStreamSocket::OnUvWriteError(int error) +inline void UnixStreamSocketHandle::OnUvWriteError(int error) { MS_TRACE_STD(); if (error != UV_EPIPE && error != UV_ENOTCONN) + { this->hasError = true; + } MS_ERROR_STD("write error, closing the pipe: %s", uv_strerror(error)); diff --git a/worker/src/lib.cpp b/worker/src/lib.cpp index 3bc232f511..cca1f88b7b 100644 --- a/worker/src/lib.cpp +++ b/worker/src/lib.cpp @@ -13,7 +13,6 @@ #include "Utils.hpp" #include "Worker.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include "RTC/DtlsTransport.hpp" #include "RTC/SrtpSession.hpp" #include @@ -35,11 +34,7 @@ extern "C" int mediasoup_worker_run( ChannelReadFn channelReadFn, ChannelReadCtx channelReadCtx, ChannelWriteFn channelWriteFn, - ChannelWriteCtx channelWriteCtx, - PayloadChannelReadFn payloadChannelReadFn, - PayloadChannelReadCtx payloadChannelReadCtx, - PayloadChannelWriteFn payloadChannelWriteFn, - PayloadChannelWriteCtx payloadChannelWriteCtx) + ChannelWriteCtx channelWriteCtx) { // Initialize libuv stuff (we need it for the Channel). DepLibUV::ClassInit(); @@ -49,11 +44,6 @@ extern "C" int mediasoup_worker_run( // deallocate its UV handles. std::unique_ptr channel{ nullptr }; - // PayloadChannel socket. If Worker instance runs properly, this socket is - // closed by it in its destructor. Otherwise it's closed here by also letting - // libuv deallocate its UV handles. - std::unique_ptr payloadChannel{ nullptr }; - try { if (channelReadFn) @@ -77,31 +67,6 @@ extern "C" int mediasoup_worker_run( return 40; } - try - { - if (payloadChannelReadFn) - { - payloadChannel.reset(new PayloadChannel::PayloadChannelSocket( - payloadChannelReadFn, payloadChannelReadCtx, payloadChannelWriteFn, payloadChannelWriteCtx)); - } - else - { - payloadChannel.reset( - new PayloadChannel::PayloadChannelSocket(payloadConsumeChannelFd, payloadProduceChannelFd)); - } - } - catch (const MediaSoupError& error) - { - MS_ERROR_STD("error creating the PayloadChannel: %s", error.what()); - - channel->Close(); - DepLibUV::RunLoop(); - DepLibUV::ClassDestroy(); - - // 40 is a custom exit code to notify "unknown error" to the Node library. - return 40; - } - // Initialize the Logger. Logger::ClassInit(channel.get()); @@ -114,7 +79,6 @@ extern "C" int mediasoup_worker_run( MS_ERROR_STD("settings error: %s", error.what()); channel->Close(); - payloadChannel->Close(); DepLibUV::RunLoop(); DepLibUV::ClassDestroy(); @@ -126,7 +90,6 @@ extern "C" int mediasoup_worker_run( MS_ERROR_STD("unexpected settings error: %s", error.what()); channel->Close(); - payloadChannel->Close(); DepLibUV::RunLoop(); DepLibUV::ClassDestroy(); @@ -172,7 +135,7 @@ extern "C" int mediasoup_worker_run( #endif // Run the Worker. - Worker worker(channel.get(), payloadChannel.get()); + Worker worker(channel.get()); // Free static stuff. DepLibSRTP::ClassDestroy(); diff --git a/worker/src/lib.rs b/worker/src/lib.rs index 0e4f4e4fb7..ad666d36a6 100644 --- a/worker/src/lib.rs +++ b/worker/src/lib.rs @@ -1,5 +1,7 @@ use std::os::raw::{c_char, c_int, c_void}; +include!(concat!(env!("OUT_DIR"), "/fbs.rs")); + #[repr(transparent)] #[derive(Copy, Clone)] pub struct UvAsyncT(pub *const c_void); @@ -38,43 +40,6 @@ pub type ChannelWriteFn = unsafe extern "C" fn( unsafe impl Send for ChannelWriteCtx {} -#[repr(transparent)] -pub struct PayloadChannelReadCtx(pub *const c_void); -pub type PayloadChannelReadFreeFn = Option< - unsafe extern "C" fn( - /* message: */ *mut u8, - /* message_len: */ u32, - /* message_ctx: */ usize, - ), ->; -pub type PayloadChannelReadFn = unsafe extern "C" fn( - /* message: */ *mut *mut u8, - /* message_len: */ *mut u32, - /* message_ctx: */ *mut usize, - /* payload: */ *mut *mut u8, - /* payload_len: */ *mut u32, - /* payload_capacity: */ *mut usize, - // This is `uv_async_t` handle that can be called later with `uv_async_send()` when there is - // more data to read - /* handle */ - UvAsyncT, - /* ctx: */ PayloadChannelReadCtx, -) -> PayloadChannelReadFreeFn; - -unsafe impl Send for PayloadChannelReadCtx {} - -#[repr(transparent)] -pub struct PayloadChannelWriteCtx(pub *const c_void); -pub type PayloadChannelWriteFn = unsafe extern "C" fn( - /* message: */ *const u8, - /* message_len: */ u32, - /* payload: */ *const u8, - /* payload_len: */ u32, - /* ctx: */ PayloadChannelWriteCtx, -); - -unsafe impl Send for PayloadChannelWriteCtx {} - #[link(name = "mediasoup-worker", kind = "static")] extern "C" { /// Returns `0` on success, or an error code `< 0` on failure @@ -92,9 +57,5 @@ extern "C" { channel_read_ctx: ChannelReadCtx, channel_write_fn: ChannelWriteFn, channel_write_ctx: ChannelWriteCtx, - payload_channel_read_fn: PayloadChannelReadFn, - payload_channel_read_ctx: PayloadChannelReadCtx, - payload_channel_write_fn: PayloadChannelWriteFn, - payload_channel_write_ctx: PayloadChannelWriteCtx, ) -> c_int; } diff --git a/worker/src/main.cpp b/worker/src/main.cpp index b7aefc0198..648565f80c 100644 --- a/worker/src/main.cpp +++ b/worker/src/main.cpp @@ -35,10 +35,6 @@ int main(int argc, char* argv[]) nullptr, nullptr, nullptr, - nullptr, - nullptr, - nullptr, - nullptr, nullptr); std::_Exit(statusCode); diff --git a/worker/subprojects/flatbuffers.wrap b/worker/subprojects/flatbuffers.wrap new file mode 100644 index 0000000000..630611bdb1 --- /dev/null +++ b/worker/subprojects/flatbuffers.wrap @@ -0,0 +1,14 @@ +[wrap-file] +directory = flatbuffers-23.3.3 +source_url = https://github.com/google/flatbuffers/archive/v23.3.3.tar.gz +source_filename = flatbuffers-23.3.3.tar.gz +source_hash = 8aff985da30aaab37edf8e5b02fda33ed4cbdd962699a8e2af98fdef306f4e4d +patch_filename = flatbuffers_23.3.3-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/flatbuffers_23.3.3-1/get_patch +patch_hash = fa5faa75a99d1161be532a5d5db19543c15cb193d116d24827a251fc03488a14 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/flatbuffers_23.3.3-1/flatbuffers-23.3.3.tar.gz +wrapdb_version = 23.3.3-1 + +[provide] +flatbuffers = flatbuffers_dep +program_names = flatc, flathash diff --git a/worker/subprojects/nlohmann_json.wrap b/worker/subprojects/nlohmann_json.wrap deleted file mode 100644 index 857277a676..0000000000 --- a/worker/subprojects/nlohmann_json.wrap +++ /dev/null @@ -1,10 +0,0 @@ -[wrap-file] -directory = nlohmann_json-3.10.5 -lead_directory_missing = true -source_url = https://github.com/nlohmann/json/releases/download/v3.10.5/include.zip -source_filename = nlohmann_json-3.10.5.zip -source_hash = b94997df68856753b72f0d7a3703b7d484d4745c567f3584ef97c96c25a5798e - -[provide] -nlohmann_json = nlohmann_json_dep - diff --git a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp index 022bee4a13..970cc73284 100644 --- a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp +++ b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp @@ -4,6 +4,7 @@ #include "RTC/RtpPacket.hpp" #include #include // std::memset() +#include #include #include diff --git a/worker/test/src/Utils/TestJson.cpp b/worker/test/src/Utils/TestJson.cpp deleted file mode 100644 index 03ab8800e1..0000000000 --- a/worker/test/src/Utils/TestJson.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "common.hpp" -#include "Utils.hpp" -#include -#include - -using namespace Utils; -using json = nlohmann::json; - -SCENARIO("Json::IsPositiveInteger()") -{ - json jsonValue; - int intValue; - int8_t int8Value; - int32_t int32Value; - unsigned int uintValue; - uint8_t uint8Value; - uint32_t uint32Value; - float floatValue; - json jsonArray{ json::array() }; - json jsonObject{ json::object() }; - - jsonValue = 0; - REQUIRE(Json::IsPositiveInteger(jsonValue)); - - jsonValue = 1; - REQUIRE(Json::IsPositiveInteger(jsonValue)); - - jsonValue = 0u; - REQUIRE(Json::IsPositiveInteger(jsonValue)); - - jsonValue = 1u; - REQUIRE(Json::IsPositiveInteger(jsonValue)); - - jsonValue = -1; - REQUIRE(!Json::IsPositiveInteger(jsonValue)); - - intValue = 0; - REQUIRE(Json::IsPositiveInteger(intValue)); - - intValue = 1; - REQUIRE(Json::IsPositiveInteger(intValue)); - - intValue = -1; - REQUIRE(!Json::IsPositiveInteger(intValue)); - - int8Value = 0; - REQUIRE(Json::IsPositiveInteger(int8Value)); - - int8Value = 1; - REQUIRE(Json::IsPositiveInteger(int8Value)); - - int8Value = -1; - REQUIRE(!Json::IsPositiveInteger(int8Value)); - - int32Value = 0; - REQUIRE(Json::IsPositiveInteger(int32Value)); - - int32Value = 1; - REQUIRE(Json::IsPositiveInteger(int32Value)); - - int32Value = -1; - REQUIRE(!Json::IsPositiveInteger(int32Value)); - - uintValue = 0; - REQUIRE(Json::IsPositiveInteger(uintValue)); - - uintValue = 1; - REQUIRE(Json::IsPositiveInteger(uintValue)); - - uint8Value = 0; - REQUIRE(Json::IsPositiveInteger(uint8Value)); - - uint8Value = 1; - REQUIRE(Json::IsPositiveInteger(uint8Value)); - - uint32Value = 0; - REQUIRE(Json::IsPositiveInteger(uint32Value)); - - uint32Value = 1; - REQUIRE(Json::IsPositiveInteger(uint32Value)); - - floatValue = 0; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = 0.0; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = 1; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = 1.1; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = -1; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = -1.1; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - REQUIRE(!Json::IsPositiveInteger(jsonArray)); - REQUIRE(!Json::IsPositiveInteger(jsonObject)); - REQUIRE(!Json::IsPositiveInteger(nullptr)); - REQUIRE(!Json::IsPositiveInteger(true)); - REQUIRE(!Json::IsPositiveInteger(false)); -} diff --git a/worker/test/src/Utils/TestString.cpp b/worker/test/src/Utils/TestString.cpp index 3b4dcf016d..99fe49e751 100644 --- a/worker/test/src/Utils/TestString.cpp +++ b/worker/test/src/Utils/TestString.cpp @@ -76,40 +76,3 @@ SCENARIO("String::Base64Encode() and String::Base64Decode()") REQUIRE(outLen == sizeof(rtpPacket)); REQUIRE(std::memcmp(decodedPtr, rtpPacket, outLen) == 0); } - -SCENARIO("String::Split()", "[utils][string]") -{ - SECTION("empty string") - { - std::string foo{}; - - auto v = String::Split(foo, ','); - - REQUIRE(v.size() == 0); - } - - SECTION("character separated string with no limit") - { - std::string foo{ "a,b,c,d" }; - - auto v = String::Split(foo, ','); - - REQUIRE(v.size() == 4); - REQUIRE(v[0] == "a"); - REQUIRE(v[1] == "b"); - REQUIRE(v[2] == "c"); - REQUIRE(v[3] == "d"); - } - - SECTION("character separated string with limit") - { - std::string foo{ "a,b,c,d" }; - - auto v = String::Split(foo, ',', 2); - - REQUIRE(v.size() == 3); - REQUIRE(v[0] == "a"); - REQUIRE(v[1] == "b"); - REQUIRE(v[2] == "c,d"); - } -} From 48f8f4c94f04982773d14915e1527adba9f4ee84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 8 Nov 2023 11:17:23 +0100 Subject: [PATCH 175/525] Update NPM deps --- package-lock.json | 374 +++++++++++++++++++++++----------------------- package.json | 10 +- 2 files changed, 192 insertions(+), 192 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8a46af3217..c5d3d7162a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,11 +19,11 @@ }, "devDependencies": { "@octokit/rest": "^20.0.2", - "@types/debug": "^4.1.10", - "@types/jest": "^29.5.7", - "@types/node": "^20.8.10", - "@typescript-eslint/eslint-plugin": "^6.9.1", - "@typescript-eslint/parser": "^6.9.1", + "@types/debug": "^4.1.11", + "@types/jest": "^29.5.8", + "@types/node": "^20.9.0", + "@typescript-eslint/eslint-plugin": "^6.10.0", + "@typescript-eslint/parser": "^6.10.0", "eslint": "^8.53.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", @@ -1549,9 +1549,9 @@ } }, "node_modules/@types/debug": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.10.tgz", - "integrity": "sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.11.tgz", + "integrity": "sha512-R2qflTjHDs4CL6D/6TkqBeIHr54WzZfIxN729xvCNlYIVp2LknlnCro5Yo3frNaX2E5gO9pZ3/QAPVdGmu+q9w==", "dev": true, "dependencies": { "@types/ms": "*" @@ -1591,9 +1591,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.7", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.7.tgz", - "integrity": "sha512-HLyetab6KVPSiF+7pFcUyMeLsx25LDNDemw9mGsJBkai/oouwrjTycocSDYopMEwFhN2Y4s9oPyOCZNofgSt2g==", + "version": "29.5.8", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.8.tgz", + "integrity": "sha512-fXEFTxMV2Co8ZF5aYFJv+YeA08RTYJfhtN5c9JSv/mFEMe+xxjufCb+PHL+bJcMs/ebPUsBu+UNTEz+ydXrR6g==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1619,9 +1619,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", - "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1661,16 +1661,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", - "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz", + "integrity": "sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/type-utils": "6.9.1", - "@typescript-eslint/utils": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/type-utils": "6.10.0", + "@typescript-eslint/utils": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1696,13 +1696,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", - "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", + "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1" + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1713,9 +1713,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", - "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", + "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1726,13 +1726,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", - "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", + "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1753,17 +1753,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", - "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", + "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/typescript-estree": "6.10.0", "semver": "^7.5.4" }, "engines": { @@ -1778,12 +1778,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", - "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", + "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/types": "6.10.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1795,15 +1795,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", - "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz", + "integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4" }, "engines": { @@ -1823,13 +1823,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", - "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", + "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1" + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1840,9 +1840,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", - "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", + "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1853,13 +1853,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", - "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", + "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1880,12 +1880,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", - "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", + "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/types": "6.10.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1914,13 +1914,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", - "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz", + "integrity": "sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.9.1", - "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/utils": "6.10.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1941,13 +1941,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", - "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", + "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1" + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1958,9 +1958,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", - "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", + "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1971,13 +1971,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", - "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", + "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1998,17 +1998,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", - "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", + "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/typescript-estree": "6.10.0", "semver": "^7.5.4" }, "engines": { @@ -2023,12 +2023,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", - "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", + "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/types": "6.10.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -7936,9 +7936,9 @@ } }, "@types/debug": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.10.tgz", - "integrity": "sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.11.tgz", + "integrity": "sha512-R2qflTjHDs4CL6D/6TkqBeIHr54WzZfIxN729xvCNlYIVp2LknlnCro5Yo3frNaX2E5gO9pZ3/QAPVdGmu+q9w==", "dev": true, "requires": { "@types/ms": "*" @@ -7978,9 +7978,9 @@ } }, "@types/jest": { - "version": "29.5.7", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.7.tgz", - "integrity": "sha512-HLyetab6KVPSiF+7pFcUyMeLsx25LDNDemw9mGsJBkai/oouwrjTycocSDYopMEwFhN2Y4s9oPyOCZNofgSt2g==", + "version": "29.5.8", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.8.tgz", + "integrity": "sha512-fXEFTxMV2Co8ZF5aYFJv+YeA08RTYJfhtN5c9JSv/mFEMe+xxjufCb+PHL+bJcMs/ebPUsBu+UNTEz+ydXrR6g==", "dev": true, "requires": { "expect": "^29.0.0", @@ -8006,9 +8006,9 @@ "dev": true }, "@types/node": { - "version": "20.8.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", - "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -8048,16 +8048,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", - "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz", + "integrity": "sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/type-utils": "6.9.1", - "@typescript-eslint/utils": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/type-utils": "6.10.0", + "@typescript-eslint/utils": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8067,29 +8067,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", - "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", + "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1" + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0" } }, "@typescript-eslint/types": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", - "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", + "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", - "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", + "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8098,69 +8098,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", - "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", + "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/typescript-estree": "6.10.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", - "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", + "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/types": "6.10.0", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", - "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz", + "integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", - "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", + "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1" + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0" } }, "@typescript-eslint/types": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", - "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", + "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", - "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", + "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8169,12 +8169,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", - "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", + "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/types": "6.10.0", "eslint-visitor-keys": "^3.4.1" } } @@ -8191,41 +8191,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", - "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz", + "integrity": "sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.9.1", - "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/utils": "6.10.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", - "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", + "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1" + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0" } }, "@typescript-eslint/types": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", - "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", + "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", - "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", + "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8234,27 +8234,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", - "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", + "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/typescript-estree": "6.10.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", - "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", + "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/types": "6.10.0", "eslint-visitor-keys": "^3.4.1" } } diff --git a/package.json b/package.json index b7af4b973b..3482aa0076 100644 --- a/package.json +++ b/package.json @@ -104,11 +104,11 @@ }, "devDependencies": { "@octokit/rest": "^20.0.2", - "@types/debug": "^4.1.10", - "@types/jest": "^29.5.7", - "@types/node": "^20.8.10", - "@typescript-eslint/eslint-plugin": "^6.9.1", - "@typescript-eslint/parser": "^6.9.1", + "@types/debug": "^4.1.11", + "@types/jest": "^29.5.8", + "@types/node": "^20.9.0", + "@typescript-eslint/eslint-plugin": "^6.10.0", + "@typescript-eslint/parser": "^6.10.0", "eslint": "^8.53.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", From 78090becdffa47b71718cbc571741af622444fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Wed, 8 Nov 2023 11:24:25 +0100 Subject: [PATCH 176/525] 3.13.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3a1d4891a..91c6c107b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.13.0 * Switch from JSON based messages to `flatbuffers` ([PR #1064](https://github.com/versatica/mediasoup/pull/1064)). * Add `ListenInfo` in all transports and send/recv buffer size options ([PR #1084](https://github.com/versatica/mediasoup/pull/1084)). diff --git a/package-lock.json b/package-lock.json index c5d3d7162a..9bdac9a21e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.12.16", + "version": "3.13.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.12.16", + "version": "3.13.0", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 3482aa0076..dcfee51a4d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.12.16", + "version": "3.13.0", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 56cf121405bd29c83e835c18b83ea53f30cf1365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 8 Nov 2023 11:33:21 +0100 Subject: [PATCH 177/525] npm-scripts.mjs: fix upload of mac ARM prebuilt --- npm-scripts.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 42b07a6b10..b5ee8d83fa 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -247,6 +247,7 @@ async function run() // and upload it to the release. if (os.platform() === 'darwin' && os.arch() === 'arm64') { + await prebuildWorker(); await uploadMacArmPrebuiltWorker(); } From 40e1fef30fe9c7e8158335c325ace7b8bb250dce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Nov 2023 13:12:49 +0100 Subject: [PATCH 178/525] Bump rustix from 0.37.23 to 0.37.27 (#1212) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.37.23 to 0.37.27. - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.37.23...v0.37.27) --- updated-dependencies: - dependency-name: rustix dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Iñaki Baz Castillo --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b08783920d..786fcb172d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -385,7 +385,7 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.23", + "rustix 0.37.27", "slab", "socket2 0.4.9", "waker-fn", @@ -1998,9 +1998,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", From d44b81491c88d667696b8003cd5fafa1e74352b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 8 Nov 2023 13:13:46 +0100 Subject: [PATCH 179/525] CI: remove unmaintained actions-rs/cargo actions Fixes #1215 Also cosmetic changes in other CI files. --- .github/workflows/mediasoup-node.yaml | 15 ++++++++++----- .github/workflows/mediasoup-rust.yaml | 20 ++++++-------------- .github/workflows/mediasoup-worker.yaml | 9 ++++++--- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 7fdfaef856..d901f61233 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -27,7 +27,7 @@ jobs: runs-on: ${{ matrix.ci.os }} env: - MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: "true" + MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' steps: - name: Checkout @@ -47,8 +47,13 @@ jobs: restore-keys: | ${{ matrix.ci.os }}-node- - # NOTE: Add --force since otherwise `npm ci` fails in Node 26 because + # NOTE: Add --force since otherwise `npm ci` fails in Node 16 because # @octokit/auth-token dev dependency requires Node >= 16. - - run: npm ci --force - - run: npm run lint:node - - run: npm run test:node + - name: Install + run: npm ci --force + + - name: Lint + run: npm run lint:node + + - name: Test + run: npm run test:node diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index e3304d29a7..0778129e84 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -23,6 +23,9 @@ jobs: runs-on: ${{ matrix.os }} + env: + KEEP_BUILD_ARTIFACTS: '1' + steps: - name: Checkout uses: actions/checkout@v3 @@ -36,21 +39,10 @@ jobs: key: ${{ matrix.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - name: cargo fmt - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + run: cargo fmt --all -- --check - name: cargo clippy - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --all-targets -- -D warnings + run: cargo clippy --all-targets -- -D warnings - name: cargo test - uses: actions-rs/cargo@v1 - env: - KEEP_BUILD_ARTIFACTS: '1' - with: - command: test - args: --verbose + run: cargo test --verbose diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index f65fdef77c..0746bb6a83 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -44,7 +44,7 @@ jobs: env: CC: ${{ matrix.build.cc }} CXX: ${{ matrix.build.cxx }} - MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: "true" + MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' steps: - name: Checkout @@ -73,7 +73,10 @@ jobs: restore-keys: | ${{ matrix.build.os }}-node-${{matrix.build.cc}}- - - run: npm run worker:build - - run: npm run test:worker + - name: Build + run: npm run worker:build + + - name: Test + run: npm run test:worker # TODO: Maybe fix this one day. if: runner.os != 'Windows' From e02622a11a60365c38c576fc0d967773d45143cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 8 Nov 2023 13:28:47 +0100 Subject: [PATCH 180/525] cosmetic --- .github/workflows/mediasoup-node.yaml | 6 +++--- .github/workflows/mediasoup-worker.yaml | 27 +++++++++++++++---------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index d901f61233..f22c707306 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -49,11 +49,11 @@ jobs: # NOTE: Add --force since otherwise `npm ci` fails in Node 16 because # @octokit/auth-token dev dependency requires Node >= 16. - - name: Install + - name: npm ci run: npm ci --force - - name: Lint + - name: npm run lint:node run: npm run lint:node - - name: Test + - name: npm run test:node run: npm run test:node diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 0746bb6a83..6045c4df11 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -55,15 +55,6 @@ jobs: with: node-version: ${{ matrix.node }} - # We need to install some NPM production deps for npm-scripts.mjs to work. - - run: npm ci --ignore-scripts --omit=dev - - run: npm run install-clang-tools - # TODO: Maybe fix this one day. - if: runner.os != 'Windows' - - run: npm run lint:worker - # TODO: Maybe fix this one day. - if: runner.os != 'Windows' - - name: Configure cache uses: actions/cache@v3 with: @@ -73,10 +64,24 @@ jobs: restore-keys: | ${{ matrix.build.os }}-node-${{matrix.build.cc}}- - - name: Build + # We need to install some NPM production deps for npm-scripts.mjs to work. + - name: npm ci + run: npm ci --ignore-scripts --omit=dev + + - name: npm run install-clang-tools + run: npm run install-clang-tools + # TODO: Maybe fix this one day. + if: runner.os != 'Windows' + + - name: npm run lint:worker + run: npm run lint:worker + # TODO: Maybe fix this one day. + if: runner.os != 'Windows' + + - name: npm run worker:build run: npm run worker:build - - name: Test + - name: npm run test:worker run: npm run test:worker # TODO: Maybe fix this one day. if: runner.os != 'Windows' From 3a2aa831010d1b2480ee3b61eeb8d078a2696107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 8 Nov 2023 13:34:36 +0100 Subject: [PATCH 181/525] more changes --- .github/workflows/mediasoup-worker-prebuild.yaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 5e5f588fc4..39392aae04 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -32,7 +32,7 @@ jobs: cc: cl cxx: cl node: - - 18 + - 20 runs-on: ${{ matrix.build.os }} @@ -51,10 +51,16 @@ jobs: node-version: ${{ matrix.node }} # We need to install some NPM production deps for npm-scripts.mjs to work. - - run: npm ci --ignore-scripts --omit=dev - - run: npm run worker:build + - name: npm ci + run: npm ci --ignore-scripts --omit=dev + + - name: npm run worker:build + run: npm run worker:build + # Publish prebuild binaries on tag. - - run: npm run worker:prebuild + - name: npm run worker:prebuild + run: npm run worker:prebuild + - name: Upload mediasoup-worker prebuilt binary uses: softprops/action-gh-release@v1 with: From ea0fb9712ea67a91765a134056bfc013cbf2009f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 9 Nov 2023 18:35:52 +0100 Subject: [PATCH 182/525] update types/debug NPM dep --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9bdac9a21e..58d5730e1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ }, "devDependencies": { "@octokit/rest": "^20.0.2", - "@types/debug": "^4.1.11", + "@types/debug": "^4.1.12", "@types/jest": "^29.5.8", "@types/node": "^20.9.0", "@typescript-eslint/eslint-plugin": "^6.10.0", @@ -1549,9 +1549,9 @@ } }, "node_modules/@types/debug": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.11.tgz", - "integrity": "sha512-R2qflTjHDs4CL6D/6TkqBeIHr54WzZfIxN729xvCNlYIVp2LknlnCro5Yo3frNaX2E5gO9pZ3/QAPVdGmu+q9w==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dev": true, "dependencies": { "@types/ms": "*" @@ -7936,9 +7936,9 @@ } }, "@types/debug": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.11.tgz", - "integrity": "sha512-R2qflTjHDs4CL6D/6TkqBeIHr54WzZfIxN729xvCNlYIVp2LknlnCro5Yo3frNaX2E5gO9pZ3/QAPVdGmu+q9w==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dev": true, "requires": { "@types/ms": "*" diff --git a/package.json b/package.json index dcfee51a4d..de77a45e87 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ }, "devDependencies": { "@octokit/rest": "^20.0.2", - "@types/debug": "^4.1.11", + "@types/debug": "^4.1.12", "@types/jest": "^29.5.8", "@types/node": "^20.9.0", "@typescript-eslint/eslint-plugin": "^6.10.0", From 1ab97962a7bd01f7fd503fc7fd4c91ff615fe5f0 Mon Sep 17 00:00:00 2001 From: Camille Oudot Date: Fri, 10 Nov 2023 09:44:08 +0100 Subject: [PATCH 183/525] Node: extract version from package.json using require() This allows JS bundlers such as webpack to embed the version string in the bundle. Otherwise a bundled JS app would look for mediasoup's package.json in "../.." on the filesystem (and it's very likely not there). --- node/src/index.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/node/src/index.ts b/node/src/index.ts index 4277b665d9..faf33812a7 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -1,5 +1,3 @@ -import * as fs from 'node:fs'; -import * as path from 'node:path'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { workerBin, Worker, WorkerSettings } from './Worker'; @@ -16,9 +14,8 @@ export { types }; /** * Expose mediasoup version. */ -export const { version } = JSON.parse(fs.readFileSync( - path.join(__dirname, '..', '..', 'package.json'), { encoding: 'utf-8' } -)); +// eslint-disable-next-line @typescript-eslint/no-var-requires +export const version: string = require('../../package.json').version; /** * Expose parseScalabilityMode() function. From e84ac6ffd239900ba3091b395e4b0fc3cb103b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 10 Nov 2023 13:05:02 +0100 Subject: [PATCH 184/525] 3.13.1 --- CHANGELOG.md | 5 +++++ package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91c6c107b6..ac74202929 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.13.1 + +* Node: Extract version from `package.json` using `require()` ([PR #1217](https://github.com/versatica/mediasoup/pull/1217) by @arcinston). + + ### 3.13.0 * Switch from JSON based messages to `flatbuffers` ([PR #1064](https://github.com/versatica/mediasoup/pull/1064)). diff --git a/package-lock.json b/package-lock.json index 58d5730e1c..6b16cbb039 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.0", + "version": "3.13.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.0", + "version": "3.13.1", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -27,7 +27,7 @@ "eslint": "^8.53.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^9.1.5", + "marked": "^9.1.6", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -4849,9 +4849,9 @@ } }, "node_modules/marked": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.5.tgz", - "integrity": "sha512-14QG3shv8Kg/xc0Yh6TNkMj90wXH9mmldi5941I2OevfJ/FQAFLEwtwU2/FfgSAOMlWHrEukWSGQf8MiVYNG2A==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz", + "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -10280,9 +10280,9 @@ "dev": true }, "marked": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.5.tgz", - "integrity": "sha512-14QG3shv8Kg/xc0Yh6TNkMj90wXH9mmldi5941I2OevfJ/FQAFLEwtwU2/FfgSAOMlWHrEukWSGQf8MiVYNG2A==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz", + "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==", "dev": true }, "meow": { diff --git a/package.json b/package.json index de77a45e87..0af57af123 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.0", + "version": "3.13.1", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -112,7 +112,7 @@ "eslint": "^8.53.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^9.1.5", + "marked": "^9.1.6", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From e441bb283b794556947e995072f17d927b4d817a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 13 Nov 2023 13:16:03 +0100 Subject: [PATCH 185/525] Update NPM marked dep to 10.0.0 --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6b16cbb039..31e1dcbc92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "eslint": "^8.53.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^9.1.6", + "marked": "^10.0.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -4849,15 +4849,15 @@ } }, "node_modules/marked": { - "version": "9.1.6", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz", - "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-10.0.0.tgz", + "integrity": "sha512-YiGcYcWj50YrwBgNzFoYhQ1hT6GmQbFG8SksnYJX1z4BXTHSOrz1GB5/Jm2yQvMg4nN1FHP4M6r03R10KrVUiA==", "dev": true, "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 16" + "node": ">= 18" } }, "node_modules/meow": { @@ -10280,9 +10280,9 @@ "dev": true }, "marked": { - "version": "9.1.6", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz", - "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-10.0.0.tgz", + "integrity": "sha512-YiGcYcWj50YrwBgNzFoYhQ1hT6GmQbFG8SksnYJX1z4BXTHSOrz1GB5/Jm2yQvMg4nN1FHP4M6r03R10KrVUiA==", "dev": true }, "meow": { diff --git a/package.json b/package.json index 0af57af123..59987fbef2 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "eslint": "^8.53.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^9.1.6", + "marked": "^10.0.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From f451275c675fff8450e53e7ac05c1a3742827dd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 14 Nov 2023 16:53:40 +0100 Subject: [PATCH 186/525] cosmetic: C++: add some brackets in if conditions --- worker/src/DepLibSRTP.cpp | 2 ++ worker/src/DepLibUV.cpp | 8 ++++++++ worker/src/DepUsrSCTP.cpp | 10 ++++++++++ 3 files changed, 20 insertions(+) diff --git a/worker/src/DepLibSRTP.cpp b/worker/src/DepLibSRTP.cpp index 70c7b8530a..e3c8c4be3f 100644 --- a/worker/src/DepLibSRTP.cpp +++ b/worker/src/DepLibSRTP.cpp @@ -59,7 +59,9 @@ void DepLibSRTP::ClassInit() const srtp_err_status_t err = srtp_init(); if (DepLibSRTP::IsError(err)) + { MS_THROW_ERROR("srtp_init() failed: %s", DepLibSRTP::GetErrorString(err)); + } } ++globalInstances; diff --git a/worker/src/DepLibUV.cpp b/worker/src/DepLibUV.cpp index dfe5f9b6fb..2871895033 100644 --- a/worker/src/DepLibUV.cpp +++ b/worker/src/DepLibUV.cpp @@ -27,7 +27,9 @@ inline static void onWalk(uv_handle_t* handle, void* /*arg*/) uv_has_ref(handle)); if (!uv_is_closing(handle)) + { uv_close(handle, onCloseLoop); + } } /* Static methods. */ @@ -41,7 +43,9 @@ void DepLibUV::ClassInit() const int err = uv_loop_init(DepLibUV::loop); if (err != 0) + { MS_ABORT("libuv loop initialization failed"); + } } void DepLibUV::ClassDestroy() @@ -63,13 +67,17 @@ void DepLibUV::ClassDestroy() err = uv_loop_close(DepLibUV::loop); if (err != UV_EBUSY) + { break; + } uv_run(DepLibUV::loop, UV_RUN_NOWAIT); } if (err != 0) + { MS_ERROR_STD("failed to close libuv loop: %s", uv_err_name(err)); + } delete DepLibUV::loop; } diff --git a/worker/src/DepUsrSCTP.cpp b/worker/src/DepUsrSCTP.cpp index 57b0a3cd51..a19eb51a04 100644 --- a/worker/src/DepUsrSCTP.cpp +++ b/worker/src/DepUsrSCTP.cpp @@ -127,7 +127,9 @@ uintptr_t DepUsrSCTP::GetNextSctpAssociationId() // NOTE: usrsctp_connect() fails with a value of 0. if (DepUsrSCTP::nextSctpAssociationId == 0u) + { ++DepUsrSCTP::nextSctpAssociationId; + } // In case we've wrapped around and need to find an empty spot from a removed // SctpAssociation. Assumes we'll never be full. @@ -137,7 +139,9 @@ uintptr_t DepUsrSCTP::GetNextSctpAssociationId() ++DepUsrSCTP::nextSctpAssociationId; if (DepUsrSCTP::nextSctpAssociationId == 0u) + { ++DepUsrSCTP::nextSctpAssociationId; + } } return DepUsrSCTP::nextSctpAssociationId++; @@ -160,7 +164,9 @@ void DepUsrSCTP::RegisterSctpAssociation(RTC::SctpAssociation* sctpAssociation) DepUsrSCTP::mapIdSctpAssociation[sctpAssociation->id] = sctpAssociation; if (++DepUsrSCTP::numSctpAssociations == 1u) + { DepUsrSCTP::checker->Start(); + } } void DepUsrSCTP::DeregisterSctpAssociation(RTC::SctpAssociation* sctpAssociation) @@ -177,7 +183,9 @@ void DepUsrSCTP::DeregisterSctpAssociation(RTC::SctpAssociation* sctpAssociation MS_ASSERT(DepUsrSCTP::numSctpAssociations > 0u, "numSctpAssociations was not higher than 0"); if (--DepUsrSCTP::numSctpAssociations == 0u) + { DepUsrSCTP::checker->Stop(); + } } RTC::SctpAssociation* DepUsrSCTP::RetrieveSctpAssociation(uintptr_t id) @@ -189,7 +197,9 @@ RTC::SctpAssociation* DepUsrSCTP::RetrieveSctpAssociation(uintptr_t id) auto it = DepUsrSCTP::mapIdSctpAssociation.find(id); if (it == DepUsrSCTP::mapIdSctpAssociation.end()) + { return nullptr; + } return it->second; } From b65509ef76e3948b01288b1b07d213066b387f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 14 Nov 2023 18:57:54 +0100 Subject: [PATCH 187/525] update Node deps --- package-lock.json | 332 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 168 insertions(+), 168 deletions(-) diff --git a/package-lock.json b/package-lock.json index 31e1dcbc92..5724f7b5f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,8 +22,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.8", "@types/node": "^20.9.0", - "@typescript-eslint/eslint-plugin": "^6.10.0", - "@typescript-eslint/parser": "^6.10.0", + "@typescript-eslint/eslint-plugin": "^6.11.0", + "@typescript-eslint/parser": "^6.11.0", "eslint": "^8.53.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", @@ -1661,16 +1661,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz", - "integrity": "sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.11.0.tgz", + "integrity": "sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/type-utils": "6.10.0", - "@typescript-eslint/utils": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/scope-manager": "6.11.0", + "@typescript-eslint/type-utils": "6.11.0", + "@typescript-eslint/utils": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1696,13 +1696,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", - "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", + "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0" + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1713,9 +1713,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", - "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", + "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1726,13 +1726,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", - "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", + "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1753,17 +1753,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", - "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz", + "integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/scope-manager": "6.11.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/typescript-estree": "6.11.0", "semver": "^7.5.4" }, "engines": { @@ -1778,12 +1778,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", - "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", + "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/types": "6.11.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1795,15 +1795,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz", - "integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.11.0.tgz", + "integrity": "sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/typescript-estree": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/scope-manager": "6.11.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/typescript-estree": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4" }, "engines": { @@ -1823,13 +1823,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", - "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", + "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0" + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1840,9 +1840,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", - "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", + "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1853,13 +1853,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", - "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", + "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1880,12 +1880,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", - "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", + "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/types": "6.11.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1914,13 +1914,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz", - "integrity": "sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.11.0.tgz", + "integrity": "sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.10.0", - "@typescript-eslint/utils": "6.10.0", + "@typescript-eslint/typescript-estree": "6.11.0", + "@typescript-eslint/utils": "6.11.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1941,13 +1941,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", - "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", + "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0" + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1958,9 +1958,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", - "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", + "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1971,13 +1971,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", - "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", + "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1998,17 +1998,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", - "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz", + "integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/scope-manager": "6.11.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/typescript-estree": "6.11.0", "semver": "^7.5.4" }, "engines": { @@ -2023,12 +2023,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", - "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", + "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/types": "6.11.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -8048,16 +8048,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz", - "integrity": "sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.11.0.tgz", + "integrity": "sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/type-utils": "6.10.0", - "@typescript-eslint/utils": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/scope-manager": "6.11.0", + "@typescript-eslint/type-utils": "6.11.0", + "@typescript-eslint/utils": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8067,29 +8067,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", - "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", + "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0" + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0" } }, "@typescript-eslint/types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", - "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", + "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", - "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", + "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8098,69 +8098,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", - "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz", + "integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/scope-manager": "6.11.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/typescript-estree": "6.11.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", - "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", + "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/types": "6.11.0", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz", - "integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.11.0.tgz", + "integrity": "sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/typescript-estree": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/scope-manager": "6.11.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/typescript-estree": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", - "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", + "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0" + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0" } }, "@typescript-eslint/types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", - "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", + "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", - "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", + "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8169,12 +8169,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", - "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", + "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/types": "6.11.0", "eslint-visitor-keys": "^3.4.1" } } @@ -8191,41 +8191,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz", - "integrity": "sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.11.0.tgz", + "integrity": "sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.10.0", - "@typescript-eslint/utils": "6.10.0", + "@typescript-eslint/typescript-estree": "6.11.0", + "@typescript-eslint/utils": "6.11.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", - "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", + "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0" + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0" } }, "@typescript-eslint/types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", - "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", + "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", - "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", + "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8234,27 +8234,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", - "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz", + "integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/scope-manager": "6.11.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/typescript-estree": "6.11.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", - "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", + "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/types": "6.11.0", "eslint-visitor-keys": "^3.4.1" } } diff --git a/package.json b/package.json index 59987fbef2..18aeb4257e 100644 --- a/package.json +++ b/package.json @@ -107,8 +107,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.8", "@types/node": "^20.9.0", - "@typescript-eslint/eslint-plugin": "^6.10.0", - "@typescript-eslint/parser": "^6.10.0", + "@typescript-eslint/eslint-plugin": "^6.11.0", + "@typescript-eslint/parser": "^6.11.0", "eslint": "^8.53.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", From 88a399d4ecb3105f95e34aae2a137c90b0a812f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 15 Nov 2023 12:46:12 +0100 Subject: [PATCH 188/525] C++: add brackers in if () conditions in all .cpp files --- .../src/RTC/RTCP/FuzzerFeedbackPsFir.cpp | 3 +- .../src/RTC/RTCP/FuzzerFeedbackPsLei.cpp | 3 +- .../src/RTC/RTCP/FuzzerFeedbackPsRpsi.cpp | 3 +- .../src/RTC/RTCP/FuzzerFeedbackPsSli.cpp | 3 +- .../src/RTC/RTCP/FuzzerFeedbackPsTst.cpp | 6 +- .../src/RTC/RTCP/FuzzerFeedbackPsVbcm.cpp | 3 +- .../src/RTC/RTCP/FuzzerFeedbackRtpEcn.cpp | 3 +- .../src/RTC/RTCP/FuzzerFeedbackRtpNack.cpp | 3 +- .../src/RTC/RTCP/FuzzerFeedbackRtpTllei.cpp | 3 +- .../src/RTC/RTCP/FuzzerFeedbackRtpTmmb.cpp | 6 +- worker/fuzzer/src/RTC/RTCP/FuzzerPacket.cpp | 4 + .../src/RTC/RTCP/FuzzerReceiverReport.cpp | 3 +- worker/fuzzer/src/RTC/RTCP/FuzzerSdes.cpp | 7 +- .../src/RTC/RTCP/FuzzerSenderReport.cpp | 5 +- worker/fuzzer/src/RTC/RTCP/FuzzerXr.cpp | 3 +- worker/src/Channel/ChannelSocket.cpp | 12 ++ worker/src/RTC/ActiveSpeakerObserver.cpp | 13 ++ worker/src/RTC/AudioLevelObserver.cpp | 12 ++ worker/src/RTC/Codecs/H264.cpp | 6 + worker/src/RTC/Codecs/H264_SVC.cpp | 30 ++++ worker/src/RTC/DataProducer.cpp | 1 + worker/src/RTC/IceServer.cpp | 8 + worker/src/RTC/PipeConsumer.cpp | 28 ++++ worker/src/RTC/PipeTransport.cpp | 26 ++++ worker/src/RTC/PortManager.cpp | 14 ++ worker/src/RTC/RTCP/Bye.cpp | 4 + worker/src/RTC/RTCP/CompoundPacket.cpp | 25 ++++ worker/src/RTC/RTCP/Feedback.cpp | 2 + worker/src/RTC/RTCP/FeedbackPsRemb.cpp | 2 + worker/src/RTC/RTCP/Packet.cpp | 10 ++ worker/src/RTC/RTCP/ReceiverReport.cpp | 2 + worker/src/RTC/RTCP/SenderReport.cpp | 2 + worker/src/RTC/RateCalculator.cpp | 13 ++ worker/src/RTC/Router.cpp | 16 ++ worker/src/RTC/RtpDictionaries/Parameters.cpp | 14 ++ .../RTC/RtpDictionaries/RtcpParameters.cpp | 2 + .../RTC/RtpDictionaries/RtpCodecMimeType.cpp | 4 + .../RtpDictionaries/RtpCodecParameters.cpp | 4 + .../RtpDictionaries/RtpEncodingParameters.cpp | 6 + .../RtpHeaderExtensionParameters.cpp | 2 + .../RtpDictionaries/RtpHeaderExtensionUri.cpp | 64 ++++++++ .../src/RTC/RtpDictionaries/RtpParameters.cpp | 39 +++++ worker/src/RTC/RtpListener.cpp | 14 ++ worker/src/RTC/RtpObserver.cpp | 4 + worker/src/RTC/RtpPacket.cpp | 38 +++++ worker/src/RTC/RtpProbationGenerator.cpp | 4 + worker/src/RTC/RtpStream.cpp | 10 ++ worker/src/RTC/RtxStream.cpp | 8 + worker/src/RTC/SctpAssociation.cpp | 36 +++++ .../SctpDictionaries/SctpStreamParameters.cpp | 4 + worker/src/RTC/SenderBandwidthEstimator.cpp | 12 ++ worker/src/RTC/SimpleConsumer.cpp | 52 +++++++ worker/src/RTC/SimulcastConsumer.cpp | 140 ++++++++++++++++++ worker/src/RTC/SrtpSession.cpp | 4 + worker/src/RTC/StunPacket.cpp | 44 ++++++ worker/src/RTC/SvcConsumer.cpp | 110 ++++++++++++++ worker/src/RTC/WebRtcTransport.cpp | 22 +++ worker/src/Settings.cpp | 64 ++++++++ worker/src/Utils/Crypto.cpp | 4 + worker/src/Utils/File.cpp | 6 + worker/src/Utils/IP.cpp | 12 ++ worker/src/Utils/String.cpp | 20 +++ worker/src/Worker.cpp | 22 +++ 63 files changed, 1014 insertions(+), 35 deletions(-) diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsFir.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsFir.cpp index dc48fcc4ca..27929efb9f 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsFir.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsFir.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::FeedbackPsFir::Fuzz(::RTC::RTCP::FeedbackPsFirPacket* pa // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsLei.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsLei.cpp index 51128fdd86..c1cf7e1d1a 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsLei.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsLei.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::FeedbackPsLei::Fuzz(::RTC::RTCP::FeedbackPsLeiPacket* pa // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsRpsi.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsRpsi.cpp index 51024f2a65..95d270581e 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsRpsi.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsRpsi.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::FeedbackPsRpsi::Fuzz(::RTC::RTCP::FeedbackPsRpsiPacket* // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsSli.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsSli.cpp index db69ff0593..989ca41171 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsSli.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsSli.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::FeedbackPsSli::Fuzz(::RTC::RTCP::FeedbackPsSliPacket* pa // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsTst.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsTst.cpp index 68b209b943..6d62d371fc 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsTst.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsTst.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::FeedbackPsTstn::Fuzz(::RTC::RTCP::FeedbackPsTstnPacket* // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); @@ -34,8 +33,7 @@ void Fuzzer::RTC::RTCP::FeedbackPsTstr::Fuzz(::RTC::RTCP::FeedbackPsTstrPacket* // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsVbcm.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsVbcm.cpp index 17542d5fcc..9ea8543acc 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsVbcm.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackPsVbcm.cpp @@ -12,8 +12,7 @@ void Fuzzer::RTC::RTCP::FeedbackPsVbcm::Fuzz(::RTC::RTCP::FeedbackPsVbcmPacket* // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpEcn.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpEcn.cpp index 54941c5e37..2e5199be52 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpEcn.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpEcn.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::FeedbackRtpEcn::Fuzz(::RTC::RTCP::FeedbackRtpEcnPacket* // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpNack.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpNack.cpp index f2725f9864..9070672208 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpNack.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpNack.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::FeedbackRtpNack::Fuzz(::RTC::RTCP::FeedbackRtpNackPacket // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpTllei.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpTllei.cpp index 58bd8b88ae..e3d76edc0f 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpTllei.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpTllei.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::FeedbackRtpTllei::Fuzz(::RTC::RTCP::FeedbackRtpTlleiPack // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpTmmb.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpTmmb.cpp index bbb8d773f9..1488e668ca 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpTmmb.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerFeedbackRtpTmmb.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::FeedbackRtpTmmbn::Fuzz(::RTC::RTCP::FeedbackRtpTmmbnPack // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); @@ -37,8 +36,7 @@ void Fuzzer::RTC::RTCP::FeedbackRtpTmmbr::Fuzz(::RTC::RTCP::FeedbackRtpTmmbrPack // TODO. // AddItem(Item* item); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& item = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerPacket.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerPacket.cpp index 43279e2aad..d1498ebc52 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerPacket.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerPacket.cpp @@ -11,7 +11,9 @@ void Fuzzer::RTC::RTCP::Packet::Fuzz(const uint8_t* data, size_t len) { if (!::RTC::RTCP::Packet::IsRtcp(data, len)) + { return; + } // We need to clone the given data into a separate buffer because setters // below will try to write into packet memory. @@ -22,7 +24,9 @@ void Fuzzer::RTC::RTCP::Packet::Fuzz(const uint8_t* data, size_t len) ::RTC::RTCP::Packet* packet = ::RTC::RTCP::Packet::Parse(data2, len); if (!packet) + { return; + } while (packet != nullptr) { diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerReceiverReport.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerReceiverReport.cpp index a7aa6c97bc..36d8028beb 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerReceiverReport.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerReceiverReport.cpp @@ -14,8 +14,7 @@ void Fuzzer::RTC::RTCP::ReceiverReport::Fuzz(::RTC::RTCP::ReceiverReportPacket* // TODO. // AddReport(ReceiverReport* report); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& report = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerSdes.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerSdes.cpp index 9d7442634b..aafc012295 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerSdes.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerSdes.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::Sdes::Fuzz(::RTC::RTCP::SdesPacket* packet) // TODO. // AddChunk(SdesChunk* chunk); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& chunk = (*it); @@ -24,15 +23,13 @@ void Fuzzer::RTC::RTCP::Sdes::Fuzz(::RTC::RTCP::SdesPacket* packet) // TODO // AddItem(SdesItem* item); - auto it2 = chunk->Begin(); - for (; it2 != chunk->End(); ++it2) + for (auto it2 = chunk->Begin(); it2 != chunk->End(); ++it2) { auto& item = (*it2); // item->Dump(); item->Serialize(::RTC::RTCP::Buffer); item->GetSize(); - item->GetType(); item->GetLength(); item->GetValue(); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerSenderReport.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerSenderReport.cpp index 3d91cc394a..26627cb34c 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerSenderReport.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerSenderReport.cpp @@ -5,7 +5,9 @@ void Fuzzer::RTC::RTCP::SenderReport::Fuzz(::RTC::RTCP::SenderReportPacket* pack { // A well formed packet must have a single report. if (packet->GetCount() == 1) + { packet->Serialize(::RTC::RTCP::Buffer); + } // packet->Dump(); packet->GetCount(); @@ -14,8 +16,7 @@ void Fuzzer::RTC::RTCP::SenderReport::Fuzz(::RTC::RTCP::SenderReportPacket* pack // TODO. // AddReport(SenderReport* report); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& report = (*it); diff --git a/worker/fuzzer/src/RTC/RTCP/FuzzerXr.cpp b/worker/fuzzer/src/RTC/RTCP/FuzzerXr.cpp index b81d128a03..ea65cbee12 100644 --- a/worker/fuzzer/src/RTC/RTCP/FuzzerXr.cpp +++ b/worker/fuzzer/src/RTC/RTCP/FuzzerXr.cpp @@ -10,8 +10,7 @@ void Fuzzer::RTC::RTCP::ExtendedReport::Fuzz(::RTC::RTCP::ExtendedReportPacket* packet->GetSsrc(); packet->SetSsrc(1111); - auto it = packet->Begin(); - for (; it != packet->End(); ++it) + for (auto it = packet->Begin(); it != packet->End(); ++it) { auto& report = (*it); diff --git a/worker/src/Channel/ChannelSocket.cpp b/worker/src/Channel/ChannelSocket.cpp index 570bc6c2f5..d9310692f8 100644 --- a/worker/src/Channel/ChannelSocket.cpp +++ b/worker/src/Channel/ChannelSocket.cpp @@ -79,7 +79,9 @@ namespace Channel MS_TRACE_STD(); if (!this->closed) + { Close(); + } delete this->consumerSocket; delete this->producerSocket; @@ -90,7 +92,9 @@ namespace Channel MS_TRACE_STD(); if (this->closed) + { return; + } this->closed = true; @@ -123,7 +127,9 @@ namespace Channel MS_TRACE_STD(); if (this->closed) + { return; + } if (messageLen > PayloadMaxLen) { @@ -140,7 +146,9 @@ namespace Channel MS_TRACE_STD(); if (this->closed) + { return; + } if (messageLen > PayloadMaxLen) { @@ -163,7 +171,9 @@ namespace Channel MS_TRACE_STD(); if (this->closed) + { return false; + } uint8_t* msg{ nullptr }; uint32_t msgLen; @@ -342,7 +352,9 @@ namespace Channel while (true) { if (IsClosed()) + { return; + } size_t readLen = this->bufferDataLen - msgStart; diff --git a/worker/src/RTC/ActiveSpeakerObserver.cpp b/worker/src/RTC/ActiveSpeakerObserver.cpp index ad332f6f51..b0f15ae037 100644 --- a/worker/src/RTC/ActiveSpeakerObserver.cpp +++ b/worker/src/RTC/ActiveSpeakerObserver.cpp @@ -106,9 +106,13 @@ namespace RTC this->interval = options->interval(); if (this->interval < 100) + { this->interval = 100; + } else if (this->interval > 5000) + { this->interval = 5000; + } this->periodicTimer = new TimerHandle(this); @@ -145,10 +149,14 @@ namespace RTC MS_TRACE(); if (producer->GetKind() != RTC::Media::Kind::AUDIO) + { MS_THROW_TYPE_ERROR("not an audio Producer"); + } if (this->mapProducerSpeakers.find(producer->id) != this->mapProducerSpeakers.end()) + { MS_THROW_ERROR("Producer already in map"); + } this->mapProducerSpeakers[producer->id] = new ProducerSpeaker(producer); } @@ -211,13 +219,18 @@ namespace RTC MS_TRACE(); if (IsPaused()) + { return; + } uint8_t level; bool voice; if (!packet->ReadSsrcAudioLevel(level, voice)) + { return; + } + uint8_t volume = 127 - level; auto it = this->mapProducerSpeakers.find(producer->id); diff --git a/worker/src/RTC/AudioLevelObserver.cpp b/worker/src/RTC/AudioLevelObserver.cpp index 2b0b6ccda4..126a3ac72d 100644 --- a/worker/src/RTC/AudioLevelObserver.cpp +++ b/worker/src/RTC/AudioLevelObserver.cpp @@ -27,12 +27,18 @@ namespace RTC this->interval = options->interval(); if (this->threshold > 0) + { MS_THROW_TYPE_ERROR("invalid threshold value %" PRIi8, this->threshold); + } if (this->interval < 250) + { this->interval = 250; + } else if (this->interval > 5000) + { this->interval = 5000; + } this->periodicTimer = new TimerHandle(this); @@ -59,7 +65,9 @@ namespace RTC MS_TRACE(); if (producer->GetKind() != RTC::Media::Kind::AUDIO) + { MS_THROW_TYPE_ERROR("not an audio Producer"); + } // Insert into the map. this->mapProducerDBovs[producer]; @@ -78,13 +86,17 @@ namespace RTC MS_TRACE(); if (IsPaused()) + { return; + } uint8_t volume; bool voice; if (!packet->ReadSsrcAudioLevel(volume, voice)) + { return; + } auto& dBovs = this->mapProducerDBovs.at(producer); diff --git a/worker/src/RTC/Codecs/H264.cpp b/worker/src/RTC/Codecs/H264.cpp index 2aa999f376..fef2c1d56e 100644 --- a/worker/src/RTC/Codecs/H264.cpp +++ b/worker/src/RTC/Codecs/H264.cpp @@ -170,11 +170,17 @@ namespace RTC this->d, this->b); if (this->hasTid) + { MS_DUMP(" tid : %" PRIu8, this->tid); + } if (this->hasLid) + { MS_DUMP(" lid : %" PRIu8, this->lid); + } if (this->hasTl0picidx) + { MS_DUMP(" tl0picidx : %" PRIu8, this->tl0picidx); + } MS_DUMP(" isKeyFrame : %s", this->isKeyFrame ? "true" : "false"); MS_DUMP("
"); } diff --git a/worker/src/RTC/Codecs/H264_SVC.cpp b/worker/src/RTC/Codecs/H264_SVC.cpp index 193e75d08c..f4ff7fc319 100644 --- a/worker/src/RTC/Codecs/H264_SVC.cpp +++ b/worker/src/RTC/Codecs/H264_SVC.cpp @@ -16,7 +16,9 @@ namespace RTC MS_TRACE(); if (len < 2) + { return nullptr; + } std::unique_ptr payloadDescriptor(new PayloadDescriptor()); @@ -47,7 +49,9 @@ namespace RTC // Detect key frame. if (frameMarking->start && frameMarking->independent) + { payloadDescriptor->isKeyFrame = true; + } } // NOTE: Unfortunately libwebrtc produces wrong Frame-Marking (without i=1 in @@ -74,7 +78,9 @@ namespace RTC H264_SVC::ParseSingleNalu(data, len, std::move(payloadDescriptor), true); if (payloadDescriptor == nullptr) + { return nullptr; + } break; } @@ -97,8 +103,11 @@ namespace RTC (len - sizeof(naluSize)), std::move(payloadDescriptor), true); + if (payloadDescriptor == nullptr) + { return nullptr; + } if (payloadDescriptor->isKeyFrame) { @@ -107,7 +116,9 @@ namespace RTC // Check if there is room for the indicated NAL unit size. if (len < (naluSize + sizeof(naluSize))) + { break; + } offset += naluSize + sizeof(naluSize); len -= naluSize + sizeof(naluSize); @@ -128,8 +139,11 @@ namespace RTC payloadDescriptor = H264_SVC::ParseSingleNalu( (data + 1), (len - 1), std::move(payloadDescriptor), (startBit == 128 ? true : false)); } + if (payloadDescriptor == nullptr) + { return nullptr; + } break; } @@ -174,14 +188,18 @@ namespace RTC payloadDescriptor->isKeyFrame = (isStartBit && payloadDescriptor->idr) ? true : false; if (len < ++offset + 1) + { return nullptr; + } byte = data[offset]; payloadDescriptor->noIntLayerPredFlag = byte >> 7 & 0x01; payloadDescriptor->slIndex = byte >> 4 & 0x03; if (len < ++offset + 1) + { return nullptr; + } byte = data[offset]; @@ -218,7 +236,9 @@ namespace RTC H264_SVC::Parse(data, len, frameMarking, frameMarkingLen); if (!payloadDescriptor) + { return; + } auto* payloadDescriptorHandler = new PayloadDescriptorHandler(payloadDescriptor); @@ -352,7 +372,9 @@ namespace RTC // Filter spatial layers higher than current one (unless old packet). if (packetSpatialLayer > tmpSpatialLayer && !isOldPacket) + { return false; + } // Check and handle temporal layer (unless old packet). if (!isOldPacket) @@ -402,20 +424,28 @@ namespace RTC // Filter temporal layers higher than current one. if (packetTemporalLayer > tmpTemporalLayer) + { return false; + } } // Set marker bit if needed. if (packetSpatialLayer == tmpSpatialLayer && this->payloadDescriptor->e) + { marker = true; + } // Update current spatial layer if needed. if (tmpSpatialLayer != context->GetCurrentSpatialLayer()) + { context->SetCurrentSpatialLayer(tmpSpatialLayer); + } // Update current temporal layer if needed. if (tmpTemporalLayer != context->GetCurrentTemporalLayer()) + { context->SetCurrentTemporalLayer(tmpTemporalLayer); + } return true; } diff --git a/worker/src/RTC/DataProducer.cpp b/worker/src/RTC/DataProducer.cpp index 34c9efc525..2bb16ecab6 100644 --- a/worker/src/RTC/DataProducer.cpp +++ b/worker/src/RTC/DataProducer.cpp @@ -31,6 +31,7 @@ namespace RTC break; } + case FBS::DataProducer::Type::DIRECT: { this->type = DataProducer::Type::DIRECT; diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index aac5716186..1584f8b54b 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -20,16 +20,24 @@ namespace RTC switch (state) { case FBS::WebRtcTransport::IceState::NEW: + { return IceServer::IceState::NEW; + } case FBS::WebRtcTransport::IceState::CONNECTED: + { return IceServer::IceState::CONNECTED; + } case FBS::WebRtcTransport::IceState::COMPLETED: + { return IceServer::IceState::COMPLETED; + } case FBS::WebRtcTransport::IceState::DISCONNECTED: + { return IceServer::IceState::DISCONNECTED; + } } } diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index 3af878f6db..d80cba0ab8 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -24,7 +24,9 @@ namespace RTC // Ensure there are as many encodings as consumable encodings. if (this->rtpParameters.encodings.size() != this->consumableRtpEncodings.size()) + { MS_THROW_TYPE_ERROR("number of rtpParameters.encodings and consumableRtpEncodings do not match"); + } auto& encoding = this->rtpParameters.encodings[0]; const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); @@ -124,7 +126,9 @@ namespace RTC case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) + { RequestKeyFrame(); + } request->Accept(); @@ -258,7 +262,9 @@ namespace RTC if (isSyncPacket) { if (packet->IsKeyFrame()) + { MS_DEBUG_TAG(rtp, "sync key frame received"); + } rtpSeqManager.Sync(packet->GetSequenceNumber() - 1); @@ -346,7 +352,9 @@ namespace RTC auto* report = rtpStream->GetRtcpSenderReport(nowMs); if (!report) + { continue; + } senderReports.push_back(report); @@ -367,7 +375,9 @@ namespace RTC // RTCP Compound packet buffer cannot hold the data. if (!packet->Add(senderReports, sdesChunks, xrReports)) + { return false; + } this->lastRtcpSentTime = nowMs; @@ -379,7 +389,9 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return; + } for (auto* rtpStream : this->rtpStreams) { @@ -387,7 +399,9 @@ namespace RTC // If our fraction lost is worse than the given one, update it. if (fractionLost > worstRemoteFractionLost) + { worstRemoteFractionLost = fractionLost; + } } } @@ -396,7 +410,9 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return; + } // May emit 'trace' event. EmitTraceEventNackType(); @@ -435,7 +451,9 @@ namespace RTC rtpStream->ReceiveKeyFrameRequest(messageType); if (IsActive()) + { RequestKeyFrame(); + } } void PipeConsumer::ReceiveRtcpReceiverReport(RTC::RTCP::ReceiverReport* report) @@ -462,7 +480,9 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return 0u; + } uint32_t rate{ 0u }; @@ -483,7 +503,9 @@ namespace RTC for (auto* rtpStream : this->rtpStreams) { if (rtpStream->GetRtt() > rtt) + { rtt = rtpStream->GetRtt(); + } } return rtt; @@ -626,12 +648,16 @@ namespace RTC // If the Consumer is paused, tell the RtpStreamSend. if (IsPaused() || IsProducerPaused()) + { rtpStream->Pause(); + } const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); if (rtxCodec && encoding.hasRtx) + { rtpStream->SetRtx(rtxCodec->payloadType, encoding.rtx.ssrc); + } this->rtpStreams.push_back(rtpStream); this->mapMappedSsrcSsrc[consumableEncoding.ssrc] = encoding.ssrc; @@ -646,7 +672,9 @@ namespace RTC MS_TRACE(); if (this->kind != RTC::Media::Kind::VIDEO) + { return; + } for (auto& consumableRtpEncoding : this->consumableRtpEncodings) { diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index 9c42fd9e33..950697b111 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -266,7 +266,9 @@ namespace RTC { // Ensure this method is not called twice. if (this->tuple) + { MS_THROW_ERROR("connect() already called"); + } try { @@ -306,7 +308,9 @@ namespace RTC auto* srtpKey = Utils::String::Base64Decode(srtpKeyBase64, outLen); if (outLen != PipeTransport::srtpMasterLength) + { MS_THROW_TYPE_ERROR("invalid decoded SRTP key length"); + } auto* srtpLocalKey = new uint8_t[PipeTransport::srtpMasterLength]; auto* srtpRemoteKey = new uint8_t[PipeTransport::srtpMasterLength]; @@ -351,7 +355,9 @@ namespace RTC } if (!flatbuffers::IsFieldPresent(body, FBS::PipeTransport::ConnectRequest::VT_IP)) + { MS_THROW_TYPE_ERROR("missing ip"); + } ip = body->ip()->str(); @@ -377,7 +383,9 @@ namespace RTC reinterpret_cast(&this->remoteAddrStorage)); if (err != 0) + { MS_THROW_ERROR("uv_ip4_addr() failed: %s", uv_strerror(err)); + } break; } @@ -390,7 +398,9 @@ namespace RTC reinterpret_cast(&this->remoteAddrStorage)); if (err != 0) + { MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); + } break; } @@ -507,13 +517,17 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } const uint8_t* data = packet->GetData(); auto intLen = static_cast(packet->GetSize()); if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &intLen)) + { return; + } auto len = static_cast(intLen); @@ -528,7 +542,9 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } packet->Serialize(RTC::RTCP::Buffer); @@ -536,7 +552,9 @@ namespace RTC auto intLen = static_cast(packet->GetSize()); if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &intLen)) + { return; + } auto len = static_cast(intLen); @@ -559,7 +577,9 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } this->tuple->Send(data, len); @@ -620,7 +640,9 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } // Decrypt the SRTP packet. auto intLen = static_cast(len); @@ -680,7 +702,9 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } // Decrypt the SRTCP packet. auto intLen = static_cast(len); @@ -717,7 +741,9 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } // Verify that the packet's tuple matches our tuple. if (!this->tuple->Compare(tuple)) diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index 5b0023ca58..0d19d686f3 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -75,7 +75,9 @@ namespace RTC err = uv_ip4_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); if (err != 0) + { MS_THROW_ERROR("uv_ip4_addr() failed: %s", uv_strerror(err)); + } break; } @@ -85,7 +87,9 @@ namespace RTC err = uv_ip6_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); if (err != 0) + { MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); + } // Don't also bind into IPv4 when listening in IPv6. flags |= UV_UDP_IPV6ONLY; @@ -277,7 +281,9 @@ namespace RTC // If it succeeded, exit the loop here. if (err == 0) + { break; + } // If it failed, close the handle and check the reason. switch (transport) @@ -382,7 +388,9 @@ namespace RTC err = uv_ip4_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); if (err != 0) + { MS_THROW_ERROR("uv_ip4_addr() failed: %s", uv_strerror(err)); + } break; } @@ -392,7 +400,9 @@ namespace RTC err = uv_ip6_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); if (err != 0) + { MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); + } // Don't also bind into IPv4 when listening in IPv6. flags |= UV_UDP_IPV6ONLY; @@ -558,7 +568,9 @@ namespace RTC auto it = PortManager::mapUdpIpPorts.find(ip); if (it == PortManager::mapUdpIpPorts.end()) + { return; + } auto& ports = it->second; @@ -573,7 +585,9 @@ namespace RTC auto it = PortManager::mapTcpIpPorts.find(ip); if (it == PortManager::mapTcpIpPorts.end()) + { return; + } auto& ports = it->second; diff --git a/worker/src/RTC/RTCP/Bye.cpp b/worker/src/RTC/RTCP/Bye.cpp index 8673d06449..94772b5eed 100644 --- a/worker/src/RTC/RTCP/Bye.cpp +++ b/worker/src/RTC/RTCP/Bye.cpp @@ -42,7 +42,9 @@ namespace RTC offset += 1u; if (length <= len - offset) + { packet->SetReason(std::string(reinterpret_cast(data) + offset, length)); + } } return packet.release(); @@ -95,7 +97,9 @@ namespace RTC MS_DUMP(" ssrc : %" PRIu32, ssrc); } if (!this->reason.empty()) + { MS_DUMP(" reason : %s", this->reason.c_str()); + } MS_DUMP(""); } } // namespace RTCP diff --git a/worker/src/RTC/RTCP/CompoundPacket.cpp b/worker/src/RTC/RTCP/CompoundPacket.cpp index ff1b875373..811968b850 100644 --- a/worker/src/RTC/RTCP/CompoundPacket.cpp +++ b/worker/src/RTC/RTCP/CompoundPacket.cpp @@ -18,16 +18,21 @@ namespace RTC { size += this->senderReportPacket.GetSize(); } + if (this->receiverReportPacket.GetCount() > 0u) { size += this->receiverReportPacket.GetSize(); } if (this->sdesPacket.GetCount() > 0u) + { size += this->sdesPacket.GetSize(); + } if (this->xrPacket.Begin() != this->xrPacket.End()) + { size += this->xrPacket.GetSize(); + } return size; } @@ -72,17 +77,25 @@ namespace RTC // Add the items into the packet. if (senderReport) + { this->senderReportPacket.AddReport(senderReport); + } if (sdesChunk) + { this->sdesPacket.AddChunk(sdesChunk); + } if (delaySinceLastRrReport) + { this->xrPacket.AddReport(delaySinceLastRrReport); + } // New items can hold in the packet, report it. if (GetSize() <= MaxSize) + { return true; + } // New items can not hold in the packet, remove them, // delete and report it. @@ -126,7 +139,9 @@ namespace RTC // New items can hold in the packet, report it. if (GetSize() <= MaxSize) + { return true; + } // New items can not hold in the packet, remove them, // delete and report it. @@ -162,11 +177,15 @@ namespace RTC this->receiverReportPacket.AddReport(report); if (receiverReferenceTimeReport) + { this->xrPacket.AddReport(receiverReferenceTimeReport); + } // New items can hold in the packet, report it. if (GetSize() <= MaxSize) + { return true; + } // New items can not hold in the packet, remove them, // delete and report it. @@ -197,7 +216,9 @@ namespace RTC this->senderReportPacket.Dump(); if (this->receiverReportPacket.GetCount() != 0u) + { this->receiverReportPacket.Dump(); + } } else { @@ -205,10 +226,14 @@ namespace RTC } if (this->sdesPacket.GetCount() != 0u) + { this->sdesPacket.Dump(); + } if (this->xrPacket.Begin() != this->xrPacket.End()) + { this->xrPacket.Dump(); + } MS_DUMP(""); } diff --git a/worker/src/RTC/RTCP/Feedback.cpp b/worker/src/RTC/RTCP/Feedback.cpp index 37178ead5e..0ba7d01a7e 100644 --- a/worker/src/RTC/RTCP/Feedback.cpp +++ b/worker/src/RTC/RTCP/Feedback.cpp @@ -34,7 +34,9 @@ namespace RTC auto it = FeedbackPacket::type2String.find(type); if (it == FeedbackPacket::type2String.end()) + { return Unknown; + } return it->second; } diff --git a/worker/src/RTC/RTCP/FeedbackPsRemb.cpp b/worker/src/RTC/RTCP/FeedbackPsRemb.cpp index 7bb9833d69..a4855984ba 100644 --- a/worker/src/RTC/RTCP/FeedbackPsRemb.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsRemb.cpp @@ -32,7 +32,9 @@ namespace RTC std::unique_ptr packet(new FeedbackPsRembPacket(commonHeader, len)); if (!packet->IsCorrect()) + { return nullptr; + } return packet.release(); } diff --git a/worker/src/RTC/RTCP/Packet.cpp b/worker/src/RTC/RTCP/Packet.cpp index 599a94a435..bb9a47b949 100644 --- a/worker/src/RTC/RTCP/Packet.cpp +++ b/worker/src/RTC/RTCP/Packet.cpp @@ -76,14 +76,18 @@ namespace RTC current = SenderReportPacket::Parse(data, packetLen); if (!current) + { break; + } if (header->count > 0) { Packet* rr = ReceiverReportPacket::Parse(data, packetLen, current->GetSize()); if (!rr) + { break; + } current->SetNext(rr); } @@ -172,9 +176,13 @@ namespace RTC len -= packetLen; if (!first) + { first = current; + } else + { last->SetNext(current); + } last = current->GetNext() != nullptr ? current->GetNext() : current; } @@ -191,7 +199,9 @@ namespace RTC auto it = Packet::type2String.find(type); if (it == Packet::type2String.end()) + { return Unknown; + } return it->second; } diff --git a/worker/src/RTC/RTCP/ReceiverReport.cpp b/worker/src/RTC/RTCP/ReceiverReport.cpp index 2ae8f747fe..4ca41739e5 100644 --- a/worker/src/RTC/RTCP/ReceiverReport.cpp +++ b/worker/src/RTC/RTCP/ReceiverReport.cpp @@ -92,7 +92,9 @@ namespace RTC packet->SetSsrc(ssrc); if (offset == 0) + { offset = Packet::CommonHeaderSize + 4u /* ssrc */; + } uint8_t count = header->count; diff --git a/worker/src/RTC/RTCP/SenderReport.cpp b/worker/src/RTC/RTCP/SenderReport.cpp index 89d835c6ec..510ecc06c6 100644 --- a/worker/src/RTC/RTCP/SenderReport.cpp +++ b/worker/src/RTC/RTCP/SenderReport.cpp @@ -70,7 +70,9 @@ namespace RTC SenderReport* report = SenderReport::Parse(data + offset, len - offset); if (report) + { packet->AddReport(report); + } return packet.release(); } diff --git a/worker/src/RTC/RateCalculator.cpp b/worker/src/RTC/RateCalculator.cpp index b449eb7d06..6d0e9f709c 100644 --- a/worker/src/RTC/RateCalculator.cpp +++ b/worker/src/RTC/RateCalculator.cpp @@ -13,7 +13,9 @@ namespace RTC // Ignore too old data. Should never happen. if (nowMs < this->oldestItemStartTime) + { return; + } // Increase bytes. this->bytes += size; @@ -26,8 +28,11 @@ namespace RTC { this->newestItemIndex++; this->newestItemStartTime = nowMs; + if (this->newestItemIndex >= this->windowItems) + { this->newestItemIndex = 0; + } MS_ASSERT( this->newestItemIndex != this->oldestItemIndex || this->oldestItemIndex == -1, @@ -65,7 +70,9 @@ namespace RTC MS_TRACE(); if (nowMs == this->lastTime) + { return this->lastRate; + } RemoveOldData(nowMs); @@ -83,13 +90,17 @@ namespace RTC // No item set. if (this->newestItemIndex < 0 || this->oldestItemIndex < 0) + { return; + } const uint64_t newOldestTime = nowMs - this->windowSizeMs; // Oldest item already removed. if (newOldestTime < this->oldestItemStartTime) + { return; + } // A whole window size time has elapsed since last entry. Reset the buffer. if (newOldestTime >= this->newestItemStartTime) @@ -107,7 +118,9 @@ namespace RTC oldestItem.time = 0u; if (++this->oldestItemIndex >= this->windowItems) + { this->oldestItemIndex = 0; + } const BufferItem& newOldestItem = this->buffer[this->oldestItemIndex]; this->oldestItemStartTime = newOldestItem.time; diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index 33e543909b..3313b58031 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -246,7 +246,9 @@ namespace RTC auto* webRtcServer = this->listener->OnRouterNeedWebRtcServer(this, webRtcServerId); if (!webRtcServer) + { MS_THROW_ERROR("wrong webRtcServerId (no associated WebRtcServer found)"); + } auto iceCandidates = webRtcServer->GetIceCandidates( options->enableUdp(), options->enableTcp(), options->preferUdp(), options->preferTcp()); @@ -443,13 +445,17 @@ namespace RTC void Router::CheckNoTransport(const std::string& transportId) const { if (this->mapTransports.find(transportId) != this->mapTransports.end()) + { MS_THROW_ERROR("a Transport with same id already exists"); + } } void Router::CheckNoRtpObserver(const std::string& rtpObserverId) const { if (this->mapRtpObservers.find(rtpObserverId) != this->mapRtpObservers.end()) + { MS_THROW_ERROR("an RtpObserver with same id already exists"); + } } RTC::Transport* Router::GetTransportById(const std::string& transportId) const @@ -459,7 +465,9 @@ namespace RTC auto it = this->mapTransports.find(transportId); if (this->mapTransports.find(transportId) == this->mapTransports.end()) + { MS_THROW_ERROR("Transport not found"); + } return it->second; } @@ -471,7 +479,9 @@ namespace RTC auto it = this->mapRtpObservers.find(rtpObserverId); if (this->mapRtpObservers.find(rtpObserverId) == this->mapRtpObservers.end()) + { MS_THROW_ERROR("RtpObserver not found"); + } return it->second; } @@ -656,7 +666,9 @@ namespace RTC const auto& mid = consumer->GetRtpParameters().mid; if (!mid.empty()) + { packet->UpdateMid(mid); + } consumer->SendRtpPacket(packet, sharedPacket); } @@ -699,7 +711,9 @@ namespace RTC auto mapProducersIt = this->mapProducers.find(producerId); if (mapProducersIt == this->mapProducers.end()) + { MS_THROW_ERROR("Producer not found [producerId:%s]", producerId.c_str()); + } auto* producer = mapProducersIt->second; auto mapProducerConsumersIt = this->mapProducerConsumers.find(producer); @@ -1025,7 +1039,9 @@ namespace RTC auto it = this->mapProducers.find(id); if (it == this->mapProducers.end()) + { MS_THROW_ERROR("Producer not found"); + } RTC::Producer* producer = it->second; diff --git a/worker/src/RTC/RtpDictionaries/Parameters.cpp b/worker/src/RTC/RtpDictionaries/Parameters.cpp index c6ce8df665..2376c73838 100644 --- a/worker/src/RTC/RtpDictionaries/Parameters.cpp +++ b/worker/src/RTC/RtpDictionaries/Parameters.cpp @@ -139,7 +139,9 @@ namespace RTC auto it = this->mapKeyValues.find(key); if (it == this->mapKeyValues.end()) + { return false; + } const auto& value = it->second; @@ -153,7 +155,9 @@ namespace RTC auto it = this->mapKeyValues.find(key); if (it == this->mapKeyValues.end()) + { return false; + } const auto& value = it->second; @@ -167,7 +171,9 @@ namespace RTC auto it = this->mapKeyValues.find(key); if (it == this->mapKeyValues.end()) + { return false; + } const auto& value = it->second; @@ -181,7 +187,9 @@ namespace RTC auto it = this->mapKeyValues.find(key); if (it == this->mapKeyValues.end()) + { return false; + } const auto& value = it->second; @@ -195,7 +203,9 @@ namespace RTC auto it = this->mapKeyValues.find(key); if (it == this->mapKeyValues.end()) + { return false; + } const auto& value = it->second; @@ -209,7 +219,9 @@ namespace RTC auto it = this->mapKeyValues.find(key); if (it == this->mapKeyValues.end()) + { return false; + } const auto& value = it->second; @@ -223,7 +235,9 @@ namespace RTC auto it = this->mapKeyValues.find(key); if (it == this->mapKeyValues.end()) + { return false; + } const auto& value = it->second; const auto& array = value.arrayOfIntegers; diff --git a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp index c98713a9f9..7766cf3881 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp @@ -16,7 +16,9 @@ namespace RTC // cname is optional. if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtcpParameters::VT_CNAME)) + { this->cname = data->cname()->str(); + } // reducedSize is optional, default value is true. this->reducedSize = data->reducedSize(); diff --git a/worker/src/RTC/RtpDictionaries/RtpCodecMimeType.cpp b/worker/src/RTC/RtpDictionaries/RtpCodecMimeType.cpp index b49f42844f..ae87b1eea7 100644 --- a/worker/src/RTC/RtpDictionaries/RtpCodecMimeType.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpCodecMimeType.cpp @@ -104,7 +104,9 @@ namespace RTC auto it = RtpCodecMimeType::string2Type.find(type); if (it == RtpCodecMimeType::string2Type.end()) + { MS_THROW_TYPE_ERROR("unknown codec MIME type '%s'", type.c_str()); + } this->type = it->second; } @@ -114,7 +116,9 @@ namespace RTC auto it = RtpCodecMimeType::string2Subtype.find(subtype); if (it == RtpCodecMimeType::string2Subtype.end()) + { MS_THROW_TYPE_ERROR("unknown codec MIME subtype '%s'", subtype.c_str()); + } this->subtype = it->second; } diff --git a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp index 92655338ef..024e4229d0 100644 --- a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp @@ -32,7 +32,9 @@ namespace RTC // parameters is optional. if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpCodecParameters::VT_PARAMETERS)) + { this->parameters.Set(data->parameters()); + } // rtcpFeedback is optional. if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpCodecParameters::VT_RTCPFEEDBACK)) @@ -87,7 +89,9 @@ namespace RTC { // A RTX codec must have 'apt' parameter. if (!this->parameters.HasPositiveInteger(aptString)) + { MS_THROW_TYPE_ERROR("missing apt parameter in RTX codec"); + } break; } diff --git a/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp index e046c350e6..ec79f515bf 100644 --- a/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp @@ -18,11 +18,15 @@ namespace RTC // ssrc is optional. if (data->ssrc().has_value()) + { this->ssrc = data->ssrc().value(); + } // rid is optional. if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpEncodingParameters::VT_RID)) + { this->rid = data->rid()->str(); + } // codecPayloadType is optional. if (data->codecPayloadType().has_value()) @@ -40,7 +44,9 @@ namespace RTC // maxBitrate is optional. if (data->maxBitrate().has_value()) + { this->maxBitrate = data->maxBitrate().value(); + } // dtx is optional, default is false. this->dtx = data->dtx(); diff --git a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp index 3810a759d0..96e0e3a6a7 100644 --- a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp @@ -22,7 +22,9 @@ namespace RTC // Don't allow id 0. if (this->id == 0u) + { MS_THROW_TYPE_ERROR("invalid id 0"); + } // encrypt is false by default. this->encrypt = data->encrypt(); diff --git a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp index e5125ea90c..051e42f5ae 100644 --- a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp @@ -15,27 +15,59 @@ namespace RTC switch (uri) { case FBS::RtpParameters::RtpHeaderExtensionUri::Mid: + { return RtpHeaderExtensionUri::Type::MID; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::RtpStreamId: + { return RtpHeaderExtensionUri::Type::RTP_STREAM_ID; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::RepairRtpStreamId: + { return RtpHeaderExtensionUri::Type::REPAIRED_RTP_STREAM_ID; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::FrameMarkingDraft07: + { return RtpHeaderExtensionUri::Type::FRAME_MARKING_07; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::FrameMarking: + { return RtpHeaderExtensionUri::Type::FRAME_MARKING; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::AudioLevel: + { return RtpHeaderExtensionUri::Type::SSRC_AUDIO_LEVEL; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::VideoOrientation: + { return RtpHeaderExtensionUri::Type::VIDEO_ORIENTATION; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::TimeOffset: + { return RtpHeaderExtensionUri::Type::TOFFSET; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::TransportWideCcDraft01: + { return RtpHeaderExtensionUri::Type::TRANSPORT_WIDE_CC_01; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::AbsSendTime: + { return RtpHeaderExtensionUri::Type::ABS_SEND_TIME; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::AbsCaptureTime: + { return RtpHeaderExtensionUri::Type::ABS_CAPTURE_TIME; + } } } @@ -45,27 +77,59 @@ namespace RTC switch (uri) { case RtpHeaderExtensionUri::Type::MID: + { return FBS::RtpParameters::RtpHeaderExtensionUri::Mid; + } + case RtpHeaderExtensionUri::Type::RTP_STREAM_ID: + { return FBS::RtpParameters::RtpHeaderExtensionUri::RtpStreamId; + } + case RtpHeaderExtensionUri::Type::REPAIRED_RTP_STREAM_ID: + { return FBS::RtpParameters::RtpHeaderExtensionUri::RepairRtpStreamId; + } + case RtpHeaderExtensionUri::Type::ABS_SEND_TIME: + { return FBS::RtpParameters::RtpHeaderExtensionUri::AbsSendTime; + } + case RtpHeaderExtensionUri::Type::TRANSPORT_WIDE_CC_01: + { return FBS::RtpParameters::RtpHeaderExtensionUri::TransportWideCcDraft01; + } + case RtpHeaderExtensionUri::Type::FRAME_MARKING_07: + { return FBS::RtpParameters::RtpHeaderExtensionUri::FrameMarkingDraft07; + } + case RtpHeaderExtensionUri::Type::FRAME_MARKING: + { return FBS::RtpParameters::RtpHeaderExtensionUri::FrameMarking; + } + case RtpHeaderExtensionUri::Type::SSRC_AUDIO_LEVEL: + { return FBS::RtpParameters::RtpHeaderExtensionUri::AudioLevel; + } + case RtpHeaderExtensionUri::Type::VIDEO_ORIENTATION: + { return FBS::RtpParameters::RtpHeaderExtensionUri::VideoOrientation; + } + case RtpHeaderExtensionUri::Type::TOFFSET: + { return FBS::RtpParameters::RtpHeaderExtensionUri::TimeOffset; + } + case RtpHeaderExtensionUri::Type::ABS_CAPTURE_TIME: + { return FBS::RtpParameters::RtpHeaderExtensionUri::AbsCaptureTime; + } } } diff --git a/worker/src/RTC/RtpDictionaries/RtpParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpParameters.cpp index df62479110..490d1f8dbe 100644 --- a/worker/src/RTC/RtpDictionaries/RtpParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpParameters.cpp @@ -72,13 +72,24 @@ namespace RTC switch (type) { case Type::SIMPLE: + { return FBS::RtpParameters::Type::SIMPLE; + } + case Type::SIMULCAST: + { return FBS::RtpParameters::Type::SIMULCAST; + } + case Type::SVC: + { return FBS::RtpParameters::Type::SVC; + } + case Type::PIPE: + { return FBS::RtpParameters::Type::PIPE; + } } } @@ -94,7 +105,9 @@ namespace RTC this->mid = data->mid()->str(); if (this->mid.empty()) + { MS_THROW_TYPE_ERROR("empty mid"); + } } this->codecs.reserve(data->codecs()->size()); @@ -106,7 +119,9 @@ namespace RTC } if (this->codecs.empty()) + { MS_THROW_TYPE_ERROR("empty codecs"); + } this->encodings.reserve(data->encodings()->size()); @@ -117,7 +132,9 @@ namespace RTC } if (this->encodings.empty()) + { MS_THROW_TYPE_ERROR("empty encodings"); + } this->headerExtensions.reserve(data->headerExtensions()->size()); @@ -188,12 +205,16 @@ namespace RTC const auto& codec = *it; if (codec.payloadType == payloadType) + { return std::addressof(codec); + } } // This should never happen. if (it == this->codecs.end()) + { MS_ABORT("no valid codec payload type for the given encoding"); + } return nullptr; } @@ -228,7 +249,9 @@ namespace RTC for (auto& codec : this->codecs) { if (payloadTypes.find(codec.payloadType) != payloadTypes.end()) + { MS_THROW_TYPE_ERROR("duplicated payloadType"); + } payloadTypes.insert(codec.payloadType); @@ -248,18 +271,28 @@ namespace RTC if (static_cast(codec.payloadType) == apt) { if (codec.mimeType.subtype == RTC::RtpCodecMimeType::Subtype::RTX) + { MS_THROW_TYPE_ERROR("apt in RTX codec points to a RTX codec"); + } else if (codec.mimeType.subtype == RTC::RtpCodecMimeType::Subtype::ULPFEC) + { MS_THROW_TYPE_ERROR("apt in RTX codec points to a ULPFEC codec"); + } else if (codec.mimeType.subtype == RTC::RtpCodecMimeType::Subtype::FLEXFEC) + { MS_THROW_TYPE_ERROR("apt in RTX codec points to a FLEXFEC codec"); + } else + { break; + } } } if (it == this->codecs.end()) + { MS_THROW_TYPE_ERROR("apt in RTX codec points to a non existing codec"); + } break; } @@ -290,7 +323,9 @@ namespace RTC } if (it == this->codecs.end()) + { MS_THROW_TYPE_ERROR("no media codecs found"); + } } // Iterate all the encodings, set the first payloadType in all of them with @@ -323,14 +358,18 @@ namespace RTC { // Must be a media codec. if (codec.mimeType.IsMediaCodec()) + { break; + } MS_THROW_TYPE_ERROR("invalid codecPayloadType"); } } if (it == this->codecs.end()) + { MS_THROW_TYPE_ERROR("unknown codecPayloadType"); + } } } } diff --git a/worker/src/RTC/RtpListener.cpp b/worker/src/RTC/RtpListener.cpp index e8a4e43e24..c11b43e44a 100644 --- a/worker/src/RTC/RtpListener.cpp +++ b/worker/src/RTC/RtpListener.cpp @@ -123,7 +123,9 @@ namespace RTC const auto& rid = encoding.rid; if (rid.empty()) + { continue; + } if (this->ridTable.find(rid) == this->ridTable.end()) { @@ -148,25 +150,37 @@ namespace RTC for (auto it = this->ssrcTable.begin(); it != this->ssrcTable.end();) { if (it->second == producer) + { it = this->ssrcTable.erase(it); + } else + { ++it; + } } for (auto it = this->midTable.begin(); it != this->midTable.end();) { if (it->second == producer) + { it = this->midTable.erase(it); + } else + { ++it; + } } for (auto it = this->ridTable.begin(); it != this->ridTable.end();) { if (it->second == producer) + { it = this->ridTable.erase(it); + } else + { ++it; + } } } diff --git a/worker/src/RTC/RtpObserver.cpp b/worker/src/RTC/RtpObserver.cpp index 203ee99cea..b8c66bf72b 100644 --- a/worker/src/RTC/RtpObserver.cpp +++ b/worker/src/RTC/RtpObserver.cpp @@ -89,7 +89,9 @@ namespace RTC MS_TRACE(); if (this->paused) + { return; + } this->paused = true; @@ -101,7 +103,9 @@ namespace RTC MS_TRACE(); if (!this->paused) + { return; + } this->paused = false; diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index dae9b41e10..8ebe9cce96 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -17,7 +17,9 @@ namespace RTC MS_TRACE(); if (!RtpPacket::IsRtp(data, len)) + { return nullptr; + } auto* ptr = const_cast(data); @@ -136,7 +138,9 @@ namespace RTC MS_TRACE(); if (this->header->csrcCount != 0u) + { this->csrcList = reinterpret_cast(header) + HeaderSize; + } // Parse RFC 5285 header extension. ParseExtensions(); @@ -408,9 +412,13 @@ namespace RTC else if (this->headerExtension) { if (type == 1u) + { this->headerExtension->id = uint16_t{ htons(0xBEDE) }; + } else if (type == 2u) + { this->headerExtension->id = uint16_t{ htons(0b0001000000000000) }; + } } // Calculate total size required for all extensions (with padding if needed). @@ -486,9 +494,13 @@ namespace RTC // Set the header extension id. if (type == 1u) + { this->headerExtension->id = uint16_t{ htons(0xBEDE) }; + } else if (type == 2u) + { this->headerExtension->id = uint16_t{ htons(0b0001000000000000) }; + } // Set the header extension length. this->headerExtension->length = htons(extensionsTotalSize / 4); @@ -502,7 +514,9 @@ namespace RTC if (type == 1u) { if (extension.id == 0 || extension.id > 14 || extension.len == 0 || extension.len > 16) + { continue; + } // Store the One-Byte extension element in an array. // `-1` because we have 14 elements total 0..13 and `id` is in the range 1..14. @@ -516,7 +530,9 @@ namespace RTC else if (type == 2u) { if (extension.id == 0) + { continue; + } // Store the Two-Bytes extension element in the map. this->mapTwoBytesExtensions[extension.id] = reinterpret_cast(ptr); @@ -547,7 +563,9 @@ namespace RTC uint8_t* extenValue = GetExtension(this->midExtensionId, extenLen); if (!extenValue) + { return; + } const size_t midLen = mid.length(); @@ -593,13 +611,17 @@ namespace RTC auto* extension = this->oneByteExtensions[id - 1]; if (!extension) + { return false; + } auto currentLen = extension->len + 1; // Fill with 0's if new length is minor. if (len < currentLen) + { std::memset(extension->value + len, 0, currentLen - len); + } // In One-Byte extensions value length 0 means 1. extension->len = len - 1; @@ -611,14 +633,18 @@ namespace RTC auto it = this->mapTwoBytesExtensions.find(id); if (it == this->mapTwoBytesExtensions.end()) + { return false; + } auto* extension = it->second; auto currentLen = extension->len; // Fill with 0's if new length is minor. if (len < currentLen) + { std::memset(extension->value + len, 0, currentLen - len); + } extension->len = len; @@ -771,7 +797,9 @@ namespace RTC // Chrome sends some RTX packets with no payload when the stream is started. // Just ignore them. if (this->payloadLength < 2u) + { return false; + } // Rewrite the payload type. SetPayloadType(payloadType); @@ -808,7 +836,9 @@ namespace RTC MS_TRACE(); if (!this->payloadDescriptorHandler) + { return true; + } if (this->payloadDescriptorHandler->Process(context, this->payload, marker)) { @@ -825,7 +855,9 @@ namespace RTC MS_TRACE(); if (!this->payloadDescriptorHandler) + { return; + } this->payloadDescriptorHandler->Restore(this->payload); } @@ -835,12 +867,16 @@ namespace RTC MS_TRACE(); if (shift == 0u) + { return; + } MS_ASSERT(payloadOffset < this->payloadLength, "payload offset bigger than payload size"); if (!expand) + { MS_ASSERT(shift <= (this->payloadLength - payloadOffset), "shift too big"); + } uint8_t* payloadOffsetPtr = this->payload + payloadOffset; size_t shiftedLen{ 0 }; @@ -887,7 +923,9 @@ namespace RTC // id=15 in One-Byte extensions means "stop parsing here". if (id == 15u) + { break; + } // Valid extension id. if (id != 0u) diff --git a/worker/src/RTC/RtpProbationGenerator.cpp b/worker/src/RTC/RtpProbationGenerator.cpp index 1fe7ec6596..959bf7470a 100644 --- a/worker/src/RTC/RtpProbationGenerator.cpp +++ b/worker/src/RTC/RtpProbationGenerator.cpp @@ -139,9 +139,13 @@ namespace RTC // Make the packet length fit into our available limits. if (size > MaxProbationPacketSize) + { size = MaxProbationPacketSize; + } else if (size < ProbationPacketHeaderSize) + { size = ProbationPacketHeaderSize; + } // Just send up to StepNumPackets per step. // Increase RTP seq number and timestamp. diff --git a/worker/src/RTC/RtpStream.cpp b/worker/src/RTC/RtpStream.cpp index 45add75d99..9e3b9754d2 100644 --- a/worker/src/RTC/RtpStream.cpp +++ b/worker/src/RTC/RtpStream.cpp @@ -43,7 +43,9 @@ namespace RTC flatbuffers::Offset rtxStream; if (HasRtx()) + { rtxStream = this->rtxStream->FillBuffer(builder); + } return FBS::RtpStream::CreateDump(builder, params, this->score, rtxStream); } @@ -167,11 +169,15 @@ namespace RTC // If previous score was 0 (and new one is not 0) then update activeSinceMs. if (previousScore == 0u) + { this->activeSinceMs = DepLibUV::GetTimeMs(); + } // Notify the listener. if (notify) + { this->listener->OnRtpStreamScore(this, score, previousScore); + } } } @@ -252,7 +258,9 @@ namespace RTC // Add the score into the histogram. if (this->scores.size() == ScoreHistogramLength) + { this->scores.erase(this->scores.begin()); + } auto previousScore = this->score; @@ -300,7 +308,9 @@ namespace RTC // If previous score was 0 (and new one is not 0) then update activeSinceMs. if (previousScore == 0u) + { this->activeSinceMs = DepLibUV::GetTimeMs(); + } this->listener->OnRtpStreamScore(this, this->score, previousScore); } diff --git a/worker/src/RTC/RtxStream.cpp b/worker/src/RTC/RtxStream.cpp index 6f900906f4..008aa65b6b 100644 --- a/worker/src/RTC/RtxStream.cpp +++ b/worker/src/RTC/RtxStream.cpp @@ -95,9 +95,13 @@ namespace RTC auto expected = GetExpectedPackets(); if (expected > this->packetsCount) + { this->packetsLost = expected - this->packetsCount; + } else + { this->packetsLost = 0u; + } // Calculate Fraction Lost. const uint32_t expectedInterval = expected - this->expectedPrior; @@ -111,9 +115,13 @@ namespace RTC const int32_t lostInterval = expectedInterval - receivedInterval; if (expectedInterval == 0 || lostInterval <= 0) + { this->fractionLost = 0; + } else + { this->fractionLost = std::round((static_cast(lostInterval << 8) / expectedInterval)); + } this->reportedPacketLost += (this->packetsLost - prevPacketsLost); diff --git a/worker/src/RTC/SctpAssociation.cpp b/worker/src/RTC/SctpAssociation.cpp index 13922f00c8..2dd56f452f 100644 --- a/worker/src/RTC/SctpAssociation.cpp +++ b/worker/src/RTC/SctpAssociation.cpp @@ -293,7 +293,9 @@ namespace RTC // Just run the SCTP stack if our state is 'new'. if (this->state != SctpState::NEW) + { return; + } try { @@ -311,7 +313,9 @@ namespace RTC ret = usrsctp_connect(this->socket, reinterpret_cast(&rconn), sizeof(rconn)); if (ret < 0 && errno != EINPROGRESS) + { MS_THROW_ERROR("usrsctp_connect() failed: %s", std::strerror(errno)); + } // Disable MTU discovery. sctp_paddrparams peerAddrParams; // NOLINT(cppcoreguidelines-pro-type-member-init) @@ -328,7 +332,9 @@ namespace RTC this->socket, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &peerAddrParams, sizeof(peerAddrParams)); if (ret < 0) + { MS_THROW_ERROR("usrsctp_setsockopt(SCTP_PEER_ADDR_PARAMS) failed: %s", std::strerror(errno)); + } // Announce connecting state. this->state = SctpState::CONNECTING; @@ -485,7 +491,9 @@ namespace RTC // We need more OS. if (streamId > this->os - 1) + { AddOutgoingStreams(/*force*/ false); + } } void SctpAssociation::DataProducerClosed(RTC::DataProducer* dataProducer) @@ -497,9 +505,13 @@ namespace RTC // Send SCTP_RESET_STREAMS to the remote. // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.7 if (this->isDataChannel) + { ResetSctpStream(streamId, StreamDirection::OUTGOING); + } else + { ResetSctpStream(streamId, StreamDirection::INCOMING); + } } void SctpAssociation::DataConsumerClosed(RTC::DataConsumer* dataConsumer) @@ -518,7 +530,9 @@ namespace RTC // Do nothing if an outgoing stream that could not be allocated by us. if (direction == StreamDirection::OUTGOING && streamId > this->os - 1) + { return; + } int ret; struct sctp_assoc_value av; // NOLINT(cppcoreguidelines-pro-type-member-init) @@ -585,9 +599,13 @@ namespace RTC uint16_t additionalOs{ 0 }; if (MaxSctpStreams - this->os >= 32) + { additionalOs = 32; + } else + { additionalOs = MaxSctpStreams - this->os; + } if (additionalOs == 0) { @@ -600,7 +618,9 @@ namespace RTC // Already in progress, ignore (unless forced). if (!force && nextDesiredOs == this->desiredOs) + { return; + } // Update desired value. this->desiredOs = nextDesiredOs; @@ -625,7 +645,9 @@ namespace RTC this->socket, IPPROTO_SCTP, SCTP_ADD_STREAMS, &sas, static_cast(sizeof(sas))); if (ret < 0) + { MS_WARN_TAG(sctp, "usrsctp_setsockopt(SCTP_ADD_STREAMS) failed: %s", std::strerror(errno)); + } } void SctpAssociation::OnUsrSctpSendSctpData(void* buffer, size_t len) @@ -708,7 +730,9 @@ namespace RTC { // Allocate the buffer if not already done. if (!this->messageBuffer) + { this->messageBuffer = new uint8_t[this->maxSctpMessageSize]; + } std::memcpy(this->messageBuffer + this->messageBufferLen, data, len); this->messageBufferLen += len; @@ -720,7 +744,9 @@ namespace RTC void SctpAssociation::OnUsrSctpReceiveSctpNotification(union sctp_notification* notification, size_t len) { if (notification->sn_header.sn_length != (uint32_t)len) + { return; + } switch (notification->sn_header.sn_type) { @@ -751,7 +777,9 @@ namespace RTC // Increase if requested before connected. if (this->desiredOs > this->os) + { AddOutgoingStreams(/*force*/ true); + } if (this->state != SctpState::CONNECTED) { @@ -807,7 +835,9 @@ namespace RTC // Increase if requested before connected. if (this->desiredOs > this->os) + { AddOutgoingStreams(/*force*/ true); + } if (this->state != SctpState::CONNECTED) { @@ -947,10 +977,14 @@ namespace RTC sizeof(uint16_t); if (notification->sn_strreset_event.strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) + { incoming = true; + } if (notification->sn_strreset_event.strreset_flags & SCTP_STREAM_RESET_OUTGOING_SSN) + { outgoing = true; + } if (MS_HAS_DEBUG_TAG(sctp)) { @@ -969,7 +1003,9 @@ namespace RTC } if (i > 0) + { streamIds.append(","); + } streamIds.append(std::to_string(streamId)); } diff --git a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp index 1634783876..c99947c61e 100644 --- a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp +++ b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp @@ -17,7 +17,9 @@ namespace RTC this->streamId = data->streamId(); if (this->streamId > 65534) + { MS_THROW_TYPE_ERROR("streamId must not be greater than 65534"); + } // ordered is optional. bool orderedGiven = false; @@ -41,7 +43,9 @@ namespace RTC } if (this->maxPacketLifeTime && this->maxRetransmits) + { MS_THROW_TYPE_ERROR("cannot provide both maxPacketLifeTime and maxRetransmits"); + } // clang-format off if ( diff --git a/worker/src/RTC/SenderBandwidthEstimator.cpp b/worker/src/RTC/SenderBandwidthEstimator.cpp index 7de3504e04..6cc7476a72 100644 --- a/worker/src/RTC/SenderBandwidthEstimator.cpp +++ b/worker/src/RTC/SenderBandwidthEstimator.cpp @@ -88,12 +88,16 @@ namespace RTC // Drop ongoing cummulative result if too old. if (elapsedMs > 1000u) + { this->cummulativeResult.Reset(); + } for (auto& result : feedback->GetPacketResults()) { if (!result.received) + { continue; + } const uint16_t wideSeq = result.sequenceNumber; auto it = this->sentInfos.find(wideSeq); @@ -238,16 +242,24 @@ namespace RTC else { if (sentAtMs < this->firstPacketSentAtMs) + { this->firstPacketSentAtMs = sentAtMs; + } if (receivedAtMs < this->firstPacketReceivedAtMs) + { this->firstPacketReceivedAtMs = receivedAtMs; + } if (sentAtMs > this->lastPacketSentAtMs) + { this->lastPacketSentAtMs = sentAtMs; + } if (receivedAtMs > this->lastPacketReceivedAtMs) + { this->lastPacketReceivedAtMs = receivedAtMs; + } } this->numPackets++; diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index 9f05f36dfe..f7d7a885b1 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -24,7 +24,9 @@ namespace RTC // Ensure there is a single encoding. if (this->consumableRtpEncodings.size() != 1u) + { MS_THROW_TYPE_ERROR("invalid consumableRtpEncodings with size != 1"); + } auto& encoding = this->rtpParameters.encodings[0]; const auto* mediaCodec = this->rtpParameters.GetCodecForEncoding(encoding); @@ -110,7 +112,9 @@ namespace RTC uint8_t producerScore{ 0 }; if (this->producerRtpStream) + { producerScore = this->producerRtpStream->GetScore(); + } return FBS::Consumer::CreateConsumerScoreDirect( builder, this->rtpStream->GetScore(), producerScore, this->producerRtpStreamScores); @@ -134,7 +138,9 @@ namespace RTC case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) + { RequestKeyFrame(); + } request->Accept(); @@ -202,10 +208,14 @@ namespace RTC // Audio SimpleConsumer does not play the BWE game. if (this->kind != RTC::Media::Kind::VIDEO) + { return 0u; + } if (!IsActive()) + { return 0u; + } return this->priority; } @@ -221,7 +231,9 @@ namespace RTC // If this is not the first time this method is called within the same iteration, // return 0 since a video SimpleConsumer does not keep state about this. if (this->managingBitrate) + { return 0u; + } this->managingBitrate = true; @@ -231,9 +243,13 @@ namespace RTC auto desiredBitrate = this->producerRtpStream->GetBitrate(nowMs); if (desiredBitrate < bitrate) + { return desiredBitrate; + } else + { return bitrate; + } } void SimpleConsumer::ApplyLayers() @@ -257,10 +273,14 @@ namespace RTC // Audio SimpleConsumer does not play the BWE game. if (this->kind != RTC::Media::Kind::VIDEO) + { return 0u; + } if (!IsActive()) + { return 0u; + } auto nowMs = DepLibUV::GetTimeMs(); auto desiredBitrate = this->producerRtpStream->GetBitrate(nowMs); @@ -270,7 +290,9 @@ namespace RTC auto maxBitrate = this->rtpParameters.encodings[0].maxBitrate; if (maxBitrate > desiredBitrate) + { desiredBitrate = maxBitrate; + } return desiredBitrate; } @@ -335,7 +357,9 @@ namespace RTC if (isSyncPacket) { if (packet->IsKeyFrame()) + { MS_DEBUG_TAG(rtp, "sync key frame received"); + } this->rtpSeqManager.Sync(packet->GetSequenceNumber() - 1); @@ -401,12 +425,16 @@ namespace RTC MS_TRACE(); if (static_cast((nowMs - this->lastRtcpSentTime) * 1.15) < this->maxRtcpInterval) + { return true; + } auto* senderReport = this->rtpStream->GetRtcpSenderReport(nowMs); if (!senderReport) + { return true; + } // Build SDES chunk for this sender. auto* sdesChunk = this->rtpStream->GetRtcpSdesChunk(); @@ -423,7 +451,9 @@ namespace RTC // RTCP Compound packet buffer cannot hold the data. if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrReport)) + { return false; + } this->lastRtcpSentTime = nowMs; @@ -436,13 +466,17 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return; + } auto fractionLost = this->rtpStream->GetFractionLost(); // If our fraction lost is worse than the given one, update it. if (fractionLost > worstRemoteFractionLost) + { worstRemoteFractionLost = fractionLost; + } } void SimpleConsumer::ReceiveNack(RTC::RTCP::FeedbackRtpNackPacket* nackPacket) @@ -450,7 +484,9 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return; + } // May emit 'trace' event. EmitTraceEventNackType(); @@ -485,7 +521,9 @@ namespace RTC this->rtpStream->ReceiveKeyFrameRequest(messageType); if (IsActive()) + { RequestKeyFrame(); + } } void SimpleConsumer::ReceiveRtcpReceiverReport(RTC::RTCP::ReceiverReport* report) @@ -507,7 +545,9 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return 0u; + } return this->rtpStream->GetBitrate(nowMs); } @@ -526,7 +566,9 @@ namespace RTC this->syncRequired = true; if (IsActive()) + { RequestKeyFrame(); + } } void SimpleConsumer::UserOnTransportDisconnected() @@ -543,7 +585,9 @@ namespace RTC this->rtpStream->Pause(); if (this->externallyManagedBitrate && this->kind == RTC::Media::Kind::VIDEO) + { this->listener->OnConsumerNeedZeroBitrate(this); + } } void SimpleConsumer::UserOnResumed() @@ -553,7 +597,9 @@ namespace RTC this->syncRequired = true; if (IsActive()) + { RequestKeyFrame(); + } } void SimpleConsumer::CreateRtpStream() @@ -626,12 +672,16 @@ namespace RTC // If the Consumer is paused, tell the RtpStreamSend. if (IsPaused() || IsProducerPaused()) + { this->rtpStream->Pause(); + } const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); if (rtxCodec && encoding.hasRtx) + { this->rtpStream->SetRtx(rtxCodec->payloadType, encoding.rtx.ssrc); + } } void SimpleConsumer::RequestKeyFrame() @@ -639,7 +689,9 @@ namespace RTC MS_TRACE(); if (this->kind != RTC::Media::Kind::VIDEO) + { return; + } auto mappedSsrc = this->consumableRtpEncodings[0].ssrc; diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index 20378a69a3..de0f491904 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -59,14 +59,18 @@ namespace RTC this->preferredSpatialLayer = preferredLayers->spatialLayer(); if (this->preferredSpatialLayer > encoding.spatialLayers - 1) + { this->preferredSpatialLayer = encoding.spatialLayers - 1; + } if (preferredLayers->temporalLayer().has_value()) { this->preferredTemporalLayer = preferredLayers->temporalLayer().value(); if (this->preferredTemporalLayer > encoding.temporalLayers - 1) + { this->preferredTemporalLayer = encoding.temporalLayers - 1; + } } else { @@ -181,9 +185,13 @@ namespace RTC uint8_t producerScore{ 0 }; if (producerCurrentRtpStream) + { producerScore = producerCurrentRtpStream->GetScore(); + } else + { producerScore = 0; + } return FBS::Consumer::CreateConsumerScoreDirect( builder, this->rtpStream->GetScore(), producerScore, this->producerRtpStreamScores); @@ -207,7 +215,9 @@ namespace RTC case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) + { RequestKeyFrames(); + } request->Accept(); @@ -226,7 +236,9 @@ namespace RTC this->preferredSpatialLayer = preferredLayers->spatialLayer(); if (this->preferredSpatialLayer > this->rtpStream->GetSpatialLayers() - 1) + { this->preferredSpatialLayer = this->rtpStream->GetSpatialLayers() - 1; + } // preferredTemporaLayer is optional. if (preferredLayers->temporalLayer().has_value()) @@ -234,7 +246,9 @@ namespace RTC this->preferredTemporalLayer = preferredLayers->temporalLayer().value(); if (this->preferredTemporalLayer > this->rtpStream->GetTemporalLayers() - 1) + { this->preferredTemporalLayer = this->rtpStream->GetTemporalLayers() - 1; + } } else { @@ -308,7 +322,9 @@ namespace RTC EmitScore(); if (IsActive()) + { MayChangeLayers(); + } } void SimulcastConsumer::ProducerRtpStreamScore( @@ -345,7 +361,9 @@ namespace RTC // Just interested if this is the first Sender Report for a RTP stream. if (!first) + { return; + } MS_DEBUG_TAG(simulcast, "first SenderReport [ssrc:%" PRIu32 "]", rtpStream->GetSsrc()); @@ -354,10 +372,14 @@ namespace RTC auto* producerCurrentRtpStream = GetProducerCurrentRtpStream(); if (!producerCurrentRtpStream || !producerCurrentRtpStream->GetSenderReportNtpMs()) + { return; + } if (IsActive()) + { MayChangeLayers(); + } } uint8_t SimulcastConsumer::GetBitratePriority() const @@ -367,7 +389,9 @@ namespace RTC MS_ASSERT(this->externallyManagedBitrate, "bitrate is not externally managed"); if (!IsActive()) + { return 0u; + } return this->priority; } @@ -399,11 +423,17 @@ namespace RTC auto lossPercentage = this->rtpStream->GetLossPercentage(); if (lossPercentage < 2) + { virtualBitrate = 1.08 * bitrate; + } else if (lossPercentage > 10) + { virtualBitrate = (1 - 0.5 * (lossPercentage / 100)) * bitrate; + } else + { virtualBitrate = bitrate; + } } else { @@ -434,14 +464,18 @@ namespace RTC // Ignore spatial layers lower than the one we already have. if (spatialLayer < this->provisionalTargetSpatialLayer) + { continue; + } // This can be null. auto* producerRtpStream = this->producerRtpStreams.at(spatialLayer); // Producer stream does not exist. Ignore. if (!producerRtpStream) + { continue; + } // If the stream has not been active time enough and we have an active one // already, move to the next spatial layer. @@ -459,12 +493,16 @@ namespace RTC // The stream for the current provisional spatial layer has been active // for enough time, move to the next spatial layer. if (provisionalProducerRtpStream->GetActiveMs() >= StreamMinActiveMs) + { continue; + } } // We may not yet switch to this spatial layer. if (!CanSwitchToSpatialLayer(spatialLayer)) + { continue; + } temporalLayer = 0; @@ -503,9 +541,13 @@ namespace RTC provisionalProducerRtpStream->GetBitrate(nowMs, 0, this->provisionalTargetTemporalLayer); if (requiredBitrate > provisionalRequiredBitrate) + { requiredBitrate -= provisionalRequiredBitrate; + } else + { requiredBitrate = 1u; // Don't set 0 since it would be ignored. + } } MS_DEBUG_DEV( @@ -518,25 +560,35 @@ namespace RTC // If active layer, end iterations here. Otherwise move to next spatial layer. if (requiredBitrate) + { goto done; + } else + { break; + } } // If this is the preferred or higher spatial layer, take it and exit. if (spatialLayer >= this->preferredSpatialLayer) + { break; + } } done: // No higher active layers found. if (!requiredBitrate) + { return 0u; + } // No luck. if (requiredBitrate > virtualBitrate) + { return 0u; + } // Set provisional layers. this->provisionalTargetSpatialLayer = spatialLayer; @@ -551,11 +603,17 @@ namespace RTC requiredBitrate); if (requiredBitrate <= bitrate) + { return requiredBitrate; + } else if (requiredBitrate <= virtualBitrate) + { return bitrate; + } else + { return requiredBitrate; // NOTE: This cannot happen. + } } void SimulcastConsumer::ApplyLayers() @@ -608,7 +666,9 @@ namespace RTC MS_ASSERT(this->externallyManagedBitrate, "bitrate is not externally managed"); if (!IsActive()) + { return 0u; + } auto nowMs = DepLibUV::GetTimeMs(); uint32_t desiredBitrate{ 0u }; @@ -623,12 +683,16 @@ namespace RTC auto* producerRtpStream = this->producerRtpStreams.at(sIdx); if (!producerRtpStream) + { continue; + } auto streamBitrate = producerRtpStream->GetBitrate(nowMs); if (streamBitrate > desiredBitrate) + { desiredBitrate = streamBitrate; + } } // If consumer.rtpParameters.encodings[0].maxBitrate was given and it's @@ -636,7 +700,9 @@ namespace RTC auto maxBitrate = this->rtpParameters.encodings[0].maxBitrate; if (maxBitrate > desiredBitrate) + { desiredBitrate = maxBitrate; + } return desiredBitrate; } @@ -720,7 +786,9 @@ namespace RTC if (isSyncPacket && (this->spatialLayerToSync == -1 || this->spatialLayerToSync == spatialLayer)) { if (packet->IsKeyFrame()) + { MS_DEBUG_TAG(rtp, "sync key frame received"); + } uint32_t tsOffset{ 0u }; @@ -751,9 +819,13 @@ namespace RTC int64_t diffMs; if (ntpMs2 >= ntpMs1) + { diffMs = ntpMs2 - ntpMs1; + } else + { diffMs = -1 * (ntpMs1 - ntpMs2); + } const int64_t diffTs = diffMs * this->rtpStream->GetClockRate() / 1000; const uint32_t newTs2 = ts2 - diffTs; @@ -913,7 +985,9 @@ namespace RTC } if (previousTemporalLayer != this->encodingContext->GetCurrentTemporalLayer()) + { EmitLayersChange(); + } } // Update RTP seq number and timestamp based on NTP offset. @@ -953,7 +1027,9 @@ namespace RTC if (this->rtpStream->ReceivePacket(packet, sharedPacket)) { if (this->rtpSeqManager.GetMaxOutput() == packet->GetSequenceNumber()) + { this->lastSentPacketHasMarker = packet->HasMarker(); + } // Send the packet. this->listener->OnConsumerSendRtpPacket(this, packet); @@ -991,12 +1067,16 @@ namespace RTC MS_TRACE(); if (static_cast((nowMs - this->lastRtcpSentTime) * 1.15) < this->maxRtcpInterval) + { return true; + } auto* senderReport = this->rtpStream->GetRtcpSenderReport(nowMs); if (!senderReport) + { return true; + } // Build SDES chunk for this sender. auto* sdesChunk = this->rtpStream->GetRtcpSdesChunk(); @@ -1013,7 +1093,9 @@ namespace RTC // RTCP Compound packet buffer cannot hold the data. if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrReport)) + { return false; + } this->lastRtcpSentTime = nowMs; @@ -1026,13 +1108,17 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return; + } auto fractionLost = this->rtpStream->GetFractionLost(); // If our fraction lost is worse than the given one, update it. if (fractionLost > worstRemoteFractionLost) + { worstRemoteFractionLost = fractionLost; + } } void SimulcastConsumer::ReceiveNack(RTC::RTCP::FeedbackRtpNackPacket* nackPacket) @@ -1040,7 +1126,9 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return; + } // May emit 'trace' event. EmitTraceEventNackType(); @@ -1075,7 +1163,9 @@ namespace RTC this->rtpStream->ReceiveKeyFrameRequest(messageType); if (IsActive()) + { RequestKeyFrameForCurrentSpatialLayer(); + } } void SimulcastConsumer::ReceiveRtcpReceiverReport(RTC::RTCP::ReceiverReport* report) @@ -1097,7 +1187,9 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return 0u; + } return this->rtpStream->GetBitrate(nowMs); } @@ -1118,7 +1210,9 @@ namespace RTC this->keyFrameForTsOffsetRequested = false; if (IsActive()) + { MayChangeLayers(); + } } void SimulcastConsumer::UserOnTransportDisconnected() @@ -1143,7 +1237,9 @@ namespace RTC UpdateTargetLayers(-1, -1); if (this->externallyManagedBitrate) + { this->listener->OnConsumerNeedZeroBitrate(this); + } } void SimulcastConsumer::UserOnResumed() @@ -1156,7 +1252,9 @@ namespace RTC this->checkingForOldPacketsInSpatialLayer = false; if (IsActive()) + { MayChangeLayers(); + } } void SimulcastConsumer::CreateRtpStream() @@ -1231,12 +1329,16 @@ namespace RTC // If the Consumer is paused, tell the RtpStreamSend. if (IsPaused() || IsProducerPaused()) + { this->rtpStream->Pause(); + } const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); if (rtxCodec && encoding.hasRtx) + { this->rtpStream->SetRtx(rtxCodec->payloadType, encoding.rtx.ssrc); + } } void SimulcastConsumer::RequestKeyFrames() @@ -1244,7 +1346,9 @@ namespace RTC MS_TRACE(); if (this->kind != RTC::Media::Kind::VIDEO) + { return; + } auto* producerTargetRtpStream = GetProducerTargetRtpStream(); auto* producerCurrentRtpStream = GetProducerCurrentRtpStream(); @@ -1269,12 +1373,16 @@ namespace RTC MS_TRACE(); if (this->kind != RTC::Media::Kind::VIDEO) + { return; + } auto* producerTargetRtpStream = GetProducerTargetRtpStream(); if (!producerTargetRtpStream) + { return; + } auto mappedSsrc = this->consumableRtpEncodings[this->targetSpatialLayer].ssrc; @@ -1286,12 +1394,16 @@ namespace RTC MS_TRACE(); if (this->kind != RTC::Media::Kind::VIDEO) + { return; + } auto* producerCurrentRtpStream = GetProducerCurrentRtpStream(); if (!producerCurrentRtpStream) + { return; + } auto mappedSsrc = this->consumableRtpEncodings[this->currentSpatialLayer].ssrc; @@ -1315,7 +1427,9 @@ namespace RTC if (this->externallyManagedBitrate) { if (newTargetSpatialLayer != this->targetSpatialLayer || force) + { this->listener->OnConsumerNeedBitrateChange(this); + } } else { @@ -1346,13 +1460,17 @@ namespace RTC if (nowMs - this->lastBweDowngradeAtMs < BweDowngradeConservativeMs) { if (newTargetSpatialLayer > -1 && spatialLayer > this->currentSpatialLayer) + { continue; + } } // Ignore spatial layers for non existing Producer streams or for those // with score 0. if (producerScore == 0u) + { continue; + } // If the stream has not been active time enough and we have an active one // already, move to the next spatial layer. @@ -1370,23 +1488,33 @@ namespace RTC // We may not yet switch to this spatial layer. if (!CanSwitchToSpatialLayer(spatialLayer)) + { continue; + } newTargetSpatialLayer = spatialLayer; // If this is the preferred or higher spatial layer take it and exit. if (spatialLayer >= this->preferredSpatialLayer) + { break; + } } if (newTargetSpatialLayer != -1) { if (newTargetSpatialLayer == this->preferredSpatialLayer) + { newTargetTemporalLayer = this->preferredTemporalLayer; + } else if (newTargetSpatialLayer < this->preferredSpatialLayer) + { newTargetTemporalLayer = this->rtpStream->GetTemporalLayers() - 1; + } else + { newTargetTemporalLayer = 0; + } } // Return true if any target layer changed. @@ -1435,7 +1563,9 @@ namespace RTC // If the new target spatial layer matches the current one, apply the new // target temporal layer now. if (this->targetSpatialLayer == this->currentSpatialLayer) + { this->encodingContext->SetTargetTemporalLayer(this->targetTemporalLayer); + } MS_DEBUG_TAG( simulcast, @@ -1447,7 +1577,9 @@ namespace RTC // If the target spatial layer is different than the current one, request // a key frame. if (this->targetSpatialLayer != this->currentSpatialLayer) + { RequestKeyFrameForTargetSpatialLayer(); + } } inline bool SimulcastConsumer::CanSwitchToSpatialLayer(int16_t spatialLayer) const @@ -1530,7 +1662,9 @@ namespace RTC MS_TRACE(); if (this->currentSpatialLayer == -1) + { return nullptr; + } // This may return nullptr. return this->producerRtpStreams.at(this->currentSpatialLayer); @@ -1541,7 +1675,9 @@ namespace RTC MS_TRACE(); if (this->targetSpatialLayer == -1) + { return nullptr; + } // This may return nullptr. return this->producerRtpStreams.at(this->targetSpatialLayer); @@ -1552,7 +1688,9 @@ namespace RTC MS_TRACE(); if (this->tsReferenceSpatialLayer == -1) + { return nullptr; + } // This may return nullptr. return this->producerRtpStreams.at(this->tsReferenceSpatialLayer); @@ -1572,7 +1710,9 @@ namespace RTC // NOTE: For now this is a bit useless since, when locally managed, we do // not check the Consumer score at all. if (!this->externallyManagedBitrate) + { MayChangeLayers(); + } } } diff --git a/worker/src/RTC/SrtpSession.cpp b/worker/src/RTC/SrtpSession.cpp index ee400c07eb..0a136d4e31 100644 --- a/worker/src/RTC/SrtpSession.cpp +++ b/worker/src/RTC/SrtpSession.cpp @@ -166,7 +166,9 @@ namespace RTC const srtp_err_status_t err = srtp_create(&this->session, &policy); if (DepLibSRTP::IsError(err)) + { MS_THROW_ERROR("srtp_create() failed: %s", DepLibSRTP::GetErrorString(err)); + } } SrtpSession::~SrtpSession() @@ -178,7 +180,9 @@ namespace RTC const srtp_err_status_t err = srtp_dealloc(this->session); if (DepLibSRTP::IsError(err)) + { MS_ABORT("srtp_dealloc() failed: %s", DepLibSRTP::GetErrorString(err)); + } } } diff --git a/worker/src/RTC/StunPacket.cpp b/worker/src/RTC/StunPacket.cpp index b49ecdd796..e420871595 100644 --- a/worker/src/RTC/StunPacket.cpp +++ b/worker/src/RTC/StunPacket.cpp @@ -20,7 +20,9 @@ namespace RTC MS_TRACE(); if (!StunPacket::IsStun(data, len)) + { return nullptr; + } /* The message type field is decomposed further into the following @@ -381,17 +383,29 @@ namespace RTC } MS_DUMP(" transactionId: %s", transactionId); if (this->errorCode != 0u) + { MS_DUMP(" errorCode: %" PRIu16, this->errorCode); + } if (!this->username.empty()) + { MS_DUMP(" username: %s", this->username.c_str()); + } if (this->priority != 0u) + { MS_DUMP(" priority: %" PRIu32, this->priority); + } if (this->iceControlling != 0u) + { MS_DUMP(" iceControlling: %" PRIu64, this->iceControlling); + } if (this->iceControlled != 0u) + { MS_DUMP(" iceControlled: %" PRIu64, this->iceControlled); + } if (this->hasUseCandidate) + { MS_DUMP(" useCandidate"); + } if (this->xorMappedAddress != nullptr) { int family; @@ -414,7 +428,9 @@ namespace RTC MS_DUMP(" messageIntegrity: %s", messageIntegrity); } if (this->hasFingerprint) + { MS_DUMP(" has fingerprint"); + } MS_DUMP(""); } @@ -431,7 +447,9 @@ namespace RTC { // Both USERNAME and MESSAGE-INTEGRITY must be present. if (!this->messageIntegrity || this->username.empty()) + { return Authentication::BAD_REQUEST; + } // Check that USERNAME attribute begins with our local username plus ":". const size_t localUsernameLen = localUsername.length(); @@ -459,8 +477,10 @@ namespace RTC // If there is FINGERPRINT it must be discarded for MESSAGE-INTEGRITY calculation, // so the header length field must be modified (and later restored). if (this->hasFingerprint) + { // Set the header length field: full size - header length (20) - FINGERPRINT length (8). Utils::Byte::Set2Bytes(this->data, 2, static_cast(this->size - 20 - 8)); + } // Calculate the HMAC-SHA1 of the message according to MESSAGE-INTEGRITY rules. const uint8_t* computedMessageIntegrity = Utils::Crypto::GetHmacSha1( @@ -470,13 +490,19 @@ namespace RTC // Compare the computed HMAC-SHA1 with the MESSAGE-INTEGRITY in the packet. if (std::memcmp(this->messageIntegrity, computedMessageIntegrity, 20) == 0) + { result = Authentication::OK; + } else + { result = Authentication::UNAUTHORIZED; + } // Restore the header length field. if (this->hasFingerprint) + { Utils::Byte::Set2Bytes(this->data, 2, static_cast(this->size - 20)); + } return result; } @@ -549,16 +575,24 @@ namespace RTC } if (this->priority != 0u) + { this->size += 4 + 4; + } if (this->iceControlling != 0u) + { this->size += 4 + 8; + } if (this->iceControlled != 0u) + { this->size += 4 + 8; + } if (this->hasUseCandidate) + { this->size += 4; + } if (addXorMappedAddress) { @@ -590,13 +624,19 @@ namespace RTC } if (addErrorCode) + { this->size += 4 + 4; + } if (addMessageIntegrity) + { this->size += 4 + 20; + } if (addFingerprint) + { this->size += 4 + 4; + } // Merge class and method fields into type. uint16_t typeField = (static_cast(this->method) & 0x0f80) << 2; @@ -763,7 +803,9 @@ namespace RTC { // Ignore FINGERPRINT. if (addFingerprint) + { Utils::Byte::Set2Bytes(buffer, 2, static_cast(this->size - 20 - 8)); + } // Calculate the HMAC-SHA1 of the packet according to MESSAGE-INTEGRITY rules. const uint8_t* computedMessageIntegrity = @@ -779,7 +821,9 @@ namespace RTC // Restore length field. if (addFingerprint) + { Utils::Byte::Set2Bytes(buffer, 2, static_cast(this->size - 20)); + } } else { diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index 9b3a18101e..b02183f048 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -29,13 +29,17 @@ namespace RTC // Ensure there is a single encoding. if (this->consumableRtpEncodings.size() != 1u) + { MS_THROW_TYPE_ERROR("invalid consumableRtpEncodings with size != 1"); + } auto& encoding = this->rtpParameters.encodings[0]; // Ensure there are multiple spatial or temporal layers. if (encoding.spatialLayers < 2u && encoding.temporalLayers < 2u) + { MS_THROW_TYPE_ERROR("invalid number of layers"); + } // Set preferredLayers (if given). if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeRequest::VT_PREFERREDLAYERS)) @@ -43,13 +47,17 @@ namespace RTC this->preferredSpatialLayer = data->preferredLayers()->spatialLayer(); if (this->preferredSpatialLayer > encoding.spatialLayers - 1) + { this->preferredSpatialLayer = encoding.spatialLayers - 1; + } if (flatbuffers::IsFieldPresent( data->preferredLayers(), FBS::Consumer::ConsumerLayers::VT_TEMPORALLAYER)) { if (this->preferredTemporalLayer > encoding.temporalLayers - 1) + { this->preferredTemporalLayer = encoding.temporalLayers - 1; + } } else { @@ -155,9 +163,13 @@ namespace RTC uint8_t producerScore{ 0 }; if (this->producerRtpStream) + { producerScore = this->producerRtpStream->GetScore(); + } else + { producerScore = 0; + } return FBS::Consumer::CreateConsumerScoreDirect( builder, this->rtpStream->GetScore(), producerScore, this->producerRtpStreamScores); @@ -181,7 +193,9 @@ namespace RTC case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) + { RequestKeyFrame(); + } request->Accept(); @@ -200,7 +214,9 @@ namespace RTC this->preferredSpatialLayer = preferredLayers->spatialLayer(); if (this->preferredSpatialLayer > this->rtpStream->GetSpatialLayers() - 1) + { this->preferredSpatialLayer = this->rtpStream->GetSpatialLayers() - 1; + } // preferredTemporaLayer is optional. if (preferredLayers->temporalLayer().has_value()) @@ -208,7 +224,9 @@ namespace RTC this->preferredTemporalLayer = preferredLayers->temporalLayer().value(); if (this->preferredTemporalLayer > this->rtpStream->GetTemporalLayers() - 1) + { this->preferredTemporalLayer = this->rtpStream->GetTemporalLayers() - 1; + } } else { @@ -270,7 +288,9 @@ namespace RTC EmitScore(); if (IsActive()) + { MayChangeLayers(); + } } void SvcConsumer::ProducerRtpStreamScore( @@ -310,7 +330,9 @@ namespace RTC MS_ASSERT(this->externallyManagedBitrate, "bitrate is not externally managed"); if (!IsActive()) + { return 0u; + } return this->priority; } @@ -323,7 +345,9 @@ namespace RTC MS_ASSERT(IsActive(), "should be active"); if (this->producerRtpStream->GetScore() == 0u) + { return 0u; + } // If already in the preferred layers, do nothing. // clang-format off @@ -345,11 +369,17 @@ namespace RTC auto lossPercentage = this->rtpStream->GetLossPercentage(); if (lossPercentage < 2) + { virtualBitrate = 1.08 * bitrate; + } else if (lossPercentage > 10) + { virtualBitrate = (1 - 0.5 * (lossPercentage / 100)) * bitrate; + } else + { virtualBitrate = bitrate; + } } else { @@ -378,7 +408,9 @@ namespace RTC // Ignore spatial layers lower than the one we already have. if (spatialLayer < this->provisionalTargetSpatialLayer) + { continue; + } temporalLayer = 0; @@ -417,9 +449,13 @@ namespace RTC nowMs, this->provisionalTargetSpatialLayer, this->provisionalTargetTemporalLayer); if (requiredBitrate > provisionalRequiredBitrate) + { requiredBitrate -= provisionalRequiredBitrate; + } else + { requiredBitrate = 1u; // Don't set 0 since it would be ignored. + } } MS_DEBUG_DEV( @@ -432,25 +468,35 @@ namespace RTC // If active layer, end iterations here. Otherwise move to next spatial layer. if (requiredBitrate) + { goto done; + } else + { break; + } } // If this is the preferred or higher spatial layer, take it and exit. if (spatialLayer >= this->preferredSpatialLayer) + { break; + } } done: // No higher active layers found. if (!requiredBitrate) + { return 0u; + } // No luck. if (requiredBitrate > virtualBitrate) + { return 0u; + } // Set provisional layers. this->provisionalTargetSpatialLayer = spatialLayer; @@ -465,11 +511,17 @@ namespace RTC requiredBitrate); if (requiredBitrate <= bitrate) + { return requiredBitrate; + } else if (requiredBitrate <= virtualBitrate) + { return bitrate; + } else + { return requiredBitrate; // NOTE: This cannot happen. + } } void SvcConsumer::ApplyLayers() @@ -487,7 +539,9 @@ namespace RTC this->provisionalTargetTemporalLayer = -1; if (!IsActive()) + { return; + } // clang-format off if ( @@ -525,7 +579,9 @@ namespace RTC MS_ASSERT(this->externallyManagedBitrate, "bitrate is not externally managed"); if (!IsActive()) + { return 0u; + } auto nowMs = DepLibUV::GetTimeMs(); uint32_t desiredBitrate{ 0u }; @@ -545,7 +601,9 @@ namespace RTC this->producerRtpStream->GetSpatialLayerBitrate(nowMs, spatialLayer); if (spatialLayerBitrate > desiredBitrate) + { desiredBitrate = spatialLayerBitrate; + } } } else @@ -558,7 +616,9 @@ namespace RTC auto maxBitrate = this->rtpParameters.encodings[0].maxBitrate; if (maxBitrate > desiredBitrate) + { desiredBitrate = maxBitrate; + } return desiredBitrate; } @@ -616,7 +676,9 @@ namespace RTC if (isSyncPacket) { if (packet->IsKeyFrame()) + { MS_DEBUG_TAG(rtp, "sync key frame received"); + } this->rtpSeqManager.Sync(packet->GetSequenceNumber() - 1); this->encodingContext->SyncRequired(); @@ -719,12 +781,16 @@ namespace RTC MS_TRACE(); if (static_cast((nowMs - this->lastRtcpSentTime) * 1.15) < this->maxRtcpInterval) + { return true; + } auto* senderReport = this->rtpStream->GetRtcpSenderReport(nowMs); if (!senderReport) + { return true; + } // Build SDES chunk for this sender. auto* sdesChunk = this->rtpStream->GetRtcpSdesChunk(); @@ -741,7 +807,9 @@ namespace RTC // RTCP Compound packet buffer cannot hold the data. if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrReport)) + { return false; + } this->lastRtcpSentTime = nowMs; @@ -753,13 +821,17 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return; + } auto fractionLost = this->rtpStream->GetFractionLost(); // If our fraction lost is worse than the given one, update it. if (fractionLost > worstRemoteFractionLost) + { worstRemoteFractionLost = fractionLost; + } } void SvcConsumer::ReceiveNack(RTC::RTCP::FeedbackRtpNackPacket* nackPacket) @@ -767,7 +839,9 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return; + } // May emit 'trace' event. EmitTraceEventNackType(); @@ -801,7 +875,9 @@ namespace RTC this->rtpStream->ReceiveKeyFrameRequest(messageType); if (IsActive()) + { RequestKeyFrame(); + } } void SvcConsumer::ReceiveRtcpReceiverReport(RTC::RTCP::ReceiverReport* report) @@ -823,7 +899,9 @@ namespace RTC MS_TRACE(); if (!IsActive()) + { return 0u; + } return this->rtpStream->GetBitrate(nowMs); } @@ -842,7 +920,9 @@ namespace RTC this->syncRequired = true; if (IsActive()) + { MayChangeLayers(); + } } void SvcConsumer::UserOnTransportDisconnected() @@ -867,7 +947,9 @@ namespace RTC UpdateTargetLayers(-1, -1); if (this->externallyManagedBitrate) + { this->listener->OnConsumerNeedZeroBitrate(this); + } } void SvcConsumer::UserOnResumed() @@ -877,7 +959,9 @@ namespace RTC this->syncRequired = true; if (IsActive()) + { MayChangeLayers(); + } } void SvcConsumer::CreateRtpStream() @@ -952,12 +1036,16 @@ namespace RTC // If the Consumer is paused, tell the RtpStreamSend. if (IsPaused() || IsProducerPaused()) + { this->rtpStream->Pause(); + } const auto* rtxCodec = this->rtpParameters.GetRtxCodecForEncoding(encoding); if (rtxCodec && encoding.hasRtx) + { this->rtpStream->SetRtx(rtxCodec->payloadType, encoding.rtx.ssrc); + } } void SvcConsumer::RequestKeyFrame() @@ -965,7 +1053,9 @@ namespace RTC MS_TRACE(); if (this->kind != RTC::Media::Kind::VIDEO) + { return; + } auto mappedSsrc = this->consumableRtpEncodings[0].ssrc; @@ -989,7 +1079,9 @@ namespace RTC if (this->externallyManagedBitrate) { if (newTargetSpatialLayer != this->encodingContext->GetTargetSpatialLayer() || force) + { this->listener->OnConsumerNeedBitrateChange(this); + } } else { @@ -1011,10 +1103,14 @@ namespace RTC int16_t spatialLayer{ 0 }; if (!this->producerRtpStream) + { goto done; + } if (this->producerRtpStream->GetScore() == 0u) + { goto done; + } for (; spatialLayer < this->producerRtpStream->GetSpatialLayers(); ++spatialLayer) { @@ -1023,28 +1119,40 @@ namespace RTC if (nowMs - this->lastBweDowngradeAtMs < BweDowngradeConservativeMs) { if (newTargetSpatialLayer > -1 && spatialLayer > this->encodingContext->GetCurrentSpatialLayer()) + { continue; + } } if (!this->producerRtpStream->GetSpatialLayerBitrate(nowMs, spatialLayer)) + { continue; + } newTargetSpatialLayer = spatialLayer; // If this is the preferred or higher spatial layer and has bitrate, // take it and exit. if (spatialLayer >= this->preferredSpatialLayer) + { break; + } } if (newTargetSpatialLayer != -1) { if (newTargetSpatialLayer == this->preferredSpatialLayer) + { newTargetTemporalLayer = this->preferredTemporalLayer; + } else if (newTargetSpatialLayer < this->preferredSpatialLayer) + { newTargetTemporalLayer = this->rtpStream->GetTemporalLayers() - 1; + } else + { newTargetTemporalLayer = 0; + } } done: @@ -1169,7 +1277,9 @@ namespace RTC // NOTE: For now this is a bit useless since, when locally managed, we do // not check the Consumer score at all. if (!this->externallyManagedBitrate) + { MayChangeLayers(); + } } } diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 837066be13..19e33d5f6d 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -218,7 +218,9 @@ namespace RTC try { if (iceCandidates.empty()) + { MS_THROW_TYPE_ERROR("empty iceCandidates"); + } // Create a ICE server. this->iceServer = new RTC::IceServer( @@ -295,7 +297,9 @@ namespace RTC // Notify the webRtcTransportListener. if (this->webRtcTransportListener) + { this->webRtcTransportListener->OnWebRtcTransportClosed(this); + } } flatbuffers::Offset WebRtcTransport::FillBuffer( @@ -325,7 +329,9 @@ namespace RTC flatbuffers::Offset iceSelectedTuple; if (this->iceServer->GetSelectedTuple()) + { iceSelectedTuple = this->iceServer->GetSelectedTuple()->FillBuffer(builder); + } // Add dtlsParameters.fingerprints. std::vector> fingerprints; @@ -373,7 +379,9 @@ namespace RTC flatbuffers::Offset iceSelectedTuple; if (this->iceServer->GetSelectedTuple()) + { iceSelectedTuple = this->iceServer->GetSelectedTuple()->FillBuffer(builder); + } auto dtlsState = DtlsTransport::StateToFbs(this->dtlsTransport->GetState()); @@ -418,7 +426,9 @@ namespace RTC { // Ensure this method is not called twice. if (this->connectCalled) + { MS_THROW_ERROR("connect() already called"); + } const auto* body = request->data->body_as(); const auto* dtlsParameters = body->dtlsParameters(); @@ -589,7 +599,9 @@ namespace RTC // Do nothing if we have the same local DTLS role as the DTLS transport. // NOTE: local role in DTLS transport can be NONE, but not ours. if (this->dtlsTransport->GetLocalRole() == this->dtlsRole) + { return; + } // Check our local DTLS role. switch (this->dtlsRole) @@ -717,7 +729,9 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } const uint8_t* data = packet->GetData(); auto intLen = static_cast(packet->GetSize()); @@ -731,7 +745,9 @@ namespace RTC } if (!this->srtpSendSession->EncryptRtcp(&data, &intLen)) + { return; + } auto len = static_cast(intLen); @@ -746,7 +762,9 @@ namespace RTC MS_TRACE(); if (!IsConnected()) + { return; + } packet->Serialize(RTC::RTCP::Buffer); @@ -762,7 +780,9 @@ namespace RTC } if (!this->srtpSendSession->EncryptRtcp(&data, &intLen)) + { return; + } auto len = static_cast(intLen); @@ -1006,7 +1026,9 @@ namespace RTC auto intLen = static_cast(len); if (!this->srtpRecvSession->DecryptSrtcp(const_cast(data), &intLen)) + { return; + } RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, static_cast(intLen)); diff --git a/worker/src/Settings.cpp b/worker/src/Settings.cpp index 41a91f1592..8f271fc908 100644 --- a/worker/src/Settings.cpp +++ b/worker/src/Settings.cpp @@ -76,7 +76,9 @@ void Settings::SetConfiguration(int argc, char* argv[]) while ((c = getopt_long_only(argc, argv, "", options, &optionIdx)) != -1) { if (!optarg) + { MS_THROW_TYPE_ERROR("unknown configuration parameter: %s", optarg); + } switch (c) { @@ -160,9 +162,13 @@ void Settings::SetConfiguration(int argc, char* argv[]) case '?': { if (isprint(optopt) != 0) + { MS_THROW_TYPE_ERROR("invalid option '-%c'", (char)optopt); + } else + { MS_THROW_TYPE_ERROR("unknown long option given as argument"); + } } // Valid option, but it requires and argument that is not given. @@ -183,11 +189,15 @@ void Settings::SetConfiguration(int argc, char* argv[]) // Set logTags. if (!logTags.empty()) + { Settings::SetLogTags(logTags); + } // Validate RTC ports. if (Settings::configuration.rtcMaxPort < Settings::configuration.rtcMinPort) + { MS_THROW_TYPE_ERROR("rtcMaxPort cannot be less than rtcMinPort"); + } // Set DTLS certificate files (if provided), Settings::SetDtlsCertificateAndPrivateKeyFiles(); @@ -201,31 +211,57 @@ void Settings::PrintConfiguration() std::ostringstream logTagsStream; if (Settings::configuration.logTags.info) + { logTags.emplace_back("info"); + } if (Settings::configuration.logTags.ice) + { logTags.emplace_back("ice"); + } if (Settings::configuration.logTags.dtls) + { logTags.emplace_back("dtls"); + } if (Settings::configuration.logTags.rtp) + { logTags.emplace_back("rtp"); + } if (Settings::configuration.logTags.srtp) + { logTags.emplace_back("srtp"); + } if (Settings::configuration.logTags.rtcp) + { logTags.emplace_back("rtcp"); + } if (Settings::configuration.logTags.rtx) + { logTags.emplace_back("rtx"); + } if (Settings::configuration.logTags.bwe) + { logTags.emplace_back("bwe"); + } if (Settings::configuration.logTags.score) + { logTags.emplace_back("score"); + } if (Settings::configuration.logTags.simulcast) + { logTags.emplace_back("simulcast"); + } if (Settings::configuration.logTags.svc) + { logTags.emplace_back("svc"); + } if (Settings::configuration.logTags.sctp) + { logTags.emplace_back("sctp"); + } if (Settings::configuration.logTags.message) + { logTags.emplace_back("message"); + } if (!logTags.empty()) { @@ -313,7 +349,9 @@ void Settings::SetLogLevel(std::string& level) Utils::String::ToLowerCase(level); if (Settings::string2LogLevel.find(level) == Settings::string2LogLevel.end()) + { MS_THROW_TYPE_ERROR("invalid value '%s' for logLevel", level.c_str()); + } Settings::configuration.logLevel = Settings::string2LogLevel[level]; } @@ -328,31 +366,57 @@ void Settings::SetLogTags(const std::vector& tags) for (const auto& tag : tags) { if (tag == "info") + { newLogTags.info = true; + } else if (tag == "ice") + { newLogTags.ice = true; + } else if (tag == "dtls") + { newLogTags.dtls = true; + } else if (tag == "rtp") + { newLogTags.rtp = true; + } else if (tag == "srtp") + { newLogTags.srtp = true; + } else if (tag == "rtcp") + { newLogTags.rtcp = true; + } else if (tag == "rtx") + { newLogTags.rtx = true; + } else if (tag == "bwe") + { newLogTags.bwe = true; + } else if (tag == "score") + { newLogTags.score = true; + } else if (tag == "simulcast") + { newLogTags.simulcast = true; + } else if (tag == "svc") + { newLogTags.svc = true; + } else if (tag == "sctp") + { newLogTags.sctp = true; + } else if (tag == "message") + { newLogTags.message = true; + } } Settings::configuration.logTags = newLogTags; diff --git a/worker/src/Utils/Crypto.cpp b/worker/src/Utils/Crypto.cpp index 0717e7f8c0..45dc91a6fa 100644 --- a/worker/src/Utils/Crypto.cpp +++ b/worker/src/Utils/Crypto.cpp @@ -71,10 +71,14 @@ namespace Utils MS_TRACE(); if (Crypto::hmacSha1Ctx != nullptr) + { EVP_MAC_CTX_free(Crypto::hmacSha1Ctx); + } if (Crypto::mac != nullptr) + { EVP_MAC_free(Crypto::mac); + } } const uint8_t* Crypto::GetHmacSha1(const std::string& key, const uint8_t* data, size_t len) diff --git a/worker/src/Utils/File.cpp b/worker/src/Utils/File.cpp index 8ec27aed25..196eddca7c 100644 --- a/worker/src/Utils/File.cpp +++ b/worker/src/Utils/File.cpp @@ -27,16 +27,22 @@ namespace Utils err = stat(file, &fileStat); if (err != 0) + { MS_THROW_ERROR("cannot read file '%s': %s", file, std::strerror(errno)); + } // Ensure it is a regular file. if (!S_ISREG(fileStat.st_mode)) + { MS_THROW_ERROR("'%s' is not a regular file", file); + } // Ensure it is readable. err = access(file, R_OK); if (err != 0) + { MS_THROW_ERROR("cannot read file '%s': %s", file, std::strerror(errno)); + } } } // namespace Utils diff --git a/worker/src/Utils/IP.cpp b/worker/src/Utils/IP.cpp index 16b9fdd626..81a5c7e093 100644 --- a/worker/src/Utils/IP.cpp +++ b/worker/src/Utils/IP.cpp @@ -13,17 +13,25 @@ namespace Utils MS_TRACE(); if (ip.size() >= INET6_ADDRSTRLEN) + { return AF_UNSPEC; + } auto ipPtr = ip.c_str(); char ipBuffer[INET6_ADDRSTRLEN] = { 0 }; if (uv_inet_pton(AF_INET, ipPtr, ipBuffer) == 0) + { return AF_INET; + } else if (uv_inet_pton(AF_INET6, ipPtr, ipBuffer) == 0) + { return AF_INET6; + } else + { return AF_UNSPEC; + } } void IP::GetAddressInfo(const struct sockaddr* addr, int& family, std::string& ip, uint16_t& port) @@ -44,7 +52,9 @@ namespace Utils sizeof(ipBuffer)); if (err) + { MS_ABORT("uv_inet_ntop() failed: %s", uv_strerror(err)); + } port = static_cast(ntohs(reinterpret_cast(addr)->sin_port)); @@ -61,7 +71,9 @@ namespace Utils sizeof(ipBuffer)); if (err) + { MS_ABORT("uv_inet_ntop() failed: %s", uv_strerror(err)); + } port = static_cast(ntohs(reinterpret_cast(addr)->sin6_port)); diff --git a/worker/src/Utils/String.cpp b/worker/src/Utils/String.cpp index 04086187cb..8c9f250907 100644 --- a/worker/src/Utils/String.cpp +++ b/worker/src/Utils/String.cpp @@ -38,9 +38,13 @@ namespace Utils olen = len * 4 / 3 + 4; // 3-byte blocks to 4-byte. if (olen < len) + { MS_THROW_TYPE_ERROR("integer overflow"); + } else if (olen > BufferOutSize - 1) + { MS_THROW_TYPE_ERROR("data too big"); + } end = data + len; in = data; @@ -100,7 +104,9 @@ namespace Utils // NOTE: This is not really accurate but anyway. if (len > BufferOutSize - 1) + { MS_THROW_TYPE_ERROR("data too big"); + } std::memset(dtable, 0x80, 256); @@ -114,11 +120,15 @@ namespace Utils for (i = 0; i < len; ++i) { if (dtable[data[i]] != 0x80) + { count++; + } } if (count == 0 || count % 4) + { MS_THROW_TYPE_ERROR("invalid data"); + } pos = out; count = 0; @@ -128,10 +138,14 @@ namespace Utils tmp = dtable[data[i]]; if (tmp == 0x80) + { continue; + } if (data[i] == '=') + { pad++; + } block[count] = tmp; count++; @@ -146,11 +160,17 @@ namespace Utils if (pad) { if (pad == 1) + { pos--; + } else if (pad == 2) + { pos -= 2; + } else + { MS_THROW_TYPE_ERROR("integer padding"); + } break; } diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 46c63d4215..c7432525ec 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -54,7 +54,9 @@ Worker::~Worker() MS_TRACE(); if (!this->closed) + { Close(); + } } void Worker::Close() @@ -62,7 +64,9 @@ void Worker::Close() MS_TRACE(); if (this->closed) + { return; + } this->closed = true; @@ -139,7 +143,9 @@ flatbuffers::Offset Worker::FillBufferResour err = uv_getrusage(std::addressof(uvRusage)); if (err != 0) + { MS_THROW_ERROR("uv_getrusagerequest() failed: %s", uv_strerror(err)); + } return FBS::Worker::CreateResourceUsageResponse( builder, @@ -195,7 +201,9 @@ RTC::Router* Worker::GetRouter(const std::string& routerId) const auto it = this->mapRouters.find(routerId); if (it == this->mapRouters.end()) + { MS_THROW_ERROR("Router not found"); + } return it->second; } @@ -203,13 +211,17 @@ RTC::Router* Worker::GetRouter(const std::string& routerId) const void Worker::CheckNoWebRtcServer(const std::string& webRtcServerId) const { if (this->mapWebRtcServers.find(webRtcServerId) != this->mapWebRtcServers.end()) + { MS_THROW_ERROR("a WebRtcServer with same webRtcServerId already exists"); + } } void Worker::CheckNoRouter(const std::string& routerId) const { if (this->mapRouters.find(routerId) != this->mapRouters.end()) + { MS_THROW_ERROR("a Router with same routerId already exists"); + } } RTC::WebRtcServer* Worker::GetWebRtcServer(const std::string& webRtcServerId) const @@ -217,7 +229,9 @@ RTC::WebRtcServer* Worker::GetWebRtcServer(const std::string& webRtcServerId) co auto it = this->mapWebRtcServers.find(webRtcServerId); if (it == this->mapWebRtcServers.end()) + { MS_THROW_ERROR("WebRtcServer not found"); + } return it->second; } @@ -234,7 +248,9 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) case Channel::ChannelRequest::Method::WORKER_CLOSE: { if (this->closed) + { return; + } MS_DEBUG_DEV("Worker close request, stopping"); @@ -459,14 +475,18 @@ inline void Worker::OnSignal(SignalHandle* /*signalHandle*/, int signum) MS_TRACE(); if (this->closed) + { return; + } switch (signum) { case SIGINT: { if (this->closed) + { return; + } MS_DEBUG_DEV("INT signal received, closing myself"); @@ -478,7 +498,9 @@ inline void Worker::OnSignal(SignalHandle* /*signalHandle*/, int signum) case SIGTERM: { if (this->closed) + { return; + } MS_DEBUG_DEV("TERM signal received, closing myself"); From 0efec5f200f31ce27e3e85619cffa70730e17cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 15 Nov 2023 12:47:50 +0100 Subject: [PATCH 189/525] C++: add missing { } in if() conditions --- worker/src/RTC/SctpListener.cpp | 4 ++++ worker/src/RTC/TcpConnection.cpp | 4 ++++ worker/src/RTC/Transport.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/worker/src/RTC/SctpListener.cpp b/worker/src/RTC/SctpListener.cpp index 3daf7aa76f..bce61d30f0 100644 --- a/worker/src/RTC/SctpListener.cpp +++ b/worker/src/RTC/SctpListener.cpp @@ -57,9 +57,13 @@ namespace RTC for (auto it = this->streamIdTable.begin(); it != this->streamIdTable.end();) { if (it->second == dataProducer) + { it = this->streamIdTable.erase(it); + } else + { ++it; + } } } diff --git a/worker/src/RTC/TcpConnection.cpp b/worker/src/RTC/TcpConnection.cpp index 143447367f..da26865379 100644 --- a/worker/src/RTC/TcpConnection.cpp +++ b/worker/src/RTC/TcpConnection.cpp @@ -60,13 +60,17 @@ namespace RTC // a DTLS Close Alert this would be closed (Close() called) so we cannot call // our listeners anymore. if (IsClosed()) + { return; + } const size_t dataLen = this->bufferDataLen - this->frameStart; size_t packetLen; if (dataLen >= 2) + { packetLen = size_t{ Utils::Byte::Get2Bytes(this->buffer + this->frameStart, 0) }; + } // We have packetLen bytes. if (dataLen >= 2 && dataLen >= 2 + packetLen) diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index e4c39263ff..cdf0a606e3 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -336,20 +336,34 @@ namespace RTC switch (this->sctpAssociation->GetState()) { case RTC::SctpAssociation::SctpState::NEW: + { sctpState = FBS::SctpAssociation::SctpState::NEW; break; + } + case RTC::SctpAssociation::SctpState::CONNECTING: + { sctpState = FBS::SctpAssociation::SctpState::CONNECTING; break; + } + case RTC::SctpAssociation::SctpState::CONNECTED: + { sctpState = FBS::SctpAssociation::SctpState::CONNECTED; break; + } + case RTC::SctpAssociation::SctpState::FAILED: + { sctpState = FBS::SctpAssociation::SctpState::FAILED; break; + } + case RTC::SctpAssociation::SctpState::CLOSED: + { sctpState = FBS::SctpAssociation::SctpState::CLOSED; break; + } } sctpListener = this->sctpListener.FillBuffer(builder); @@ -403,20 +417,34 @@ namespace RTC switch (this->sctpAssociation->GetState()) { case RTC::SctpAssociation::SctpState::NEW: + { sctpState = FBS::SctpAssociation::SctpState::NEW; break; + } + case RTC::SctpAssociation::SctpState::CONNECTING: + { sctpState = FBS::SctpAssociation::SctpState::CONNECTING; break; + } + case RTC::SctpAssociation::SctpState::CONNECTED: + { sctpState = FBS::SctpAssociation::SctpState::CONNECTED; break; + } + case RTC::SctpAssociation::SctpState::FAILED: + { sctpState = FBS::SctpAssociation::SctpState::FAILED; break; + } + case RTC::SctpAssociation::SctpState::CLOSED: + { sctpState = FBS::SctpAssociation::SctpState::CLOSED; break; + } } } From 262dba06c88dee279a6e10853e71dcd7cc0430e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 15 Nov 2023 13:17:13 +0100 Subject: [PATCH 190/525] C++: add { } in all remaining if() conditions (test and include folders) --- worker/include/Logger.hpp | 2 + .../include/RTC/RTCP/FeedbackRtpTransport.hpp | 2 + worker/include/RTC/RTCP/ReceiverReport.hpp | 6 +++ worker/include/RTC/RTCP/Sdes.hpp | 2 + worker/include/RTC/RTCP/SenderReport.hpp | 2 + worker/include/RTC/RTCP/XR.hpp | 2 + worker/include/RTC/RtpPacket.hpp | 44 +++++++++++++++++++ worker/include/RTC/TransportTuple.hpp | 30 +++++++++++++ worker/test/include/helpers.hpp | 34 ++++++++++++++ worker/test/src/RTC/Codecs/TestVP8.cpp | 2 + worker/test/src/RTC/TestRtpPacket.cpp | 28 ++++++++++++ worker/test/src/RTC/TestRtpPacketH264Svc.cpp | 33 ++++++++++++++ worker/test/src/RTC/TestRtpStreamRecv.cpp | 4 ++ worker/test/src/RTC/TestSeqManager.cpp | 1 + 14 files changed, 192 insertions(+) diff --git a/worker/include/Logger.hpp b/worker/include/Logger.hpp index db523dbc05..53c16f32a4 100644 --- a/worker/include/Logger.hpp +++ b/worker/include/Logger.hpp @@ -355,7 +355,9 @@ class Logger bufferDataLen += loggerWritten; \ } \ if (bufferDataLen != 0) \ + { \ Logger::channel->SendLog(Logger::buffer, static_cast(bufferDataLen)); \ + } \ } \ while (false) diff --git a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp index 2c333e966c..6c4398664d 100644 --- a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp +++ b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp @@ -293,7 +293,9 @@ namespace RTC size_t GetSize() const override { if (this->size) + { return this->size; + } // Fixed packet size. size_t size = FeedbackRtpPacket::GetSize(); diff --git a/worker/include/RTC/RTCP/ReceiverReport.hpp b/worker/include/RTC/RTCP/ReceiverReport.hpp index 44fbb2e02e..21de42211e 100644 --- a/worker/include/RTC/RTCP/ReceiverReport.hpp +++ b/worker/include/RTC/RTCP/ReceiverReport.hpp @@ -71,11 +71,15 @@ namespace RTC // Possitive value. if (((value >> 23) & 1) == 0) + { return value; + } // Negative value. if (value != 0x0800000) + { value &= ~(1 << 23); + } return -value; } @@ -170,7 +174,9 @@ namespace RTC auto it = std::find(this->reports.begin(), this->reports.end(), report); if (it != this->reports.end()) + { this->reports.erase(it); + } } Iterator Begin() { diff --git a/worker/include/RTC/RTCP/Sdes.hpp b/worker/include/RTC/RTCP/Sdes.hpp index 24bf977c77..717da20590 100644 --- a/worker/include/RTC/RTCP/Sdes.hpp +++ b/worker/include/RTC/RTCP/Sdes.hpp @@ -188,7 +188,9 @@ namespace RTC auto it = std::find(this->chunks.begin(), this->chunks.end(), chunk); if (it != this->chunks.end()) + { this->chunks.erase(it); + } } Iterator Begin() { diff --git a/worker/include/RTC/RTCP/SenderReport.hpp b/worker/include/RTC/RTCP/SenderReport.hpp index 80b2fcc38a..d9f4f9cf16 100644 --- a/worker/include/RTC/RTCP/SenderReport.hpp +++ b/worker/include/RTC/RTCP/SenderReport.hpp @@ -133,7 +133,9 @@ namespace RTC auto it = std::find(this->reports.begin(), this->reports.end(), report); if (it != this->reports.end()) + { this->reports.erase(it); + } } Iterator Begin() { diff --git a/worker/include/RTC/RTCP/XR.hpp b/worker/include/RTC/RTCP/XR.hpp index aadc54aff8..efdfb3a64a 100644 --- a/worker/include/RTC/RTCP/XR.hpp +++ b/worker/include/RTC/RTCP/XR.hpp @@ -107,7 +107,9 @@ namespace RTC auto it = std::find(this->reports.begin(), this->reports.end(), report); if (it != this->reports.end()) + { this->reports.erase(it); + } } uint32_t GetSsrc() const { diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index 0f555c4320..3c72e7b2a8 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -224,7 +224,9 @@ namespace RTC uint16_t GetHeaderExtensionId() const { if (!this->headerExtension) + { return 0u; + } return uint16_t{ ntohs(this->headerExtension->id) }; } @@ -232,7 +234,9 @@ namespace RTC size_t GetHeaderExtensionLength() const { if (!this->headerExtension) + { return 0u; + } return static_cast(ntohs(this->headerExtension->length) * 4); } @@ -240,7 +244,9 @@ namespace RTC uint8_t* GetHeaderExtensionValue() const { if (!this->headerExtension) + { return nullptr; + } return this->headerExtension->value; } @@ -307,7 +313,9 @@ namespace RTC uint8_t* extenValue = GetExtension(this->midExtensionId, extenLen); if (!extenValue || extenLen == 0u) + { return false; + } mid.assign(reinterpret_cast(extenValue), static_cast(extenLen)); @@ -347,7 +355,9 @@ namespace RTC uint8_t* extenValue = GetExtension(this->absSendTimeExtensionId, extenLen); if (!extenValue || extenLen != 3u) + { return false; + } absSendtime = Utils::Byte::Get3Bytes(extenValue, 0); @@ -360,7 +370,9 @@ namespace RTC uint8_t* extenValue = GetExtension(this->absSendTimeExtensionId, extenLen); if (!extenValue || extenLen != 3u) + { return false; + } auto absSendTime = Utils::Time::TimeMsToAbsSendTime(ms); @@ -375,7 +387,9 @@ namespace RTC uint8_t* extenValue = GetExtension(this->transportWideCc01ExtensionId, extenLen); if (!extenValue || extenLen != 2u) + { return false; + } wideSeqNumber = Utils::Byte::Get2Bytes(extenValue, 0); @@ -388,7 +402,9 @@ namespace RTC uint8_t* extenValue = GetExtension(this->transportWideCc01ExtensionId, extenLen); if (!extenValue || extenLen != 2u) + { return false; + } Utils::Byte::Set2Bytes(extenValue, 0, wideSeqNumber); @@ -402,10 +418,14 @@ namespace RTC // NOTE: Remove this once framemarking draft becomes RFC. if (!extenValue) + { extenValue = GetExtension(this->frameMarking07ExtensionId, extenLen); + } if (!extenValue || extenLen > 3u) + { return false; + } *frameMarking = reinterpret_cast(extenValue); length = extenLen; @@ -419,7 +439,9 @@ namespace RTC uint8_t* extenValue = GetExtension(this->ssrcAudioLevelExtensionId, extenLen); if (!extenValue || extenLen != 1u) + { return false; + } volume = Utils::Byte::Get1Byte(extenValue, 0); voice = (volume & (1 << 7)) ? true : false; @@ -434,7 +456,9 @@ namespace RTC uint8_t* extenValue = GetExtension(this->videoOrientationExtensionId, extenLen); if (!extenValue || extenLen != 1u) + { return false; + } uint8_t cvoByte = Utils::Byte::Get1Byte(extenValue, 0); uint8_t cameraValue = ((cvoByte & 0b00001000) >> 3); @@ -472,7 +496,9 @@ namespace RTC else if (HasOneByteExtensions()) { if (id > 14) + { return false; + } // `-1` because we have 14 elements total 0..13 and `id` is in the range 1..14. return this->oneByteExtensions[id - 1] != nullptr; @@ -482,13 +508,17 @@ namespace RTC auto it = this->mapTwoBytesExtensions.find(id); if (it == this->mapTwoBytesExtensions.end()) + { return false; + } auto* extension = it->second; // In Two-Byte extensions value length may be zero. If so, return false. if (extension->len == 0u) + { return false; + } return true; } @@ -509,13 +539,17 @@ namespace RTC else if (HasOneByteExtensions()) { if (id > 14) + { return nullptr; + } // `-1` because we have 14 elements total 0..13 and `id` is in the range 1..14. auto* extension = this->oneByteExtensions[id - 1]; if (!extension) + { return nullptr; + } // In One-Byte extensions value length 0 means 1. len = extension->len + 1; @@ -527,7 +561,9 @@ namespace RTC auto it = this->mapTwoBytesExtensions.find(id); if (it == this->mapTwoBytesExtensions.end()) + { return nullptr; + } auto* extension = it->second; @@ -535,7 +571,9 @@ namespace RTC // In Two-Byte extensions value length may be zero. If so, return nullptr. if (extension->len == 0u) + { return nullptr; + } return extension->value; } @@ -567,7 +605,9 @@ namespace RTC uint8_t GetSpatialLayer() const { if (!this->payloadDescriptorHandler) + { return 0u; + } return this->payloadDescriptorHandler->GetSpatialLayer(); } @@ -575,7 +615,9 @@ namespace RTC uint8_t GetTemporalLayer() const { if (!this->payloadDescriptorHandler) + { return 0u; + } return this->payloadDescriptorHandler->GetTemporalLayer(); } @@ -583,7 +625,9 @@ namespace RTC bool IsKeyFrame() const { if (!this->payloadDescriptorHandler) + { return false; + } return this->payloadDescriptorHandler->IsKeyFrame(); } diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 75c124ecd4..772539c391 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -45,24 +45,34 @@ namespace RTC protocol(tuple->protocol) { if (protocol == TransportTuple::Protocol::UDP) + { StoreUdpRemoteAddress(); + } } public: void Close() { if (this->protocol == Protocol::UDP) + { this->udpSocket->Close(); + } else + { this->tcpConnection->Close(); + } } bool IsClosed() { if (this->protocol == Protocol::UDP) + { return this->udpSocket->IsClosed(); + } else + { return this->tcpConnection->IsClosed(); + } } flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; @@ -90,9 +100,13 @@ namespace RTC void Send(const uint8_t* data, size_t len, RTC::TransportTuple::onSendCallback* cb = nullptr) { if (this->protocol == Protocol::UDP) + { this->udpSocket->Send(data, len, this->udpRemoteAddr, cb); + } else + { this->tcpConnection->Send(data, len, cb); + } } Protocol GetProtocol() const @@ -103,33 +117,49 @@ namespace RTC const struct sockaddr* GetLocalAddress() const { if (this->protocol == Protocol::UDP) + { return this->udpSocket->GetLocalAddress(); + } else + { return this->tcpConnection->GetLocalAddress(); + } } const struct sockaddr* GetRemoteAddress() const { if (this->protocol == Protocol::UDP) + { return (const struct sockaddr*)this->udpRemoteAddr; + } else + { return this->tcpConnection->GetPeerAddress(); + } } size_t GetRecvBytes() const { if (this->protocol == Protocol::UDP) + { return this->udpSocket->GetRecvBytes(); + } else + { return this->tcpConnection->GetRecvBytes(); + } } size_t GetSentBytes() const { if (this->protocol == Protocol::UDP) + { return this->udpSocket->GetSentBytes(); + } else + { return this->tcpConnection->GetSentBytes(); + } } private: diff --git a/worker/test/include/helpers.hpp b/worker/test/include/helpers.hpp index a416052a40..c95f323a2e 100644 --- a/worker/test/include/helpers.hpp +++ b/worker/test/include/helpers.hpp @@ -18,7 +18,9 @@ namespace helpers std::ifstream in(filePath, std::ios::ate | std::ios::binary); if (!in) + { return false; + } *len = static_cast(in.tellg()) - 1; in.seekg(0, std::ios::beg); @@ -31,9 +33,12 @@ namespace helpers inline bool addToBuffer(uint8_t* buf, int* size, uint8_t* data, size_t len) { if (*size + len > BUFFER_SIZE) + { return false; + } int i = 0; + if (len == 1) { buf[*size] = *data; @@ -59,12 +64,15 @@ namespace helpers std::ifstream in(filePath, std::ios::ate | std::ios::binary); if (!in) + { return false; + } in.seekg(pos, std::ios::beg); in.read(reinterpret_cast(payload), bytes); in.close(); + return true; } @@ -93,52 +101,78 @@ namespace helpers // write the RTP header if (!addToBuffer(buf, &packet_size, buffer, 16)) + { return false; + } // write ID and length of frame marking extension // if first layer then length should be 0, else 1 oneByte = oneByte | 1 << 4; + if (sid != -1) { oneByte = oneByte | 0x01; } if (!addToBuffer(buf, &packet_size, &oneByte, 1)) + { return false; + } // write SEIDB TID bits oneByte = 0; + if (firstSliceId == 1) + { oneByte = oneByte | 1 << 7; + } if (lastSliceId == 1) + { oneByte = oneByte | 1 << 6; + } if (isIdr == 1) + { oneByte = oneByte | 1 << 5; + } if (tid != -1) + { oneByte = oneByte | tid; + } if (!addToBuffer(buf, &packet_size, &oneByte, 1)) + { return false; + } // write DID QID bits oneByte = 0; + if (sid != -1) + { oneByte = oneByte | sid << 6; + } if (!addToBuffer(buf, &packet_size, &oneByte, 1)) + { return false; + } // write TL0PICIDX oneByte = 0; + if (!addToBuffer(buf, &packet_size, &oneByte, 1)) + { return false; + } // write payload if (!addToBuffer(buf, &packet_size, payload, nalLength)) + { return false; + } *len = packet_size; diff --git a/worker/test/src/RTC/Codecs/TestVP8.cpp b/worker/test/src/RTC/Codecs/TestVP8.cpp index 9675fb2e51..0a3042246b 100644 --- a/worker/test/src/RTC/Codecs/TestVP8.cpp +++ b/worker/test/src/RTC/Codecs/TestVP8.cpp @@ -228,7 +228,9 @@ Codecs::VP8::PayloadDescriptor* CreatePacket( buffer[5] = tlIndex << 6; if (layerSync) + { buffer[5] |= 0x20; // y bit + } auto* payloadDescriptor = Codecs::VP8::Parse(buffer, bufferLen); diff --git a/worker/test/src/RTC/TestRtpPacket.cpp b/worker/test/src/RTC/TestRtpPacket.cpp index 5c0368fbe3..2eea35b8b0 100644 --- a/worker/test/src/RTC/TestRtpPacket.cpp +++ b/worker/test/src/RTC/TestRtpPacket.cpp @@ -20,12 +20,16 @@ SCENARIO("parse RTP packets", "[parser][rtp]") std::string rid; if (!helpers::readBinaryFile("data/packet1.raw", buffer, &len)) + { FAIL("cannot open file"); + } RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -55,12 +59,16 @@ SCENARIO("parse RTP packets", "[parser][rtp]") size_t len; if (!helpers::readBinaryFile("data/packet2.raw", buffer, &len)) + { FAIL("cannot open file"); + } RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == false); @@ -86,12 +94,16 @@ SCENARIO("parse RTP packets", "[parser][rtp]") uint32_t absSendTime; if (!helpers::readBinaryFile("data/packet3.raw", buffer, &len)) + { FAIL("cannot open file"); + } RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -181,7 +193,9 @@ SCENARIO("parse RTP packets", "[parser][rtp]") RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == false); @@ -213,7 +227,9 @@ SCENARIO("parse RTP packets", "[parser][rtp]") RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -258,7 +274,9 @@ SCENARIO("parse RTP packets", "[parser][rtp]") RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -325,7 +343,9 @@ SCENARIO("parse RTP packets", "[parser][rtp]") RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -399,7 +419,9 @@ SCENARIO("parse RTP packets", "[parser][rtp]") RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->GetPayloadType() == 1); @@ -511,7 +533,9 @@ SCENARIO("parse RTP packets", "[parser][rtp]") uint8_t* extenValue; if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->GetSize() == 28); REQUIRE(packet->HasHeaderExtension() == false); @@ -674,7 +698,9 @@ SCENARIO("parse RTP packets", "[parser][rtp]") uint8_t* extenValue; if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->GetSize() == 28); REQUIRE(packet->HasHeaderExtension() == false); @@ -810,7 +836,9 @@ SCENARIO("parse RTP packets", "[parser][rtp]") RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); diff --git a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp index 970cc73284..68b3c0033f 100644 --- a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp +++ b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp @@ -22,12 +22,16 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") uint8_t* extenValue; if (!helpers::readBinaryFile("data/H264_SVC/I0-7.bin", buffer, &len)) + { FAIL("cannot open file"); + } RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -82,12 +86,16 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") uint8_t* extenValue; if (!helpers::readBinaryFile("data/H264_SVC/I0-8.bin", buffer, &len)) + { FAIL("cannot open file"); + } RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -142,12 +150,16 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") uint8_t* extenValue; if (!helpers::readBinaryFile("data/H264_SVC/I0-5.bin", buffer, &len)) + { FAIL("cannot open file"); + } RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -201,12 +213,16 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") uint8_t* extenValue; if (!helpers::readBinaryFile("data/H264_SVC/I1-15.bin", buffer, &len)) + { FAIL("cannot open file"); + } RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -261,12 +277,16 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") uint8_t* extenValue; if (!helpers::readBinaryFile("data/H264_SVC/I0-14.bin", buffer, &len)) + { FAIL("cannot open file"); + } RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -321,12 +341,16 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") uint8_t* extenValue; if (!helpers::readBinaryFile("data/H264_SVC/2SL-I14.bin", buffer, &len)) + { FAIL("cannot open file"); + } RtpPacket* packet = RtpPacket::Parse(buffer, len); if (!packet) + { FAIL("not a RTP packet"); + } REQUIRE(packet->HasMarker() == false); REQUIRE(packet->HasHeaderExtension() == true); @@ -391,10 +415,12 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") std::fstream nf; nf.open("data/H264_SVC/naluInfo/naluInfo.csv", std::ios::in); + if (nf.is_open()) { std::string line, word; getline(nf, line); // omit the header in the CSV + while (getline(nf, line)) { std::stringstream s(line); @@ -413,19 +439,26 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") if (!helpers::readPayloadData( "data/H264_SVC/naluInfo/naluInfo.264", pos + 4, bytes - 4, buffer)) + { FAIL("Failed to read payload data!\n"); + } // TODO: One additional byte is written as last value is omitted in the // test bench std::string strFile1 = "rtp-" + std::to_string(rows) + ".bin"; + if (!helpers::writeRtpPacket( strFile1.c_str(), type, bytes - 4, sid, tid, isIdr, start, end, buffer, buffer2, &len)) + { FAIL("Failed to write RTP packet!\n"); + } RtpPacket* packet = RtpPacket::Parse(buffer2, len); if (!packet) + { FAIL("not a RTP packet"); + } packet->SetFrameMarkingExtensionId(1); diff --git a/worker/test/src/RTC/TestRtpStreamRecv.cpp b/worker/test/src/RTC/TestRtpStreamRecv.cpp index 3f8399df60..d1d67cf489 100644 --- a/worker/test/src/RTC/TestRtpStreamRecv.cpp +++ b/worker/test/src/RTC/TestRtpStreamRecv.cpp @@ -86,7 +86,9 @@ SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") for (size_t i{ 1 }; i < MaxRequestedPackets; ++i) { if ((bitmask & 1) != 0) + { this->nackedSeqNumbers.push_back(firstSeq + i); + } bitmask >>= 1; } @@ -129,7 +131,9 @@ SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); if (!packet) + { FAIL("not a RTP packet"); + } RtpStream::Params params; diff --git a/worker/test/src/RTC/TestSeqManager.cpp b/worker/test/src/RTC/TestSeqManager.cpp index 828f479b70..2e393a7923 100644 --- a/worker/test/src/RTC/TestSeqManager.cpp +++ b/worker/test/src/RTC/TestSeqManager.cpp @@ -45,6 +45,7 @@ void validate(SeqManager& seqManager, std::vector>& // Covert to string because otherwise Catch will print uint8_t as char. REQUIRE(std::to_string(output) == std::to_string(element.output)); + if (element.maxInput != -1) { REQUIRE(std::to_string(element.maxInput) == std::to_string(seqManager.GetMaxInput())); From 31917af584123b98fc0605d8ab91a075f0baef3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 15 Nov 2023 18:02:43 +0100 Subject: [PATCH 191/525] Modernize clang-format (#1221) --- .github/workflows/mediasoup-worker.yaml | 5 +- npm-scripts.mjs | 10 +- package.json | 2 +- worker/.clang-format | 1 + worker/Makefile | 5 +- worker/include/RTC/RTCP/FeedbackItem.hpp | 2 + worker/scripts/clang-format.mjs | 89 + worker/scripts/gulpfile.mjs | 25 - worker/scripts/package-lock.json | 9711 +++-------------- worker/scripts/package.json | 13 +- worker/src/RTC/RTCP/CompoundPacket.cpp | 8 + .../src/RTC/RTCP/TestFeedbackRtpTransport.cpp | 28 +- 12 files changed, 1450 insertions(+), 8449 deletions(-) create mode 100644 worker/scripts/clang-format.mjs delete mode 100644 worker/scripts/gulpfile.mjs diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 6045c4df11..f4e3bc16b6 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -68,8 +68,9 @@ jobs: - name: npm ci run: npm ci --ignore-scripts --omit=dev - - name: npm run install-clang-tools - run: npm run install-clang-tools + # We need to install deps on worker/scripts/package.json. + - name: npm run install-worker-dev-tools + run: npm run install-worker-dev-tools # TODO: Maybe fix this one day. if: runner.os != 'Windows' diff --git a/npm-scripts.mjs b/npm-scripts.mjs index b5ee8d83fa..2de2298c8a 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -192,7 +192,7 @@ async function run() break; } - case 'install-clang-tools': + case 'install-worker-dev-tools': { executeCmd('npm ci --prefix worker/scripts'); @@ -353,7 +353,7 @@ function lintNode() { logInfo('lintNode()'); - executeCmd('eslint -c node/.eslintrc.js --ignore-path node/.eslintignore --max-warnings 0 node/src node/.eslintrc.js npm-scripts.mjs worker/scripts/gulpfile.mjs'); + executeCmd('eslint -c node/.eslintrc.js --ignore-path node/.eslintignore --max-warnings 0 node/src node/.eslintrc.js npm-scripts.mjs worker/scripts/clang-format.mjs'); } function lintWorker() @@ -744,19 +744,19 @@ function executeCmd(command, exitOnError = true) function logInfo(message) { // eslint-disable-next-line no-console - console.log(`npm-scripts \x1b[36m[INFO] [${task}]\x1b\[0m`, message); + console.log(`npm-scripts.mjs \x1b[36m[INFO] [${task}]\x1b\[0m`, message); } function logWarn(message) { // eslint-disable-next-line no-console - console.warn(`npm-scripts \x1b[33m[WARN] [${task}]\x1b\[0m`, message); + console.warn(`npm-scripts.mjs \x1b[33m[WARN] [${task}]\x1b\[0m`, message); } function logError(message) { // eslint-disable-next-line no-console - console.error(`npm-scripts \x1b[31m[ERROR] [${task}]\x1b\[0m`, message); + console.error(`npm-scripts.mjs \x1b[31m[ERROR] [${task}]\x1b\[0m`, message); } function exitWithError() diff --git a/package.json b/package.json index 18aeb4257e..bfe2446c19 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "test:worker": "node npm-scripts.mjs test:worker", "coverage:node": "node npm-scripts.mjs coverage:node", "install-deps:node": "node npm-scripts.mjs install-deps:node", - "install-clang-tools": "node npm-scripts.mjs install-clang-tools", + "install-worker-dev-tools": "node npm-scripts.mjs install-worker-dev-tools", "release:check": "node npm-scripts.mjs release:check", "release": "node npm-scripts.mjs release", "release:upload-mac-arm-prebuilt-worker": "node npm-scripts.mjs release:upload-mac-arm-prebuilt-worker" diff --git a/worker/.clang-format b/worker/.clang-format index e4b051bfbe..2217415190 100644 --- a/worker/.clang-format +++ b/worker/.clang-format @@ -61,6 +61,7 @@ IncludeIsMainRegex: '$' IndentCaseLabels: true IndentWidth: 2 IndentWrappedFunctionNames: false +InsertBraces: true KeepEmptyLinesAtTheStartOfBlocks: false MaxEmptyLinesToKeep: 1 NamespaceIndentation: All diff --git a/worker/Makefile b/worker/Makefile index be41dd515f..a3f33cf4b1 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -13,7 +13,6 @@ MEDIASOUP_OUT_DIR ?= $(shell pwd)/out # Check the meaning of useful macros in the `worker/include/Logger.hpp` header # file if you want to enable tracing or other debug information. MEDIASOUP_BUILDTYPE ?= Release -GULP = ./scripts/node_modules/.bin/gulp LCOV = ./deps/lcov/bin/lcov DOCKER ?= docker PIP_DIR = $(MEDIASOUP_OUT_DIR)/pip @@ -213,10 +212,10 @@ xcode: setup $(MESON) setup --buildtype debug --backend xcode $(MEDIASOUP_OUT_DIR)/xcode lint: - $(GULP) --gulpfile ./scripts/gulpfile.mjs lint:worker + npm run lint --prefix scripts/ format: - $(GULP) --gulpfile ./scripts/gulpfile.mjs format:worker + npm run format --prefix scripts/ test: setup flatc $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test diff --git a/worker/include/RTC/RTCP/FeedbackItem.hpp b/worker/include/RTC/RTCP/FeedbackItem.hpp index 3649ab41c8..9a453a7d99 100644 --- a/worker/include/RTC/RTCP/FeedbackItem.hpp +++ b/worker/include/RTC/RTCP/FeedbackItem.hpp @@ -15,7 +15,9 @@ namespace RTC { // data size must be >= header. if (Item::HeaderSize > len) + { return nullptr; + } auto* header = const_cast(reinterpret_cast(data)); diff --git a/worker/scripts/clang-format.mjs b/worker/scripts/clang-format.mjs new file mode 100644 index 0000000000..a7a0f00f4d --- /dev/null +++ b/worker/scripts/clang-format.mjs @@ -0,0 +1,89 @@ +import { execSync } from 'node:child_process'; +import { glob } from 'glob'; +import clangFormat from 'clang-format'; + +const task = process.argv.slice(2).join(' '); + +run(); + +async function run() +{ + const clangFormatNativeBinary = clangFormat.getNativeBinary(); + const workerFiles = await glob( + [ + '../src/**/*.cpp', + '../include/**/*.hpp', + '../test/src/**/*.cpp', + '../test/include/helpers.hpp', + '../fuzzer/src/**/*.cpp', + '../fuzzer/include/**/*.hpp' + ] + ); + + switch (task) + { + case 'lint': + { + executeCmd( + `${clangFormatNativeBinary} --Werror --dry-run ${workerFiles.join(' ')}` + ); + + break; + } + + case 'format': + { + executeCmd( + `${clangFormatNativeBinary} --Werror -i ${workerFiles.join(' ')}` + ); + + break; + } + + default: + { + logError('unknown task'); + + exitWithError(); + } + } +} + +function executeCmd(command) +{ + try + { + execSync(command, { stdio: [ 'ignore', process.stdout, process.stderr ] }); + } + catch (error) + { + logError('executeCmd() failed'); + + exitWithError(); + } +} + +// eslint-disable-next-line no-unused-vars +function logInfo(message) +{ + // eslint-disable-next-line no-console + console.log(`clang-format.mjs \x1b[36m[INFO] [${task}]\x1b\[0m`, message); +} + +// eslint-disable-next-line no-unused-vars +function logWarn(message) +{ + // eslint-disable-next-line no-console + console.warn(`clang-format.mjs \x1b[33m[WARN] [${task}]\x1b\[0m`, message); +} + +function logError(message) +{ + // eslint-disable-next-line no-console + console.error(`clang-format.mjs \x1b[31m[ERROR] [${task}]\x1b\[0m`, message); +} + +function exitWithError() +{ + process.exit(1); +} diff --git a/worker/scripts/gulpfile.mjs b/worker/scripts/gulpfile.mjs deleted file mode 100644 index b4c3e9650d..0000000000 --- a/worker/scripts/gulpfile.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import gulp from 'gulp'; -import clangFormat from 'gulp-clang-format'; - -const workerFiles = -[ - '../src/**/*.cpp', - '../include/**/*.hpp', - '../test/src/**/*.cpp', - '../test/include/helpers.hpp', - '../fuzzer/src/**/*.cpp', - '../fuzzer/include/**/*.hpp' -]; - -gulp.task('lint:worker', () => -{ - return gulp.src(workerFiles) - .pipe(clangFormat.checkFormat('file', null, { verbose: true, fail: true })); -}); - -gulp.task('format:worker', () => -{ - return gulp.src(workerFiles, { base: '.' }) - .pipe(clangFormat.format('file')) - .pipe(gulp.dest('.')); -}); diff --git a/worker/scripts/package-lock.json b/worker/scripts/package-lock.json index be2dde4032..5933306013 100644 --- a/worker/scripts/package-lock.json +++ b/worker/scripts/package-lock.json @@ -7,280 +7,129 @@ "": { "name": "mediasoup-worker-dev-tools", "version": "0.0.1", - "devDependencies": { - "clang-tools-prebuilt": "^0.1.4", - "gulp": "^4.0.2", - "gulp-clang-format": "^1.0.27" - }, - "peerDependencies": { - "uuid": "^3.3.2" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" + "clang-format": "^1.8.0", + "clang-tools-prebuilt": "^0.1.4", + "glob": "^10.3.10" } }, - "node_modules/ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dependencies": { - "ansi-wrap": "0.1.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dependencies": { - "remove-trailing-separator": "^1.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { - "buffer-equal": "^1.0.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dependencies": { - "make-iterator": "^1.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=14" } }, - "node_modules/arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { - "make-iterator": "^1.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "dependencies": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "dependencies": { - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "dependencies": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -289,7 +138,6 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, "dependencies": { "safer-buffer": "~2.1.0" } @@ -298,82 +146,24 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, "engines": { "node": ">=0.8" } }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "dependencies": { - "async-done": "^1.2.2" - }, - "engines": { - "node": ">= 0.10" - } + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, "engines": { "node": "*" } @@ -381,186 +171,33 @@ "node_modules/aws4": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "node_modules/bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "dependencies": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, "dependencies": { "tweetnacl": "^0.14.3" } }, - "node_modules/beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "balanced-match": "^1.0.0" } }, "node_modules/camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -569,7 +206,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, "dependencies": { "camelcase": "^2.0.0", "map-obj": "^1.0.0" @@ -581,55 +217,14 @@ "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "node_modules/clang-format": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.6.0.tgz", - "integrity": "sha512-W3/L7fWkA8DoLkz9UGjrRnNi+J5a5TuS2HDLqk6WsicpOzb66MBu4eY/EcXhicHriVnAXWQVyk5/VeHWY6w4ow==", - "dev": true, + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", + "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==", "dependencies": { - "async": "^1.5.2", + "async": "^3.2.3", "glob": "^7.0.0", "resolve": "^1.1.6" }, @@ -639,225 +234,84 @@ "git-clang-format": "bin/git-clang-format" } }, - "node_modules/clang-tools-prebuilt": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", - "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", - "dev": true, - "hasInstallScript": true, + "node_modules/clang-format/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "home-path": "^0.1.1", - "mkdirp": "^0.5.0", - "nugget": "^1.5.1", - "path-exists": "^1.0.0" - }, - "bin": { - "clang-apply-replacements": "tools/clang-apply-replacements.js", - "clang-include-fixer": "tools/clang-include-fixer.js", - "clang-rename": "tools/clang-rename.js", - "clang-tidy": "tools/clang-tidy.js", - "find-all-symbols": "tools/find-all-symbols.js" - } - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, + "node_modules/clang-format/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { - "is-descriptor": "^0.1.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" + "node": "*" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, + "node_modules/clang-format/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { - "is-buffer": "^1.1.5" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/class-utils/node_modules/is-data-descriptor": { + "node_modules/clang-tools-prebuilt": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "dev": true, - "dependencies": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - } - }, - "node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, + "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", + "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", + "hasInstallScript": true, "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "home-path": "^0.1.1", + "mkdirp": "^0.5.0", + "nugget": "^1.5.1", + "path-exists": "^1.0.0" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "clang-apply-replacements": "tools/clang-apply-replacements.js", + "clang-include-fixer": "tools/clang-include-fixer.js", + "clang-rename": "tools/clang-rename.js", + "clang-tidy": "tools/clang-tidy.js", + "find-all-symbols": "tools/find-all-symbols.js" } }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -865,72 +319,47 @@ "node": ">= 0.8" } }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dependencies": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, "node_modules/currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, "dependencies": { "array-find-index": "^1.0.1" }, @@ -938,21 +367,10 @@ "node": ">=0.10.0" } }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, "dependencies": { "assert-plus": "^1.0.0" }, @@ -960,20 +378,10 @@ "node": ">=0.10" } }, - "node_modules/dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -982,62 +390,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "dependencies": { - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, "engines": { "node": ">=0.10.0" } @@ -1046,3483 +398,942 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, "engines": { "node": ">=0.4.0" } }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/diff": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz", - "integrity": "sha1-YOr9DSjukG5Oj/ClLBIpUhAzv5k=", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "dependencies": { - "readable-stream": "~1.1.9" - } - }, - "node_modules/duplexer2/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/duplexer2/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "node_modules/each-props/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] }, - "node_modules/es6-symbol": { + "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "node_modules/event-stream": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.5.tgz", - "integrity": "sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, + "node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, + "node_modules/find-up/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dependencies": { - "is-descriptor": "^0.1.0" + "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dependencies": { - "kind-of": "^3.0.2" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" + "node": ">=14" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "engines": { - "node": ">=0.10.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "engines": { "node": ">=0.10.0" } }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=0.10.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, + "node_modules/graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", "dependencies": { - "homedir-polyfill": "^1.0.1" + "ajv": "^6.12.3", + "har-schema": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", - "dev": true, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dependencies": { - "type": "^2.5.0" + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/ext/node_modules/type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true + "node_modules/home-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/home-path/-/home-path-0.1.2.tgz", + "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=" }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dependencies": { - "is-extendable": "^0.1.0" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8", + "npm": ">=1.3.7" } }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, + "node_modules/indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "repeating": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "node_modules/is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", "dependencies": { - "is-descriptor": "^1.0.0" + "has": "^1.0.3" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", "engines": { "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">= 0.10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, - "node_modules/fast-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", - "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", - "dev": true + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, - "node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" } }, - "node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/find-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, + "node_modules/loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dependencies": { - "pinkie-promise": "^2.0.0" + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, + "node_modules/lru-cache": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", + "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "semver": "^7.3.5" }, "engines": { - "node": ">= 0.10" + "node": "14 || >=16.14" } }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, + "node_modules/lru-cache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10" } }, - "node_modules/fined/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, + "node_modules/lru-cache/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { - "isobject": "^3.0.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/flagged-respawn": { + "node_modules/map-obj": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true, + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, + "node_modules/meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "dependencies": { - "for-in": "^1.0.1" - }, + "node_modules/meow/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "engines": { "node": ">=0.10.0" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", "engines": { - "node": "*" + "node": ">= 0.6" } }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "mime-db": "1.51.0" }, "engines": { - "node": ">= 0.12" + "node": ">= 0.6" } }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dependencies": { - "map-cache": "^0.2.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "engines": { - "node": ">= 0.10" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" + "minimist": "^1.2.5" }, - "engines": { - "node": ">= 4.0" + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node_modules/nugget": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", + "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", + "dependencies": { + "debug": "^2.1.3", + "minimist": "^1.1.0", + "pretty-bytes": "^1.0.2", + "progress-stream": "^1.1.0", + "request": "^2.45.0", + "single-line-log": "^0.4.1", + "throttleit": "0.0.2" + }, + "bin": { + "nugget": "bin.js" } }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dependencies": { - "assert-plus": "^1.0.0" + "wrappy": "1" } }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "error-ex": "^1.2.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, - "node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "node_modules/path-exists": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "engines": { "node": ">=0.10.0" } }, - "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dependencies": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, + "node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "engines": { "node": ">=0.10.0" } }, - "node_modules/glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dependencies": { - "sparkles": "^1.0.0" + "pinkie": "^2.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "node_modules/gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, + "node_modules/pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", "dependencies": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" + "get-stdin": "^4.0.1", + "meow": "^3.1.0" }, "bin": { - "gulp": "bin/gulp.js" + "pretty-bytes": "cli.js" }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/gulp-clang-format": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/gulp-clang-format/-/gulp-clang-format-1.0.27.tgz", - "integrity": "sha512-Jj4PGuNXKdqVCh9fijvL7wdzma5TQRJz1vv8FjOjnSkfq3s/mvbdE/jq+5HG1c/q+jcYkXTEGkYT3CrdnJOLaQ==", - "dev": true, + "node_modules/progress-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", + "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", "dependencies": { - "clang-format": "^1.0.32", - "fancy-log": "^1.3.2", - "gulp-diff": "^1.0.0", - "plugin-error": "^1.0.1", - "stream-combiner2": "^1.1.1", - "through2": "^2.0.3" + "speedometer": "~0.1.2", + "through2": "~0.2.3" } }, - "node_modules/gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, + "node_modules/progress-stream/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/progress-stream/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "node_modules/progress-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dependencies": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.10" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "node_modules/gulp-diff": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulp-diff/-/gulp-diff-1.0.0.tgz", - "integrity": "sha1-EBsjcS3WsQe9B9BauI6jrEhf7Xc=", - "dev": true, - "dependencies": { - "cli-color": "^1.0.0", - "diff": "^2.0.2", - "event-stream": "^3.1.5", - "gulp-util": "^3.0.6", - "through2": "^2.0.0" - } - }, - "node_modules/gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5", - "dev": true, + "node_modules/progress-stream/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "node_modules/progress-stream/node_modules/through2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", "dependencies": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "engines": { - "node": ">=0.10" + "readable-stream": "~1.1.9", + "xtend": "~2.1.1" } }, - "node_modules/gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, + "node_modules/progress-stream/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", "dependencies": { - "glogg": "^1.0.0" + "object-keys": "~0.4.0" }, "engines": { - "node": ">= 0.10" + "node": ">=0.4" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "engines": { "node": ">=6" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "engines": { - "node": ">= 0.4.0" + "node": ">=0.6" } }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dependencies": { - "ansi-regex": "^2.0.0" + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/has-values": { + "node_modules/redent": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dependencies": { - "is-buffer": "^1.1.5" + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/home-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/home-path/-/home-path-0.1.2.tgz", - "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=", - "dev": true - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, + "node_modules/repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dependencies": { - "parse-passwd": "^1.0.0" + "is-finite": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" }, "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" + "node": ">= 6" } }, - "node_modules/indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dependencies": { - "repeating": "^2.0.0" + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" } }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/signal-exit": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", + "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "node_modules/single-line-log": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", + "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" }, - "node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" }, - "node_modules/is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", - "dev": true, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==" }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/speedometer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=" }, - "node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/just-debounce": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", - "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", - "dev": true - }, - "node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "dependencies": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/liftoff/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "node_modules/lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "node_modules/lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "node_modules/lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "node_modules/lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "node_modules/lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "node_modules/lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "node_modules/lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "node_modules/lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "dependencies": { - "lodash._root": "^3.0.0" - } - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "node_modules/lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "node_modules/lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "dependencies": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "node_modules/lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "node_modules/lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "dependencies": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "node_modules/lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } - }, - "node_modules/loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "dependencies": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "dependencies": { - "es5-ext": "~0.10.2" - } - }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/make-iterator/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "dependencies": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/matchdep/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/matchdep/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, - "node_modules/memoizee/node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true - }, - "node_modules/meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "dependencies": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/meow/node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "dependencies": { - "duplexer2": "0.0.2" - } - }, - "node_modules/mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "dev": true, - "optional": true - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/nugget": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", - "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", - "dev": true, - "dependencies": { - "debug": "^2.1.3", - "minimist": "^1.1.0", - "pretty-bytes": "^1.0.2", - "progress-stream": "^1.1.0", - "request": "^2.45.0", - "single-line-log": "^0.4.1", - "throttleit": "0.0.2" - }, - "bin": { - "nugget": "bin.js" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", - "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/plugin-error/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/plugin-error/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/plugin-error/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "dev": true, - "dependencies": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - }, - "bin": { - "pretty-bytes": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", - "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", - "dev": true, - "dependencies": { - "speedometer": "~0.1.2", - "through2": "~0.2.3" - } - }, - "node_modules/progress-stream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/progress-stream/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/progress-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/progress-stream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/progress-stream/node_modules/through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", - "dev": true, - "dependencies": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" - } - }, - "node_modules/progress-stream/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "dependencies": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "dependencies": { - "is-finite": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "dependencies": { - "sver-compat": "^1.5.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", - "dev": true - }, - "node_modules/single-line-log": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", - "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=", - "dev": true - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, - "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", - "dev": true - }, - "node_modules/speedometer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", - "dev": true - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" }, "bin": { "sshpk-conv": "bin/sshpk-conv", @@ -4533,594 +1344,141 @@ "node": ">=0.10.0" } }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "node_modules/stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, - "dependencies": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "node_modules/stream-combiner2/node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "dependencies": { - "get-stdin": "^4.0.1" - }, - "bin": { - "strip-indent": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/throttleit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "dependencies": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "safe-buffer": "^5.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/undertaker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", - "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" } }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "is-utf8": "^0.2.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, + "node_modules/strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "get-stdin": "^4.0.1" + }, + "bin": { + "strip-indent": "cli.js" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, + "node_modules/throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=" + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dependencies": { - "isarray": "1.0.0" + "psl": "^1.1.28", + "punycode": "^2.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8" } }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, + "node_modules/trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "engines": { "node": ">=0.10.0" } }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, "engines": { - "node": ">=4", - "yarn": "*" + "node": "*" } }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, "node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", @@ -5130,42 +1488,19 @@ "uuid": "bin/uuid" } }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, "engines": [ "node >=0.6.0" ], @@ -5178,271 +1513,159 @@ "node_modules/verror/node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "dependencies": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - }, - "engines": { - "node": ">= 0.9" - } - }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs/node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "node_modules/vinyl-fs/node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/vinyl-fs/node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs/node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" + "node": ">=10" }, - "engines": { - "node": ">= 0.10" + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/vinyl-sourcemap/node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { - "node": ">=0.8" + "node": ">=8" } }, - "node_modules/vinyl-sourcemap/node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "remove-trailing-separator": "^1.0.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/vinyl-sourcemap/node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/vinyl-sourcemap/node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "node": ">=8" } }, - "node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - } - }, - "node_modules/yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "node_modules/yargs-parser/node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "node_modules/yargs/node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } }, "dependencies": { + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5450,432 +1673,74 @@ "uri-js": "^4.2.2" } }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" }, "asn1": { "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" + "safer-buffer": "~2.1.0" } }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-settle": { + "assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - } - } + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, "requires": { "tweetnacl": "^0.14.3" } }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "balanced-match": "^1.0.0" } }, "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" }, "camelcase-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, "requires": { "camelcase": "^2.0.0", "map-obj": "^1.0.0" @@ -5884,329 +1749,132 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "clang-format": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.6.0.tgz", - "integrity": "sha512-W3/L7fWkA8DoLkz9UGjrRnNi+J5a5TuS2HDLqk6WsicpOzb66MBu4eY/EcXhicHriVnAXWQVyk5/VeHWY6w4ow==", - "dev": true, + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", + "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==", "requires": { - "async": "^1.5.2", + "async": "^3.2.3", "glob": "^7.0.0", "resolve": "^1.1.6" - } - }, - "clang-tools-prebuilt": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", - "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", - "dev": true, - "requires": { - "home-path": "^0.1.1", - "mkdirp": "^0.5.0", - "nugget": "^1.5.1", - "path-exists": "^1.0.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "brace-expansion": "^1.1.7" } } } }, - "cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "dev": true, - "requires": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, + "clang-tools-prebuilt": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", + "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "home-path": "^0.1.1", + "mkdirp": "^0.5.0", + "nugget": "^1.5.1", + "path-exists": "^1.0.0" } }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "color-name": "~1.1.4" } }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "requires": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - } + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, "requires": { "array-find-index": "^1.0.1" } }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, "requires": { "assert-plus": "^1.0.0" } }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -6214,449 +1882,64 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diff": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz", - "integrity": "sha1-YOr9DSjukG5Oj/ClLBIpUhAzv5k=", - "dev": true - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "event-stream": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.5.tgz", - "integrity": "sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g==", - "dev": true, - "requires": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", - "dev": true, - "requires": { - "type": "^2.5.0" - }, - "dependencies": { - "type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - } - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - } - } + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "fast-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", - "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", - "dev": true - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, "requires": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" @@ -6666,401 +1949,92 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, "requires": { "pinkie-promise": "^2.0.0" } } } }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" } } }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, "requires": { "assert-plus": "^1.0.0" } }, "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - } - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "requires": { - "sparkles": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" } }, "graceful-fs": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-clang-format": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/gulp-clang-format/-/gulp-clang-format-1.0.27.tgz", - "integrity": "sha512-Jj4PGuNXKdqVCh9fijvL7wdzma5TQRJz1vv8FjOjnSkfq3s/mvbdE/jq+5HG1c/q+jcYkXTEGkYT3CrdnJOLaQ==", - "dev": true, - "requires": { - "clang-format": "^1.0.32", - "fancy-log": "^1.3.2", - "gulp-diff": "^1.0.0", - "plugin-error": "^1.0.1", - "stream-combiner2": "^1.1.1", - "through2": "^2.0.3" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - } - }, - "gulp-diff": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulp-diff/-/gulp-diff-1.0.0.tgz", - "integrity": "sha1-EBsjcS3WsQe9B9BauI6jrEhf7Xc=", - "dev": true, - "requires": { - "cli-color": "^1.0.0", - "diff": "^2.0.2", - "event-stream": "^3.1.5", - "gulp-util": "^3.0.6", - "through2": "^2.0.0" - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -7070,93 +2044,24 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "home-path": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/home-path/-/home-path-0.1.2.tgz", - "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } + "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=" }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -7167,7 +2072,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, "requires": { "repeating": "^2.0.0" } @@ -7175,8 +2079,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -7185,295 +2088,79 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-core-module": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", - "dev": true, "requires": { "has": "^1.0.3" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, "is-finite": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -7481,341 +2168,62 @@ "verror": "1.10.0" } }, - "just-debounce": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", - "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", - "dev": true - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "^3.0.0" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" } }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, "requires": { "currently-unhandled": "^0.4.1", "signal-exit": "^3.0.0" } }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, + "lru-cache": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", + "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" + "semver": "^7.3.5" }, "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "yallist": "^4.0.0" } }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { - "is-extglob": "^2.1.0" + "lru-cache": "^6.0.0" } } } }, - "memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dev": true, - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "dependencies": { - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true - } - } + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, "requires": { "camelcase-keys": "^2.0.0", "decamelize": "^1.1.2", @@ -7832,133 +2240,45 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" } } }, "mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" }, "mime-types": { "version": "2.1.34", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, "requires": { "mime-db": "1.51.0" } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" } }, "minimist": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, "requires": { "minimist": "^1.2.5" } @@ -7966,97 +2286,12 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -8064,26 +2299,10 @@ "validate-npm-package-license": "^3.0.1" } }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, "nugget": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", - "dev": true, "requires": { "debug": "^2.1.3", "minimist": "^1.1.0", @@ -8094,386 +2313,102 @@ "throttleit": "0.0.2" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, "requires": { "error-ex": "^1.2.0" } }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, "path-exists": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", - "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=", - "dev": true + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "requires": { - "path-root-regex": "^0.1.0" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, "requires": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" } }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "~2.3" - } - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { "pinkie": "^2.0.0" } }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, "pretty-bytes": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "dev": true, "requires": { "get-stdin": "^4.0.1", "meow": "^3.1.0" } }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, "progress-stream": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", - "dev": true, "requires": { "speedometer": "~0.1.2", "through2": "~0.2.3" @@ -8482,20 +2417,17 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "object-keys": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" }, "readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -8506,14 +2438,12 @@ "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, "through2": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", - "dev": true, "requires": { "readable-stream": "~1.1.9", "xtend": "~2.1.1" @@ -8523,7 +2453,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, "requires": { "object-keys": "~0.4.0" } @@ -8533,47 +2462,22 @@ "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, "requires": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", @@ -8584,167 +2488,32 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, "requires": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" } }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, "requires": { "indent-string": "^2.1.0", "strip-indent": "^1.0.1" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, "repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, "requires": { "is-finite": "^1.0.0" } }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -8768,292 +2537,57 @@ "uuid": "^3.3.2" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, "requires": { "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, - "set-blocking": { + "shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } + "shebang-regex": "^3.0.0" } }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, "signal-exit": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", - "dev": true + "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" }, "single-line-log": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", - "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true + "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -9062,14 +2596,12 @@ "spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" }, "spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -9078,68 +2610,17 @@ "spdx-license-ids": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", - "dev": true + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==" }, "speedometer": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } + "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=" }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -9152,161 +2633,55 @@ "tweetnacl": "~0.14.0" } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "ansi-regex": "^5.0.1" } } } }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" + "ansi-regex": "^5.0.1" }, "dependencies": { - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" } } }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, "requires": { "is-utf8": "^0.2.0" } @@ -9315,171 +2690,19 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, "requires": { "get-stdin": "^4.0.1" } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, "throttleit": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=" }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, "requires": { "psl": "^1.1.28", "punycode": "^2.1.1" @@ -9488,14 +2711,12 @@ "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -9503,181 +2724,34 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "undertaker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", - "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "requires": { "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -9687,228 +2761,67 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" } } }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "dependencies": { - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "color-convert": "^2.0.1" } - } - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { - "remove-trailing-separator": "^1.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "ansi-regex": "^5.0.1" } } } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/worker/scripts/package.json b/worker/scripts/package.json index fc42fde271..5d58f50481 100644 --- a/worker/scripts/package.json +++ b/worker/scripts/package.json @@ -2,12 +2,13 @@ "name": "mediasoup-worker-dev-tools", "version": "0.0.1", "description": "mediasoup worker dev tools", - "devDependencies": { - "clang-tools-prebuilt": "^0.1.4", - "gulp": "^4.0.2", - "gulp-clang-format": "^1.0.27" + "scripts": { + "lint": "node clang-format.mjs lint", + "format": "node clang-format.mjs format" }, - "peerDependencies": { - "uuid": "^3.3.2" + "dependencies": { + "clang-format": "^1.8.0", + "clang-tools-prebuilt": "^0.1.4", + "glob": "^10.3.10" } } diff --git a/worker/src/RTC/RTCP/CompoundPacket.cpp b/worker/src/RTC/RTCP/CompoundPacket.cpp index 811968b850..c1809e3d11 100644 --- a/worker/src/RTC/RTCP/CompoundPacket.cpp +++ b/worker/src/RTC/RTCP/CompoundPacket.cpp @@ -129,13 +129,19 @@ namespace RTC // Add the items into the packet. for (auto* report : senderReports) + { this->senderReportPacket.AddReport(report); + } for (auto* chunk : sdesChunks) + { this->sdesPacket.AddChunk(chunk); + } for (auto* report : delaySinceLastRrReports) + { this->xrPacket.AddReport(report); + } // New items can hold in the packet, report it. if (GetSize() <= MaxSize) @@ -174,7 +180,9 @@ namespace RTC // Add the items into the packet. for (auto* report : receiverReports) + { this->receiverReportPacket.AddReport(report); + } if (receiverReferenceTimeReport) { diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp index 547e40373e..e61be9cee9 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp @@ -97,7 +97,9 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" packet->SetFeedbackPacketCount(1); for (auto& input : inputs) + { packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } REQUIRE(packet->GetLatestSequenceNumber() == 1013); REQUIRE(packet->GetLatestTimestamp() == 1000000013); @@ -170,7 +172,9 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" packet->SetFeedbackPacketCount(10); for (auto& input : inputs) + { packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } packet->Finish(); validate(inputs, packet->GetPacketResults()); @@ -233,7 +237,9 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" packet->SetFeedbackPacketCount(1); for (auto& input : inputs) + { packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } packet->Finish(); validate(inputs, packet->GetPacketResults()); @@ -289,7 +295,9 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" packet->SetFeedbackPacketCount(1); for (auto& input : inputs) + { packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } packet->Finish(); validate(inputs, packet->GetPacketResults()); @@ -354,7 +362,9 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" packet->SetFeedbackPacketCount(1); for (auto& input : inputs) + { packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } packet->Finish(); validate(inputs, packet->GetPacketResults()); @@ -413,7 +423,9 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" packet2->SetFeedbackPacketCount(2); for (auto& input : inputs2) + { packet2->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } packet2->Finish(); validate(inputs2, packet2->GetPacketResults()); @@ -593,8 +605,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" .packetStatusCount = 1, .deltas = std::vector{ 57 }, .buffer = std::vector{ 0xaf, 0xcd, 0x00, 0x05, 0xfa, 0x17, 0xfa, 0x17, - 0x00, 0x00, 0x04, 0xd2, 0x00, 0x0d, 0x00, 0x01, - 0x00, 0x8A, 0xB0, 0x00, 0x20, 0x01, 0xE4, 0x01 } }, + 0x00, 0x00, 0x04, 0xd2, 0x00, 0x0d, 0x00, 0x01, + 0x00, 0x8A, 0xB0, 0x00, 0x20, 0x01, 0xE4, 0x01 } }, { .baseTimeRaw = 35504, .baseTimeMs = 1076014080, .baseSequence = 14, @@ -630,8 +642,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" .packetStatusCount = 2, .deltas = std::vector{ 35, 17 }, .buffer = std::vector{ 0x8F, 0xCD, 0x00, 0x05, 0xFA, 0x17, 0xFA, 0x17, - 0x39, 0xE9, 0x42, 0x38, 0x00, 0x01, 0x00, 0x02, - 0xBD, 0x57, 0xAA, 0x00, 0x20, 0x02, 0x8C, 0x44 } }, + 0x39, 0xE9, 0x42, 0x38, 0x00, 0x01, 0x00, 0x02, + 0xBD, 0x57, 0xAA, 0x00, 0x20, 0x02, 0x8C, 0x44 } }, { .baseTimeRaw = 818995, .baseTimeMs = 1126157504, @@ -690,16 +702,16 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" .packetStatusCount = 2, .deltas = std::vector{ 44, 18 }, .buffer = std::vector{ 0x8F, 0xCD, 0x00, 0x05, 0xFA, 0x17, 0xFA, 0x17, - 0x08, 0xEB, 0x06, 0xD7, 0x00, 0x11, 0x00, 0x02, - 0x0C, 0x89, 0x14, 0x01, 0x20, 0x02, 0xB0, 0x48 } }, + 0x08, 0xEB, 0x06, 0xD7, 0x00, 0x11, 0x00, 0x02, + 0x0C, 0x89, 0x14, 0x01, 0x20, 0x02, 0xB0, 0x48 } }, { .baseTimeRaw = 821524, .baseTimeMs = 1126319360, .baseSequence = 17, .packetStatusCount = 1, .deltas = std::vector{ 62 }, .buffer = std::vector{ 0xAF, 0xCD, 0x00, 0x05, 0xFA, 0x17, 0xFA, 0x17, - 0x20, 0x92, 0x5E, 0xB7, 0x00, 0x11, 0x00, 0x01, - 0x0C, 0x89, 0x14, 0x00, 0x20, 0x01, 0xF8, 0x01 } }, + 0x20, 0x92, 0x5E, 0xB7, 0x00, 0x11, 0x00, 0x01, + 0x0C, 0x89, 0x14, 0x00, 0x20, 0x01, 0xF8, 0x01 } }, { .baseTimeRaw = 821526, .baseTimeMs = 1126319488, .baseSequence = 19, From cc863ebb4ff2a8076271f303c8199233df96eaa9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Nov 2023 18:08:09 +0100 Subject: [PATCH 192/525] Bump semver from 5.7.1 to 5.7.2 in /worker/scripts (#1222) Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2) --- updated-dependencies: - dependency-name: semver dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- worker/scripts/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/worker/scripts/package-lock.json b/worker/scripts/package-lock.json index 5933306013..358ebe9286 100644 --- a/worker/scripts/package-lock.json +++ b/worker/scripts/package-lock.json @@ -1251,9 +1251,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "bin": { "semver": "bin/semver" } @@ -2557,9 +2557,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "shebang-command": { "version": "2.0.0", From 3ba3540d29d301f4451834939ae9bb2bf7626764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Thu, 16 Nov 2023 13:02:12 +0100 Subject: [PATCH 193/525] Node: Producer, add missing member to ProducerScore (#1225) This member in the type has been missing for ever, even though it's documented. --- node/src/Producer.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/node/src/Producer.ts b/node/src/Producer.ts index d145bcf156..8f799244bc 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -82,6 +82,11 @@ export type ProducerTraceEventData = export type ProducerScore = { + /** + * Index of the RTP stream in the rtpParameters.encodings array. + */ + encodingIdx: number; + /** * SSRC of the RTP stream. */ @@ -719,9 +724,10 @@ function parseProducerScore( ): ProducerScore { return { - ssrc : binary.ssrc(), - rid : binary.rid() ?? undefined, - score : binary.score() + encodingIdx : binary.encodingIdx(), + ssrc : binary.ssrc(), + rid : binary.rid() ?? undefined, + score : binary.score() }; } From c7fe2ed6b2b5a55c336b688cdcd11c6debb2df3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Thu, 16 Nov 2023 14:26:29 +0100 Subject: [PATCH 194/525] DepOpenSSL: print the CPU info upon class init (#1224) --- worker/src/DepOpenSSL.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/worker/src/DepOpenSSL.cpp b/worker/src/DepOpenSSL.cpp index 7b50a83b78..f38be5fe67 100644 --- a/worker/src/DepOpenSSL.cpp +++ b/worker/src/DepOpenSSL.cpp @@ -22,6 +22,7 @@ void DepOpenSSL::ClassInit() [] { MS_DEBUG_TAG(info, "openssl version: \"%s\"", OpenSSL_version(OPENSSL_VERSION)); + MS_DEBUG_TAG(info, "openssl CPU info: \"%s\"", OpenSSL_version(OPENSSL_CPU_INFO)); // Initialize some crypto stuff. RAND_poll(); From 08b2c247e4d6ed5ba69dfc626356c2ca3239e0fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Nov 2023 21:44:14 +0100 Subject: [PATCH 195/525] Update doc/Building.md --- doc/Building.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/Building.md b/doc/Building.md index 218faa8850..c31c2aed0d 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -58,9 +58,9 @@ Same as `npm run test:node` but it also opens a browser window with JavaScript c Installs NPM dependencies and updates `package-lock.json`. -### `npm run install-clang-tools` +### `npm run install-worker-dev-tools -Installs clang tools needed for local development. +Installs worker NPM packages needed for local development. ## Rust From 40e114604718e8e45ab236fbbb828f92f6ae4b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Nov 2023 21:45:40 +0100 Subject: [PATCH 196/525] cosmetic --- worker/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/worker/Makefile b/worker/Makefile index a3f33cf4b1..5435e4c44f 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -36,6 +36,7 @@ PIP_BUILD_BINARIES = $(shell [ -f /etc/NIXOS -o -d /etc/guix ] && echo "--no-bin # https://github.com/ninja-build/ninja/issues/2211 # https://github.com/ninja-build/ninja/issues/2212 NINJA_VERSION ?= 1.10.2.4 +NPM ?= npm # Disable `*.pyc` files creation. export PYTHONDONTWRITEBYTECODE = 1 @@ -212,10 +213,10 @@ xcode: setup $(MESON) setup --buildtype debug --backend xcode $(MEDIASOUP_OUT_DIR)/xcode lint: - npm run lint --prefix scripts/ + $(NPM) run lint --prefix scripts/ format: - npm run format --prefix scripts/ + $(NPM) run format --prefix scripts/ test: setup flatc $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test From 93bbccf4c94e9a8ec81de6b135e94810dc39c300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Nov 2023 21:46:15 +0100 Subject: [PATCH 197/525] fix typo --- doc/Building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Building.md b/doc/Building.md index c31c2aed0d..d3189e6fca 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -58,7 +58,7 @@ Same as `npm run test:node` but it also opens a browser window with JavaScript c Installs NPM dependencies and updates `package-lock.json`. -### `npm run install-worker-dev-tools +### `npm run install-worker-dev-tools` Installs worker NPM packages needed for local development. From 3d2556fc901a023bad078e804c110606d8ca7ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Nov 2023 13:27:38 +0100 Subject: [PATCH 198/525] Add Linux Alpine Docker image (#1226) --- doc/Building.md | 19 +++++++++++++++---- worker/Dockerfile | 32 ++++++++++++++++---------------- worker/Dockerfile.alpine | 17 +++++++++++++++++ worker/Makefile | 19 ++++++++++++++++++- 4 files changed, 66 insertions(+), 21 deletions(-) create mode 100644 worker/Dockerfile.alpine diff --git a/doc/Building.md b/doc/Building.md index d3189e6fca..35b362765a 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -154,8 +154,7 @@ Rewrites mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/ Builds and runs the `mediasoup-worker-test` binary at `worker/out/Release/` (or at `worker/out/Debug/` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"), which uses [Catch2](https://github.com/catchorg/Catch2) to run test units located at `worker/test/` folder. - -### 'make test-asan' +### `make test-asan` Run test with Address Sanitizer. @@ -189,7 +188,7 @@ Runs all fuzzer cases. ### `make docker` -Builds a Linux image with fuzzer capable clang++. +Builds a Linux Ubuntu Docker image with fuzzer capable clang++ and all dependencies to run mediasoup. **NOTE:** Before running this command, a specific version of Linux clang must be downloaded. To get it, run: @@ -200,4 +199,16 @@ cd worker ### `make docker-run` -Runs a container of the Docker image created with `make docker`. It automatically executes a `bash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. +Runs a container of the Ubuntu Docker image created with `make docker`. It automatically executes a `bash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. + +**NOTE:** To install and run mediasoup in the container, previous installation (if any) must be properly cleaned by entering the `worker` directory and running `make clean-all`. + +### `make docker-alpine` + +Builds a Linux Alpine Docker image with all dependencies to run mediasoup. + +### `make docker-alpine-run` + +Runs a container of the Alpine Docker image created with `make docker-alpine`. It automatically executes an `ash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. + +**NOTE:** To install and run mediasoup in the container, previous installation (if any) must be properly cleaned by entering the `worker` directory and running `make clean-all`. diff --git a/worker/Dockerfile b/worker/Dockerfile index 79afad2747..df9193063d 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -5,24 +5,24 @@ RUN \ set -x \ && apt-get update \ && apt-get install --yes \ - bash-completion wget curl subversion screen gcc g++ cmake ninja-build golang \ - autoconf libtool apache2 python3-pip python3-dev pkg-config zlib1g-dev \ - libgss-dev libssl-dev libxml2-dev nasm libarchive-dev make automake \ - libdbus-1-dev libboost-dev autoconf-archive bash-completion python3-yaml \ - clang + bash-completion wget curl subversion screen gcc g++ cmake ninja-build golang \ + autoconf libtool apache2 python3-pip python3-dev pkg-config zlib1g-dev \ + libgss-dev libssl-dev libxml2-dev nasm libarchive-dev make automake \ + libdbus-1-dev libboost-dev autoconf-archive bash-completion python3-yaml \ + clang # Install node 20. - RUN set -x \ - && apt-get update \ - && apt-get install --yes ca-certificates curl gnupg \ - && mkdir -p /etc/apt/keyrings \ - && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ - | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ - && NODE_MAJOR=20 \ - && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \ - > /etc/apt/sources.list.d/nodesource.list \ - && apt-get update \ - && apt-get install nodejs --yes +RUN set -x \ + && apt-get update \ + && apt-get install --yes ca-certificates curl gnupg \ + && mkdir -p /etc/apt/keyrings \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ + | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ + && NODE_MAJOR=20 \ + && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \ + > /etc/apt/sources.list.d/nodesource.list \ + && apt-get update \ + && apt-get install nodejs --yes # Make CC and CXX point to clang/clang++ installed above. ENV LANG="C.UTF-8" diff --git a/worker/Dockerfile.alpine b/worker/Dockerfile.alpine new file mode 100644 index 0000000000..5ae43d88c1 --- /dev/null +++ b/worker/Dockerfile.alpine @@ -0,0 +1,17 @@ +FROM alpine + +# Install dependencies. +RUN \ + set -x \ + && apk add \ + nodejs-current npm python3 py3-pip \ + make gcc g++ + +# Make CC and CXX point to gcc/g++. +ENV LANG="C.UTF-8" +ENV CC="gcc" +ENV CXX="g++" + +WORKDIR /mediasoup + +CMD ["ash"] diff --git a/worker/Makefile b/worker/Makefile index 5435e4c44f..2ebe5d746a 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -87,7 +87,9 @@ endif fuzzer \ fuzzer-run-all \ docker \ - docker-run + docker-run \ + docker-alpine \ + docker-alpine-run default: mediasoup-worker @@ -266,3 +268,18 @@ docker-run: --cap-add SYS_PTRACE \ -v $(shell pwd)/../:/mediasoup \ mediasoup/docker:latest + +docker-alpine: +ifeq ($(DOCKER_NO_CACHE),true) + $(DOCKER) build -f Dockerfile.alpine --no-cache --tag mediasoup/docker-alpine:latest . +else + $(DOCKER) build -f Dockerfile.alpine --tag mediasoup/docker-alpine:latest . +endif + +docker-alpine-run: + $(DOCKER) run \ + --name=mediasoupDockerAlpine -it --rm \ + --privileged \ + --cap-add SYS_PTRACE \ + -v $(shell pwd)/../:/mediasoup \ + mediasoup/docker-alpine:latest From f88f68ed4ea991592e62245bf576b13c463c763f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Fri, 17 Nov 2023 14:20:53 +0100 Subject: [PATCH 199/525] FBS: LayersChangeNotification body must be optional (#1227) --- CHANGELOG.md | 5 +++++ rust/src/router/consumer.rs | 12 ++++++++---- worker/fbs/consumer.fbs | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac74202929..a96e310f7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* FBS: `LayersChangeNotification` body must be optional ([PR #1227](https://github.com/versatica/mediasoup/pull/1227)). + + ### 3.13.1 * Node: Extract version from `package.json` using `require()` ([PR #1217](https://github.com/versatica/mediasoup/pull/1217) by @arcinston). diff --git a/rust/src/router/consumer.rs b/rust/src/router/consumer.rs index cfc6e0697d..361868f2eb 100644 --- a/rust/src/router/consumer.rs +++ b/rust/src/router/consumer.rs @@ -621,11 +621,15 @@ impl Notification { panic!("Wrong message from worker: {notification:?}"); }; - let layers_fbs = - consumer::ConsumerLayers::try_from(body.layers().unwrap()).unwrap(); - let layers = ConsumerLayers::from_fbs(layers_fbs); + match body.layers().unwrap() { + Some(layers) => { + let layers_fbs = consumer::ConsumerLayers::try_from(layers).unwrap(); + let layers = ConsumerLayers::from_fbs(layers_fbs); - Ok(Notification::LayersChange(Some(layers))) + Ok(Notification::LayersChange(Some(layers))) + } + None => Ok(Notification::LayersChange(None)), + } } notification::Event::ConsumerTrace => { let Ok(Some(notification::BodyRef::ConsumerTraceNotification(body))) = diff --git a/worker/fbs/consumer.fbs b/worker/fbs/consumer.fbs index 660e1dedc9..715ce2bd53 100644 --- a/worker/fbs/consumer.fbs +++ b/worker/fbs/consumer.fbs @@ -80,7 +80,7 @@ table GetStatsResponse { // Notifications from Worker. table LayersChangeNotification { - layers: ConsumerLayers (required); + layers: ConsumerLayers; } table RtpNotification { From b6ce70ec5df8ac8440a72b59ef836f070b42b143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Nov 2023 14:27:48 +0100 Subject: [PATCH 200/525] 3.13.2 --- CHANGELOG.md | 4 ++-- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a96e310f7e..0bceba479c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,9 @@ # Changelog -### NEXT +### 3.13.2 -* FBS: `LayersChangeNotification` body must be optional ([PR #1227](https://github.com/versatica/mediasoup/pull/1227)). +* FBS: `LayersChangeNotification` body must be optional (fixes a crash) ([PR #1227](https://github.com/versatica/mediasoup/pull/1227)). ### 3.13.1 diff --git a/package-lock.json b/package-lock.json index 5724f7b5f2..25e8a12c48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.1", + "version": "3.13.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.1", + "version": "3.13.2", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -21,7 +21,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.8", - "@types/node": "^20.9.0", + "@types/node": "^20.9.1", "@typescript-eslint/eslint-plugin": "^6.11.0", "@typescript-eslint/parser": "^6.11.0", "eslint": "^8.53.0", @@ -1619,9 +1619,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "version": "20.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.1.tgz", + "integrity": "sha512-HhmzZh5LSJNS5O8jQKpJ/3ZcrrlG6L70hpGqMIAoM9YVD0YBRNWYsfwcXq8VnSjlNpCpgLzMXdiPo+dxcvSmiA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -8006,9 +8006,9 @@ "dev": true }, "@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "version": "20.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.1.tgz", + "integrity": "sha512-HhmzZh5LSJNS5O8jQKpJ/3ZcrrlG6L70hpGqMIAoM9YVD0YBRNWYsfwcXq8VnSjlNpCpgLzMXdiPo+dxcvSmiA==", "dev": true, "requires": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index bfe2446c19..3c2437fd0a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.1", + "version": "3.13.2", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -106,7 +106,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.8", - "@types/node": "^20.9.0", + "@types/node": "^20.9.1", "@typescript-eslint/eslint-plugin": "^6.11.0", "@typescript-eslint/parser": "^6.11.0", "eslint": "^8.53.0", From 7b2bad0b40ed0d07a1115e9116107472f513f087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Nov 2023 17:44:24 +0100 Subject: [PATCH 201/525] Node: Add 'listenererror' in all entities (#1228) --- node/src/Consumer.ts | 1 + node/src/DataConsumer.ts | 1 + node/src/DataProducer.ts | 1 + node/src/EnhancedEventEmitter.ts | 18 +++++-- node/src/Producer.ts | 1 + node/src/Router.ts | 1 + node/src/RtpObserver.ts | 1 + node/src/Transport.ts | 1 + node/src/WebRtcServer.ts | 1 + node/src/Worker.ts | 1 + node/src/tests/test-DirectTransport.ts | 54 ++++++++++++++------ node/src/tests/test-Producer.ts | 48 +++++++----------- node/src/tests/test-node-sctp.ts | 69 +++++++++++++++++--------- 13 files changed, 124 insertions(+), 74 deletions(-) diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 0a9d60d832..7964ec92ea 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -173,6 +173,7 @@ export type ConsumerEvents = layerschange: [ConsumerLayers?]; trace: [ConsumerTraceEventData]; rtp: [Buffer]; + listenererror: [string, Error]; // Private events. '@close': []; '@producerclose': []; diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 17a41dd41d..5df47431ff 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -85,6 +85,7 @@ export type DataConsumerEvents = message: [Buffer, number]; sctpsendbufferfull: []; bufferedamountlow: [number]; + listenererror: [string, Error]; // Private events. '@close': []; '@dataproducerclose': []; diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 26fc8efd81..66003db76d 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -61,6 +61,7 @@ export type DataProducerType = 'sctp' | 'direct'; export type DataProducerEvents = { transportclose: []; + listenererror: [string, Error]; // Private events. '@close': []; }; diff --git a/node/src/EnhancedEventEmitter.ts b/node/src/EnhancedEventEmitter.ts index f2e3a057d5..3460f034ab 100644 --- a/node/src/EnhancedEventEmitter.ts +++ b/node/src/EnhancedEventEmitter.ts @@ -23,8 +23,6 @@ export class EnhancedEventEmitter extends EventEmitte */ safeEmit(eventName: K, ...args: E[K]): boolean { - const numListeners = super.listenerCount(eventName); - try { return super.emit(eventName, ...args); @@ -33,9 +31,19 @@ export class EnhancedEventEmitter extends EventEmitte { logger.error( 'safeEmit() | event listener threw an error [eventName:%s]:%o', - eventName, error); - - return Boolean(numListeners); + eventName, error + ); + + try + { + super.emit('listenererror', eventName, error); + } + catch (error2) + { + // Ignore it. + } + + return Boolean(super.listenerCount(eventName)); } } diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 8f799244bc..149ba0811a 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -134,6 +134,7 @@ export type ProducerEvents = score: [ProducerScore[]]; videoorientationchange: [ProducerVideoOrientation]; trace: [ProducerTraceEventData]; + listenererror: [string, Error]; // Private events. '@close': []; }; diff --git a/node/src/Router.ts b/node/src/Router.ts index edecf0ce4b..9b836f67ad 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -172,6 +172,7 @@ type PipeTransportPair = export type RouterEvents = { workerclose: []; + listenererror: [string, Error]; // Private events. '@close': []; }; diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 4c3d64051c..42ee9f099c 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -11,6 +11,7 @@ import * as FbsRtpObserver from './fbs/rtp-observer'; export type RtpObserverEvents = { routerclose: []; + listenererror: [string, Error]; // Private events. '@close': []; }; diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 7486cf8065..a0e3449a62 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -154,6 +154,7 @@ export type TransportEvents = routerclose: []; listenserverclose: []; trace: [TransportTraceEventData]; + listenererror: [string, Error]; // Private events. '@close': []; '@newproducer': [Producer]; diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index ad45f9e179..abfd064c0f 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -31,6 +31,7 @@ export type WebRtcServerListenInfo = TransportListenInfo; export type WebRtcServerEvents = { workerclose: []; + listenererror: [string, Error]; // Private events. '@close': []; }; diff --git a/node/src/Worker.ts b/node/src/Worker.ts index d4e930970c..a7af360bfb 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -197,6 +197,7 @@ export type WorkerDump = export type WorkerEvents = { died: [Error]; + listenererror: [string, Error]; // Private events. '@success': []; '@failure': [Error]; diff --git a/node/src/tests/test-DirectTransport.ts b/node/src/tests/test-DirectTransport.ts index 2a8431ddc3..39fc9f8671 100644 --- a/node/src/tests/test-DirectTransport.ts +++ b/node/src/tests/test-DirectTransport.ts @@ -127,19 +127,38 @@ test('dataProducer.send() succeeds', async () => let sentMessageBytes = 0; let effectivelySentMessageBytes = 0; let recvMessageBytes = 0; - let lastSentMessageId = 0; - let lastRecvMessageId = 0; + let numSentMessages = 0; + let numReceivedMessages = 0; // eslint-disable-next-line no-async-promise-executor - await new Promise(async (resolve) => + await new Promise(async (resolve, reject) => { - // Send messages over the sctpSendStream created above. + transport2.on('listenererror', (eventName, error) => + { + reject( + new Error(`transport2 'listenererror' [eventName:${eventName}]: ${error}`) + ); + }); + + dataProducer.on('listenererror', (eventName, error) => + { + reject( + new Error(`dataProducer 'listenererror' [eventName:${eventName}]: ${error}`) + ); + }); + + dataConsumer.on('listenererror', (eventName, error) => + { + reject( + new Error(`dataConsumer 'listenererror' [eventName:${eventName}]: ${error}`) + ); + }); sendNextMessage(); - async function sendNextMessage() + async function sendNextMessage(): Promise { - const id = ++lastSentMessageId; + const id = ++numSentMessages; let ppid; let message; @@ -190,6 +209,8 @@ test('dataProducer.send() succeeds', async () => dataConsumer.on('message', (message, ppid) => { + ++numReceivedMessages; + // message is always a Buffer. recvMessageBytes += message.byteLength; @@ -199,22 +220,25 @@ test('dataProducer.send() succeeds', async () => { resolve(); } - - if (id < numMessages / 2) + // PPID of WebRTC DataChannel string. + else if (id < numMessages / 2 && ppid !== 51) { - expect(ppid).toBe(51); // PPID of WebRTC DataChannel string. + reject( + new Error(`ppid in message with id ${id} should be 51 but it is ${ppid}`) + ); } - else + // PPID of WebRTC DataChannel binary. + else if (id > numMessages / 2 && ppid !== 53) { - expect(ppid).toBe(53); // PPID of WebRTC DataChannel binary. + reject( + new Error(`ppid in message with id ${id} should be 53 but it is ${ppid}`) + ); } - - ++lastRecvMessageId; }); }); - expect(lastSentMessageId).toBe(numMessages); - expect(lastRecvMessageId).toBe(expectedReceivedNumMessages); + expect(numSentMessages).toBe(numMessages); + expect(numReceivedMessages).toBe(expectedReceivedNumMessages); expect(recvMessageBytes).toBe(effectivelySentMessageBytes); await expect(dataProducer.getStats()) diff --git a/node/src/tests/test-Producer.ts b/node/src/tests/test-Producer.ts index 05b2a515f3..c39d156098 100644 --- a/node/src/tests/test-Producer.ts +++ b/node/src/tests/test-Producer.ts @@ -235,18 +235,18 @@ test('transport2.produce() succeeds', async () => }); }, 2000); -test.only('transport1.produce() without header extensions and rtcp succeeds', async () => +test('transport1.produce() without header extensions and rtcp succeeds', async () => { const onObserverNewProducer = jest.fn(); transport1.observer.once('newproducer', onObserverNewProducer); - audioProducer = await transport1.produce( + const audioProducer2 = await transport1.produce( { kind : 'audio', rtpParameters : { - mid : 'AUDIO', + mid : 'AUDIO2', codecs : [ { @@ -268,34 +268,19 @@ test.only('transport1.produce() without header extensions and rtcp succeeds', as }); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); - expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer); - expect(typeof audioProducer.id).toBe('string'); - expect(audioProducer.closed).toBe(false); - expect(audioProducer.kind).toBe('audio'); - expect(typeof audioProducer.rtpParameters).toBe('object'); - expect(audioProducer.type).toBe('simple'); + expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer2); + expect(typeof audioProducer2.id).toBe('string'); + expect(audioProducer2.closed).toBe(false); + expect(audioProducer2.kind).toBe('audio'); + expect(typeof audioProducer2.rtpParameters).toBe('object'); + expect(audioProducer2.type).toBe('simple'); // Private API. - expect(typeof audioProducer.consumableRtpParameters).toBe('object'); - expect(audioProducer.paused).toBe(false); - expect(audioProducer.score).toEqual([]); - expect(audioProducer.appData).toEqual({ foo: 1, bar: '2' }); - - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : [ { key: audioProducer.id, values: [] } ], - mapConsumerIdProducerId : [] - }); + expect(typeof audioProducer2.consumableRtpParameters).toBe('object'); + expect(audioProducer2.paused).toBe(false); + expect(audioProducer2.score).toEqual([]); + expect(audioProducer2.appData).toEqual({ foo: 1, bar: '2' }); - await expect(transport1.dump()) - .resolves - .toMatchObject( - { - id : transport1.id, - producerIds : [ audioProducer.id ], - consumerIds : [] - }); + audioProducer2.close(); }, 2000); test('transport1.produce() with wrong arguments rejects with TypeError', async () => @@ -782,7 +767,10 @@ test('Producer emits "score"', async () => expect(onScore).toHaveBeenCalledTimes(3); expect(videoProducer.score).toEqual( - [ { ssrc: 11, score: 10 }, { ssrc: 22, score: 9 } ]); + [ + { ssrc: 11, rid: undefined, score: 10, encodingIdx: 0 }, + { ssrc: 22, rid: undefined, score: 9, encodingIdx: 1 } + ]); }, 2000); test('producer.close() succeeds', async () => diff --git a/node/src/tests/test-node-sctp.ts b/node/src/tests/test-node-sctp.ts index 8354a2fbf8..31804c6962 100644 --- a/node/src/tests/test-node-sctp.ts +++ b/node/src/tests/test-node-sctp.ts @@ -114,11 +114,16 @@ beforeAll(async () => dataConsumer = await transport.consumeData({ dataProducerId: dataProducer.id }); }); -afterAll(() => +afterAll(async () => { udpSocket.close(); sctpSocket.end(); worker.close(); + + // NOTE: For some reason we have to wait a bit for the SCTP stuff to release + // internal things, otherwise Jest reports open handles. We don't care much + // honestly. + await new Promise((resolve) => setTimeout(resolve, 2000)); }); test('ordered DataProducer delivers all SCTP messages to the DataConsumer', async () => @@ -127,18 +132,20 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn const numMessages = 200; let sentMessageBytes = 0; let recvMessageBytes = 0; - let lastSentMessageId = 0; - let lastRecvMessageId = 0; + let numSentMessages = 0; + let numReceivedMessages = 0; // It must be zero because it's the first DataConsumer on the transport. expect(dataConsumer.sctpStreamParameters?.streamId).toBe(0); - await new Promise((resolve) => + // eslint-disable-next-line no-async-promise-executor + await new Promise(async (resolve, reject) => { - // Send SCTP messages over the sctpSendStream created above. - const interval = setInterval(() => + sendNextMessage(); + + async function sendNextMessage(): Promise { - const id = ++lastSentMessageId; + const id = ++numSentMessages; const data = Buffer.from(String(id)); // Set ppid of type WebRTC DataChannel string. @@ -157,11 +164,11 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn sctpSendStream.write(data); sentMessageBytes += data.byteLength; - if (id === numMessages) + if (id < numMessages) { - clearInterval(interval); + sendNextMessage(); } - }, 10); + } sctpSocket.on('stream', onStream); @@ -171,40 +178,54 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn { // It must be zero because it's the first SCTP incoming stream (so first // DataConsumer). - expect(streamId).toBe(0); + if (streamId !== 0) + { + reject(new Error(`streamId should be 0 but it is ${streamId}`)); + + return; + } // @ts-ignore stream.on('data', (data: Buffer) => { + ++numReceivedMessages; recvMessageBytes += data.byteLength; const id = Number(data.toString('utf8')); + // @ts-ignore + const ppid = data.ppid; - if (id === numMessages) + if (id !== numReceivedMessages) { - clearInterval(interval); - resolve(); + reject( + new Error(`id ${id} in message should match numReceivedMessages ${numReceivedMessages}`) + ); } - - if (id < numMessages / 2) + else if (id === numMessages) { - // @ts-ignore - expect(data.ppid).toBe(sctp.PPID.WEBRTC_STRING); + resolve(); } - else + else if (id < numMessages / 2 && ppid !== sctp.PPID.WEBRTC_STRING) { - // @ts-ignore - expect(data.ppid).toBe(sctp.PPID.WEBRTC_BINARY); + reject( + new Error(`ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_STRING} but it is ${ppid}`) + ); } + else if (id > numMessages / 2 && ppid !== sctp.PPID.WEBRTC_BINARY) + { + reject( + new Error(`ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_BINARY} but it is ${ppid}`) + ); - expect(id).toBe(++lastRecvMessageId); + return; + } }); }); }); expect(onStream).toHaveBeenCalledTimes(1); - expect(lastSentMessageId).toBe(numMessages); - expect(lastRecvMessageId).toBe(numMessages); + expect(numSentMessages).toBe(numMessages); + expect(numReceivedMessages).toBe(numMessages); expect(recvMessageBytes).toBe(sentMessageBytes); await expect(dataProducer.getStats()) From 4474cfde82b34dc77d2b927d8454f2d1e1700079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Nov 2023 13:39:04 +0100 Subject: [PATCH 202/525] cosmetic --- node/src/tests/test-DirectTransport.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/node/src/tests/test-DirectTransport.ts b/node/src/tests/test-DirectTransport.ts index 39fc9f8671..d4324b212a 100644 --- a/node/src/tests/test-DirectTransport.ts +++ b/node/src/tests/test-DirectTransport.ts @@ -133,13 +133,6 @@ test('dataProducer.send() succeeds', async () => // eslint-disable-next-line no-async-promise-executor await new Promise(async (resolve, reject) => { - transport2.on('listenererror', (eventName, error) => - { - reject( - new Error(`transport2 'listenererror' [eventName:${eventName}]: ${error}`) - ); - }); - dataProducer.on('listenererror', (eventName, error) => { reject( From 6401ff239839308eb298e5979868e530caa45897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Nov 2023 14:47:28 +0100 Subject: [PATCH 203/525] Reliable make clean-all (#1229) --- worker/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/worker/Makefile b/worker/Makefile index 2ebe5d746a..2bc6fb82d7 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -190,7 +190,9 @@ clean-pip: clean-subprojects: meson-ninja $(MESON) subprojects purge --include-cache --confirm -clean-all: clean-subprojects +# Clean subprojects (ignore if it fails) and delete out dir. +clean-all: + -$(MESON) subprojects purge --include-cache --confirm $(RM) -rf $(MEDIASOUP_OUT_DIR) # Update the wrap file of a subproject. Usage example: From 92ff5ab48c304b75eb3e05e999a931b5b3e20e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 20 Nov 2023 13:56:53 +0100 Subject: [PATCH 204/525] Fix issue when pause/resume events are not emitted (#1231) Co-authored-by: Douglas Amorim Ferreira --- CHANGELOG.md | 5 ++++ node/src/Consumer.ts | 18 +++++------- node/src/DataConsumer.ts | 20 +++++-------- node/src/DataProducer.ts | 8 ++--- node/src/Producer.ts | 8 ++--- node/src/tests/test-Consumer.ts | 45 +++++++++++++++++++++++++++++ node/src/tests/test-DataConsumer.ts | 45 +++++++++++++++++++++++++++++ node/src/tests/test-DataProducer.ts | 42 +++++++++++++++++++++++++++ node/src/tests/test-Producer.ts | 42 +++++++++++++++++++++++++++ rust/src/router/consumer.rs | 7 ++--- rust/src/router/data_consumer.rs | 7 ++--- 11 files changed, 208 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bceba479c..8cccb44652 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* Node: Fix issue when 'pause'/'resume' events are not emitted ([PR #1231](https://github.com/versatica/mediasoup/pull/1231) by @douglaseel). + + ### 3.13.2 * FBS: `LayersChangeNotification` body must be optional (fixes a crash) ([PR #1227](https://github.com/versatica/mediasoup/pull/1227)). diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 7964ec92ea..e8d9a5981d 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -612,8 +612,6 @@ export class Consumer { logger.debug('pause()'); - const wasPaused = this.#paused || this.#producerPaused; - await this.#channel.request( FbsRequest.Method.CONSUMER_PAUSE, undefined, @@ -621,10 +619,12 @@ export class Consumer this.#internal.consumerId ); + const wasPaused = this.#paused; + this.#paused = true; // Emit observer event. - if (!wasPaused) + if (!wasPaused && !this.#producerPaused) { this.#observer.safeEmit('pause'); } @@ -637,8 +637,6 @@ export class Consumer { logger.debug('resume()'); - const wasPaused = this.#paused || this.#producerPaused; - await this.#channel.request( FbsRequest.Method.CONSUMER_RESUME, undefined, @@ -646,6 +644,8 @@ export class Consumer this.#internal.consumerId ); + const wasPaused = this.#paused; + this.#paused = false; // Emit observer event. @@ -853,14 +853,12 @@ export class Consumer break; } - const wasPaused = this.#paused || this.#producerPaused; - this.#producerPaused = true; this.safeEmit('producerpause'); // Emit observer event. - if (!wasPaused) + if (!this.#paused) { this.#observer.safeEmit('pause'); } @@ -875,14 +873,12 @@ export class Consumer break; } - const wasPaused = this.#paused || this.#producerPaused; - this.#producerPaused = false; this.safeEmit('producerresume'); // Emit observer event. - if (wasPaused && !this.#paused) + if (!this.#paused) { this.#observer.safeEmit('resume'); } diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 5df47431ff..12b7e5db68 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -407,8 +407,6 @@ export class DataConsumer { logger.debug('pause()'); - const wasPaused = this.#paused; - await this.#channel.request( FbsRequest.Method.DATACONSUMER_PAUSE, undefined, @@ -416,10 +414,12 @@ export class DataConsumer this.#internal.dataConsumerId ); + const wasPaused = this.#paused; + this.#paused = true; // Emit observer event. - if (!wasPaused) + if (!wasPaused && !this.#dataProducerPaused) { this.#observer.safeEmit('pause'); } @@ -432,8 +432,6 @@ export class DataConsumer { logger.debug('resume()'); - const wasPaused = this.#paused; - await this.#channel.request( FbsRequest.Method.DATACONSUMER_RESUME, undefined, @@ -441,10 +439,12 @@ export class DataConsumer this.#internal.dataConsumerId ); + const wasPaused = this.#paused; + this.#paused = false; // Emit observer event. - if (wasPaused) + if (wasPaused && !this.#dataProducerPaused) { this.#observer.safeEmit('resume'); } @@ -620,14 +620,12 @@ export class DataConsumer break; } - const wasPaused = this.#paused || this.#dataProducerPaused; - this.#dataProducerPaused = true; this.safeEmit('dataproducerpause'); // Emit observer event. - if (!wasPaused) + if (!this.#paused) { this.#observer.safeEmit('pause'); } @@ -642,14 +640,12 @@ export class DataConsumer break; } - const wasPaused = this.#paused || this.#dataProducerPaused; - this.#dataProducerPaused = false; this.safeEmit('dataproducerresume'); // Emit observer event. - if (wasPaused && !this.#paused) + if (!this.#paused) { this.#observer.safeEmit('resume'); } diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 66003db76d..94ffccf5cf 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -342,8 +342,6 @@ export class DataProducer { logger.debug('pause()'); - const wasPaused = this.#paused; - await this.#channel.request( FbsRequest.Method.DATAPRODUCER_PAUSE, undefined, @@ -351,6 +349,8 @@ export class DataProducer this.#internal.dataProducerId ); + const wasPaused = this.#paused; + this.#paused = true; // Emit observer event. @@ -367,8 +367,6 @@ export class DataProducer { logger.debug('resume()'); - const wasPaused = this.#paused; - await this.#channel.request( FbsRequest.Method.DATAPRODUCER_RESUME, undefined, @@ -376,6 +374,8 @@ export class DataProducer this.#internal.dataProducerId ); + const wasPaused = this.#paused; + this.#paused = false; // Emit observer event. diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 149ba0811a..d45c1d1be7 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -446,8 +446,6 @@ export class Producer { logger.debug('pause()'); - const wasPaused = this.#paused; - await this.#channel.request( FbsRequest.Method.PRODUCER_PAUSE, undefined, @@ -455,6 +453,8 @@ export class Producer this.#internal.producerId ); + const wasPaused = this.#paused; + this.#paused = true; // Emit observer event. @@ -471,8 +471,6 @@ export class Producer { logger.debug('resume()'); - const wasPaused = this.#paused; - await this.#channel.request( FbsRequest.Method.PRODUCER_RESUME, undefined, @@ -480,6 +478,8 @@ export class Producer this.#internal.producerId ); + const wasPaused = this.#paused; + this.#paused = false; // Emit observer event. diff --git a/node/src/tests/test-Consumer.ts b/node/src/tests/test-Consumer.ts index 3723019460..722d84c29b 100644 --- a/node/src/tests/test-Consumer.ts +++ b/node/src/tests/test-Consumer.ts @@ -823,6 +823,12 @@ test('consumer.getStats() succeeds', async () => test('consumer.pause() and resume() succeed', async () => { + const onObserverPause = jest.fn(); + const onObserverResume = jest.fn(); + + audioConsumer.observer.on('pause', onObserverPause); + audioConsumer.observer.on('resume', onObserverResume); + await audioConsumer.pause(); expect(audioConsumer.paused).toBe(true); @@ -836,6 +842,45 @@ test('consumer.pause() and resume() succeed', async () => await expect(audioConsumer.dump()) .resolves .toMatchObject({ paused: false }); + + // Even if we don't await for pause()/resume() completion, the observer must + // fire 'pause' and 'resume' events if state was the opposite. + audioConsumer.pause(); + audioConsumer.resume(); + audioConsumer.pause(); + audioConsumer.pause(); + audioConsumer.pause(); + await audioConsumer.resume(); + + expect(onObserverPause).toHaveBeenCalledTimes(3); + expect(onObserverResume).toHaveBeenCalledTimes(3); +}, 2000); + +test('producer.pause() and resume() emit events', async () => +{ + const promises = []; + const events: string[] = []; + + audioConsumer.observer.once('resume', () => + { + events.push('resume'); + }); + + audioConsumer.observer.once('pause', () => + { + events.push('pause'); + }); + + promises.push(audioProducer.pause()); + promises.push(audioProducer.resume()); + + await Promise.all(promises); + + // Must also wait a bit for the corresponding events in the consumer. + await new Promise((resolve) => setTimeout(resolve, 100)); + + expect(events).toEqual([ 'pause', 'resume' ]); + expect(audioConsumer.paused).toBe(false); }, 2000); test('consumer.setPreferredLayers() succeed', async () => diff --git a/node/src/tests/test-DataConsumer.ts b/node/src/tests/test-DataConsumer.ts index b8a7181ed1..5bbf33fa0c 100644 --- a/node/src/tests/test-DataConsumer.ts +++ b/node/src/tests/test-DataConsumer.ts @@ -203,6 +203,12 @@ test('dataConsumer.getStats() on a DirectTransport succeeds', async () => test('dataConsumer.pause() and resume() succeed', async () => { + const onObserverPause = jest.fn(); + const onObserverResume = jest.fn(); + + dataConsumer1.observer.on('pause', onObserverPause); + dataConsumer1.observer.on('resume', onObserverResume); + let data; await dataConsumer1.pause(); @@ -220,6 +226,45 @@ test('dataConsumer.pause() and resume() succeed', async () => data = await dataConsumer1.dump(); expect(data.paused).toBe(false); + + // Even if we don't await for pause()/resume() completion, the observer must + // fire 'pause' and 'resume' events if state was the opposite. + dataConsumer1.pause(); + dataConsumer1.resume(); + dataConsumer1.pause(); + dataConsumer1.pause(); + dataConsumer1.pause(); + await dataConsumer1.resume(); + + expect(onObserverPause).toHaveBeenCalledTimes(3); + expect(onObserverResume).toHaveBeenCalledTimes(3); +}, 2000); + +test('dataProducer.pause() and resume() emit events', async () => +{ + const promises = []; + const events: string[] = []; + + dataConsumer1.observer.once('resume', () => + { + events.push('resume'); + }); + + dataConsumer1.observer.once('pause', () => + { + events.push('pause'); + }); + + promises.push(dataProducer.pause()); + promises.push(dataProducer.resume()); + + await Promise.all(promises); + + // Must also wait a bit for the corresponding events in the data consumer. + await new Promise((resolve) => setTimeout(resolve, 100)); + + expect(events).toEqual([ 'pause', 'resume' ]); + expect(dataConsumer1.paused).toBe(false); }, 2000); test('dataConsumer.close() succeeds', async () => diff --git a/node/src/tests/test-DataProducer.ts b/node/src/tests/test-DataProducer.ts index 3918d20263..8c0c6bd5aa 100644 --- a/node/src/tests/test-DataProducer.ts +++ b/node/src/tests/test-DataProducer.ts @@ -235,6 +235,12 @@ test('dataProducer.getStats() succeeds', async () => test('dataProducer.pause() and resume() succeed', async () => { + const onObserverPause = jest.fn(); + const onObserverResume = jest.fn(); + + dataProducer1.observer.on('pause', onObserverPause); + dataProducer1.observer.on('resume', onObserverResume); + let data; await dataProducer1.pause(); @@ -252,6 +258,42 @@ test('dataProducer.pause() and resume() succeed', async () => data = await dataProducer1.dump(); expect(data.paused).toBe(false); + + // Even if we don't await for pause()/resume() completion, the observer must + // fire 'pause' and 'resume' events if state was the opposite. + dataProducer1.pause(); + dataProducer1.resume(); + dataProducer1.pause(); + dataProducer1.pause(); + dataProducer1.pause(); + await dataProducer1.resume(); + + expect(onObserverPause).toHaveBeenCalledTimes(3); + expect(onObserverResume).toHaveBeenCalledTimes(3); +}, 2000); + +test('producer.pause() and resume() emit events', async () => +{ + const promises = []; + const events: string[] = []; + + dataProducer1.observer.once('resume', () => + { + events.push('resume'); + }); + + dataProducer1.observer.once('pause', () => + { + events.push('pause'); + }); + + promises.push(dataProducer1.pause()); + promises.push(dataProducer1.resume()); + + await Promise.all(promises); + + expect(events).toEqual([ 'pause', 'resume' ]); + expect(dataProducer1.paused).toBe(false); }, 2000); test('dataProducer.close() succeeds', async () => diff --git a/node/src/tests/test-Producer.ts b/node/src/tests/test-Producer.ts index c39d156098..75b9b66380 100644 --- a/node/src/tests/test-Producer.ts +++ b/node/src/tests/test-Producer.ts @@ -675,6 +675,12 @@ test('producer.getStats() succeeds', async () => test('producer.pause() and resume() succeed', async () => { + const onObserverPause = jest.fn(); + const onObserverResume = jest.fn(); + + audioProducer.observer.on('pause', onObserverPause); + audioProducer.observer.on('resume', onObserverResume); + await audioProducer.pause(); expect(audioProducer.paused).toBe(true); @@ -688,6 +694,42 @@ test('producer.pause() and resume() succeed', async () => await expect(audioProducer.dump()) .resolves .toMatchObject({ paused: false }); + + // Even if we don't await for pause()/resume() completion, the observer must + // fire 'pause' and 'resume' events if state was the opposite. + audioProducer.pause(); + audioProducer.resume(); + audioProducer.pause(); + audioProducer.pause(); + audioProducer.pause(); + await audioProducer.resume(); + + expect(onObserverPause).toHaveBeenCalledTimes(3); + expect(onObserverResume).toHaveBeenCalledTimes(3); +}, 2000); + +test('producer.pause() and resume() emit events', async () => +{ + const promises = []; + const events: string[] = []; + + audioProducer.observer.once('resume', () => + { + events.push('resume'); + }); + + audioProducer.observer.once('pause', () => + { + events.push('pause'); + }); + + promises.push(audioProducer.pause()); + promises.push(audioProducer.resume()); + + await Promise.all(promises); + + expect(events).toEqual([ 'pause', 'resume' ]); + expect(audioProducer.paused).toBe(false); }, 2000); test('producer.enableTraceEvent() succeed', async () => diff --git a/rust/src/router/consumer.rs b/rust/src/router/consumer.rs index 361868f2eb..8aa63ad83e 100644 --- a/rust/src/router/consumer.rs +++ b/rust/src/router/consumer.rs @@ -815,24 +815,23 @@ impl Consumer { } Notification::ProducerPause => { let mut producer_paused = producer_paused.lock(); - let was_paused = *paused.lock() || *producer_paused; + let paused = *paused.lock(); *producer_paused = true; handlers.producer_pause.call_simple(); - if !was_paused { + if !paused { handlers.pause.call_simple(); } } Notification::ProducerResume => { let mut producer_paused = producer_paused.lock(); let paused = *paused.lock(); - let was_paused = paused || *producer_paused; *producer_paused = false; handlers.producer_resume.call_simple(); - if was_paused && !paused { + if !paused { handlers.resume.call_simple(); } } diff --git a/rust/src/router/data_consumer.rs b/rust/src/router/data_consumer.rs index 2b7fe52e5b..d235f4c894 100644 --- a/rust/src/router/data_consumer.rs +++ b/rust/src/router/data_consumer.rs @@ -509,24 +509,23 @@ impl DataConsumer { } Notification::DataProducerPause => { let mut data_producer_paused = data_producer_paused.lock(); - let was_paused = *paused.lock() || *data_producer_paused; + let paused = *paused.lock(); *data_producer_paused = true; handlers.data_producer_pause.call_simple(); - if !was_paused { + if !paused { handlers.pause.call_simple(); } } Notification::DataProducerResume => { let mut data_producer_paused = data_producer_paused.lock(); let paused = *paused.lock(); - let was_paused = paused || *data_producer_paused; *data_producer_paused = false; handlers.data_producer_resume.call_simple(); - if was_paused && !paused { + if !paused { handlers.resume.call_simple(); } } From 9379183f0f08d0eeb37a8796894808d419ddb5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 20 Nov 2023 13:58:33 +0100 Subject: [PATCH 205/525] Update Node deps --- package-lock.json | 44 ++++++++++++++++++++++---------------------- package.json | 4 ++-- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 25e8a12c48..7a9b2476dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,10 +21,10 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.8", - "@types/node": "^20.9.1", + "@types/node": "^20.9.2", "@typescript-eslint/eslint-plugin": "^6.11.0", "@typescript-eslint/parser": "^6.11.0", - "eslint": "^8.53.0", + "eslint": "^8.54.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", "marked": "^10.0.0", @@ -765,9 +765,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", - "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1619,9 +1619,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.1.tgz", - "integrity": "sha512-HhmzZh5LSJNS5O8jQKpJ/3ZcrrlG6L70hpGqMIAoM9YVD0YBRNWYsfwcXq8VnSjlNpCpgLzMXdiPo+dxcvSmiA==", + "version": "20.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", + "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3023,15 +3023,15 @@ } }, "node_modules/eslint": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", - "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.53.0", + "@eslint/js": "8.54.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7301,9 +7301,9 @@ } }, "@eslint/js": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", - "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", "dev": true }, "@humanwhocodes/config-array": { @@ -8006,9 +8006,9 @@ "dev": true }, "@types/node": { - "version": "20.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.1.tgz", - "integrity": "sha512-HhmzZh5LSJNS5O8jQKpJ/3ZcrrlG6L70hpGqMIAoM9YVD0YBRNWYsfwcXq8VnSjlNpCpgLzMXdiPo+dxcvSmiA==", + "version": "20.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", + "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -8949,15 +8949,15 @@ "dev": true }, "eslint": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", - "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.53.0", + "@eslint/js": "8.54.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", diff --git a/package.json b/package.json index 3c2437fd0a..7af25b4e80 100644 --- a/package.json +++ b/package.json @@ -106,10 +106,10 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.8", - "@types/node": "^20.9.1", + "@types/node": "^20.9.2", "@typescript-eslint/eslint-plugin": "^6.11.0", "@typescript-eslint/parser": "^6.11.0", - "eslint": "^8.53.0", + "eslint": "^8.54.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", "marked": "^10.0.0", From e3f63c31b1a5930728c09f89900f6131f205721e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 20 Nov 2023 14:00:17 +0100 Subject: [PATCH 206/525] 3.13.3 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cccb44652..689f6f8233 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.13.3 * Node: Fix issue when 'pause'/'resume' events are not emitted ([PR #1231](https://github.com/versatica/mediasoup/pull/1231) by @douglaseel). diff --git a/package-lock.json b/package-lock.json index 7a9b2476dd..e2399bd17f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.2", + "version": "3.13.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.2", + "version": "3.13.3", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 7af25b4e80..c7d9976240 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.2", + "version": "3.13.3", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 7f758de2aee13fd8e450198535874a0d85e34418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 20 Nov 2023 14:41:00 +0100 Subject: [PATCH 207/525] npm package: include worker/scripts/*.mjs instead of worker/scripts/*.js --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c7d9976240..338d21e762 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "worker/fuzzer/include", "worker/fuzzer/src", "worker/include", - "worker/scripts/*.js", + "worker/scripts/*.mjs", "worker/scripts/*.json", "worker/scripts/*.py", "worker/scripts/*.sh", From c65f8ffdcfe5d175e0450469508c50c430fd1348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Nov 2023 11:12:42 +0100 Subject: [PATCH 208/525] Update NPM deps --- package-lock.json | 410 +++++++++++++++++++++++----------------------- package.json | 10 +- 2 files changed, 210 insertions(+), 210 deletions(-) diff --git a/package-lock.json b/package-lock.json index e2399bd17f..2e615aa09b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,10 +20,10 @@ "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.8", - "@types/node": "^20.9.2", - "@typescript-eslint/eslint-plugin": "^6.11.0", - "@typescript-eslint/parser": "^6.11.0", + "@types/jest": "^29.5.9", + "@types/node": "^20.9.3", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", "eslint": "^8.54.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", @@ -32,7 +32,7 @@ "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", - "typescript": "^5.2.2" + "typescript": "^5.3.2" }, "engines": { "node": ">=16" @@ -185,9 +185,9 @@ "dev": true }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -241,9 +241,9 @@ } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1591,9 +1591,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.8", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.8.tgz", - "integrity": "sha512-fXEFTxMV2Co8ZF5aYFJv+YeA08RTYJfhtN5c9JSv/mFEMe+xxjufCb+PHL+bJcMs/ebPUsBu+UNTEz+ydXrR6g==", + "version": "29.5.9", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.9.tgz", + "integrity": "sha512-zJeWhqBwVoPm83sP8h1/SVntwWTu5lZbKQGCvBjxQOyEWnKnsaomt2y7SlV4KfwlrHAHHAn00Sh4IAWaIsGOgQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1619,9 +1619,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.9.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", - "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", + "version": "20.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.3.tgz", + "integrity": "sha512-nk5wXLAXGBKfrhLB0cyHGbSqopS+nz0BUgZkUQqSHSSgdee0kssp1IAqlQOu333bW+gMNs2QREx7iynm19Abxw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1661,16 +1661,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.11.0.tgz", - "integrity": "sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.11.0", - "@typescript-eslint/type-utils": "6.11.0", - "@typescript-eslint/utils": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1696,13 +1696,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", - "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1713,9 +1713,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", - "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1726,13 +1726,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", - "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1753,17 +1753,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz", - "integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.11.0", - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/typescript-estree": "6.11.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" }, "engines": { @@ -1778,12 +1778,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", - "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1795,15 +1795,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.11.0.tgz", - "integrity": "sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.11.0", - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/typescript-estree": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4" }, "engines": { @@ -1823,13 +1823,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", - "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1840,9 +1840,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", - "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1853,13 +1853,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", - "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1880,12 +1880,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", - "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1914,13 +1914,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.11.0.tgz", - "integrity": "sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.11.0", - "@typescript-eslint/utils": "6.11.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1941,13 +1941,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", - "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1958,9 +1958,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", - "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1971,13 +1971,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", - "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1998,17 +1998,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz", - "integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.11.0", - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/typescript-estree": "6.11.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" }, "engines": { @@ -2023,12 +2023,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", - "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4027,9 +4027,9 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -6458,9 +6458,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -6864,9 +6864,9 @@ "dev": true }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -6909,9 +6909,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -7978,9 +7978,9 @@ } }, "@types/jest": { - "version": "29.5.8", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.8.tgz", - "integrity": "sha512-fXEFTxMV2Co8ZF5aYFJv+YeA08RTYJfhtN5c9JSv/mFEMe+xxjufCb+PHL+bJcMs/ebPUsBu+UNTEz+ydXrR6g==", + "version": "29.5.9", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.9.tgz", + "integrity": "sha512-zJeWhqBwVoPm83sP8h1/SVntwWTu5lZbKQGCvBjxQOyEWnKnsaomt2y7SlV4KfwlrHAHHAn00Sh4IAWaIsGOgQ==", "dev": true, "requires": { "expect": "^29.0.0", @@ -8006,9 +8006,9 @@ "dev": true }, "@types/node": { - "version": "20.9.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", - "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", + "version": "20.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.3.tgz", + "integrity": "sha512-nk5wXLAXGBKfrhLB0cyHGbSqopS+nz0BUgZkUQqSHSSgdee0kssp1IAqlQOu333bW+gMNs2QREx7iynm19Abxw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -8048,16 +8048,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.11.0.tgz", - "integrity": "sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.11.0", - "@typescript-eslint/type-utils": "6.11.0", - "@typescript-eslint/utils": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8067,29 +8067,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", - "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" } }, "@typescript-eslint/types": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", - "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", - "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8098,69 +8098,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz", - "integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.11.0", - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/typescript-estree": "6.11.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", - "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.11.0.tgz", - "integrity": "sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.11.0", - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/typescript-estree": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", - "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" } }, "@typescript-eslint/types": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", - "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", - "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8169,12 +8169,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", - "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" } } @@ -8191,41 +8191,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.11.0.tgz", - "integrity": "sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.11.0", - "@typescript-eslint/utils": "6.11.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", - "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" } }, "@typescript-eslint/types": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", - "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", - "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/visitor-keys": "6.11.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8234,27 +8234,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz", - "integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.11.0", - "@typescript-eslint/types": "6.11.0", - "@typescript-eslint/typescript-estree": "6.11.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", - "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" } } @@ -9652,9 +9652,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -11363,9 +11363,9 @@ "dev": true }, "typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true }, "undici-types": { diff --git a/package.json b/package.json index 338d21e762..3db1cc98c1 100644 --- a/package.json +++ b/package.json @@ -105,10 +105,10 @@ "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.8", - "@types/node": "^20.9.2", - "@typescript-eslint/eslint-plugin": "^6.11.0", - "@typescript-eslint/parser": "^6.11.0", + "@types/jest": "^29.5.9", + "@types/node": "^20.9.3", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", "eslint": "^8.54.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", @@ -117,6 +117,6 @@ "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", - "typescript": "^5.2.2" + "typescript": "^5.3.2" } } From 2e9c231bc228fd1c638cfc0bba5f428b5d8e371b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Nov 2023 16:10:11 +0100 Subject: [PATCH 209/525] Fix RTCP DLRR (Delay Since Last Receiver Report) block parsing (#1234) --- CHANGELOG.md | 5 ++ worker/Makefile | 6 +- .../remote_bitrate_estimator_abs_send_time.cc | 4 + worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp | 4 +- worker/test/src/RTC/RTCP/TestXr.cpp | 87 +++++++++++++++++++ 5 files changed, 100 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 689f6f8233..a997edaac9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* Fix RTCP DLRR (Delay Since Last Receiver Report) block parsing ([PR #1234](https://github.com/versatica/mediasoup/pull/1234)). + + ### 3.13.3 * Node: Fix issue when 'pause'/'resume' events are not emitted ([PR #1231](https://github.com/versatica/mediasoup/pull/1231) by @douglaseel). diff --git a/worker/Makefile b/worker/Makefile index 2bc6fb82d7..06b8087ddd 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -213,7 +213,7 @@ libmediasoup-worker: setup flatc flatc: setup $(MESON) compile -C $(BUILD_DIR) flatbuffers-generator -xcode: setup +xcode: setup flatc $(MESON) setup --buildtype debug --backend xcode $(MEDIASOUP_OUT_DIR)/xcode lint: @@ -234,7 +234,7 @@ else $(BUILD_DIR)/mediasoup-worker-test --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS) endif -test-asan: setup +test-asan: setup flatc $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test-asan $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-test-asan ASAN_OPTIONS=detect_leaks=1 $(BUILD_DIR)/mediasoup-worker-test-asan --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS) @@ -249,7 +249,7 @@ tidy: -checks=$(MEDIASOUP_TIDY_CHECKS) \ -quiet -fuzzer: setup +fuzzer: setup flatc $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-fuzzer $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-fuzzer diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc index 30da04df75..80b2a2835d 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc @@ -289,6 +289,8 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo( if (payload_size > kMinProbePacketSize && (!remote_rate_.ValidEstimate() || now_ms - first_packet_time_ms_ < kInitialProbingIntervalMs)) { + +#if MS_LOG_DEV_LEVEL == 3 // TODO(holmer): Use a map instead to get correct order? if (total_probes_received_ < kMaxProbePackets) { int send_delta_ms = -1; @@ -306,6 +308,8 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo( send_delta_ms, recv_delta_ms); } +#endif + probes_.push_back(Probe(send_time_ms, arrival_time_ms, payload_size)); ++total_probes_received_; // Make sure that a probe which updated the bitrate immediately has an diff --git a/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp b/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp index ace7ef334d..a626e6e175 100644 --- a/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp +++ b/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp @@ -75,14 +75,12 @@ namespace RTC { report->AddSsrcInfo(ssrcInfo); offset += ssrcInfo->GetSize(); + reportLength -= ssrcInfo->GetSize(); } else { return report.release(); } - - offset += ssrcInfo->GetSize(); - reportLength -= DelaySinceLastRr::SsrcInfo::BodySize; } return report.release(); diff --git a/worker/test/src/RTC/RTCP/TestXr.cpp b/worker/test/src/RTC/RTCP/TestXr.cpp index 09db0d0862..fcde2041ac 100644 --- a/worker/test/src/RTC/RTCP/TestXr.cpp +++ b/worker/test/src/RTC/RTCP/TestXr.cpp @@ -1,4 +1,5 @@ #include "common.hpp" +#include "RTC/RTCP/XR.hpp" #include "RTC/RTCP/XrDelaySinceLastRr.hpp" #include "RTC/RTCP/XrReceiverReferenceTime.hpp" #include @@ -6,6 +7,92 @@ using namespace RTC::RTCP; +SCENARIO("RTCP XR parsing", "[parser][rtcp][xr]") +{ + // clang-format off + uint8_t buffer[] = + { + 0xa0, 0xcf, 0x00, 0x08, // Padding, Type: 207 (XR), Length: 8 + 0x5d, 0x93, 0x15, 0x34, // Sender SSRC: 0x5d931534 + // Extended Report DLRR + 0x05, 0x00, 0x00, 0x06, // BT: 5 (DLRR), Block Length: 6 + 0x11, 0x12, 0x13, 0x14, // SSRC 1 + 0x00, 0x11, 0x00, 0x11, // LRR 1 + 0x11, 0x00, 0x11, 0x00, // DLRR 1 + 0x21, 0x22, 0x23, 0x24, // SSRC 2 + 0x00, 0x22, 0x00, 0x22, // LRR 2 + 0x22, 0x00, 0x22, 0x00, // DLRR 2 + 0x00, 0x00, 0x00, 0x04 // Padding (4 bytes) + }; + // clang-format on + + SECTION("parse XR packet") + { + auto* packet = ExtendedReportPacket::Parse(buffer, sizeof(buffer)); + + REQUIRE(packet); + // Despite total buffer size is 40 bytes, our GetSize() method doesn't not + // consider RTCP padding (4 bytes in this case). + REQUIRE(packet->GetSize() == 36); + REQUIRE(packet->GetCount() == 0); + REQUIRE(packet->GetSsrc() == 0x5d931534); + + size_t blockIdx{ 0u }; + + for (auto it = packet->Begin(); it != packet->End(); ++it, ++blockIdx) + { + auto* block = *it; + + switch (blockIdx) + { + case 0: + { + REQUIRE(block->GetSize() == 28); + + size_t ssrcInfoIdx{ 0u }; + auto* dlrrBlock = reinterpret_cast(block); + + for (auto it2 = dlrrBlock->Begin(); it2 != dlrrBlock->End(); ++it2, ++ssrcInfoIdx) + { + auto* ssrcInfo = *it2; + + switch (ssrcInfoIdx) + { + case 0: + { + REQUIRE(ssrcInfo->GetSsrc() == 0x11121314); + REQUIRE(ssrcInfo->GetLastReceiverReport() == 0x00110011); + REQUIRE(ssrcInfo->GetDelaySinceLastReceiverReport() == 0x11001100); + + break; + } + + case 1: + { + REQUIRE(ssrcInfo->GetSsrc() == 0x21222324); + REQUIRE(ssrcInfo->GetLastReceiverReport() == 0x00220022); + REQUIRE(ssrcInfo->GetDelaySinceLastReceiverReport() == 0x22002200); + + break; + } + } + } + + // There are 2 SSRC infos. + REQUIRE(ssrcInfoIdx == 2); + + break; + } + } + } + + // There are 1 block (the DLRR block). + REQUIRE(blockIdx == 1); + + delete packet; + } +} + SCENARIO("RTCP XrDelaySinceLastRt parsing", "[parser][rtcp][xr-dlrr]") { SECTION("create RRT") From 8d24fa7c9a88345f7998a9fcd73701217dc70b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Nov 2023 16:13:38 +0100 Subject: [PATCH 210/525] 3.13.4 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a997edaac9..586092b2e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.13.4 * Fix RTCP DLRR (Delay Since Last Receiver Report) block parsing ([PR #1234](https://github.com/versatica/mediasoup/pull/1234)). diff --git a/package-lock.json b/package-lock.json index 2e615aa09b..636092fbd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.3", + "version": "3.13.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.3", + "version": "3.13.4", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 3db1cc98c1..105585878c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.3", + "version": "3.13.4", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 9522597f573625dc291407bdd6da199ca0cb7324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 22 Nov 2023 10:46:28 +0100 Subject: [PATCH 211/525] Improve TestXr.cpp --- worker/test/src/RTC/Codecs/TestVP8.cpp | 2 +- worker/test/src/RTC/RTCP/TestXr.cpp | 39 ++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/worker/test/src/RTC/Codecs/TestVP8.cpp b/worker/test/src/RTC/Codecs/TestVP8.cpp index 0a3042246b..dd1c6d3333 100644 --- a/worker/test/src/RTC/Codecs/TestVP8.cpp +++ b/worker/test/src/RTC/Codecs/TestVP8.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "RTC/Codecs/VP8.hpp" #include -#include // std::memcmp() +#include // std::memcmp(), std::memcpy() using namespace RTC; diff --git a/worker/test/src/RTC/RTCP/TestXr.cpp b/worker/test/src/RTC/RTCP/TestXr.cpp index fcde2041ac..6580208b52 100644 --- a/worker/test/src/RTC/RTCP/TestXr.cpp +++ b/worker/test/src/RTC/RTCP/TestXr.cpp @@ -3,7 +3,7 @@ #include "RTC/RTCP/XrDelaySinceLastRr.hpp" #include "RTC/RTCP/XrReceiverReferenceTime.hpp" #include -#include // std::memcmp +#include // std::memcmp(), std::memcpy() using namespace RTC::RTCP; @@ -12,7 +12,7 @@ SCENARIO("RTCP XR parsing", "[parser][rtcp][xr]") // clang-format off uint8_t buffer[] = { - 0xa0, 0xcf, 0x00, 0x08, // Padding, Type: 207 (XR), Length: 8 + 0xa0, 0xcf, 0x00, 0x09, // Padding, Type: 207 (XR), Length: 9 0x5d, 0x93, 0x15, 0x34, // Sender SSRC: 0x5d931534 // Extended Report DLRR 0x05, 0x00, 0x00, 0x06, // BT: 5 (DLRR), Block Length: 6 @@ -33,6 +33,7 @@ SCENARIO("RTCP XR parsing", "[parser][rtcp][xr]") REQUIRE(packet); // Despite total buffer size is 40 bytes, our GetSize() method doesn't not // consider RTCP padding (4 bytes in this case). + // https://github.com/versatica/mediasoup/issues/1233 REQUIRE(packet->GetSize() == 36); REQUIRE(packet->GetCount() == 0); REQUIRE(packet->GetSsrc() == 0x5d931534); @@ -89,6 +90,40 @@ SCENARIO("RTCP XR parsing", "[parser][rtcp][xr]") // There are 1 block (the DLRR block). REQUIRE(blockIdx == 1); + SECTION("serialize packet instance") + { + // NOTE: Padding in RTCP is removed (if not needed) when serializing the + // packet, so we must mangle the buffer content (padding bit) and the + // buffer length before comparing the serialized packet with and original + // buffer. + + const size_t paddingBytes{ 4 }; + const size_t serializedBufferLength = sizeof(buffer) - paddingBytes; + uint8_t serialized[serializedBufferLength] = { 0 }; + + // Clone the original buffer into a new buffer without padding. + uint8_t clonedBuffer[serializedBufferLength] = { 0 }; + std::memcpy(clonedBuffer, buffer, serializedBufferLength); + + // Remove the padding bit in the first byte of the cloned buffer. + clonedBuffer[0] = 0x80; + + // Change RTCP length field in the cloned buffer. + clonedBuffer[3] = clonedBuffer[3] - 1; + + packet->Serialize(serialized); + + auto* packet2 = ExtendedReportPacket::Parse(serialized, serializedBufferLength); + + REQUIRE(packet2->GetType() == Type::XR); + REQUIRE(packet2->GetCount() == 0); + REQUIRE(packet2->GetSize() == 36); + + REQUIRE(std::memcmp(clonedBuffer, serialized, serializedBufferLength) == 0); + + delete packet2; + } + delete packet; } } From 1ed3a2474b829a7fb9c553ecf4fed9032d87cd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 22 Nov 2023 13:10:48 +0100 Subject: [PATCH 212/525] RTCP SDES: fix packet size calculation (#1236) --- CHANGELOG.md | 5 ++ worker/include/RTC/RTCP/Sdes.hpp | 2 +- worker/test/src/RTC/RTCP/TestSdes.cpp | 96 ++++++++++++++++++++++++--- 3 files changed, 94 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 586092b2e5..b49660845b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* Fix RTCP SDES packet size calculation ([PR #1236](https://github.com/versatica/mediasoup/pull/1236) based on PR [PR #1234](https://github.com/versatica/mediasoup/pull/1234) by @ybybwdwd). + + ### 3.13.4 * Fix RTCP DLRR (Delay Since Last Receiver Report) block parsing ([PR #1234](https://github.com/versatica/mediasoup/pull/1234)). diff --git a/worker/include/RTC/RTCP/Sdes.hpp b/worker/include/RTC/RTCP/Sdes.hpp index 717da20590..45ac1b752d 100644 --- a/worker/include/RTC/RTCP/Sdes.hpp +++ b/worker/include/RTC/RTCP/Sdes.hpp @@ -214,7 +214,7 @@ namespace RTC // A serialized packet can contain a maximum of 31 chunks. // If number of chunks exceeds 31 then the required number of packets // will be serialized which will take the size calculated below. - size_t size = Packet::CommonHeaderSize * ((this->GetCount() / MaxChunksPerPacket) + 1); + size_t size = Packet::CommonHeaderSize * ((this->GetCount() / (MaxChunksPerPacket + 1)) + 1); for (auto* chunk : this->chunks) { diff --git a/worker/test/src/RTC/RTCP/TestSdes.cpp b/worker/test/src/RTC/RTCP/TestSdes.cpp index eb64766391..9edc5e2a22 100644 --- a/worker/test/src/RTC/RTCP/TestSdes.cpp +++ b/worker/test/src/RTC/RTCP/TestSdes.cpp @@ -1,4 +1,5 @@ #include "common.hpp" +#include "RTC/RTCP/Packet.hpp" #include "RTC/RTCP/Sdes.hpp" #include #include // std::memcmp() @@ -383,40 +384,118 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") REQUIRE(!packet); } + SECTION("create SDES packet with 31 chunks") + { + const size_t count = 31; + + SdesPacket packet; + // Create a chunk and an item to obtain their size. + SdesChunk* chunk = new SdesChunk(1234 /*ssrc*/); + auto* item1 = + new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str()); + + chunk->AddItem(item1); + + auto chunkSize = chunk->GetSize(); + + delete chunk; + + for (auto i{ 1 }; i <= count; ++i) + { + // Create chunk and add to packet. + SdesChunk* chunk = new SdesChunk(i /*ssrc*/); + + auto* item1 = + new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str()); + + chunk->AddItem(item1); + + packet.AddChunk(chunk); + } + + REQUIRE(packet.GetCount() == count); + REQUIRE(packet.GetSize() == Packet::CommonHeaderSize + (count * chunkSize)); + + uint8_t buffer1[1500] = { 0 }; + + // Serialization must contain 1 SDES packet since report count doesn't + // exceed 31. + packet.Serialize(buffer1); + + auto* packet2 = static_cast(Packet::Parse(buffer1, sizeof(buffer1))); + + REQUIRE(packet2 != nullptr); + REQUIRE(packet2->GetCount() == count); + REQUIRE(packet2->GetSize() == Packet::CommonHeaderSize + (count * chunkSize)); + + auto reportIt = packet2->Begin(); + + for (auto i{ 1 }; i <= 31; ++i, reportIt++) + { + auto* chunk = *reportIt; + + REQUIRE(chunk->GetSsrc() == i); + + auto* item = *(chunk->Begin()); + + REQUIRE(item->GetType() == SdesItem::Type::CNAME); + REQUIRE(item->GetSize() == 2 + item1Value.size()); + REQUIRE(std::string(item->GetValue()) == item1Value); + } + + SdesPacket* packet3 = static_cast(packet2->GetNext()); + + REQUIRE(packet3 == nullptr); + + delete packet3; + } + SECTION("create SDES packet with more than 31 chunks") { const size_t count = 33; SdesPacket packet; + // Create a chunk and an item to obtain their size. + SdesChunk* chunk = new SdesChunk(1234 /*ssrc*/); + auto* item1 = + new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str()); + + chunk->AddItem(item1); + + auto chunkSize = chunk->GetSize(); + + delete chunk; - for (auto i = 1; i <= count; i++) + for (auto i{ 1 }; i <= count; ++i) { // Create chunk and add to packet. - SdesChunk* chunk1 = new SdesChunk(i /*ssrc*/); + SdesChunk* chunk = new SdesChunk(i /*ssrc*/); auto* item1 = new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str()); - chunk1->AddItem(item1); + chunk->AddItem(item1); - packet.AddChunk(chunk1); + packet.AddChunk(chunk); } REQUIRE(packet.GetCount() == count); + REQUIRE(packet.GetSize() == Packet::CommonHeaderSize + (31 * chunkSize) + Packet::CommonHeaderSize + ((count - 31) * chunkSize)); uint8_t buffer1[1500] = { 0 }; - // Serialization must contain 2 RR packets since report count exceeds 31. + // Serialization must contain 2 SDES packets since report count exceeds 31. packet.Serialize(buffer1); auto* packet2 = static_cast(Packet::Parse(buffer1, sizeof(buffer1))); REQUIRE(packet2 != nullptr); REQUIRE(packet2->GetCount() == 31); + REQUIRE(packet2->GetSize() == Packet::CommonHeaderSize + (31 * chunkSize)); auto reportIt = packet2->Begin(); - for (auto i = 1; i <= 31; i++, reportIt++) + for (auto i{ 1 }; i <= 31; ++i, reportIt++) { auto* chunk = *reportIt; @@ -432,11 +511,12 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") SdesPacket* packet3 = static_cast(packet2->GetNext()); REQUIRE(packet3 != nullptr); - REQUIRE(packet3->GetCount() == 2); + REQUIRE(packet3->GetCount() == count - 31); + REQUIRE(packet3->GetSize() == Packet::CommonHeaderSize + ((count - 31) * chunkSize)); reportIt = packet3->Begin(); - for (auto i = 1; i <= 2; i++, reportIt++) + for (auto i{ 1 }; i <= 2; ++i, reportIt++) { auto* chunk = *reportIt; From e952f34fea8489fa26ef30d29cb87118c5e6a707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 22 Nov 2023 18:28:14 +0100 Subject: [PATCH 213/525] RTCP `CompoundPacket`: Use a single DLRR block to hold all ssrc infos (#1237) --- CHANGELOG.md | 1 + worker/include/RTC/RTCP/CompoundPacket.hpp | 17 ++++-- .../include/RTC/RTCP/XrDelaySinceLastRr.hpp | 13 +++++ worker/include/RTC/RtpStreamSend.hpp | 2 +- worker/src/RTC/PipeConsumer.cpp | 13 ++--- worker/src/RTC/RTCP/CompoundPacket.cpp | 54 ++++++++++--------- worker/src/RTC/RtpStreamSend.cpp | 2 +- worker/src/RTC/SimpleConsumer.cpp | 12 +---- worker/src/RTC/SimulcastConsumer.cpp | 12 +---- worker/src/RTC/SvcConsumer.cpp | 12 +---- 10 files changed, 68 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b49660845b..2317eb66b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### NEXT * Fix RTCP SDES packet size calculation ([PR #1236](https://github.com/versatica/mediasoup/pull/1236) based on PR [PR #1234](https://github.com/versatica/mediasoup/pull/1234) by @ybybwdwd). +* RTCP Compound Packet: Use a single DLRR report to hold all ssrc info sub-blocks ([PR #1237](https://github.com/versatica/mediasoup/pull/1237)). ### 3.13.4 diff --git a/worker/include/RTC/RTCP/CompoundPacket.hpp b/worker/include/RTC/RTCP/CompoundPacket.hpp index 3e377d394a..228ba06d73 100644 --- a/worker/include/RTC/RTCP/CompoundPacket.hpp +++ b/worker/include/RTC/RTCP/CompoundPacket.hpp @@ -48,14 +48,16 @@ namespace RTC // Adds the given data and returns true if there is enough space to hold it, // false otherwise. bool Add( - SenderReport* senderReport, SdesChunk* sdesChunk, DelaySinceLastRr* delaySinceLastRrReport); + SenderReport* senderReport, + SdesChunk* sdesChunk, + DelaySinceLastRr::SsrcInfo* delaySinceLastRrSsrcInfo); // RTCP additions per Consumer (pipe). // Adds the given data and returns true if there is enough space to hold it, // false otherwise. bool Add( std::vector& senderReports, std::vector& sdesChunks, - std::vector& delaySinceLastRrReports); + std::vector& delaySinceLastRrSsrcInfos); // RTCP additions per Producer. // Adds the given data and returns true if there is enough space to hold it, // false otherwise. @@ -63,8 +65,6 @@ namespace RTC void AddSenderReport(SenderReport* report); void AddReceiverReport(ReceiverReport* report); void AddSdesChunk(SdesChunk* chunk); - void AddReceiverReferenceTime(ReceiverReferenceTime* report); - void AddDelaySinceLastRr(DelaySinceLastRr* report); bool HasSenderReport() { return this->senderReportPacket.Begin() != this->senderReportPacket.End(); @@ -77,6 +77,14 @@ namespace RTC [](const ExtendedReportBlock* report) { return report->GetType() == ExtendedReportBlock::Type::RRT; }); } + bool HasDelaySinceLastRr() + { + return std::any_of( + this->xrPacket.Begin(), + this->xrPacket.End(), + [](const ExtendedReportBlock* report) + { return report->GetType() == ExtendedReportBlock::Type::DLRR; }); + } void Serialize(uint8_t* data); private: @@ -85,6 +93,7 @@ namespace RTC ReceiverReportPacket receiverReportPacket; SdesPacket sdesPacket; ExtendedReportPacket xrPacket; + DelaySinceLastRr* delaySinceLastRr{ nullptr }; }; } // namespace RTCP } // namespace RTC diff --git a/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp b/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp index b2a7ec2c88..fa77eff277 100644 --- a/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp +++ b/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp @@ -119,6 +119,19 @@ namespace RTC { this->ssrcInfos.push_back(ssrcInfo); } + // NOTE: This method not only removes given number of ssrc info sub-blocks + // but also deletes their SsrcInfo instances. + void RemoveLastSsrcInfos(size_t number) + { + while (!this->ssrcInfos.empty() && number-- > 0) + { + auto* ssrcInfo = this->ssrcInfos.back(); + + this->ssrcInfos.pop_back(); + + delete ssrcInfo; + } + } Iterator Begin() { return this->ssrcInfos.begin(); diff --git a/worker/include/RTC/RtpStreamSend.hpp b/worker/include/RTC/RtpStreamSend.hpp index f98d399aca..a5fe733b84 100644 --- a/worker/include/RTC/RtpStreamSend.hpp +++ b/worker/include/RTC/RtpStreamSend.hpp @@ -37,7 +37,7 @@ namespace RTC void ReceiveRtcpReceiverReport(RTC::RTCP::ReceiverReport* report); void ReceiveRtcpXrReceiverReferenceTime(RTC::RTCP::ReceiverReferenceTime* report); RTC::RTCP::SenderReport* GetRtcpSenderReport(uint64_t nowMs); - RTC::RTCP::DelaySinceLastRr::SsrcInfo* GetRtcpXrDelaySinceLastRr(uint64_t nowMs); + RTC::RTCP::DelaySinceLastRr::SsrcInfo* GetRtcpXrDelaySinceLastRrSsrcInfo(uint64_t nowMs); RTC::RTCP::SdesChunk* GetRtcpSdesChunk(); void Pause() override; void Resume() override; diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index d80cba0ab8..5ac3f65c09 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -345,7 +345,7 @@ namespace RTC std::vector senderReports; std::vector sdesChunks; - std::vector xrReports; + std::vector delaySinceLastRrSsrcInfos; for (auto* rtpStream : this->rtpStreams) { @@ -362,19 +362,16 @@ namespace RTC auto* sdesChunk = rtpStream->GetRtcpSdesChunk(); sdesChunks.push_back(sdesChunk); - auto* dlrr = rtpStream->GetRtcpXrDelaySinceLastRr(nowMs); + auto* delaySinceLastRrSsrcInfo = rtpStream->GetRtcpXrDelaySinceLastRrSsrcInfo(nowMs); - if (dlrr) + if (delaySinceLastRrSsrcInfo) { - auto* report = new RTC::RTCP::DelaySinceLastRr(); - report->AddSsrcInfo(dlrr); - - xrReports.push_back(report); + delaySinceLastRrSsrcInfos.push_back(delaySinceLastRrSsrcInfo); } } // RTCP Compound packet buffer cannot hold the data. - if (!packet->Add(senderReports, sdesChunks, xrReports)) + if (!packet->Add(senderReports, sdesChunks, delaySinceLastRrSsrcInfos)) { return false; } diff --git a/worker/src/RTC/RTCP/CompoundPacket.cpp b/worker/src/RTC/RTCP/CompoundPacket.cpp index c1809e3d11..4429f4d2f6 100644 --- a/worker/src/RTC/RTCP/CompoundPacket.cpp +++ b/worker/src/RTC/RTCP/CompoundPacket.cpp @@ -72,7 +72,9 @@ namespace RTC } bool CompoundPacket::Add( - SenderReport* senderReport, SdesChunk* sdesChunk, DelaySinceLastRr* delaySinceLastRrReport) + SenderReport* senderReport, + SdesChunk* sdesChunk, + DelaySinceLastRr::SsrcInfo* delaySinceLastRrSsrcInfo) { // Add the items into the packet. @@ -86,9 +88,16 @@ namespace RTC this->sdesPacket.AddChunk(sdesChunk); } - if (delaySinceLastRrReport) + if (delaySinceLastRrSsrcInfo) { - this->xrPacket.AddReport(delaySinceLastRrReport); + // Add a DLRR block into the XR packet if no present. + if (!this->delaySinceLastRr) + { + this->delaySinceLastRr = new RTC::RTCP::DelaySinceLastRr(); + this->xrPacket.AddReport(this->delaySinceLastRr); + } + + this->delaySinceLastRr->AddSsrcInfo(delaySinceLastRrSsrcInfo); } // New items can hold in the packet, report it. @@ -112,10 +121,10 @@ namespace RTC delete sdesChunk; } - if (delaySinceLastRrReport) + if (delaySinceLastRrSsrcInfo) { - this->xrPacket.RemoveReport(delaySinceLastRrReport); - delete delaySinceLastRrReport; + // NOTE: This method deletes the removed instances in place. + this->delaySinceLastRr->RemoveLastSsrcInfos(1); } return false; @@ -124,7 +133,7 @@ namespace RTC bool CompoundPacket::Add( std::vector& senderReports, std::vector& sdesChunks, - std::vector& delaySinceLastRrReports) + std::vector& delaySinceLastRrSsrcInfos) { // Add the items into the packet. @@ -138,9 +147,16 @@ namespace RTC this->sdesPacket.AddChunk(chunk); } - for (auto* report : delaySinceLastRrReports) + // Add a DLRR block into the XR packet if no present. + if (!delaySinceLastRrSsrcInfos.empty() && !this->delaySinceLastRr) { - this->xrPacket.AddReport(report); + this->delaySinceLastRr = new RTC::RTCP::DelaySinceLastRr(); + this->xrPacket.AddReport(this->delaySinceLastRr); + } + + for (auto* ssrcInfo : delaySinceLastRrSsrcInfos) + { + this->delaySinceLastRr->AddSsrcInfo(ssrcInfo); } // New items can hold in the packet, report it. @@ -164,10 +180,10 @@ namespace RTC delete chunk; } - for (auto* report : delaySinceLastRrReports) + if (!delaySinceLastRrSsrcInfos.empty()) { - this->xrPacket.RemoveReport(report); - delete report; + // NOTE: This method deletes the instances in place. + this->delaySinceLastRr->RemoveLastSsrcInfos(delaySinceLastRrSsrcInfos.size()); } return false; @@ -266,19 +282,5 @@ namespace RTC this->sdesPacket.AddChunk(chunk); } - - void CompoundPacket::AddReceiverReferenceTime(ReceiverReferenceTime* report) - { - MS_TRACE(); - - this->xrPacket.AddReport(report); - } - - void CompoundPacket::AddDelaySinceLastRr(DelaySinceLastRr* report) - { - MS_TRACE(); - - this->xrPacket.AddReport(report); - } } // namespace RTCP } // namespace RTC diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index a76ce3fce4..191e116236 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -274,7 +274,7 @@ namespace RTC return report; } - RTC::RTCP::DelaySinceLastRr::SsrcInfo* RtpStreamSend::GetRtcpXrDelaySinceLastRr(uint64_t nowMs) + RTC::RTCP::DelaySinceLastRr::SsrcInfo* RtpStreamSend::GetRtcpXrDelaySinceLastRrSsrcInfo(uint64_t nowMs) { MS_TRACE(); diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index f7d7a885b1..6488e776d2 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -439,18 +439,10 @@ namespace RTC // Build SDES chunk for this sender. auto* sdesChunk = this->rtpStream->GetRtcpSdesChunk(); - RTC::RTCP::DelaySinceLastRr* delaySinceLastRrReport{ nullptr }; - - auto* dlrr = this->rtpStream->GetRtcpXrDelaySinceLastRr(nowMs); - - if (dlrr) - { - delaySinceLastRrReport = new RTC::RTCP::DelaySinceLastRr(); - delaySinceLastRrReport->AddSsrcInfo(dlrr); - } + auto* delaySinceLastRrSsrcInfo = this->rtpStream->GetRtcpXrDelaySinceLastRrSsrcInfo(nowMs); // RTCP Compound packet buffer cannot hold the data. - if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrReport)) + if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrSsrcInfo)) { return false; } diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index de0f491904..cbafc1d05d 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -1081,18 +1081,10 @@ namespace RTC // Build SDES chunk for this sender. auto* sdesChunk = this->rtpStream->GetRtcpSdesChunk(); - RTC::RTCP::DelaySinceLastRr* delaySinceLastRrReport{ nullptr }; - - auto* dlrr = this->rtpStream->GetRtcpXrDelaySinceLastRr(nowMs); - - if (dlrr) - { - delaySinceLastRrReport = new RTC::RTCP::DelaySinceLastRr(); - delaySinceLastRrReport->AddSsrcInfo(dlrr); - } + auto* delaySinceLastRrSsrcInfo = this->rtpStream->GetRtcpXrDelaySinceLastRrSsrcInfo(nowMs); // RTCP Compound packet buffer cannot hold the data. - if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrReport)) + if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrSsrcInfo)) { return false; } diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index b02183f048..9e86e867b2 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -795,18 +795,10 @@ namespace RTC // Build SDES chunk for this sender. auto* sdesChunk = this->rtpStream->GetRtcpSdesChunk(); - RTC::RTCP::DelaySinceLastRr* delaySinceLastRrReport{ nullptr }; - - auto* dlrr = this->rtpStream->GetRtcpXrDelaySinceLastRr(nowMs); - - if (dlrr) - { - delaySinceLastRrReport = new RTC::RTCP::DelaySinceLastRr(); - delaySinceLastRrReport->AddSsrcInfo(dlrr); - } + auto* delaySinceLastRrSsrcInfo = this->rtpStream->GetRtcpXrDelaySinceLastRrSsrcInfo(nowMs); // RTCP Compound packet buffer cannot hold the data. - if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrReport)) + if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrSsrcInfo)) { return false; } From 52eb695ea4fc673605e78962817ba6c0c7fb9b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 22 Nov 2023 18:32:08 +0100 Subject: [PATCH 214/525] 3.13.5 --- CHANGELOG.md | 2 +- package-lock.json | 32 ++++++++++++++++---------------- package.json | 6 +++--- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2317eb66b5..115b1b6900 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.13.5 * Fix RTCP SDES packet size calculation ([PR #1236](https://github.com/versatica/mediasoup/pull/1236) based on PR [PR #1234](https://github.com/versatica/mediasoup/pull/1234) by @ybybwdwd). * RTCP Compound Packet: Use a single DLRR report to hold all ssrc info sub-blocks ([PR #1237](https://github.com/versatica/mediasoup/pull/1237)). diff --git a/package-lock.json b/package-lock.json index 636092fbd4..395649a599 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.4", + "version": "3.13.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.4", + "version": "3.13.5", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -20,8 +20,8 @@ "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.9", - "@types/node": "^20.9.3", + "@types/jest": "^29.5.10", + "@types/node": "^20.9.4", "@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/parser": "^6.12.0", "eslint": "^8.54.0", @@ -1591,9 +1591,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.9", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.9.tgz", - "integrity": "sha512-zJeWhqBwVoPm83sP8h1/SVntwWTu5lZbKQGCvBjxQOyEWnKnsaomt2y7SlV4KfwlrHAHHAn00Sh4IAWaIsGOgQ==", + "version": "29.5.10", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", + "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1619,9 +1619,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.9.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.3.tgz", - "integrity": "sha512-nk5wXLAXGBKfrhLB0cyHGbSqopS+nz0BUgZkUQqSHSSgdee0kssp1IAqlQOu333bW+gMNs2QREx7iynm19Abxw==", + "version": "20.9.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.4.tgz", + "integrity": "sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -7978,9 +7978,9 @@ } }, "@types/jest": { - "version": "29.5.9", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.9.tgz", - "integrity": "sha512-zJeWhqBwVoPm83sP8h1/SVntwWTu5lZbKQGCvBjxQOyEWnKnsaomt2y7SlV4KfwlrHAHHAn00Sh4IAWaIsGOgQ==", + "version": "29.5.10", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", + "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", "dev": true, "requires": { "expect": "^29.0.0", @@ -8006,9 +8006,9 @@ "dev": true }, "@types/node": { - "version": "20.9.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.3.tgz", - "integrity": "sha512-nk5wXLAXGBKfrhLB0cyHGbSqopS+nz0BUgZkUQqSHSSgdee0kssp1IAqlQOu333bW+gMNs2QREx7iynm19Abxw==", + "version": "20.9.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.4.tgz", + "integrity": "sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==", "dev": true, "requires": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index 105585878c..625cda38ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.4", + "version": "3.13.5", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -105,8 +105,8 @@ "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.9", - "@types/node": "^20.9.3", + "@types/jest": "^29.5.10", + "@types/node": "^20.9.4", "@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/parser": "^6.12.0", "eslint": "^8.54.0", From eaa2c7b3fab90316d4cc1c0d78f665fcb50b881e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 23 Nov 2023 11:39:25 +0100 Subject: [PATCH 215/525] worker/Makefile: cosmetic, use double quotes everywhere and improve log --- worker/Makefile | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/worker/Makefile b/worker/Makefile index 06b8087ddd..820bac829c 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -101,7 +101,8 @@ ifeq ($(wildcard $(PIP_DIR)),) # fallback to command without `--system` if the first one fails. $(PYTHON) -m pip install --system --target=$(PIP_DIR) pip setuptools || \ $(PYTHON) -m pip install --target=$(PIP_DIR) pip setuptools || \ - echo "Installation failed, likely because PIP is unavailable, if you are on Debian/Ubuntu or derivative please install the python3-pip package" + (echo "update of pip or setuptools failed, likely because pip is not installed (if you are on Debian/Ubuntu or derivative please install the python3-pip package)" >&2) + # Install `meson` and `ninja` using `pip` into custom location, so we don't # depend on system-wide installation. $(PYTHON) -m pip install --upgrade --target=$(PIP_DIR) $(PIP_BUILD_BINARIES) meson==$(MESON_VERSION) ninja==$(NINJA_VERSION) @@ -113,8 +114,8 @@ setup: meson-ninja ifeq ($(MEDIASOUP_BUILDTYPE),Release) $(MESON) setup \ --prefix $(INSTALL_DIR) \ - --bindir '' \ - --libdir '' \ + --bindir "" \ + --libdir "" \ --buildtype release \ -Db_ndebug=true \ -Db_pie=true \ @@ -124,8 +125,8 @@ ifeq ($(MEDIASOUP_BUILDTYPE),Release) $(BUILD_DIR) || \ $(MESON) setup \ --prefix $(INSTALL_DIR) \ - --bindir '' \ - --libdir '' \ + --bindir "" \ + --libdir "" \ --buildtype release \ -Db_ndebug=true \ -Db_pie=true \ @@ -136,8 +137,8 @@ else ifeq ($(MEDIASOUP_BUILDTYPE),Debug) $(MESON) setup \ --prefix $(INSTALL_DIR) \ - --bindir '' \ - --libdir '' \ + --bindir "" \ + --libdir "" \ --buildtype debug \ -Db_pie=true \ -Db_staticpic=true \ @@ -146,8 +147,8 @@ ifeq ($(MEDIASOUP_BUILDTYPE),Debug) $(BUILD_DIR) || \ $(MESON) setup \ --prefix $(INSTALL_DIR) \ - --bindir '' \ - --libdir '' \ + --bindir "" \ + --libdir "" \ --buildtype debug \ -Db_pie=true \ -Db_staticpic=true \ @@ -156,8 +157,8 @@ ifeq ($(MEDIASOUP_BUILDTYPE),Debug) else $(MESON) setup \ --prefix $(INSTALL_DIR) \ - --bindir '' \ - --libdir '' \ + --bindir "" \ + --libdir "" \ --buildtype $(MEDIASOUP_BUILDTYPE) \ -Db_ndebug=if-release \ -Db_pie=true \ @@ -167,8 +168,8 @@ else $(BUILD_DIR) || \ $(MESON) setup \ --prefix $(INSTALL_DIR) \ - --bindir '' \ - --libdir '' \ + --bindir "" \ + --libdir "" \ --buildtype $(MEDIASOUP_BUILDTYPE) \ -Db_ndebug=if-release \ -Db_pie=true \ @@ -243,7 +244,7 @@ tidy: $(PYTHON) ./scripts/clang-tidy.py \ -clang-tidy-binary=./scripts/node_modules/.bin/clang-tidy \ -clang-apply-replacements-binary=./scripts/node_modules/.bin/clang-apply-replacements \ - -header-filter='(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|handles/**/*.hpp)' \ + -header-filter="(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|handles/**/*.hpp)" \ -p=$(BUILD_DIR) \ -j=$(CORES) \ -checks=$(MEDIASOUP_TIDY_CHECKS) \ From 3f0594d33b1d0638a474327d9a1ce9e3d223c809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 27 Nov 2023 13:27:11 +0100 Subject: [PATCH 216/525] Replace make + Makefile with Python Invoke library + tasks.py ((also fix installation under path with whitespaces) (#1239) --- .github/workflows/{codeql.yml => codeql.yaml} | 3 + .../workflows/mediasoup-worker-prebuild.yaml | 5 + .github/workflows/mediasoup-worker.yaml | 24 +- .gitignore | 5 +- CHANGELOG.md | 5 + doc/Building.md | 137 ++-- npm-scripts.mjs | 179 +++--- package.json | 16 +- worker/Dockerfile | 11 +- worker/Dockerfile.alpine | 7 +- worker/Makefile | 288 ++------- worker/build.rs | 101 ++- worker/scripts/clang-format.mjs | 4 +- worker/scripts/cpu_cores.sh | 19 - worker/scripts/get-dep.sh | 2 +- worker/scripts/getmake.py | 28 - worker/tasks.py | 602 ++++++++++++++++++ 17 files changed, 918 insertions(+), 518 deletions(-) rename .github/workflows/{codeql.yml => codeql.yaml} (96%) delete mode 100755 worker/scripts/cpu_cores.sh delete mode 100644 worker/scripts/getmake.py create mode 100644 worker/tasks.py diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yaml similarity index 96% rename from .github/workflows/codeql.yml rename to .github/workflows/codeql.yaml index b26646fd42..15c104f781 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yaml @@ -55,6 +55,9 @@ jobs: # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality + # We need to install pip invoke library. + - name: pip3 install invoke + run: pip3 install invoke # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below) diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 39392aae04..ea1491cf72 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -54,6 +54,11 @@ jobs: - name: npm ci run: npm ci --ignore-scripts --omit=dev + # However we also need to install pip invoke manually (since + # `--ignore-scripts` prevented invoke from being installed). + - name: pip3 install invoke + run: pip3 install invoke + - name: npm run worker:build run: npm run worker:build diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index f4e3bc16b6..ac0cb4d042 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -64,25 +64,25 @@ jobs: restore-keys: | ${{ matrix.build.os }}-node-${{matrix.build.cc}}- - # We need to install some NPM production deps for npm-scripts.mjs to work. - - name: npm ci - run: npm ci --ignore-scripts --omit=dev + # We need to install pip invoke manually. + - name: pip3 install invoke + run: pip3 install invoke - # We need to install deps on worker/scripts/package.json. - - name: npm run install-worker-dev-tools - run: npm run install-worker-dev-tools + # We need to install npm deps of worker/scripts/package.json. + - name: npm ci --prefix worker/scripts + run: npm ci --prefix worker/scripts # TODO: Maybe fix this one day. if: runner.os != 'Windows' - - name: npm run lint:worker - run: npm run lint:worker + - name: invoke -r worker lint + run: invoke -r worker lint # TODO: Maybe fix this one day. if: runner.os != 'Windows' - - name: npm run worker:build - run: npm run worker:build + - name: invoke -r worker mediasoup-worker + run: invoke -r worker mediasoup-worker - - name: npm run test:worker - run: npm run test:worker + - name: invoke -r worker test + run: invoke -r worker test # TODO: Maybe fix this one day. if: runner.os != 'Windows' diff --git a/.gitignore b/.gitignore index abbaa0f7f2..e2f65fca29 100644 --- a/.gitignore +++ b/.gitignore @@ -20,10 +20,11 @@ # Flatc generated files. /worker/include/FBS /worker/prebuild -# Vistual Studio generated Stuff. +# Python invoke. +/worker/pip_invoke +# Build artifacts. /worker/**/Debug /worker/**/Release -/worker/.vs # clang-fuzzer stuff is too big. /worker/deps/clang-fuzzer # Ignore all fuzzer generated test inputs. diff --git a/CHANGELOG.md b/CHANGELOG.md index 115b1b6900..59b0bfeb9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* Replace make + Makefile with Python Invoke library + tasks.py (also fix installation under path with whitespaces) ([PR #1239](https://github.com/versatica/mediasoup/pull/1239)). + + ### 3.13.5 * Fix RTCP SDES packet size calculation ([PR #1236](https://github.com/versatica/mediasoup/pull/1236) based on PR [PR #1234](https://github.com/versatica/mediasoup/pull/1234) by @ybybwdwd). diff --git a/doc/Building.md b/doc/Building.md index 35b362765a..7408111f9e 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -16,11 +16,11 @@ Compiles mediasoup TypeScript code (`lib` folder) JavaScript, places it into the ### `npm run worker:build` -Builds the `mediasoup-worker` binary. It invokes `make`below. +Builds the `mediasoup-worker` binary. It invokes `invoke`below. ### `npm run worker:prebuild` -Creates a prebuilt of `mediasoup-worker` in the `worker/prebuild` folder. +Creates a prebuilt of `mediasoup-worker` binary in the `worker/prebuild` folder. ### `npm run lint` @@ -32,11 +32,23 @@ Validates mediasoup JavaScript files using [ESLint](https://eslint.org). ### `npm run lint:worker` -Validates mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It invokes `make lint` below. +Validates mediasoup worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It invokes `invoke lint` below. ### `npm run format:worker` -Rewrites mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It invokes `make format` below. +Rewrites mediasoup worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It invokes `invoke format` below. + +### `npm run flatc` + +Runs both `npm run flatc:node` and `npm run flatc:worker`. + +### `npm run flatc:node` + +Compiles [FlatBuffers](https://github.com/google/flatbuffers) `.fbs` files in `worker/fbs` to TypeScript code. + +### `npm run flatc:worker` + +Compiles [FlatBuffers](https://github.com/google/flatbuffers) `.fbs` files in `worker/fbs` to C++ code. ### `npm run test` @@ -48,129 +60,136 @@ Runs [Jest](https://jestjs.io) test units located at `test/` folder. ### `npm run test:worker` -Runs [Catch2](https://github.com/catchorg/Catch2) test units located at `worker/test/` folder. It invokes `make test` below. +Runs [Catch2](https://github.com/catchorg/Catch2) test units located at `worker/test/` folder. It invokes `invoke test` below. ### `npm run coverage:node` Same as `npm run test:node` but it also opens a browser window with JavaScript coverage results. -### `npm run install-deps:node` +### `npm run release:check` -Installs NPM dependencies and updates `package-lock.json`. - -### `npm run install-worker-dev-tools` - -Installs worker NPM packages needed for local development. +Runs linters and tests in Node and C++ code. ## Rust -The only special feature in Rust case is special environment variable `"KEEP_BUILD_ARTIFACTS", that when set to `1` will allow incremental recompilation of changed C++ sources during hacking on mediasoup. +The only special feature in Rust case is special environment variable "KEEP_BUILD_ARTIFACTS", that when set to "1" will allow incremental recompilation of changed C++ sources during hacking on mediasoup. + It is not necessary for normal usage of mediasoup as a dependency. -## Makefile +## Python Invoke and `tasks.py` file + +mediasoup uses Python [Invoke](https://www.pyinvoke.org/) library for managing and organizing tasks in the `worker` folder (mediasoup worker C++ subproject). `Invoke` is basically a replacemente of `make` + `Makefile` written in Python. mediasoup automatically installs `Invoke` in a local custom path during the installation process (in both Node and Rust) so the user doesn't need to worry about it. -The `worker` folder contains a `Makefile` for the mediasoup-worker C++ subproject. It includes the following tasks: +Tasks are defined in `worker/tasks.py`. For development purposes, developers or contributors can install `Invoke` using `pip3 install invoke` and run tasks below within the `worker` folder. -### `make` or `make mediasoup-worker` +See all the tasks by running `invoke --list` within the `worker` folder. -Alias of ``make mediasoup-worker` below. +*NOTE:* For some of these tasks to work, npm dependencies of `worker/scripts/package.json` must be installed: -### `make meson-ninja` +```bash +npm ci --prefix worker/scripts +``` + +### `invoke` (default task) -Installs `meson` and `ninja`. +Alias of `invoke mediasoup-worker` task below. -### `make clean` +### `invoke meson-ninja` + +Installs `meson` and `ninja` into a local custom path. + +### `invoke clean` Cleans built objects and binaries. -### `make clean-build` +### `invoke clean-build` Cleans built objects and other artifacts, but keeps `mediasoup-worker` binary in place. -### `make clean-pip` +### `invoke clean-pip` Cleans `meson` and `ninja` installed in local prefix with pip. -### `make clean-subprojects` +### `invoke clean-subprojects` Cleans subprojects downloaded with Meson. -### `make clean-all` +### `invoke clean-all` Cleans built objects and binaries, `meson` and `ninja` installed in local prefix with pip and all subprojects downloaded with Meson. -### `make update-wrap-file` +### `invoke update-wrap-file [subproject]` -Update the wrap file of a subproject with Meson. Usage example: +Updates the wrap file of a subproject (those in `worker/subprojects` folder) with Meson. Usage example: ```bash cd worker -make update-wrap-file SUBPROJECT=openssl +invoke update-wrap-file openssl ``` -### `make mediasoup-worker` +### `invoke mediasoup-worker` Builds the `mediasoup-worker` binary at `worker/out/Release/`. If the "MEDIASOUP_MAX_CORES" environment variable is set, the build process will use that number of CPU cores. Otherwise it will auto-detect the number of cores in the machine. -"MEDIASOUP_BUILDTYPE" environment variable controls build types, `Release` and `Debug` are presets optimized for those use cases. -Other build types are possible too, but they are not presets and will require "MESON_ARGS" use to customize build configuration. +"MEDIASOUP_BUILDTYPE" environment variable controls build types, "Release" and "Debug" are presets optimized for those use cases. Other build types are possible too, but they are not presets and will require "MESON_ARGS" use to customize build configuration. + Check the meaning of useful macros in the `worker/include/Logger.hpp` header file if you want to enable tracing or other debug information. Binary is built at `worker/out/MEDIASOUP_BUILDTYPE/build`. -In order to instruct the mediasoup Node.js module to use the `Debug` mediasoup-worker binary, an environment variable must be set before running the Node.js application: +In order to instruct the mediasoup Node.js module to use the "Debug"` `mediasoup-worker` binary, an environment variable must be set before running the Node.js application: ```bash MEDIASOUP_BUILDTYPE=Debug node myapp.js ``` -If the "MEDIASOUP_WORKER_BIN" environment variable is set (it must be an absolute file path), mediasoup will use the it as mediasoup-worker binary and **won't** compile the binary: +If the "MEDIASOUP_WORKER_BIN" environment variable is set (it must be an absolute file path), mediasoup will use the it as `mediasoup-worker` binary and **won't** compile the binary: ```bash MEDIASOUP_WORKER_BIN="/home/xxx/src/foo/mediasoup-worker" node myapp.js ``` -### `make libmediasoup-worker` +### `invoke libmediasoup-worker` Builds the `libmediasoup-worker` static library at `worker/out/Release/`. "MEDIASOUP_MAX_CORES"` and "MEDIASOUP_BUILDTYPE" environment variables from above still apply for static library build. -### `make xcode` +### `invoke xcode` -Builds a Xcode project for the mediasoup-worker subproject. +Builds a Xcode project for the mediasoup worker subproject. -### `make lint` +### `invoke lint` -Validates mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html) and rules in `worker/.clang-format`. +Validates mediasoup worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html) and rules in `worker/.clang-format`. -### `make format` +### `invoke format` -Rewrites mediasoup-worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). +Rewrites mediasoup worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). -### `make test` +### `invoke test` Builds and runs the `mediasoup-worker-test` binary at `worker/out/Release/` (or at `worker/out/Debug/` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"), which uses [Catch2](https://github.com/catchorg/Catch2) to run test units located at `worker/test/` folder. -### `make test-asan` +### `invoke test-asan` Run test with Address Sanitizer. -### `make tidy` +### `invoke tidy` Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy/) and performs C++ code checks following `worker/.clang-tidy` rules. **Requirements:** -* `make clean` and `make` must have been called first. +* `invoke clean` and `invoke mediasoup-worker` must have been called first. * [PyYAML](https://pyyaml.org/) is required. - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. "MEDIASOUP_TIDY_CHECKS" environment variable with a comma separated list of checks overrides the checks defined in `.clang-tidy` file. -### `make fuzzer` +### `invoke fuzzer` Builds the `mediasoup-worker-fuzzer` binary (which uses [libFuzzer](http://llvm.org/docs/LibFuzzer.html)) at `worker/out/Release/` (or at `worker/out/Debug/` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"). @@ -182,11 +201,11 @@ Builds the `mediasoup-worker-fuzzer` binary (which uses [libFuzzer](http://llvm. Read the [Fuzzer](Fuzzer.md) documentation for detailed information. -### `make fuzzer-run-all` +### `invoke fuzzer-run-all` Runs all fuzzer cases. -### `make docker` +### `invoke docker` Builds a Linux Ubuntu Docker image with fuzzer capable clang++ and all dependencies to run mediasoup. @@ -194,21 +213,33 @@ Builds a Linux Ubuntu Docker image with fuzzer capable clang++ and all dependenc ```bash cd worker -./scripts/get-dep.sh clang-fuzzer +scripts/get-dep.sh clang-fuzzer ``` -### `make docker-run` +### `invoke docker-run` -Runs a container of the Ubuntu Docker image created with `make docker`. It automatically executes a `bash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. +Runs a container of the Ubuntu Docker image created with `invoke docker`. It automatically executes a `bash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. -**NOTE:** To install and run mediasoup in the container, previous installation (if any) must be properly cleaned by entering the `worker` directory and running `make clean-all`. +**NOTE:** To install and run mediasoup in the container, previous installation (if any) must be properly cleaned by entering the `worker` directory and running `invoke clean-all`. -### `make docker-alpine` +### `invoke docker-alpine` Builds a Linux Alpine Docker image with all dependencies to run mediasoup. -### `make docker-alpine-run` +### `invoke docker-alpine-run` + +Runs a container of the Alpine Docker image created with `invoke docker-alpine`. It automatically executes an `ash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. + +**NOTE:** To install and run mediasoup in the container, previous installation (if any) must be properly cleaned by entering the `worker` directory and running `invoke clean-all`. + +## Makefile + +The `worker` folder contains a `Makefile` file for the mediasoup worker C++ subproject. It acts as a proxy to the `Invoke` tasks defined in `tasks.py`. The `Makefile` file exists to help developers or contributors that prefer keep using `make` commands. -Runs a container of the Alpine Docker image created with `make docker-alpine`. It automatically executes an `ash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. +All tasks defined in `tasks.py` (see above) are available in `Makefile`. There is only one exception: -**NOTE:** To install and run mediasoup in the container, previous installation (if any) must be properly cleaned by entering the `worker` directory and running `make clean-all`. +- The `update-wrap-file` needs a "SUBPROJECT" environment variable indicating the subproject to update. Usage example: + ```bash + cd worker + make update-wrap-file SUBPROJECT=openssl + ``` diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 2de2298c8a..80ebc35c3e 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -2,15 +2,16 @@ import process from 'node:process'; import os from 'node:os'; import fs from 'node:fs'; import path from 'node:path'; -import { execSync, spawnSync } from 'node:child_process'; +import { execSync } from 'node:child_process'; import fetch from 'node-fetch'; import tar from 'tar'; const PKG = JSON.parse(fs.readFileSync('./package.json').toString()); -const IS_FREEBSD = os.platform() === 'freebsd'; const IS_WINDOWS = os.platform() === 'win32'; const MAYOR_VERSION = PKG.version.split('.')[0]; -const MAKE = process.env.MAKE || (IS_FREEBSD ? 'gmake' : 'make'); +const PYTHON = getPython(); +const PIP_INVOKE_DIR = path.resolve('worker/pip_invoke'); +const INVOKE_VERSION = process.env.INVOKE_VERSION ?? '2.2.0'; const FLATBUFFERS_VERSION = '23.3.3'; const WORKER_RELEASE_DIR = 'worker/out/Release'; const WORKER_RELEASE_BIN = IS_WINDOWS ? 'mediasoup-worker.exe' : 'mediasoup-worker'; @@ -23,12 +24,37 @@ const GH_REPO = 'mediasoup'; const task = process.argv.slice(2).join(' '); +// PYTHONPATH env must be updated now so all invoke calls below will find the +// pip invoke module. +if (process.env.PYTHONPATH) +{ + if (IS_WINDOWS) + { + process.env.PYTHONPATH = `${PIP_INVOKE_DIR};${process.env.PYTHONPATH}`; + } + else + { + process.env.PYTHONPATH = `${PIP_INVOKE_DIR}:${process.env.PYTHONPATH}`; + } +} +else +{ + process.env.PYTHONPATH = PIP_INVOKE_DIR; +} + run(); async function run() { switch (task) { + case 'preinstall': + { + installInvoke(); + + break; + } + // As per NPM documentation (https://docs.npmjs.com/cli/v9/using-npm/scripts) // `prepare` script: // @@ -142,7 +168,7 @@ async function run() case 'format:worker': { - executeCmd(`${MAKE} format -C worker`); + executeCmd(`"${PYTHON}" -m invoke -r worker format`); break; } @@ -185,20 +211,6 @@ async function run() break; } - case 'install-deps:node': - { - installNodeDeps(); - - break; - } - - case 'install-worker-dev-tools': - { - executeCmd('npm ci --prefix worker/scripts'); - - break; - } - case 'release:check': { checkRelease(); @@ -274,6 +286,42 @@ async function run() } } +function getPython() +{ + let python = process.env.PYTHON; + + if (!python) + { + try + { + execSync('python3 --version', { stdio: [ 'ignore', 'ignore', 'ignore' ] }); + python = 'python3'; + } + catch (error) + { + python = 'python'; + } + } + + return python; +} + +function installInvoke() +{ + if (fs.existsSync(PIP_INVOKE_DIR)) + { + return; + } + + logInfo('installInvoke()'); + + // Install pip invoke into custom location, so we don't depend on system-wide + // installation. + executeCmd( + `"${PYTHON}" -m pip install --upgrade --target="${PIP_INVOKE_DIR}" invoke==${INVOKE_VERSION}`, /* exitOnError */ true + ); +} + function deleteNodeLib() { if (!fs.existsSync('node/lib')) @@ -311,22 +359,7 @@ function buildWorker() { logInfo('buildWorker()'); - if (IS_WINDOWS) - { - if (!fs.existsSync('worker/out/msys/bin/make.exe')) - { - installMsysMake(); - } - - const msysPath = `${process.cwd()}\\worker\\out\\msys\\bin`; - - if (!process.env.PATH.includes(msysPath)) - { - process.env.PATH = `${msysPath};${process.env.PATH}`; - } - } - - executeCmd(`${MAKE} -C worker`); + executeCmd(`"${PYTHON}" -m invoke -r worker mediasoup-worker`); } function cleanWorkerArtifacts() @@ -334,19 +367,11 @@ function cleanWorkerArtifacts() logInfo('cleanWorkerArtifacts()'); // Clean build artifacts except `mediasoup-worker`. - executeCmd(`${MAKE} clean-build -C worker`); + executeCmd(`"${PYTHON}" -m invoke -r worker clean-build`); // Clean downloaded dependencies. - executeCmd(`${MAKE} clean-subprojects -C worker`); + executeCmd(`"${PYTHON}" -m invoke -r worker clean-subprojects`); // Clean PIP/Meson/Ninja. - executeCmd(`${MAKE} clean-pip -C worker`); - - if (IS_WINDOWS) - { - if (fs.existsSync('worker/out/msys')) - { - executeCmd('rd /s /q worker\\out\\msys'); - } - } + executeCmd(`"${PYTHON}" -m invoke -r worker clean-pip`); } function lintNode() @@ -360,7 +385,7 @@ function lintWorker() { logInfo('lintWorker()'); - executeCmd(`${MAKE} lint -C worker`); + executeCmd(`"${PYTHON}" -m invoke -r worker lint`); } function flatcNode() @@ -368,24 +393,24 @@ function flatcNode() logInfo('flatcNode()'); // Build flatc if needed. - executeCmd(`${MAKE} -C worker flatc`); + executeCmd(`"${PYTHON}" -m invoke -r worker flatc`); const buildType = process.env.MEDIASOUP_BUILDTYPE || 'Release'; const extension = IS_WINDOWS ? '.exe' : ''; const flatc = path.resolve(path.join( 'worker', 'out', buildType, 'build', 'subprojects', `flatbuffers-${FLATBUFFERS_VERSION}`, `flatc${extension}`)); - const src = path.resolve(path.join('worker', 'fbs', '*.fbs')); const out = path.resolve(path.join('node', 'src')); - const options = '--ts-no-import-ext --gen-object-api'; - const command = `${flatc} --ts ${options} -o ${out} `; - if (IS_WINDOWS) + for (const dirent of fs.readdirSync(path.join('worker', 'fbs'), { withFileTypes: true })) { - executeCmd(`for %f in (${src}) do ${command} %f`); - } - else - { - executeCmd(`for file in ${src}; do ${command} \$\{file\}; done`); + if (!dirent.isFile() || path.parse(dirent.name).ext !== '.fbs') + { + continue; + } + + const filePath = path.resolve(path.join('worker', 'fbs', dirent.name)); + + executeCmd(`"${flatc}" --ts --ts-no-import-ext --gen-object-api -o "${out}" "${filePath}"`); } } @@ -393,7 +418,7 @@ function flatcWorker() { logInfo('flatcWorker()'); - executeCmd(`${MAKE} -C worker flatc`); + executeCmd(`"${PYTHON}" -m invoke -r worker flatc`); } function testNode() @@ -406,7 +431,7 @@ function testNode() } else { - executeCmd(`jest --testPathPattern ${process.env.TEST_FILE}`); + executeCmd(`jest --testPathPattern "${process.env.TEST_FILE}"`); } } @@ -414,7 +439,7 @@ function testWorker() { logInfo('testWorker()'); - executeCmd(`${MAKE} test -C worker`); + executeCmd(`"${PYTHON}" -m invoke -r worker test`); } function installNodeDeps() @@ -441,42 +466,6 @@ function checkRelease() testWorker(); } -function installMsysMake() -{ - logInfo('installMsysMake()'); - - let pythonPath; - - // If PYTHON environment variable is given, use it. - if (process.env.PYTHON) - { - pythonPath = process.env.PYTHON; - } - // Otherwise ensure python3.exe is available in the PATH. - else - { - let res = spawnSync('where', [ 'python3.exe' ]); - - if (res.status !== 0) - { - res = spawnSync('where', [ 'python.exe' ]); - - if (res.status !== 0) - { - logError('`installMsysMake() | cannot find Python executable'); - - exitWithError(); - } - } - - pythonPath = String(res.stdout).trim(); - } - - const dir = path.resolve('worker/out/msys'); - - executeCmd(`${pythonPath} worker\\scripts\\getmake.py --dir="${dir}"`); -} - function ensureDir(dir) { logInfo(`ensureDir() [dir:${dir}]`); diff --git a/package.json b/package.json index 625cda38ed..c21cb41714 100644 --- a/package.json +++ b/package.json @@ -21,19 +21,20 @@ "types": "node/lib/index.d.ts", "files": [ "node/lib", - "worker/deps/libwebrtc", + "worker/src", + "worker/include", "worker/fbs", - "worker/fuzzer/include", + "worker/test/src", + "worker/test/include", "worker/fuzzer/src", - "worker/include", + "worker/fuzzer/include", "worker/scripts/*.mjs", "worker/scripts/*.json", "worker/scripts/*.py", "worker/scripts/*.sh", - "worker/src", "worker/subprojects/*.wrap", - "worker/test/include", - "worker/test/src", + "worker/deps/libwebrtc", + "worker/tasks.py", "worker/Makefile", "worker/meson.build", "worker/meson_options.txt", @@ -49,6 +50,7 @@ "nodejs" ], "scripts": { + "preinstall": "node npm-scripts.mjs preinstall", "prepare": "node npm-scripts.mjs prepare", "postinstall": "node npm-scripts.mjs postinstall", "typescript:build": "node npm-scripts.mjs typescript:build", @@ -66,8 +68,6 @@ "test:node": "node npm-scripts.mjs test:node", "test:worker": "node npm-scripts.mjs test:worker", "coverage:node": "node npm-scripts.mjs coverage:node", - "install-deps:node": "node npm-scripts.mjs install-deps:node", - "install-worker-dev-tools": "node npm-scripts.mjs install-worker-dev-tools", "release:check": "node npm-scripts.mjs release:check", "release": "node npm-scripts.mjs release", "release:upload-mac-arm-prebuilt-worker": "node npm-scripts.mjs release:upload-mac-arm-prebuilt-worker" diff --git a/worker/Dockerfile b/worker/Dockerfile index df9193063d..81f4294115 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -1,15 +1,12 @@ FROM ubuntu:22.04 # Install dependencies. -RUN \ - set -x \ +RUN set -x \ && apt-get update \ && apt-get install --yes \ - bash-completion wget curl subversion screen gcc g++ cmake ninja-build golang \ - autoconf libtool apache2 python3-pip python3-dev pkg-config zlib1g-dev \ - libgss-dev libssl-dev libxml2-dev nasm libarchive-dev make automake \ - libdbus-1-dev libboost-dev autoconf-archive bash-completion python3-yaml \ - clang + gcc g++ clang pkg-config bash-completion wget curl \ + screen python3-pip python3-yaml pkg-config zlib1g-dev \ + libgss-dev libssl-dev libxml2-dev # Install node 20. RUN set -x \ diff --git a/worker/Dockerfile.alpine b/worker/Dockerfile.alpine index 5ae43d88c1..d1b31a6062 100644 --- a/worker/Dockerfile.alpine +++ b/worker/Dockerfile.alpine @@ -1,11 +1,8 @@ FROM alpine # Install dependencies. -RUN \ - set -x \ - && apk add \ - nodejs-current npm python3 py3-pip \ - make gcc g++ +RUN set -x \ + && apk add gcc g++ nodejs-current npm python3 py3-pip # Make CC and CXX point to gcc/g++. ENV LANG="C.UTF-8" diff --git a/worker/Makefile b/worker/Makefile index 820bac829c..7a0492128c 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -1,72 +1,23 @@ # # make tasks for mediasoup-worker. # - -# We need Python 3 here. -PYTHON ?= $(shell command -v python3 2> /dev/null || echo python) -ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) -CORES ?= $(shell ${ROOT_DIR}/scripts/cpu_cores.sh || echo 4) -MEDIASOUP_OUT_DIR ?= $(shell pwd)/out -# Controls build types, `Release` and `Debug` are presets optimized for those -# use cases. Other build types are possible too, but they are not presets and -# will require `MESON_ARGS` use to customize build configuration. -# Check the meaning of useful macros in the `worker/include/Logger.hpp` header -# file if you want to enable tracing or other debug information. -MEDIASOUP_BUILDTYPE ?= Release -LCOV = ./deps/lcov/bin/lcov -DOCKER ?= docker -PIP_DIR = $(MEDIASOUP_OUT_DIR)/pip -INSTALL_DIR ?= $(MEDIASOUP_OUT_DIR)/$(MEDIASOUP_BUILDTYPE) -BUILD_DIR ?= $(INSTALL_DIR)/build -MESON ?= $(PIP_DIR)/bin/meson -MESON_VERSION ?= 1.2.1 -# `MESON_ARGS` can be used to provide extra configuration parameters to Meson, -# such as adding defines or changing optimization options. For instance, use -# `MESON_ARGS="-Dms_log_trace=true -Dms_log_file_line=true" npm i` to compile -# worker with tracing and enabled. +# NOTE: This Makefile is a proxy to pip invoke commands (see tasks.py). # -# NOTE: On Windows make sure to add `--vsenv` or have MSVS environment already -# active if you override this parameter. -MESON_ARGS ?= "" -# Workaround for NixOS and Guix that don't work with pre-built binaries, see: -# https://github.com/NixOS/nixpkgs/issues/142383. -PIP_BUILD_BINARIES = $(shell [ -f /etc/NIXOS -o -d /etc/guix ] && echo "--no-binary :all:") -# Let's use a specific version of ninja to avoid buggy version 1.11.1: -# https://mediasoup.discourse.group/t/partly-solved-could-not-detect-ninja-v1-8-2-or-newer/ -# https://github.com/ninja-build/ninja/issues/2211 -# https://github.com/ninja-build/ninja/issues/2212 -NINJA_VERSION ?= 1.10.2.4 -NPM ?= npm -# Disable `*.pyc` files creation. -export PYTHONDONTWRITEBYTECODE = 1 -# Instruct `meson` where to look for ninja binary. -ifeq ($(OS),Windows_NT) - # Windows is, of course, special. - export NINJA = $(PIP_DIR)/bin/ninja.exe -else - export NINJA = $(PIP_DIR)/bin/ninja -endif +PYTHON ?= $(shell command -v python3 2> /dev/null || echo python) +PIP_INVOKE_DIR = $(shell pwd)/pip_invoke +INVOKE_VERSION ?= 2.2.0 -# Instruct Python where to look for modules it needs, such that `meson` actually -# runs from installed location. -# -# NOTE: For some reason on Windows adding `:${PYTHONPATH}` breaks things. +# Instruct Python where to look for invoke module. ifeq ($(OS),Windows_NT) - export PYTHONPATH := $(PIP_DIR) + export PYTHONPATH := $(PIP_INVOKE_DIR);${PYTHONPATH} else - export PYTHONPATH := $(PIP_DIR):${PYTHONPATH} -endif - -# Activate VS environment on Windows by default. -ifeq ($(OS),Windows_NT) -ifeq ($(MESON_ARGS),"") - MESON_ARGS = $(subst $\",,"--vsenv") -endif + export PYTHONPATH := $(PIP_INVOKE_DIR):${PYTHONPATH} endif .PHONY: \ default \ + invoke \ meson-ninja \ setup \ clean \ @@ -93,196 +44,79 @@ endif default: mediasoup-worker -meson-ninja: -ifeq ($(wildcard $(PIP_DIR)),) - # Updated pip and setuptools are needed for meson. - # `--system` is not present everywhere and is only needed as workaround for - # Debian-specific issue (copied from https://github.com/gluster/gstatus/pull/33), - # fallback to command without `--system` if the first one fails. - $(PYTHON) -m pip install --system --target=$(PIP_DIR) pip setuptools || \ - $(PYTHON) -m pip install --target=$(PIP_DIR) pip setuptools || \ - (echo "update of pip or setuptools failed, likely because pip is not installed (if you are on Debian/Ubuntu or derivative please install the python3-pip package)" >&2) - - # Install `meson` and `ninja` using `pip` into custom location, so we don't - # depend on system-wide installation. - $(PYTHON) -m pip install --upgrade --target=$(PIP_DIR) $(PIP_BUILD_BINARIES) meson==$(MESON_VERSION) ninja==$(NINJA_VERSION) +invoke: +ifeq ($(wildcard $(PIP_INVOKE_DIR)),) + # Install pip invoke into custom location, so we don't depend on system-wide + # installation. + $(PYTHON) -m pip install --upgrade --target="$(PIP_INVOKE_DIR)" invoke==$(INVOKE_VERSION) endif -setup: meson-ninja -# We try to call `--reconfigure` first as a workaround for this issue: -# https://github.com/ninja-build/ninja/issues/1997 -ifeq ($(MEDIASOUP_BUILDTYPE),Release) - $(MESON) setup \ - --prefix $(INSTALL_DIR) \ - --bindir "" \ - --libdir "" \ - --buildtype release \ - -Db_ndebug=true \ - -Db_pie=true \ - -Db_staticpic=true \ - --reconfigure \ - $(MESON_ARGS) \ - $(BUILD_DIR) || \ - $(MESON) setup \ - --prefix $(INSTALL_DIR) \ - --bindir "" \ - --libdir "" \ - --buildtype release \ - -Db_ndebug=true \ - -Db_pie=true \ - -Db_staticpic=true \ - $(MESON_ARGS) \ - $(BUILD_DIR) -else -ifeq ($(MEDIASOUP_BUILDTYPE),Debug) - $(MESON) setup \ - --prefix $(INSTALL_DIR) \ - --bindir "" \ - --libdir "" \ - --buildtype debug \ - -Db_pie=true \ - -Db_staticpic=true \ - --reconfigure \ - $(MESON_ARGS) \ - $(BUILD_DIR) || \ - $(MESON) setup \ - --prefix $(INSTALL_DIR) \ - --bindir "" \ - --libdir "" \ - --buildtype debug \ - -Db_pie=true \ - -Db_staticpic=true \ - $(MESON_ARGS) \ - $(BUILD_DIR) -else - $(MESON) setup \ - --prefix $(INSTALL_DIR) \ - --bindir "" \ - --libdir "" \ - --buildtype $(MEDIASOUP_BUILDTYPE) \ - -Db_ndebug=if-release \ - -Db_pie=true \ - -Db_staticpic=true \ - --reconfigure \ - $(MESON_ARGS) \ - $(BUILD_DIR) || \ - $(MESON) setup \ - --prefix $(INSTALL_DIR) \ - --bindir "" \ - --libdir "" \ - --buildtype $(MEDIASOUP_BUILDTYPE) \ - -Db_ndebug=if-release \ - -Db_pie=true \ - -Db_staticpic=true \ - $(MESON_ARGS) \ - $(BUILD_DIR) -endif -endif +meson-ninja: invoke + $(PYTHON) -m invoke meson-ninja -clean: - $(RM) -rf $(INSTALL_DIR) +setup: invoke + $(PYTHON) -m invoke setup -clean-build: - $(RM) -rf $(BUILD_DIR) +clean: invoke + $(PYTHON) -m invoke clean -clean-pip: - $(RM) -rf $(PIP_DIR) +clean-build: invoke + $(PYTHON) -m invoke clean-build -clean-subprojects: meson-ninja - $(MESON) subprojects purge --include-cache --confirm +clean-pip: invoke + $(PYTHON) -m invoke clean-pip -# Clean subprojects (ignore if it fails) and delete out dir. -clean-all: - -$(MESON) subprojects purge --include-cache --confirm - $(RM) -rf $(MEDIASOUP_OUT_DIR) +clean-subprojects: invoke + $(PYTHON) -m invoke clean-subprojects -# Update the wrap file of a subproject. Usage example: -# make update-wrap-file SUBPROJECT=openssl -update-wrap-file: meson-ninja - $(MESON) subprojects update --reset $(SUBPROJECT) +clean-all: invoke + $(PYTHON) -m invoke clean-all -mediasoup-worker: setup flatc -ifeq ($(MEDIASOUP_WORKER_BIN),) - $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker - $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker -endif +# It requires the SUBPROJECT environment variable. +update-wrap-file: invoke + $(PYTHON) -m invoke subprojects $(SUBPROJECT) -libmediasoup-worker: setup flatc - $(MESON) compile -C $(BUILD_DIR) -j $(CORES) libmediasoup-worker - $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags libmediasoup-worker +mediasoup-worker: invoke + $(PYTHON) -m invoke mediasoup-worker -flatc: setup - $(MESON) compile -C $(BUILD_DIR) flatbuffers-generator +libmediasoup-worker: invoke + $(PYTHON) -m invoke libmediasoup-worker -xcode: setup flatc - $(MESON) setup --buildtype debug --backend xcode $(MEDIASOUP_OUT_DIR)/xcode +flatc: invoke + $(PYTHON) -m invoke flatc -lint: - $(NPM) run lint --prefix scripts/ +xcode: invoke + $(PYTHON) -m invoke xcode -format: - $(NPM) run format --prefix scripts/ +lint: invoke + $(PYTHON) -m invoke lint -test: setup flatc - $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test - $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-test -ifeq ($(OS),Windows_NT) - # On Windows lcov doesn't work (at least not yet) and we need to add `.exe` to - # the binary path. - $(BUILD_DIR)/mediasoup-worker-test.exe --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS) -else - $(LCOV) --directory ./ --zerocounters - $(BUILD_DIR)/mediasoup-worker-test --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS) -endif +format: invoke + $(PYTHON) -m invoke format -test-asan: setup flatc - $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test-asan - $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-test-asan - ASAN_OPTIONS=detect_leaks=1 $(BUILD_DIR)/mediasoup-worker-test-asan --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS) +test: invoke + $(PYTHON) -m invoke test -tidy: - $(PYTHON) ./scripts/clang-tidy.py \ - -clang-tidy-binary=./scripts/node_modules/.bin/clang-tidy \ - -clang-apply-replacements-binary=./scripts/node_modules/.bin/clang-apply-replacements \ - -header-filter="(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|handles/**/*.hpp)" \ - -p=$(BUILD_DIR) \ - -j=$(CORES) \ - -checks=$(MEDIASOUP_TIDY_CHECKS) \ - -quiet +test-asan: invoke + $(PYTHON) -m invoke test-asan -fuzzer: setup flatc - $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-fuzzer - $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-fuzzer +tidy: invoke + $(PYTHON) -m invoke tidy -fuzzer-run-all: - LSAN_OPTIONS=verbosity=1:log_threads=1 $(BUILD_DIR)/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus +fuzzer: invoke + $(PYTHON) -m invoke fuzzer -docker: -ifeq ($(DOCKER_NO_CACHE),true) - $(DOCKER) build -f Dockerfile --no-cache --tag mediasoup/docker:latest . -else - $(DOCKER) build -f Dockerfile --tag mediasoup/docker:latest . -endif +fuzzer-run-all: invoke + $(PYTHON) -m invoke fuzzer-run-all -docker-run: - $(DOCKER) run \ - --name=mediasoupDocker -it --rm \ - --privileged \ - --cap-add SYS_PTRACE \ - -v $(shell pwd)/../:/mediasoup \ - mediasoup/docker:latest +docker: invoke + $(PYTHON) -m invoke docker -docker-alpine: -ifeq ($(DOCKER_NO_CACHE),true) - $(DOCKER) build -f Dockerfile.alpine --no-cache --tag mediasoup/docker-alpine:latest . -else - $(DOCKER) build -f Dockerfile.alpine --tag mediasoup/docker-alpine:latest . -endif +docker-run: invoke + $(PYTHON) -m invoke docker-run + +docker-alpine: invoke + $(PYTHON) -m invoke docker-alpine -docker-alpine-run: - $(DOCKER) run \ - --name=mediasoupDockerAlpine -it --rm \ - --privileged \ - --cap-add SYS_PTRACE \ - -v $(shell pwd)/../:/mediasoup \ - mediasoup/docker-alpine:latest +docker-alpine-run: invoke + $(PYTHON) -m invoke docker-alpine-run diff --git a/worker/build.rs b/worker/build.rs index 8bf0b836fe..06d25c0ce6 100644 --- a/worker/build.rs +++ b/worker/build.rs @@ -7,8 +7,8 @@ fn main() { return; } - // On Windows Rust always links against release version of MSVC runtime, thus requires Release - // build here. + // On Windows Rust always links against release version of MSVC runtime, thus requires + // Release build here let build_type = if cfg!(all(debug_assertions, not(windows))) { "Debug" } else { @@ -45,15 +45,9 @@ fn main() { ) .expect("Failed to write generated Rust flatbuffers into fbs.rs"); - // Force forward slashes on Windows too so that is plays well with our dumb `Makefile`. + // Force forward slashes on Windows too so that is plays well with our tasks.py let mediasoup_out_dir = format!("{}/out", out_dir.replace('\\', "/")); - // Store original PATH so we make `make clean-all` use it. This is because, in Windows, - // we may need to fetch `make` and we store it in out/msys and then we add out/msys/bin - // to the PATH, and that folder may contain rm.exe, so `make clean-all` would use - // that rm.exe and delete itself and make the task fail. - let original_path = env::var("PATH").unwrap(); - // Add C++ std lib #[cfg(target_os = "linux")] { @@ -110,62 +104,49 @@ fn main() { println!("cargo:rustc-link-lib=dylib=c++"); println!("cargo:rustc-link-lib=dylib=c++abi"); } - #[cfg(target_os = "windows")] - { - if !std::path::Path::new("worker/out/msys/bin/make.exe").exists() { - let python = if let Ok(python) = env::var("PYTHON") { - python - } else if Command::new("where") - .arg("python3") - .status() - .expect("Failed to start") - .success() - { - "python3".to_string() - } else { - "python".to_string() - }; - - let dir = format!("{}/msys", mediasoup_out_dir.replace('\\', "/")); - - if !Command::new(python) - .arg("scripts\\getmake.py") - .arg("--dir") - .arg(dir.clone()) - .status() - .expect("Failed to start") - .success() - { - panic!("Failed to install MSYS/make") - } - - env::set_var( - "PATH", - format!("{}\\bin;{}", dir, env::var("PATH").unwrap()), - ); - } - env::set_var( - "PATH", - format!( - "{}\\worker\\out\\msys\\bin;{}", - env::current_dir() - .unwrap() - .into_os_string() - .into_string() - .unwrap(), - env::var("PATH").unwrap() - ), - ); + // Install Python invoke package in custom folder + let pip_invoke_dir = format!("{out_dir}/pip_invoke"); + let invoke_version = "2.2.0"; + let python = env::var("PYTHON").unwrap_or("python3".to_string()); + let mut pythonpath = if env::var("PYTHONPATH").is_ok() { + let original_pythonpath = env::var("PYTHONPATH").unwrap(); + format!("{pip_invoke_dir}:{original_pythonpath}") + } else { + pip_invoke_dir.clone() + }; + + // Force ";" in PYTHONPATH on Windows + if cfg!(target_os = "windows") { + pythonpath = pythonpath.replace(':', ";"); + } + + if !Command::new(&python) + .arg("-m") + .arg("pip") + .arg("install") + .arg("--upgrade") + .arg(format!("--target={pip_invoke_dir}")) + .arg(format!("invoke=={invoke_version}")) + .spawn() + .expect("Failed to start") + .wait() + .expect("Wasn't running") + .success() + { + panic!("Failed to install Python invoke package") } // Build - if !Command::new("make") + if !Command::new(&python) + .arg("-m") + .arg("invoke") .arg("libmediasoup-worker") + .env("PYTHONPATH", &pythonpath) .env("MEDIASOUP_OUT_DIR", &mediasoup_out_dir) .env("MEDIASOUP_BUILDTYPE", build_type) // Force forward slashes on Windows too, otherwise Meson thinks path is not absolute 🤷 - .env("INSTALL_DIR", &out_dir.replace('\\', "/")) + .env("MEDIASOUP_INSTALL_DIR", &out_dir.replace('\\', "/")) .spawn() .expect("Failed to start") .wait() @@ -205,9 +186,11 @@ fn main() { if env::var("KEEP_BUILD_ARTIFACTS") != Ok("1".to_string()) { // Clean - if !Command::new("make") + if !Command::new(python) + .arg("-m") + .arg("invoke") .arg("clean-all") - .env("PATH", original_path) + .env("PYTHONPATH", &pythonpath) .env("MEDIASOUP_OUT_DIR", &mediasoup_out_dir) .spawn() .expect("Failed to start") diff --git a/worker/scripts/clang-format.mjs b/worker/scripts/clang-format.mjs index a7a0f00f4d..13fbd0aaa9 100644 --- a/worker/scripts/clang-format.mjs +++ b/worker/scripts/clang-format.mjs @@ -25,7 +25,7 @@ async function run() case 'lint': { executeCmd( - `${clangFormatNativeBinary} --Werror --dry-run ${workerFiles.join(' ')}` + `"${clangFormatNativeBinary}" --Werror --dry-run ${workerFiles.join(' ')}` ); break; @@ -34,7 +34,7 @@ async function run() case 'format': { executeCmd( - `${clangFormatNativeBinary} --Werror -i ${workerFiles.join(' ')}` + `"${clangFormatNativeBinary}" --Werror -i ${workerFiles.join(' ')}` ); break; diff --git a/worker/scripts/cpu_cores.sh b/worker/scripts/cpu_cores.sh deleted file mode 100755 index b5cdde81d0..0000000000 --- a/worker/scripts/cpu_cores.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env sh - -set -e - -OS="$(uname -s)" -NUM_CORES= - -case "${OS}" in - Linux*) NUM_CORES=$(nproc);; - Darwin*|FreeBSD) NUM_CORES=$(sysctl -n hw.ncpu);; - MINGW*) NUM_CORES=$NUMBER_OF_PROCESSORS;; - *) NUM_CORES=1;; -esac - -if [ -n "${MEDIASOUP_MAX_CORES}" ]; then - NUM_CORES=$((MEDIASOUP_MAX_CORES>NUM_CORES ? NUM_CORES : MEDIASOUP_MAX_CORES)) -fi - -echo ${NUM_CORES} diff --git a/worker/scripts/get-dep.sh b/worker/scripts/get-dep.sh index d538ae8606..5d6fced81f 100755 --- a/worker/scripts/get-dep.sh +++ b/worker/scripts/get-dep.sh @@ -7,7 +7,7 @@ DEP=$1 current_dir_name=${WORKER_PWD##*/} if [ "${current_dir_name}" != "worker" ] ; then - echo ">>> [ERROR] $(basename $0) must be called from mediasoup/worker/ directory" >&2 + echo ">>> [ERROR] $(basename $0) must be called from mediasoup/worker directory" >&2 exit 1 fi diff --git a/worker/scripts/getmake.py b/worker/scripts/getmake.py deleted file mode 100644 index 50ec9ea7f1..0000000000 --- a/worker/scripts/getmake.py +++ /dev/null @@ -1,28 +0,0 @@ -import argparse, io, hashlib, tarfile, urllib.request - -argParser = argparse.ArgumentParser() - -argParser.add_argument( - '--dir', - type=str, - required=True, - help='absolute path of the directoy in which fetched content will be placed' -) - -args = argParser.parse_args() - -def get(url, digest): - data = urllib.request.urlopen(url).read() - assert hashlib.sha256(data).hexdigest() == digest - tar = tarfile.open(fileobj=io.BytesIO(data)) - tar.extractall(args.dir) - tar.close() - -get('https://sourceforge.net/projects/mingw/files/MSYS/Base/msys-core/msys-1.0.19-1/msysCORE-1.0.19-1-msys-1.0.19-bin.tar.xz/download', '8c4157d739a460f85563bc4451e9f1bbd42b13c4f63770d43b9f45a781f07858') -get('https://sourceforge.net/projects/mingw/files/MSYS/Base/libiconv/libiconv-1.14-1/libiconv-1.14-1-msys-1.0.17-dll-2.tar.lzma/download', '196921e8c232259c8e6a6852b9ee8d9ab2d29a91419f0c8dc27ba6f034231683') -get('https://sourceforge.net/projects/mingw/files/MSYS/Base/gettext/gettext-0.18.1.1-1/libintl-0.18.1.1-1-msys-1.0.17-dll-8.tar.lzma/download', '29db8c969661c511fbe2a341ab25c993c5f9c555842a75d6ddbcfa70dec16910') -get('https://sourceforge.net/projects/mingw/files/MSYS/Base/coreutils/coreutils-5.97-3/coreutils-5.97-3-msys-1.0.13-bin.tar.lzma/download', 'f8c7990416ea16a74ac336dcfe0f596bc46b8724b2d58cf8a3509414220b2366') -get('https://sourceforge.net/projects/mingw/files/MSYS/Base/regex/regex-1.20090805-2/libregex-1.20090805-2-msys-1.0.13-dll-1.tar.lzma/download', '85dd8c1e27a90675c5f867be57ba7ae2bb55dde8cd2d19f284c896be134bd3d1') -get('https://sourceforge.net/projects/mingw/files/MSYS/Base/termcap/termcap-0.20050421_1-2/libtermcap-0.20050421_1-2-msys-1.0.13-dll-0.tar.lzma/download', '62b58fe0880f0972fcc84a819265989b02439c1c5185870227bd25f870f7adb6') -get('https://sourceforge.net/projects/mingw/files/MSYS/Base/bash/bash-3.1.23-1/bash-3.1.23-1-msys-1.0.18-bin.tar.xz/download', '38da5419969ab883058a96322bb0f51434dd4e9f71de09cd4f75b96750944533') -get('https://sourceforge.net/projects/mingw/files/MSYS/Base/make/make-3.81-3/make-3.81-3-msys-1.0.13-bin.tar.lzma/download', '847f0cbbf07135801c8e67bf692d29b1821e816ad828753c997fa869a9b89988') diff --git a/worker/tasks.py b/worker/tasks.py new file mode 100644 index 0000000000..6e471b2989 --- /dev/null +++ b/worker/tasks.py @@ -0,0 +1,602 @@ +# Ignore these pylint warnings, concentions and refactoring messages: +# - W0301: Unnecessary semicolon (unnecessary-semicolon) +# - W0622: Redefining built-in 'format' (redefined-builtin) +# - W0702: No exception type(s) specified (bare-except) +# - C0114: Missing module docstring (missing-module-docstring) +# - C0301: Line too long (line-too-long) +# +# pylint: disable=W0301,W0622,W0702,C0114,C0301 + +# +# This is a tasks.py file for the pip invoke package: https://docs.pyinvoke.org/. +# +# It's a replacement of our Makefile with same tasks. +# +# Usage: +# invoke --list +# + +import sys; +import os; +import inspect; +import shutil; +# We import this from a custom location and pylint doesn't know. +from invoke import task; # pylint: disable=import-error + +MEDIASOUP_BUILDTYPE = os.getenv('MEDIASOUP_BUILDTYPE') or 'Release'; +WORKER_DIR = os.path.dirname(os.path.abspath( + inspect.getframeinfo(inspect.currentframe()).filename +)); +# NOTE: MEDIASOUP_OUT_DIR is overrided by build.rs. +MEDIASOUP_OUT_DIR = os.getenv('MEDIASOUP_OUT_DIR') or f'{WORKER_DIR}/out'; +MEDIASOUP_INSTALL_DIR = os.getenv('MEDIASOUP_INSTALL_DIR') or f'{MEDIASOUP_OUT_DIR}/{MEDIASOUP_BUILDTYPE}'; +BUILD_DIR = os.getenv('BUILD_DIR') or f'{MEDIASOUP_INSTALL_DIR}/build'; +# Custom pip folder for invoke package. +PIP_INVOKE_DIR = f'{MEDIASOUP_OUT_DIR}/pip_invoke'; +# Custom pip folder for meson and ninja packages. +PIP_MESON_NINJA_DIR = f'{MEDIASOUP_OUT_DIR}/pip_meson_ninja'; +# Custom pip folder for pylint package. +# NOTE: We do this because using --target and --upgrade in `pip install` is not +# supported and a latter invokation entirely replaces the bin folder. +PIP_PYLINT_DIR = f'{MEDIASOUP_OUT_DIR}/pip_pylint'; +# If available (only on some *nix systems), os.sched_getaffinity(0) gets set of +# CPUs the calling thread is restricted to. Instead, os.cpu_count() returns the +# total number of CPUs in a system (it doesn't take into account how many of them +# the calling thread can use). +NUM_CORES = len(os.sched_getaffinity(0)) if hasattr(os, 'sched_getaffinity') else os.cpu_count(); +PYTHON = os.getenv('PYTHON') or sys.executable; +MESON = os.getenv('MESON') or f'{PIP_MESON_NINJA_DIR}/bin/meson'; +MESON_VERSION = os.getenv('MESON_VERSION') or '1.2.1'; +# MESON_ARGS can be used to provide extra configuration parameters to meson, +# such as adding defines or changing optimization options. For instance, use +# `MESON_ARGS="-Dms_log_trace=true -Dms_log_file_line=true" npm i` to compile +# worker with tracing and enabled. +# NOTE: On Windows make sure to add `--vsenv` or have MSVS environment already +# active if you override this parameter. +MESON_ARGS = os.getenv('MESON_ARGS') if os.getenv('MESON_ARGS') else '--vsenv' if os.name == 'nt' else ''; +# Let's use a specific version of ninja to avoid buggy version 1.11.1: +# https://mediasoup.discourse.group/t/partly-solved-could-not-detect-ninja-v1-8-2-or-newer/ +# https://github.com/ninja-build/ninja/issues/2211 +# https://github.com/ninja-build/ninja/issues/2212 +NINJA_VERSION = os.getenv('NINJA_VERSION') or '1.10.2.4'; +PYLINT_VERSION = os.getenv('PYLINT_VERSION') or '3.0.2'; +NPM = os.getenv('NPM') or 'npm'; +LCOV = f'{WORKER_DIR}/deps/lcov/bin/lcov'; +DOCKER = os.getenv('DOCKER') or 'docker'; +# pty=True in ctx.run() is not available on Windows so if stdout is not a TTY +# let's assume PTY is not supported. Related issue in invoke project: +# https://github.com/pyinvoke/invoke/issues/561 +PTY_SUPPORTED = sys.stdout.isatty(); +# Use sh (widely supported, more than bash) if not in Windows. +SHELL = '/bin/sh' if not os.name == 'nt' else None; + +# Disable `*.pyc` files creation. +os.environ['PYTHONDONTWRITEBYTECODE'] = 'true'; + +# Instruct meson where to look for ninja binary. +if os.name == 'nt': + # Windows is, of course, special. + os.environ['NINJA'] = f'{PIP_MESON_NINJA_DIR}/bin/ninja.exe'; +else: + os.environ['NINJA'] = f'{PIP_MESON_NINJA_DIR}/bin/ninja'; + +# Instruct Python where to look for modules it needs, such that meson actually +# runs from installed location. +# NOTE: On Windows we must use ; instead of : to separate paths. +PYTHONPATH = os.getenv('PYTHONPATH') or ''; +if os.name == 'nt': + os.environ['PYTHONPATH'] = f'{PIP_INVOKE_DIR};{PIP_MESON_NINJA_DIR};{PIP_PYLINT_DIR};{PYTHONPATH}'; +else: + os.environ['PYTHONPATH'] = f'{PIP_INVOKE_DIR}:{PIP_MESON_NINJA_DIR}:{PIP_PYLINT_DIR}:{PYTHONPATH}'; + + +@task +def meson_ninja(ctx): + """ + Install meson and ninja (also update Python pip and setuptools packages) + """ + if os.path.isfile(MESON): + return; + + # Updated pip and setuptools are needed for meson. + # `--system` is not present everywhere and is only needed as workaround for + # Debian-specific issue (copied from https://github.com/gluster/gstatus/pull/33), + # fallback to command without `--system` if the first one fails. + try: + ctx.run( + f'"{PYTHON}" -m pip install --system --upgrade --target="{PIP_MESON_NINJA_DIR}" pip setuptools', + echo=True, + hide=True, + shell=SHELL + ); + except: + ctx.run( + f'"{PYTHON}" -m pip install --upgrade --target="{PIP_MESON_NINJA_DIR}" pip setuptools', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + # Workaround for NixOS and Guix that don't work with pre-built binaries, see: + # https://github.com/NixOS/nixpkgs/issues/142383. + pip_build_binaries = '--no-binary :all:' if os.path.isfile('/etc/NIXOS') or os.path.isdir('/etc/guix') else ''; + + # Install meson and ninja using pip into our custom location, so we don't + # depend on system-wide installation. + ctx.run( + f'"{PYTHON}" -m pip install --upgrade --target="{PIP_MESON_NINJA_DIR}" {pip_build_binaries} meson=={MESON_VERSION} ninja=={NINJA_VERSION}', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[meson_ninja]) +def setup(ctx): + """ + Run meson setup + """ + # We add --reconfigure first as a workaround for this issue: + # https://github.com/ninja-build/ninja/issues/1997 + if MEDIASOUP_BUILDTYPE == 'Release': + try: + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true -Db_pie=true -Db_staticpic=true --reconfigure {MESON_ARGS} "{BUILD_DIR}"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + except: + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + elif MEDIASOUP_BUILDTYPE == 'Debug': + try: + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug -Db_pie=true -Db_staticpic=true --reconfigure {MESON_ARGS} "{BUILD_DIR}"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + except: + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + else: + try: + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release -Db_pie=true -Db_staticpic=true --reconfigure {MESON_ARGS} "{BUILD_DIR}"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + except: + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task +def clean(ctx): # pylint: disable=unused-argument + """ + Clean the installation directory + """ + try: + shutil.rmtree(MEDIASOUP_INSTALL_DIR); + except: + pass; + + +@task +def clean_build(ctx): # pylint: disable=unused-argument + """ + Clean the build directory + """ + try: + shutil.rmtree(BUILD_DIR); + except: + pass; + + +@task +def clean_pip(ctx): # pylint: disable=unused-argument + """ + Clean the local pip setup + """ + try: + shutil.rmtree(PIP_MESON_NINJA_DIR); + except: + pass; + + try: + shutil.rmtree(PIP_PYLINT_DIR); + except: + pass; + + +@task(pre=[meson_ninja]) +def clean_subprojects(ctx): + """ + Clean meson subprojects + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" subprojects purge --include-cache --confirm', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task +def clean_all(ctx): + """ + Clean meson subprojects and all installed/built artificats + """ + with ctx.cd(WORKER_DIR): + try: + ctx.run( + f'"{MESON}" subprojects purge --include-cache --confirm', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + except: + pass; + + try: + shutil.rmtree(MEDIASOUP_OUT_DIR); + except: + pass; + + +@task(pre=[meson_ninja]) +def update_wrap_file(ctx, subproject): + """ + Update the wrap file of a subproject + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" subprojects update --reset {subproject}', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[setup]) +def flatc(ctx): + """ + Compile FlatBuffers FBS files + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" compile -C "{BUILD_DIR}" flatbuffers-generator', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[setup, flatc], default=True) +def mediasoup_worker(ctx): + """ + Compile mediasoup-worker binary + """ + if os.getenv('MEDIASOUP_WORKER_BIN'): + print('skipping mediasoup-worker compilation due to the existence of the MEDIASOUP_WORKER_BIN environment variable'); + return; + + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[setup, flatc]) +def libmediasoup_worker(ctx): + """ + Compile libmediasoup-worker library + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} libmediasoup-worker', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags libmediasoup-worker', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[setup, flatc]) +def xcode(ctx): + """ + Setup Xcode project + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --buildtype {MEDIASOUP_BUILDTYPE} --backend xcode "{MEDIASOUP_OUT_DIR}/xcode"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task +def lint(ctx): + """ + Lint source code + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{NPM}" run lint --prefix scripts/', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + if not os.path.isdir(PIP_PYLINT_DIR): + # Install pylint using pip into our custom location. + ctx.run( + f'"{PYTHON}" -m pip install --upgrade --target="{PIP_PYLINT_DIR}" pylint=={PYLINT_VERSION}', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{PYTHON}" -m pylint tasks.py', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task +def format(ctx): + """ + Format source code according to lint rules + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{NPM}" run format --prefix scripts/', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[setup, flatc]) +def test(ctx): + """ + Run worker tests + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or ''; + + # On Windows lcov doesn't work (at least not yet) and we need to add .exe to + # the binary path. + if os.name == 'nt': + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{BUILD_DIR}/mediasoup-worker-test.exe" --invisibles --use-colour=yes {mediasoup_test_tags}', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + else: + ctx.run( + f'"{LCOV}" --directory "{WORKER_DIR}" --zerocounters', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{BUILD_DIR}/mediasoup-worker-test" --invisibles --use-colour=yes {mediasoup_test_tags}', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[setup, flatc]) +def test_asan(ctx): + """ + Run worker test with Address Sanitizer + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test-asan', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test-asan', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or ''; + + with ctx.cd(WORKER_DIR): + ctx.run( + f'ASAN_OPTIONS=detect_leaks=1 "{BUILD_DIR}/mediasoup-worker-test-asan" --invisibles --use-colour=yes {mediasoup_test_tags}', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task +def tidy(ctx): + """ + Perform C++ checks with clang-tidy + """ + mediasoup_tidy_checks = os.getenv('MEDIASOUP_TIDY_CHECKS') or ''; + + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{PYTHON}" ./scripts/clang-tidy.py -clang-tidy-binary=./scripts/node_modules/.bin/clang-tidy -clang-apply-replacements-binary=./scripts/node_modules/.bin/clang-apply-replacements -header-filter="(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|handles/**/*.hpp)" -p="{BUILD_DIR}" -j={NUM_CORES} -checks={mediasoup_tidy_checks} -quiet', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[setup, flatc]) +def fuzzer(ctx): + """ + Build the mediasoup-worker-fuzzer binary (which uses libFuzzer) + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-fuzzer', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-fuzzer', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task +def fuzzer_run_all(ctx): + """ + Run all fuzzer cases + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'LSAN_OPTIONS=verbosity=1:log_threads=1 "{BUILD_DIR}/mediasoup-worker-fuzzer" -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task +def docker(ctx): + """ + Build a Linux Ubuntu Docker image with fuzzer capable clang++ + """ + if os.getenv('DOCKER_NO_CACHE') == 'true': + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{DOCKER}" build -f Dockerfile --no-cache --tag mediasoup/docker:latest .', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + else: + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{DOCKER}" build -f Dockerfile --tag mediasoup/docker:latest .', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task +def docker_run(ctx): + """ + Run a container of the Ubuntu Docker image created in the docker task + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{DOCKER}" run --name=mediasoupDocker -it --rm --privileged --cap-add SYS_PTRACE -v "{WORKER_DIR}/../:/mediasoup" mediasoup/docker:latest', + echo=True, + pty=True, # NOTE: Needed to enter the terminal of the Docker image. + shell=SHELL + ); + + +@task +def docker_alpine(ctx): + """ + Build a Linux Alpine Docker image + """ + if os.getenv('DOCKER_NO_CACHE') == 'true': + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{DOCKER}" build -f Dockerfile.alpine --no-cache --tag mediasoup/docker-alpine:latest .', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + else: + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{DOCKER}" build -f Dockerfile.alpine --tag mediasoup/docker-alpine:latest .', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task +def docker_alpine_run(ctx): + """ + Run a container of the Alpine Docker image created in the docker_alpine task + """ + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{DOCKER}" run --name=mediasoupDockerAlpine -it --rm --privileged --cap-add SYS_PTRACE -v "{WORKER_DIR}/../:/mediasoup" mediasoup/docker-alpine:latest', + echo=True, + pty=True, # NOTE: Needed to enter the terminal of the Docker image. + shell=SHELL + ); From f296e9fae73845067b2c5c7425034c7aab053c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 27 Nov 2023 13:35:16 +0100 Subject: [PATCH 217/525] 3.13.6 --- CHANGELOG.md | 2 +- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59b0bfeb9a..0b477dbc29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.13.6 * Replace make + Makefile with Python Invoke library + tasks.py (also fix installation under path with whitespaces) ([PR #1239](https://github.com/versatica/mediasoup/pull/1239)). diff --git a/package-lock.json b/package-lock.json index 395649a599..87f054cd61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.5", + "version": "3.13.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.5", + "version": "3.13.6", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -21,7 +21,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.10", - "@types/node": "^20.9.4", + "@types/node": "^20.10.0", "@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/parser": "^6.12.0", "eslint": "^8.54.0", @@ -1619,9 +1619,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.9.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.4.tgz", - "integrity": "sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==", + "version": "20.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", + "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -8006,9 +8006,9 @@ "dev": true }, "@types/node": { - "version": "20.9.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.4.tgz", - "integrity": "sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==", + "version": "20.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", + "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", "dev": true, "requires": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index c21cb41714..0fa0bf1c9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.5", + "version": "3.13.6", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -106,7 +106,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.10", - "@types/node": "^20.9.4", + "@types/node": "^20.10.0", "@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/parser": "^6.12.0", "eslint": "^8.54.0", From 6821b55c30a1bf7ba203762bb8f09963778b0f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 27 Nov 2023 17:18:12 +0100 Subject: [PATCH 218/525] liburing (#1218) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable liburing usage for linux (kernel versions >= 6). Use liburing to relay incoming RTP to Consumers. This greately reduces the number of system calls as just a single system call is needed to relay the incoming RTP packet to "every" Consumer, opposite to libuv which requires a system call to relay the RTP packet to "each" Consumer. For efficiency, memory buffers are preallocated holding the data payload being sent. --------- Co-authored-by: Iñaki Baz Castillo --- CHANGELOG.md | 5 + node/src/Worker.ts | 20 +- node/src/tests/test-Router.ts | 2 +- node/src/tests/test-WebRtcServer.ts | 6 +- node/src/tests/test-Worker.ts | 2 +- rust/src/messages.rs | 7 +- rust/src/worker.rs | 9 + worker/fbs/liburing.fbs | 8 + worker/fbs/meson.build | 1 + worker/fbs/worker.fbs | 2 + worker/include/DepLibUring.hpp | 104 ++++ .../include/handles/TcpConnectionHandle.hpp | 4 + worker/include/handles/UdpSocketHandle.hpp | 4 + worker/meson.build | 22 + worker/src/DepLibUring.cpp | 449 ++++++++++++++++++ worker/src/RTC/Router.cpp | 13 + worker/src/RTC/RtpStreamSend.cpp | 13 + worker/src/RTC/Transport.cpp | 15 +- worker/src/Worker.cpp | 24 +- worker/src/handles/TcpConnectionHandle.cpp | 36 ++ worker/src/handles/UdpSocketHandle.cpp | 36 ++ worker/src/lib.cpp | 9 + worker/subprojects/liburing.wrap | 13 + 23 files changed, 795 insertions(+), 9 deletions(-) create mode 100644 worker/fbs/liburing.fbs create mode 100644 worker/include/DepLibUring.hpp create mode 100644 worker/src/DepLibUring.cpp create mode 100644 worker/subprojects/liburing.wrap diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b477dbc29..b97dda435f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* Enable `liburing` usage for Linux (kernel versions >= 6) ([PR #1218](https://github.com/versatica/mediasoup/pull/1218)). + + ### 3.13.6 * Replace make + Makefile with Python Invoke library + tasks.py (also fix installation under path with whitespaces) ([PR #1239](https://github.com/versatica/mediasoup/pull/1239)). diff --git a/node/src/Worker.ts b/node/src/Worker.ts index a7af360bfb..62c7c5334e 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -192,6 +192,12 @@ export type WorkerDump = channelRequestHandlers : string[]; channelNotificationHandlers : string[]; }; + liburing? : + { + sqeProcessCount: number; + sqeMissCount: number; + userDataMissCount: number; + }; }; export type WorkerEvents = @@ -814,7 +820,7 @@ export function parseWorkerDumpResponse( binary: FbsWorker.DumpResponse ): WorkerDump { - return { + const dump: WorkerDump = { pid : binary.pid()!, webRtcServerIds : parseVector(binary, 'webRtcServerIds'), routerIds : parseVector(binary, 'routerIds'), @@ -824,4 +830,16 @@ export function parseWorkerDumpResponse( channelNotificationHandlers : parseVector(binary.channelMessageHandlers()!, 'channelNotificationHandlers') } }; + + if (binary.liburing()) + { + dump.liburing = + { + sqeProcessCount : Number(binary.liburing()!.sqeProcessCount()), + sqeMissCount : Number(binary.liburing()!.sqeMissCount()), + userDataMissCount : Number(binary.liburing()!.userDataMissCount()) + }; + } + + return dump; } diff --git a/node/src/tests/test-Router.ts b/node/src/tests/test-Router.ts index d639115d57..d6147cf55f 100644 --- a/node/src/tests/test-Router.ts +++ b/node/src/tests/test-Router.ts @@ -65,7 +65,7 @@ test('worker.createRouter() succeeds', async () => await expect(worker.dump()) .resolves - .toEqual( + .toMatchObject( { pid : worker.pid, webRtcServerIds : [], diff --git a/node/src/tests/test-WebRtcServer.ts b/node/src/tests/test-WebRtcServer.ts index db5a6b2f2f..24b7ca0688 100644 --- a/node/src/tests/test-WebRtcServer.ts +++ b/node/src/tests/test-WebRtcServer.ts @@ -46,7 +46,7 @@ test('worker.createWebRtcServer() succeeds', async () => await expect(worker.dump()) .resolves - .toEqual( + .toMatchObject( { pid : worker.pid, webRtcServerIds : [ webRtcServer.id ], @@ -120,7 +120,7 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => await expect(worker.dump()) .resolves - .toEqual( + .toMatchObject( { pid : worker.pid, webRtcServerIds : [ webRtcServer.id ], @@ -565,7 +565,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer await expect(worker.dump()) .resolves - .toEqual( + .toMatchObject( { pid : worker.pid, webRtcServerIds : [], diff --git a/node/src/tests/test-Worker.ts b/node/src/tests/test-Worker.ts index 65dd889f18..47cdfed464 100644 --- a/node/src/tests/test-Worker.ts +++ b/node/src/tests/test-Worker.ts @@ -135,7 +135,7 @@ test('worker.dump() succeeds', async () => await expect(worker.dump()) .resolves - .toEqual( + .toMatchObject( { pid : worker.pid, webRtcServerIds : [], diff --git a/rust/src/messages.rs b/rust/src/messages.rs index 1d38d9d9f8..e92b8521ac 100644 --- a/rust/src/messages.rs +++ b/rust/src/messages.rs @@ -29,7 +29,7 @@ use crate::webrtc_server::{ use crate::webrtc_transport::{ WebRtcTransportListen, WebRtcTransportListenInfos, WebRtcTransportOptions, }; -use crate::worker::{ChannelMessageHandlers, WorkerDump, WorkerUpdateSettings}; +use crate::worker::{ChannelMessageHandlers, LibUringDump, WorkerDump, WorkerUpdateSettings}; use mediasoup_sys::fbs::{ active_speaker_observer, audio_level_observer, consumer, data_consumer, data_producer, direct_transport, message, notification, pipe_transport, plain_transport, producer, request, @@ -165,6 +165,11 @@ impl Request for WorkerDumpRequest { .map(|id| id.parse()) .collect::>()?, }, + liburing: data.liburing.map(|liburing| LibUringDump { + sqe_process_count: liburing.sqe_process_count, + sqe_miss_count: liburing.sqe_miss_count, + user_data_miss_count: liburing.user_data_miss_count, + }), }) } } diff --git a/rust/src/worker.rs b/rust/src/worker.rs index 56766bec13..632cb08750 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -278,6 +278,14 @@ pub struct ChannelMessageHandlers { pub channel_notification_handlers: Vec, } +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] +#[doc(hidden)] +pub struct LibUringDump { + pub sqe_process_count: u64, + pub sqe_miss_count: u64, + pub user_data_miss_count: u64, +} + #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] #[doc(hidden)] @@ -288,6 +296,7 @@ pub struct WorkerDump { #[serde(rename = "webRtcServerIds")] pub webrtc_server_ids: Vec, pub channel_message_handlers: ChannelMessageHandlers, + pub liburing: Option, } /// Error that caused [`Worker::create_webrtc_server`] to fail. diff --git a/worker/fbs/liburing.fbs b/worker/fbs/liburing.fbs new file mode 100644 index 0000000000..68ce1ae074 --- /dev/null +++ b/worker/fbs/liburing.fbs @@ -0,0 +1,8 @@ +namespace FBS.LibUring; + +table Dump { + sqe_process_count: uint64; + sqe_miss_count: uint64; + user_data_miss_count: uint64; +} + diff --git a/worker/fbs/meson.build b/worker/fbs/meson.build index 6ef2c022d6..8288279ff3 100644 --- a/worker/fbs/meson.build +++ b/worker/fbs/meson.build @@ -6,6 +6,7 @@ flatbuffers_schemas = [ 'dataConsumer.fbs', 'dataProducer.fbs', 'directTransport.fbs', + 'liburing.fbs', 'log.fbs', 'message.fbs', 'notification.fbs', diff --git a/worker/fbs/worker.fbs b/worker/fbs/worker.fbs index 392598a732..2dc7702b15 100644 --- a/worker/fbs/worker.fbs +++ b/worker/fbs/worker.fbs @@ -1,3 +1,4 @@ +include "liburing.fbs"; include "transport.fbs"; namespace FBS.Worker; @@ -12,6 +13,7 @@ table DumpResponse { web_rtc_server_ids: [string] (required); router_ids: [string] (required); channel_message_handlers: ChannelMessageHandlers (required); + liburing: FBS.LibUring.Dump; } table ResourceUsageResponse { diff --git a/worker/include/DepLibUring.hpp b/worker/include/DepLibUring.hpp new file mode 100644 index 0000000000..5c2481736c --- /dev/null +++ b/worker/include/DepLibUring.hpp @@ -0,0 +1,104 @@ +#ifndef MS_DEP_LIBURING_HPP +#define MS_DEP_LIBURING_HPP + +#include "DepLibUV.hpp" +#include "FBS/liburing.h" +#include +#include +#include + +class DepLibUring +{ +public: + using onSendCallback = const std::function; + + /* Struct for the user data field of SQE and CQE. */ + struct UserData + { + uint8_t store[1500]{}; + onSendCallback* cb{ nullptr }; + size_t idx{ 0 }; + }; + + /* Number of submission queue entries (SQE). */ + static constexpr size_t QueueDepth{ 1024 * 4 }; + + static bool IsRuntimeSupported(); + static void ClassInit(); + static void ClassDestroy(); + static flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder); + static void StartPollingCQEs(); + static void StopPollingCQEs(); + static bool PrepareSend( + int sockfd, const void* data, size_t len, const struct sockaddr* addr, onSendCallback* cb); + static bool PrepareWrite( + int sockfd, const void* data1, size_t len1, const void* data2, size_t len2, onSendCallback* cb); + static void Submit(); + static void SetActive(); + static bool IsActive(); + + class LibUring; + + thread_local static LibUring* liburing; + +public: + class LibUring + { + public: + LibUring(); + ~LibUring(); + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; + void StartPollingCQEs(); + void StopPollingCQEs(); + bool PrepareSend( + int sockfd, const void* data, size_t len, const struct sockaddr* addr, onSendCallback* cb); + bool PrepareWrite( + int sockfd, const void* data1, size_t len1, const void* data2, size_t len2, onSendCallback* cb); + void Submit(); + void SetActive() + { + this->active = true; + } + bool IsActive() const + { + return this->active; + } + io_uring* GetRing() + { + return std::addressof(this->ring); + } + int GetEventFd() const + { + return this->efd; + } + void ReleaseUserDataEntry(size_t idx) + { + this->availableUserDataEntries.push(idx); + } + + private: + UserData* GetUserData(); + + private: + // io_uring instance. + io_uring ring; + // Event file descriptor to watch for completions. + int efd; + // libuv handle used to poll io_uring completions. + uv_poll_t* uvHandle{ nullptr }; + // Whether we are currently sending RTP over io_uring. + bool active{ false }; + // Pre-allocated UserData entries. + UserData userDataBuffer[QueueDepth]{}; + // Indexes of available UserData entries. + std::queue availableUserDataEntries; + // Submission queue entry process count. + uint64_t sqeProcessCount{ 0u }; + // Submission queue entry miss count. + uint64_t sqeMissCount{ 0u }; + // User data miss count. + uint64_t userDataMissCount{ 0u }; + }; +}; + +#endif diff --git a/worker/include/handles/TcpConnectionHandle.hpp b/worker/include/handles/TcpConnectionHandle.hpp index fd5b8c291d..4fff59319a 100644 --- a/worker/include/handles/TcpConnectionHandle.hpp +++ b/worker/include/handles/TcpConnectionHandle.hpp @@ -143,6 +143,10 @@ class TcpConnectionHandle uv_tcp_t* uvHandle{ nullptr }; // Others. struct sockaddr_storage* localAddr{ nullptr }; +#ifdef MS_LIBURING_SUPPORTED + // Local file descriptor for io_uring. + uv_os_fd_t fd{ 0u }; +#endif bool closed{ false }; size_t recvBytes{ 0u }; size_t sentBytes{ 0u }; diff --git a/worker/include/handles/UdpSocketHandle.hpp b/worker/include/handles/UdpSocketHandle.hpp index 486ed5bebf..37ed5fd5dc 100644 --- a/worker/include/handles/UdpSocketHandle.hpp +++ b/worker/include/handles/UdpSocketHandle.hpp @@ -103,6 +103,10 @@ class UdpSocketHandle // Allocated by this (may be passed by argument). uv_udp_t* uvHandle{ nullptr }; // Others. +#ifdef MS_LIBURING_SUPPORTED + // Local file descriptor for io_uring. + uv_os_fd_t fd{ 0u }; +#endif bool closed{ false }; size_t recvBytes{ 0u }; size_t sentBytes{ 0u }; diff --git a/worker/meson.build b/worker/meson.build index 52c2244af4..3092e41838 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -257,6 +257,28 @@ if host_machine.system() == 'windows' ] endif +if host_machine.system() == 'linux' + kernel_version = run_command('uname', '-r').stdout().strip() + + # Enable liburing for kernel versions greather than or equal to 6. + if kernel_version[0].to_int() >= 6 + liburing_proj = subproject('liburing', default_options: ['default_library=static'], required: true) + + dependencies += [ + liburing_proj.get_variable('uring'), + ] + link_whole += [ + liburing_proj.get_variable('liburing') + ] + common_sources += [ + 'src/DepLibUring.cpp', + ] + cpp_args += [ + '-DMS_LIBURING_SUPPORTED', + ] + endif +endif + libmediasoup_worker = library( 'libmediasoup-worker', name_prefix: '', diff --git a/worker/src/DepLibUring.cpp b/worker/src/DepLibUring.cpp new file mode 100644 index 0000000000..627da3ecf0 --- /dev/null +++ b/worker/src/DepLibUring.cpp @@ -0,0 +1,449 @@ +#define MS_CLASS "DepLibUring" +// #define MS_LOG_DEV_LEVEL 3 + +#include "DepLibUring.hpp" +#include "Logger.hpp" +#include "MediaSoupErrors.hpp" +#include +#include + +/* Static variables. */ + +/* liburing instance per thread. */ +thread_local DepLibUring::LibUring* DepLibUring::liburing{ nullptr }; +/* Completion queue entry array used to retrieve processes tasks. */ +thread_local struct io_uring_cqe* cqes[DepLibUring::QueueDepth]; + +/* Static methods for UV callbacks. */ + +inline static void onCloseFd(uv_handle_t* handle) +{ + delete reinterpret_cast(handle); +} + +inline static void onFdEvent(uv_poll_t* handle, int status, int events) +{ + auto* liburing = static_cast(handle->data); + auto count = io_uring_peek_batch_cqe(liburing->GetRing(), cqes, DepLibUring::QueueDepth); + + // libuv uses level triggering, so we need to read from the socket to reset + // the counter in order to avoid libuv calling this callback indefinitely. + eventfd_t v; + int err = eventfd_read(liburing->GetEventFd(), std::addressof(v)); + if (err < 0) + { + MS_ABORT("eventfd_read() failed: %s", std::strerror(-err)); + }; + + for (unsigned int i{ 0 }; i < count; ++i) + { + struct io_uring_cqe* cqe = cqes[i]; + auto* userData = static_cast(io_uring_cqe_get_data(cqe)); + + if (cqe->res < 0) + { + MS_ERROR("sending failed: %s", std::strerror(-cqe->res)); + + if (userData->cb) + { + (*userData->cb)(false); + delete userData->cb; + } + } + else + { + if (userData->cb) + { + (*userData->cb)(true); + delete userData->cb; + } + } + + io_uring_cqe_seen(liburing->GetRing(), cqe); + liburing->ReleaseUserDataEntry(userData->idx); + } +} + +/* Static class methods */ + +bool DepLibUring::IsRuntimeSupported() +{ + // clang-format off + struct utsname buffer{}; + // clang-format on + + auto err = uname(std::addressof(buffer)); + + if (err != 0) + { + MS_THROW_ERROR("uname() failed: %s", std::strerror(err)); + } + + MS_DEBUG_TAG(info, "kernel version: %s", buffer.version); + + auto* kernelMayorCstr = buffer.release; + auto kernelMayorLong = strtol(kernelMayorCstr, &kernelMayorCstr, 10); + + // liburing `sento` capabilities are supported for kernel versions greather + // than or equal to 6. + return kernelMayorLong >= 6; +} + +void DepLibUring::ClassInit() +{ + const auto mayor = io_uring_major_version(); + const auto minor = io_uring_minor_version(); + + MS_DEBUG_TAG(info, "liburing version: \"%i.%i\"", mayor, minor); + + if (DepLibUring::IsRuntimeSupported()) + { + DepLibUring::liburing = new LibUring(); + + MS_DEBUG_TAG(info, "liburing supported, enabled"); + } + else + { + MS_DEBUG_TAG(info, "liburing not supported, not enabled"); + } +} + +void DepLibUring::ClassDestroy() +{ + MS_TRACE(); + + delete DepLibUring::liburing; +} + +flatbuffers::Offset DepLibUring::FillBuffer(flatbuffers::FlatBufferBuilder& builder) +{ + MS_TRACE(); + + if (!DepLibUring::liburing) + { + return 0; + } + + return DepLibUring::liburing->FillBuffer(builder); +} + +void DepLibUring::StartPollingCQEs() +{ + MS_TRACE(); + + if (!DepLibUring::liburing) + { + return; + } + + DepLibUring::liburing->StartPollingCQEs(); +} + +void DepLibUring::StopPollingCQEs() +{ + MS_TRACE(); + + if (!DepLibUring::liburing) + { + return; + } + + DepLibUring::liburing->StopPollingCQEs(); +} + +bool DepLibUring::PrepareSend( + int sockfd, const void* data, size_t len, const struct sockaddr* addr, onSendCallback* cb) +{ + MS_TRACE(); + + MS_ASSERT(DepLibUring::liburing, "DepLibUring::liburing is not set"); + + return DepLibUring::liburing->PrepareSend(sockfd, data, len, addr, cb); +} + +bool DepLibUring::PrepareWrite( + int sockfd, const void* data1, size_t len1, const void* data2, size_t len2, onSendCallback* cb) +{ + MS_TRACE(); + + MS_ASSERT(DepLibUring::liburing, "DepLibUring::liburing is not set"); + + return DepLibUring::liburing->PrepareWrite(sockfd, data1, len1, data2, len2, cb); +} + +void DepLibUring::Submit() +{ + MS_TRACE(); + + if (!DepLibUring::liburing) + { + return; + } + + DepLibUring::liburing->Submit(); +} + +void DepLibUring::SetActive() +{ + MS_TRACE(); + + if (!DepLibUring::liburing) + { + return; + } + + DepLibUring::liburing->SetActive(); +} + +bool DepLibUring::IsActive() +{ + MS_TRACE(); + + if (!DepLibUring::liburing) + { + return false; + } + + return DepLibUring::liburing->IsActive(); +} + +/* Instance methods. */ + +DepLibUring::LibUring::LibUring() +{ + MS_TRACE(); + + /** + * IORING_SETUP_SINGLE_ISSUER: A hint to the kernel that only a single task + * (or thread) will submit requests, which is used for internal optimisations. + */ + + unsigned int flags = IORING_SETUP_SINGLE_ISSUER; + + // Initialize io_uring. + auto err = io_uring_queue_init(DepLibUring::QueueDepth, std::addressof(this->ring), flags); + + if (err < 0) + { + MS_THROW_ERROR("io_uring_queue_init() failed: %s", std::strerror(-err)); + } + + // Create an eventfd instance. + this->efd = eventfd(0, 0); + + if (this->efd < 0) + { + MS_THROW_ERROR("eventfd() failed: %s", std::strerror(-this->efd)); + } + + err = io_uring_register_eventfd(std::addressof(this->ring), this->efd); + + if (err < 0) + { + MS_THROW_ERROR("io_uring_register_eventfd() failed: %s", std::strerror(-err)); + } + + // Initialize available UserData entries. + for (size_t i{ 0 }; i < DepLibUring::QueueDepth; ++i) + { + this->availableUserDataEntries.push(i); + } +} + +DepLibUring::LibUring::~LibUring() +{ + MS_TRACE(); + + // Close the event file descriptor. + const auto err = close(this->efd); + + if (err != 0) + { + MS_ABORT("close() failed: %s", std::strerror(-err)); + } + + // Close the ring. + io_uring_queue_exit(std::addressof(this->ring)); +} + +flatbuffers::Offset DepLibUring::LibUring::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const +{ + MS_TRACE(); + + return FBS::LibUring::CreateDump( + builder, this->sqeProcessCount, this->sqeMissCount, this->userDataMissCount); +} + +void DepLibUring::LibUring::StartPollingCQEs() +{ + MS_TRACE(); + + // Watch the event file descriptor for completions. + this->uvHandle = new uv_poll_t; + + auto err = uv_poll_init(DepLibUV::GetLoop(), this->uvHandle, this->efd); + + if (err != 0) + { + delete this->uvHandle; + + MS_THROW_ERROR("uv_poll_init() failed: %s", uv_strerror(err)); + } + + this->uvHandle->data = this; + + err = uv_poll_start(this->uvHandle, UV_READABLE, static_cast(onFdEvent)); + + if (err != 0) + { + MS_THROW_ERROR("uv_poll_start() failed: %s", uv_strerror(err)); + } +} + +void DepLibUring::LibUring::StopPollingCQEs() +{ + MS_TRACE(); + + this->uvHandle->data = nullptr; + + // Stop polling the event file descriptor. + auto err = uv_poll_stop(this->uvHandle); + + if (err != 0) + { + MS_ABORT("uv_poll_stop() failed: %s", uv_strerror(err)); + } + + // NOTE: Handles that wrap file descriptors are clossed immediately. + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseFd)); +} + +bool DepLibUring::LibUring::PrepareSend( + int sockfd, const void* data, size_t len, const struct sockaddr* addr, onSendCallback* cb) +{ + MS_TRACE(); + + auto* userData = this->GetUserData(); + + if (!userData) + { + MS_WARN_DEV("no user data entry available"); + + this->userDataMissCount++; + + return false; + } + + auto* sqe = io_uring_get_sqe(std::addressof(this->ring)); + + if (!sqe) + { + MS_WARN_DEV("no sqe available"); + + this->sqeMissCount++; + + return false; + } + + std::memcpy(userData->store, data, len); + userData->cb = cb; + + io_uring_sqe_set_data(sqe, userData); + + socklen_t addrlen = 0; + + if (addr->sa_family == AF_INET) + { + addrlen = sizeof(struct sockaddr_in); + } + else if (addr->sa_family == AF_INET6) + { + addrlen = sizeof(struct sockaddr_in6); + } + + io_uring_prep_sendto(sqe, sockfd, userData->store, len, 0, addr, addrlen); + + this->sqeProcessCount++; + + return true; +} + +bool DepLibUring::LibUring::PrepareWrite( + int sockfd, const void* data1, size_t len1, const void* data2, size_t len2, onSendCallback* cb) +{ + MS_TRACE(); + + auto* userData = this->GetUserData(); + + if (!userData) + { + MS_WARN_DEV("no user data entry available"); + + this->userDataMissCount++; + + return false; + } + + auto* sqe = io_uring_get_sqe(std::addressof(this->ring)); + + if (!sqe) + { + MS_WARN_DEV("no sqe available"); + + this->sqeMissCount++; + + return false; + } + + std::memcpy(userData->store, data1, len1); + std::memcpy(userData->store + len1, data2, len2); + userData->cb = cb; + + io_uring_sqe_set_data(sqe, userData); + io_uring_prep_write(sqe, sockfd, userData->store, len1 + len2, 0); + + this->sqeProcessCount++; + + return true; +} + +void DepLibUring::LibUring::Submit() +{ + MS_TRACE(); + + // Unset active flag. + this->active = false; + + auto err = io_uring_submit(std::addressof(this->ring)); + + if (err >= 0) + { + MS_DEBUG_DEV("%i submission queue entries submitted", err); + } + else + { + MS_ERROR("io_uring_submit() failed: %s", std::strerror(-err)); + } +} + +DepLibUring::UserData* DepLibUring::LibUring::GetUserData() +{ + MS_TRACE(); + + if (this->availableUserDataEntries.empty()) + { + MS_WARN_DEV("no user data entry available"); + + return nullptr; + } + + auto idx = this->availableUserDataEntries.front(); + + this->availableUserDataEntries.pop(); + + auto* userData = std::addressof(this->userDataBuffer[idx]); + userData->idx = idx; + + return userData; +} diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index 3313b58031..b4e2dcc417 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -2,6 +2,9 @@ // #define MS_LOG_DEV_LEVEL 3 #include "RTC/Router.hpp" +#ifdef MS_LIBURING_SUPPORTED +#include "DepLibUring.hpp" +#endif #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" @@ -660,6 +663,11 @@ namespace RTC // Clone only happens if needed. std::shared_ptr sharedPacket; +#ifdef MS_LIBURING_SUPPORTED + // Activate liburing usage. + DepLibUring::SetActive(); +#endif + for (auto* consumer : consumers) { // Update MID RTP extension value. @@ -672,6 +680,11 @@ namespace RTC consumer->SendRtpPacket(packet, sharedPacket); } + +#ifdef MS_LIBURING_SUPPORTED + // Submit all prepared submission entries. + DepLibUring::Submit(); +#endif } auto it = this->mapProducerRtpObservers.find(producer); diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 191e116236..3fceb890d1 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -2,6 +2,9 @@ // #define MS_LOG_DEV_LEVEL 3 #include "RTC/RtpStreamSend.hpp" +#ifdef MS_LIBURING_SUPPORTED +#include "DepLibUring.hpp" +#endif #include "Logger.hpp" #include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" @@ -125,6 +128,11 @@ namespace RTC this->nackCount++; +#ifdef MS_LIBURING_SUPPORTED + // Activate liburing usage. + DepLibUring::SetActive(); +#endif + for (auto it = nackPacket->Begin(); it != nackPacket->End(); ++it) { RTC::RTCP::FeedbackRtpNackItem* item = *it; @@ -164,6 +172,11 @@ namespace RTC } } } + +#ifdef MS_LIBURING_SUPPORTED + // Submit all prepared submission entries. + DepLibUring::Submit(); +#endif } void RtpStreamSend::ReceiveKeyFrameRequest(RTC::RTCP::FeedbackPs::MessageType messageType) diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index cdf0a606e3..d697a17fac 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -2,6 +2,10 @@ #define MS_CLASS "RTC::Transport" // #define MS_LOG_DEV_LEVEL 3 +#include "RTC/Transport.hpp" +#ifdef MS_LIBURING_SUPPORTED +#include "DepLibUring.hpp" +#endif #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" @@ -19,7 +23,6 @@ #include "RTC/SimpleConsumer.hpp" #include "RTC/SimulcastConsumer.hpp" #include "RTC/SvcConsumer.hpp" -#include "RTC/Transport.hpp" #include // webrtc::RtpPacketSendInfo #include // std::ostream_iterator #include // std::multimap @@ -2151,6 +2154,11 @@ namespace RTC std::unique_ptr packet{ new RTC::RTCP::CompoundPacket() }; +#ifdef MS_LIBURING_SUPPORTED + // Activate liburing usage. + DepLibUring::SetActive(); +#endif + for (auto& kv : this->mapConsumers) { auto* consumer = kv.second; @@ -2194,6 +2202,11 @@ namespace RTC { SendRtcpCompoundPacket(packet.get()); } + +#ifdef MS_LIBURING_SUPPORTED + // Submit all prepared submission entries. + DepLibUring::Submit(); +#endif } void Transport::DistributeAvailableOutgoingBitrate() diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index c7432525ec..f6795d94bd 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -3,6 +3,9 @@ #include "Worker.hpp" #include "ChannelMessageRegistrator.hpp" +#ifdef MS_LIBURING_SUPPORTED +#include "DepLibUring.hpp" +#endif #include "DepLibUV.hpp" #include "DepUsrSCTP.hpp" #include "Logger.hpp" @@ -40,6 +43,11 @@ Worker::Worker(::Channel::ChannelSocket* channel) : channel(channel) // Create the Checker instance in DepUsrSCTP. DepUsrSCTP::CreateChecker(); +#ifdef MS_LIBURING_SUPPORTED + // Start polling CQEs, which will create a uv_pool_t handle. + DepLibUring::StartPollingCQEs(); +#endif + // Tell the Node process that we are running. this->shared->channelNotifier->Emit( std::to_string(Logger::pid), FBS::Notification::Event::WORKER_RUNNING); @@ -97,6 +105,11 @@ void Worker::Close() // Close the Checker instance in DepUsrSCTP. DepUsrSCTP::CloseChecker(); +#ifdef MS_LIBURING_SUPPORTED + // Stop polling CQEs, which will close the uv_pool_t handle. + DepLibUring::StopPollingCQEs(); +#endif + // Close the Channel. this->channel->Close(); } @@ -129,7 +142,16 @@ flatbuffers::Offset Worker::FillBuffer( auto channelMessageHandlers = this->shared->channelMessageRegistrator->FillBuffer(builder); return FBS::Worker::CreateDumpResponseDirect( - builder, Logger::pid, &webRtcServerIds, &routerIds, channelMessageHandlers); + builder, + Logger::pid, + &webRtcServerIds, + &routerIds, + channelMessageHandlers +#ifdef MS_LIBURING_SUPPORTED + , + DepLibUring::FillBuffer(builder) +#endif + ); } flatbuffers::Offset Worker::FillBufferResourceUsage( diff --git a/worker/src/handles/TcpConnectionHandle.cpp b/worker/src/handles/TcpConnectionHandle.cpp index e6812b165b..f254ce8673 100644 --- a/worker/src/handles/TcpConnectionHandle.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -3,6 +3,9 @@ #include "handles/TcpConnectionHandle.hpp" #include "DepLibUV.hpp" +#ifdef MS_LIBURING_SUPPORTED +#include "DepLibUring.hpp" +#endif #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" @@ -199,6 +202,15 @@ void TcpConnectionHandle::Start() { MS_THROW_ERROR("error setting peer IP and port"); } + +#ifdef MS_LIBURING_SUPPORTED + err = uv_fileno(reinterpret_cast(this->uvHandle), std::addressof(this->fd)); + + if (err != 0) + { + MS_THROW_ERROR("uv_fileno() failed: %s", uv_strerror(err)); + } +#endif } void TcpConnectionHandle::Write( @@ -232,6 +244,30 @@ void TcpConnectionHandle::Write( return; } +#ifdef MS_LIBURING_SUPPORTED + { + if (!DepLibUring::IsActive()) + { + goto write_libuv; + } + + // Prepare the data to be sent. + // NOTE: If all SQEs are currently in use or no UserData entry is available we'll + // fall back to libuv. + auto prepared = DepLibUring::PrepareWrite(this->fd, data1, len1, data2, len2, cb); + + if (!prepared) + { + MS_DEBUG_DEV("cannot write via liburing, fallback to libuv"); + + goto write_libuv; + } + + return; + } +#endif + +write_libuv: const size_t totalLen = len1 + len2; uv_buf_t buffers[2]; int written{ 0 }; diff --git a/worker/src/handles/UdpSocketHandle.cpp b/worker/src/handles/UdpSocketHandle.cpp index 092b0f041d..e5d9c91fa9 100644 --- a/worker/src/handles/UdpSocketHandle.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -2,6 +2,9 @@ // #define MS_LOG_DEV_LEVEL 3 #include "handles/UdpSocketHandle.hpp" +#ifdef MS_LIBURING_SUPPORTED +#include "DepLibUring.hpp" +#endif #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" @@ -84,6 +87,15 @@ UdpSocketHandle::UdpSocketHandle(uv_udp_t* uvHandle) : uvHandle(uvHandle) MS_THROW_ERROR("error setting local IP and port"); } + +#ifdef MS_LIBURING_SUPPORTED + err = uv_fileno(reinterpret_cast(this->uvHandle), std::addressof(this->fd)); + + if (err != 0) + { + MS_THROW_ERROR("uv_fileno() failed: %s", uv_strerror(err)); + } +#endif } UdpSocketHandle::~UdpSocketHandle() @@ -157,6 +169,30 @@ void UdpSocketHandle::Send( return; } +#ifdef MS_LIBURING_SUPPORTED + { + if (!DepLibUring::IsActive()) + { + goto send_libuv; + } + + // Prepare the data to be sent. + // NOTE: If all SQEs are currently in use or no UserData entry is available we'll + // fall back to libuv. + auto prepared = DepLibUring::PrepareSend(this->fd, data, len, addr, cb); + + if (!prepared) + { + MS_DEBUG_DEV("cannot send via liburing, fallback to libuv"); + + goto send_libuv; + } + + return; + } +#endif + +send_libuv: // First try uv_udp_try_send(). In case it can not directly send the datagram // then build a uv_req_t and use uv_udp_send(). diff --git a/worker/src/lib.cpp b/worker/src/lib.cpp index cca1f88b7b..7d427db63d 100644 --- a/worker/src/lib.cpp +++ b/worker/src/lib.cpp @@ -3,6 +3,9 @@ #include "common.hpp" #include "DepLibSRTP.hpp" +#ifdef MS_LIBURING_SUPPORTED +#include "DepLibUring.hpp" +#endif #include "DepLibUV.hpp" #include "DepLibWebRTC.hpp" #include "DepOpenSSL.hpp" @@ -124,6 +127,9 @@ extern "C" int mediasoup_worker_run( DepOpenSSL::ClassInit(); DepLibSRTP::ClassInit(); DepUsrSCTP::ClassInit(); +#ifdef MS_LIBURING_SUPPORTED + DepLibUring::ClassInit(); +#endif DepLibWebRTC::ClassInit(); Utils::Crypto::ClassInit(); RTC::DtlsTransport::ClassInit(); @@ -141,6 +147,9 @@ extern "C" int mediasoup_worker_run( DepLibSRTP::ClassDestroy(); Utils::Crypto::ClassDestroy(); DepLibWebRTC::ClassDestroy(); +#ifdef MS_LIBURING_SUPPORTED + DepLibUring::ClassDestroy(); +#endif RTC::DtlsTransport::ClassDestroy(); DepUsrSCTP::ClassDestroy(); DepLibUV::ClassDestroy(); diff --git a/worker/subprojects/liburing.wrap b/worker/subprojects/liburing.wrap new file mode 100644 index 0000000000..1074fc1e75 --- /dev/null +++ b/worker/subprojects/liburing.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = liburing-liburing-2.4 +source_url = https://github.com/axboe/liburing/archive/refs/tags/liburing-2.4.tar.gz +source_filename = liburing-2.4.tar.gz +source_hash = 2398ec82d967a6f903f3ae1fd4541c754472d3a85a584dc78c5da2fabc90706b +patch_filename = liburing_2.4-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/liburing_2.4-1/get_patch +patch_hash = 0dd939828da6a7c6d22c0f4db879405e74f9ac7153927c365642a28f871c92c2 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/liburing_2.4-1/liburing-2.4.tar.gz +wrapdb_version = 2.4-1 + +[provide] +dependency_names = liburing From 95390bd8232ab8730a178dffdc3f57f66f3cf528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 27 Nov 2023 19:11:45 +0100 Subject: [PATCH 219/525] Improvements to the build system (#1245) --- npm-scripts.mjs | 16 ++++------------ package.json | 17 ++++++++--------- worker/Cargo.toml | 2 +- worker/Makefile | 3 +-- worker/build.rs | 9 ++++----- 5 files changed, 18 insertions(+), 29 deletions(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 80ebc35c3e..f3982f253e 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -11,7 +11,6 @@ const IS_WINDOWS = os.platform() === 'win32'; const MAYOR_VERSION = PKG.version.split('.')[0]; const PYTHON = getPython(); const PIP_INVOKE_DIR = path.resolve('worker/pip_invoke'); -const INVOKE_VERSION = process.env.INVOKE_VERSION ?? '2.2.0'; const FLATBUFFERS_VERSION = '23.3.3'; const WORKER_RELEASE_DIR = 'worker/out/Release'; const WORKER_RELEASE_BIN = IS_WINDOWS ? 'mediasoup-worker.exe' : 'mediasoup-worker'; @@ -318,7 +317,8 @@ function installInvoke() // Install pip invoke into custom location, so we don't depend on system-wide // installation. executeCmd( - `"${PYTHON}" -m pip install --upgrade --target="${PIP_INVOKE_DIR}" invoke==${INVOKE_VERSION}`, /* exitOnError */ true + `"${PYTHON}" -m pip install --upgrade --target="${PIP_INVOKE_DIR}" invoke`, + /* exitOnError */ true ); } @@ -331,15 +331,7 @@ function deleteNodeLib() logInfo('deleteNodeLib()'); - if (!IS_WINDOWS) - { - executeCmd('rm -rf node/lib'); - } - else - { - // NOTE: This command fails in Windows if the dir doesn't exist. - executeCmd('rmdir /s /q "node/lib"', /* exitOnError */ false); - } + fs.rmSync('node/lib', { recursive: true, force: true }); } function buildTypescript({ force = false } = { force: false }) @@ -584,7 +576,7 @@ async function downloadPrebuiltWorker() const resolvedBinPath = path.resolve(WORKER_RELEASE_BIN_PATH); execSync( - resolvedBinPath, + `"${resolvedBinPath}"`, { stdio : [ 'ignore', 'ignore', 'ignore' ], // Ensure no env is passed to avoid accidents. diff --git a/package.json b/package.json index 0fa0bf1c9c..fdf71d2362 100644 --- a/package.json +++ b/package.json @@ -21,23 +21,22 @@ "types": "node/lib/index.d.ts", "files": [ "node/lib", - "worker/src", - "worker/include", + "worker/deps/libwebrtc", "worker/fbs", - "worker/test/src", - "worker/test/include", - "worker/fuzzer/src", "worker/fuzzer/include", - "worker/scripts/*.mjs", + "worker/fuzzer/src", + "worker/include", + "worker/src", "worker/scripts/*.json", + "worker/scripts/*.mjs", "worker/scripts/*.py", "worker/scripts/*.sh", "worker/subprojects/*.wrap", - "worker/deps/libwebrtc", - "worker/tasks.py", - "worker/Makefile", + "worker/test/include", + "worker/test/src", "worker/meson.build", "worker/meson_options.txt", + "worker/tasks.py", "npm-scripts.mjs" ], "engines": { diff --git a/worker/Cargo.toml b/worker/Cargo.toml index 9116fc8444..a3a5d412ce 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -21,9 +21,9 @@ include = [ "/test/src", "/build.rs", "/Cargo.toml", - "/Makefile", "/meson.build", "/meson_options.txt", + "/tasks.py" ] [package.metadata.docs.rs] diff --git a/worker/Makefile b/worker/Makefile index 7a0492128c..fd21742768 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -6,7 +6,6 @@ PYTHON ?= $(shell command -v python3 2> /dev/null || echo python) PIP_INVOKE_DIR = $(shell pwd)/pip_invoke -INVOKE_VERSION ?= 2.2.0 # Instruct Python where to look for invoke module. ifeq ($(OS),Windows_NT) @@ -48,7 +47,7 @@ invoke: ifeq ($(wildcard $(PIP_INVOKE_DIR)),) # Install pip invoke into custom location, so we don't depend on system-wide # installation. - $(PYTHON) -m pip install --upgrade --target="$(PIP_INVOKE_DIR)" invoke==$(INVOKE_VERSION) + $(PYTHON) -m pip install --upgrade --target="$(PIP_INVOKE_DIR)" invoke endif meson-ninja: invoke diff --git a/worker/build.rs b/worker/build.rs index 06d25c0ce6..aca5b430ad 100644 --- a/worker/build.rs +++ b/worker/build.rs @@ -107,10 +107,8 @@ fn main() { // Install Python invoke package in custom folder let pip_invoke_dir = format!("{out_dir}/pip_invoke"); - let invoke_version = "2.2.0"; let python = env::var("PYTHON").unwrap_or("python3".to_string()); - let mut pythonpath = if env::var("PYTHONPATH").is_ok() { - let original_pythonpath = env::var("PYTHONPATH").unwrap(); + let mut pythonpath = if let Ok(original_pythonpath) = env::var("PYTHONPATH") { format!("{pip_invoke_dir}:{original_pythonpath}") } else { pip_invoke_dir.clone() @@ -126,8 +124,9 @@ fn main() { .arg("pip") .arg("install") .arg("--upgrade") - .arg(format!("--target={pip_invoke_dir}")) - .arg(format!("invoke=={invoke_version}")) + .arg("--target") + .arg(pip_invoke_dir) + .arg("invoke") .spawn() .expect("Failed to start") .wait() From 3e6d969889bcddea6dc61d1a6f88264b0eca49ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 28 Nov 2023 16:34:23 +0100 Subject: [PATCH 220/525] FBS: handler_id is mandatory in requests and notifications, so do not check it Fixes #1246 --- worker/src/Channel/ChannelNotification.cpp | 7 +------ worker/src/Channel/ChannelRequest.cpp | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/worker/src/Channel/ChannelNotification.cpp b/worker/src/Channel/ChannelNotification.cpp index 6dc4d2a89c..9facac2b7c 100644 --- a/worker/src/Channel/ChannelNotification.cpp +++ b/worker/src/Channel/ChannelNotification.cpp @@ -35,11 +35,6 @@ namespace Channel } this->eventCStr = eventCStrIt->second; - - // Handler ID is optional. - if (flatbuffers::IsFieldPresent(this->data, FBS::Notification::Notification::VT_HANDLERID)) - { - this->handlerId = this->data->handlerId()->str(); - } + this->handlerId = this->data->handlerId()->str(); } } // namespace Channel diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index 01b56cf5de..adf62ba28e 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -106,12 +106,7 @@ namespace Channel } this->methodCStr = methodCStrIt->second; - - // Handler ID is optional. - if (flatbuffers::IsFieldPresent(this->data, FBS::Request::Request::VT_HANDLERID)) - { - this->handlerId = this->data->handlerId()->str(); - } + this->handlerId = this->data->handlerId()->str(); } void ChannelRequest::Accept() From d3bd4091f21e279a3d107d97a0f97dcb109fda21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 28 Nov 2023 16:37:19 +0100 Subject: [PATCH 221/525] Update npm deps --- package-lock.json | 332 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 168 insertions(+), 168 deletions(-) diff --git a/package-lock.json b/package-lock.json index 87f054cd61..f21682d839 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,8 +22,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.10", "@types/node": "^20.10.0", - "@typescript-eslint/eslint-plugin": "^6.12.0", - "@typescript-eslint/parser": "^6.12.0", + "@typescript-eslint/eslint-plugin": "^6.13.1", + "@typescript-eslint/parser": "^6.13.1", "eslint": "^8.54.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", @@ -1661,16 +1661,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", - "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.1.tgz", + "integrity": "sha512-5bQDGkXaxD46bPvQt08BUz9YSaO4S0fB1LB5JHQuXTfkGPI3+UUeS387C/e9jRie5GqT8u5kFTrMvAjtX4O5kA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/type-utils": "6.12.0", - "@typescript-eslint/utils": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/type-utils": "6.13.1", + "@typescript-eslint/utils": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1696,13 +1696,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", - "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", + "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0" + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1713,9 +1713,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", - "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", + "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1726,13 +1726,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", - "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", + "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1753,17 +1753,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", - "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", + "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.1", "semver": "^7.5.4" }, "engines": { @@ -1778,12 +1778,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", - "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", + "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/types": "6.13.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1795,15 +1795,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", - "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.1.tgz", + "integrity": "sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4" }, "engines": { @@ -1823,13 +1823,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", - "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", + "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0" + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1840,9 +1840,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", - "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", + "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1853,13 +1853,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", - "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", + "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1880,12 +1880,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", - "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", + "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/types": "6.13.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1914,13 +1914,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", - "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.1.tgz", + "integrity": "sha512-A2qPlgpxx2v//3meMqQyB1qqTg1h1dJvzca7TugM3Yc2USDY+fsRBiojAEo92HO7f5hW5mjAUF6qobOPzlBCBQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.12.0", - "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/utils": "6.13.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1941,13 +1941,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", - "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", + "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0" + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1958,9 +1958,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", - "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", + "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1971,13 +1971,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", - "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", + "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1998,17 +1998,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", - "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", + "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.1", "semver": "^7.5.4" }, "engines": { @@ -2023,12 +2023,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", - "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", + "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/types": "6.13.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -8048,16 +8048,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", - "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.1.tgz", + "integrity": "sha512-5bQDGkXaxD46bPvQt08BUz9YSaO4S0fB1LB5JHQuXTfkGPI3+UUeS387C/e9jRie5GqT8u5kFTrMvAjtX4O5kA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/type-utils": "6.12.0", - "@typescript-eslint/utils": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/type-utils": "6.13.1", + "@typescript-eslint/utils": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8067,29 +8067,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", - "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", + "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0" + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1" } }, "@typescript-eslint/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", - "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", + "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", - "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", + "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8098,69 +8098,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", - "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", + "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", - "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", + "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/types": "6.13.1", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", - "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.1.tgz", + "integrity": "sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", - "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", + "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0" + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1" } }, "@typescript-eslint/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", - "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", + "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", - "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", + "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8169,12 +8169,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", - "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", + "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/types": "6.13.1", "eslint-visitor-keys": "^3.4.1" } } @@ -8191,41 +8191,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", - "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.1.tgz", + "integrity": "sha512-A2qPlgpxx2v//3meMqQyB1qqTg1h1dJvzca7TugM3Yc2USDY+fsRBiojAEo92HO7f5hW5mjAUF6qobOPzlBCBQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.12.0", - "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/utils": "6.13.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", - "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", + "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0" + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1" } }, "@typescript-eslint/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", - "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", + "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", - "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", + "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8234,27 +8234,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", - "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", + "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", - "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", + "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/types": "6.13.1", "eslint-visitor-keys": "^3.4.1" } } diff --git a/package.json b/package.json index fdf71d2362..8ed586cc37 100644 --- a/package.json +++ b/package.json @@ -106,8 +106,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.10", "@types/node": "^20.10.0", - "@typescript-eslint/eslint-plugin": "^6.12.0", - "@typescript-eslint/parser": "^6.12.0", + "@typescript-eslint/eslint-plugin": "^6.13.1", + "@typescript-eslint/parser": "^6.13.1", "eslint": "^8.54.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", From bedb0083810a742dca819589a61c665a4fc6816a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 29 Nov 2023 14:27:01 +0100 Subject: [PATCH 222/525] Update npm marked dep --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index f21682d839..5367a612d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "eslint": "^8.54.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^10.0.0", + "marked": "^11.0.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -4849,9 +4849,9 @@ } }, "node_modules/marked": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-10.0.0.tgz", - "integrity": "sha512-YiGcYcWj50YrwBgNzFoYhQ1hT6GmQbFG8SksnYJX1z4BXTHSOrz1GB5/Jm2yQvMg4nN1FHP4M6r03R10KrVUiA==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.0.0.tgz", + "integrity": "sha512-2GsW34uXaFEGTQ/+3rCnNC6vUYTAgFuDLGl70v/aWinA5mIJtTrrFAmfbLOfVvgPyxXuDVL9He/7reCK+6j3Sw==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -10280,9 +10280,9 @@ "dev": true }, "marked": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-10.0.0.tgz", - "integrity": "sha512-YiGcYcWj50YrwBgNzFoYhQ1hT6GmQbFG8SksnYJX1z4BXTHSOrz1GB5/Jm2yQvMg4nN1FHP4M6r03R10KrVUiA==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.0.0.tgz", + "integrity": "sha512-2GsW34uXaFEGTQ/+3rCnNC6vUYTAgFuDLGl70v/aWinA5mIJtTrrFAmfbLOfVvgPyxXuDVL9He/7reCK+6j3Sw==", "dev": true }, "meow": { diff --git a/package.json b/package.json index 8ed586cc37..c32d10c51c 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "eslint": "^8.54.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^10.0.0", + "marked": "^11.0.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From 2e6913b2316354ce1f06f722903490bb7db2c31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 4 Dec 2023 13:14:27 +0100 Subject: [PATCH 223/525] Update worker dependencies (#1201) - Update abseil to 20230802.0 - Update libuv to 1.47.0 - Update usrsctp - Update openssl - Update meson - Add missing libuv linking libs in worker/build.rs --- CHANGELOG.md | 5 ++ worker/build.rs | 4 ++ worker/meson.build | 1 + worker/subprojects/abseil-cpp.wrap | 95 +++++++++++++++++++++++++++--- worker/subprojects/libuv.wrap | 18 +++--- worker/subprojects/openssl.wrap | 10 ++-- worker/subprojects/usrsctp.wrap | 8 +-- worker/tasks.py | 2 +- 8 files changed, 116 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b97dda435f..2c1c9ca068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ ### NEXT +* Update worker dependencies ([PR #1201](https://github.com/versatica/mediasoup/pull/1201)): + * abseil-cpp 20230802.0-2 + * libuv 1.47.0-1 + * OpenSSL 3.0.8-2 + * usrsctp snapshot ebb18adac6501bad4501b1f6dccb67a1c85cc299 * Enable `liburing` usage for Linux (kernel versions >= 6) ([PR #1218](https://github.com/versatica/mediasoup/pull/1218)). diff --git a/worker/build.rs b/worker/build.rs index aca5b430ad..5139edef80 100644 --- a/worker/build.rs +++ b/worker/build.rs @@ -174,6 +174,10 @@ fn main() { println!("cargo:rustc-link-lib=iphlpapi"); println!("cargo:rustc-link-lib=userenv"); println!("cargo:rustc-link-lib=ws2_32"); + println!("cargo:rustc-link-lib=dbghelp"); + println!("cargo:rustc-link-lib=ole32"); + println!("cargo:rustc-link-lib=uuid"); + println!("cargo:rustc-link-lib=shell32"); // These are required by OpenSSL on Windows println!("cargo:rustc-link-lib=ws2_32"); diff --git a/worker/meson.build b/worker/meson.build index 3092e41838..35a3a82874 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -199,6 +199,7 @@ abseil_cpp_proj = subproject( 'abseil-cpp', default_options: [ 'warning_level=0', + 'cpp_std=c++17', ], ) catch2_proj = subproject( diff --git a/worker/subprojects/abseil-cpp.wrap b/worker/subprojects/abseil-cpp.wrap index 29ad8c2ee2..61e2e4a4f6 100644 --- a/worker/subprojects/abseil-cpp.wrap +++ b/worker/subprojects/abseil-cpp.wrap @@ -1,23 +1,102 @@ [wrap-file] -directory = abseil-cpp-20220623.0 -source_url = https://github.com/abseil/abseil-cpp/archive/20220623.0.tar.gz -source_filename = abseil-cpp-20220623.0.tar.gz -source_hash = 4208129b49006089ba1d6710845a45e31c59b0ab6bff9e5788a87f55c5abd602 -patch_filename = abseil-cpp_20220623.0-2_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20220623.0-2/get_patch -patch_hash = d19cb16610d9310658a815ebcd87a9e2966aafbd57964341c0d1a3a3778c03b6 -wrapdb_version = 20220623.0-2 +directory = abseil-cpp-20230802.0 +source_url = https://github.com/abseil/abseil-cpp/archive/20230802.0.tar.gz +source_filename = abseil-cpp-20230802.0.tar.gz +source_hash = 59d2976af9d6ecf001a81a35749a6e551a335b949d34918cfade07737b9d93c5 +patch_filename = abseil-cpp_20230802.0-3_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20230802.0-3/get_patch +patch_hash = 1bcd502774c0cd7ad2f3b310bb6bffaa440a290e7300d7df79557b6be20b5daf +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20230802.0-3/abseil-cpp-20230802.0.tar.gz +wrapdb_version = 20230802.0-3 [provide] absl_base = absl_base_dep absl_container = absl_container_dep absl_debugging = absl_debugging_dep +absl_log = absl_log_dep absl_flags = absl_flags_dep absl_hash = absl_hash_dep +absl_crc = absl_crc_dep absl_numeric = absl_numeric_dep +absl_profiling = absl_profiling_dep absl_random = absl_random_dep absl_status = absl_status_dep absl_strings = absl_strings_dep absl_synchronization = absl_synchronization_dep absl_time = absl_time_dep absl_types = absl_types_dep +absl_algorithm_container = absl_base_dep +absl_any_invocable = absl_base_dep +absl_bad_any_cast_impl = absl_types_dep +absl_bad_optional_access = absl_types_dep +absl_bad_variant_access = absl_types_dep +absl_bind_front = absl_base_dep +absl_city = absl_hash_dep +absl_civil_time = absl_time_dep +absl_cleanup = absl_base_dep +absl_cord = absl_strings_dep +absl_cord_internal = absl_strings_dep +absl_cordz_functions = absl_strings_dep +absl_cordz_handle = absl_strings_dep +absl_cordz_info = absl_strings_dep +absl_cordz_sample_token = absl_strings_dep +absl_core_headers = absl_base_dep +absl_debugging_internal = absl_debugging_dep +absl_demangle_internal = absl_debugging_dep +absl_examine_stack = absl_debugging_dep +absl_exponential_biased = absl_profiling_dep +absl_failure_signal_handler = absl_debugging_dep +absl_flags_commandlineflag = absl_flags_dep +absl_flags_commandlineflag_internal = absl_flags_dep +absl_flags_config = absl_flags_dep +absl_flags_internal = absl_flags_dep +absl_flags_marshalling = absl_flags_dep +absl_flags_parse = absl_flags_dep +absl_flags_private_handle_accessor = absl_flags_dep +absl_flags_program_name = absl_flags_dep +absl_flags_reflection = absl_flags_dep +absl_flags_usage = absl_flags_dep +absl_flags_usage_internal = absl_flags_dep +absl_flat_hash_map = absl_container_dep +absl_flat_hash_set = absl_container_dep +absl_function_ref = absl_base_dep +absl_graphcycles_internal = absl_synchronization_dep +absl_hashtablez_sampler = absl_container_dep +absl_inlined_vector = absl_container_dep +absl_int128 = absl_numeric_dep +absl_leak_check = absl_debugging_dep +absl_log_severity = absl_base_dep +absl_low_level_hash = absl_hash_dep +absl_memory = absl_base_dep +absl_optional = absl_types_dep +absl_periodic_sampler = absl_profiling_dep +absl_random_bit_gen_ref = absl_random_dep +absl_random_distributions = absl_random_dep +absl_random_internal_distribution_test_util = absl_random_dep +absl_random_internal_platform = absl_random_dep +absl_random_internal_pool_urbg = absl_random_dep +absl_random_internal_randen = absl_random_dep +absl_random_internal_randen_hwaes = absl_random_dep +absl_random_internal_randen_hwaes_impl = absl_random_dep +absl_random_internal_randen_slow = absl_random_dep +absl_random_internal_seed_material = absl_random_dep +absl_random_random = absl_random_dep +absl_random_seed_gen_exception = absl_random_dep +absl_random_seed_sequences = absl_random_dep +absl_raw_hash_set = absl_container_dep +absl_raw_logging_internal = absl_base_dep +absl_scoped_set_env = absl_base_dep +absl_span = absl_types_dep +absl_spinlock_wait = absl_base_dep +absl_stacktrace = absl_debugging_dep +absl_statusor = absl_status_dep +absl_str_format = absl_strings_dep +absl_str_format_internal = absl_strings_dep +absl_strerror = absl_base_dep +absl_strings_internal = absl_strings_dep +absl_symbolize = absl_debugging_dep +absl_throw_delegate = absl_base_dep +absl_time_zone = absl_time_dep +absl_type_traits = absl_base_dep +absl_utility = absl_base_dep +absl_variant = absl_types_dep diff --git a/worker/subprojects/libuv.wrap b/worker/subprojects/libuv.wrap index b8a7529d50..53ef63575e 100644 --- a/worker/subprojects/libuv.wrap +++ b/worker/subprojects/libuv.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = libuv-v1.44.2 -source_url = https://dist.libuv.org/dist/v1.44.2/libuv-v1.44.2.tar.gz -source_filename = libuv-v1.44.2.tar.gz -source_hash = ccfcdc968c55673c6526d8270a9c8655a806ea92468afcbcabc2b16040f03cb4 -patch_filename = libuv_1.44.2-2_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/libuv_1.44.2-2/get_patch -patch_hash = 12a0850e1c925811f54bb022339d3105afaed8bc006b197351006c9c841f06ce -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libuv_1.44.2-2/libuv-v1.44.2.tar.gz -wrapdb_version = 1.44.2-2 +directory = libuv-v1.47.0 +source_url = https://dist.libuv.org/dist/v1.47.0/libuv-v1.47.0.tar.gz +source_filename = libuv-v1.47.0.tar.gz +source_hash = 20c37a4ca77a2107879473c6c8fa0dc1350e80045df98bfbe78f7cd6d7dd2965 +patch_filename = libuv_1.47.0-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/libuv_1.47.0-1/get_patch +patch_hash = 7362dfca01c8ddf89a60a4a05faa8a1fc7976b8b57aa6e3c54630e329a418b8f +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libuv_1.47.0-1/libuv-v1.47.0.tar.gz +wrapdb_version = 1.47.0-1 [provide] libuv = libuv_dep diff --git a/worker/subprojects/openssl.wrap b/worker/subprojects/openssl.wrap index 7d15b54cfc..b69462f53e 100644 --- a/worker/subprojects/openssl.wrap +++ b/worker/subprojects/openssl.wrap @@ -3,11 +3,11 @@ directory = openssl-3.0.8 source_url = https://www.openssl.org/source/openssl-3.0.8.tar.gz source_filename = openssl-3.0.8.tar.gz source_hash = 6c13d2bf38fdf31eac3ce2a347073673f5d63263398f1f69d0df4a41253e4b3e -patch_filename = openssl_3.0.8-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.8-1/get_patch -patch_hash = 12d9c884174a91ccd1aa9230e9567c019f8a582ce46c98736f99a5200b4f2514 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openssl_3.0.8-1/openssl-3.0.8.tar.gz -wrapdb_version = 3.0.8-1 +patch_filename = openssl_3.0.8-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.8-2/get_patch +patch_hash = e84b5fe469e681e3318184157a0c7c43d4cbacd078bb88f506e31569f8f75072 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openssl_3.0.8-2/openssl-3.0.8.tar.gz +wrapdb_version = 3.0.8-2 [provide] libcrypto = libcrypto_dep diff --git a/worker/subprojects/usrsctp.wrap b/worker/subprojects/usrsctp.wrap index 67ca2c8728..3cd7061b98 100644 --- a/worker/subprojects/usrsctp.wrap +++ b/worker/subprojects/usrsctp.wrap @@ -1,8 +1,8 @@ [wrap-file] -directory = usrsctp-4e06feb01cadcd127d119486b98a4bd3d64aa1e7 -source_url = https://github.com/sctplab/usrsctp/archive/4e06feb01cadcd127d119486b98a4bd3d64aa1e7.zip -source_filename = 4e06feb01cadcd127d119486b98a4bd3d64aa1e7.zip -source_hash = 15f7844c4c4ca93228ae0fe844182c72edd1d809b461cb97b1bb687a804dd4fc +directory = usrsctp-ebb18adac6501bad4501b1f6dccb67a1c85cc299 +source_url = https://github.com/sctplab/usrsctp/archive/ebb18adac6501bad4501b1f6dccb67a1c85cc299.zip +source_filename = ebb18adac6501bad4501b1f6dccb67a1c85cc299.zip +source_hash = e77a855ce395b877e9f2aa7ebe070dfaf5cb11cfecdeb424cc876fc0d98e5d11 [provide] usrsctp = usrsctp_dep diff --git a/worker/tasks.py b/worker/tasks.py index 6e471b2989..31e64c80f7 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -46,7 +46,7 @@ NUM_CORES = len(os.sched_getaffinity(0)) if hasattr(os, 'sched_getaffinity') else os.cpu_count(); PYTHON = os.getenv('PYTHON') or sys.executable; MESON = os.getenv('MESON') or f'{PIP_MESON_NINJA_DIR}/bin/meson'; -MESON_VERSION = os.getenv('MESON_VERSION') or '1.2.1'; +MESON_VERSION = os.getenv('MESON_VERSION') or '1.3.0'; # MESON_ARGS can be used to provide extra configuration parameters to meson, # such as adding defines or changing optimization options. For instance, use # `MESON_ARGS="-Dms_log_trace=true -Dms_log_file_line=true" npm i` to compile From ab46e362ef8753195e3240edfdc9d4639b35ce7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 4 Dec 2023 13:16:25 +0100 Subject: [PATCH 224/525] Update NPM deps --- package-lock.json | 60 +++++++++++++++++++++++------------------------ package.json | 4 ++-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5367a612d3..acd7342c7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,10 +21,10 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.10", - "@types/node": "^20.10.0", + "@types/node": "^20.10.3", "@typescript-eslint/eslint-plugin": "^6.13.1", "@typescript-eslint/parser": "^6.13.1", - "eslint": "^8.54.0", + "eslint": "^8.55.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", "marked": "^11.0.0", @@ -742,9 +742,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -765,9 +765,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", - "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1619,9 +1619,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", - "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "version": "20.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", + "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3023,15 +3023,15 @@ } }, "node_modules/eslint": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", - "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.54.0", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7284,9 +7284,9 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -7301,9 +7301,9 @@ } }, "@eslint/js": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", - "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", "dev": true }, "@humanwhocodes/config-array": { @@ -8006,9 +8006,9 @@ "dev": true }, "@types/node": { - "version": "20.10.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", - "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "version": "20.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", + "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -8949,15 +8949,15 @@ "dev": true }, "eslint": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", - "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.54.0", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", diff --git a/package.json b/package.json index c32d10c51c..8dc2401826 100644 --- a/package.json +++ b/package.json @@ -105,10 +105,10 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.10", - "@types/node": "^20.10.0", + "@types/node": "^20.10.3", "@typescript-eslint/eslint-plugin": "^6.13.1", "@typescript-eslint/parser": "^6.13.1", - "eslint": "^8.54.0", + "eslint": "^8.55.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", "marked": "^11.0.0", From b578d422ded68c00edca948fb28d3d489b4bb2f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 4 Dec 2023 16:16:14 +0100 Subject: [PATCH 225/525] Avoid C++ unused goto symbol warning when liburing is not supported (#1250) --- worker/src/handles/TcpConnectionHandle.cpp | 9 +++++---- worker/src/handles/UdpSocketHandle.cpp | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/worker/src/handles/TcpConnectionHandle.cpp b/worker/src/handles/TcpConnectionHandle.cpp index f254ce8673..c2de7515d8 100644 --- a/worker/src/handles/TcpConnectionHandle.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -265,17 +265,18 @@ void TcpConnectionHandle::Write( return; } -#endif write_libuv: +#endif + + // First try uv_try_write(). In case it can not directly write all the given + // data then build a uv_req_t and use uv_write(). + const size_t totalLen = len1 + len2; uv_buf_t buffers[2]; int written{ 0 }; int err; - // First try uv_try_write(). In case it can not directly write all the given - // data then build a uv_req_t and use uv_write(). - buffers[0] = uv_buf_init(reinterpret_cast(const_cast(data1)), len1); buffers[1] = uv_buf_init(reinterpret_cast(const_cast(data2)), len2); written = uv_try_write(reinterpret_cast(this->uvHandle), buffers, 2); diff --git a/worker/src/handles/UdpSocketHandle.cpp b/worker/src/handles/UdpSocketHandle.cpp index e5d9c91fa9..a963957c6d 100644 --- a/worker/src/handles/UdpSocketHandle.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -190,9 +190,10 @@ void UdpSocketHandle::Send( return; } -#endif send_libuv: +#endif + // First try uv_udp_try_send(). In case it can not directly send the datagram // then build a uv_req_t and use uv_udp_send(). From 5db9b8aefdc8b2e03de474a307478556ebde8656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 4 Dec 2023 16:25:07 +0100 Subject: [PATCH 226/525] 3.13.7 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c1c9ca068..2880121d81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.13.7 * Update worker dependencies ([PR #1201](https://github.com/versatica/mediasoup/pull/1201)): * abseil-cpp 20230802.0-2 diff --git a/package-lock.json b/package-lock.json index acd7342c7b..dbb2168b91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.6", + "version": "3.13.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.6", + "version": "3.13.7", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 8dc2401826..b15f2424a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.6", + "version": "3.13.7", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From baf3f49e054c401e211d2eb4383754b0aabeef39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 4 Dec 2023 16:34:44 +0100 Subject: [PATCH 227/525] Update Cargo mediasoup to 0.13.0 and mediasoup-sys to 0.7.0 (#1247) --- rust/CHANGELOG.md | 89 ++++++++++++++++++++++++++--------------------- rust/Cargo.toml | 4 +-- worker/Cargo.toml | 2 +- 3 files changed, 53 insertions(+), 42 deletions(-) diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index 4b536cd586..4697ba666e 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +# 0.13.0 + +* Updates from mediasoup TypeScript `3.13.0..=3.13.7`. +* General mediasoup changes: + * Switch from JSON based messages to `flatbuffers` (PR #1064). + * Enable `liburing` usage for Linux (kernel versions >= 6) (PR #1218). + * Add pause/resume API in `DataProducer` and `DataConsumer` (PR #1104). + * DataChannel subchannels feature (PR #1152). + * `Worker`: Make DTLS fragment stay within MTU size range (PR #1156). + * Replace make + Makefile with Python Invoke library + tasks.py (also fix installation under path with whitespaces) (PR #1239). + # 0.12.0 * Updates from mediasoup TypeScript `3.11.9..=3.12.16`. @@ -32,9 +43,9 @@ # 0.9.3 -* Fix a segfaults in tests and under multithreaded executor -* Fix another racy deadlock situation -* Expose hierarchical dependencies of ownership of Rust data structures, now it is possible to call `consumer.transport().router().worker().worker_manager()` +* Fix a segfaults in tests and under multithreaded executor. +* Fix another racy deadlock situation. +* Expose hierarchical dependencies of ownership of Rust data structures, now it is possible to call `consumer.transport().router().worker().worker_manager()`. * General mediasoup changes: * ICE renomination support (PR #756). * Update `libuv` to 1.43.0. @@ -52,20 +63,20 @@ # 0.9.1 -* Fix cleanup of build artifacts -* Make `Transport` implement `Send` -* Another fix to rare deadlock -* Improved Windows support (doesn't require MSVS activation) +* Fix cleanup of build artifacts. +* Make `Transport` implement `Send`. +* Another fix to rare deadlock. +* Improved Windows support (doesn't require MSVS activation). # 0.9.0 -* Fix for receiving data over payload channel -* Support thread initializer function for worker threads, can be used for pinning worker threads to CPU cores -* Significant worker communication optimizations (especially latency) -* Switch from file descriptors to function calls when communicating with worker -* Various optimizations that caused minor breaking changes to public API -* Requests no longer have internal timeout, but they can now be cancelled, add your own timeouts on top if needed -* Windows support +* Fix for receiving data over payload channel. +* Support thread initializer function for worker threads, can be used for pinning worker threads to CPU cores. +* Significant worker communication optimizations (especially latency). +* Switch from file descriptors to function calls when communicating with worker. +* Various optimizations that caused minor breaking changes to public API. +* Requests no longer have internal timeout, but they can now be cancelled, add your own timeouts on top if needed. +* Windows support. * General mediasoup changes: * Replaces GYP build system with fully-functional Meson build system (PR #622). * `Consumer`: Modification of bitrate allocation algorithm (PR #708). @@ -73,54 +84,54 @@ # 0.8.5 -* Fix types for `round_trip_time` and `bitrate_by_layer` fields `ProducerStat` and `ConsumerStat` -* Accumulation of worker fixes +* Fix types for `round_trip_time` and `bitrate_by_layer` fields `ProducerStat` and `ConsumerStat`. +* Accumulation of worker fixes. # 0.8.4 -* Add Active Speaker Observer to prelude -* Fix consumers preventing producers from being closed (regression introduced in 0.8.3) +* Add Active Speaker Observer to prelude. +* Fix consumers preventing producers from being closed (regression introduced in 0.8.3). # 0.8.3 -* prelude module containing traits and structs that should be sufficient for most basic mediasoup-based apps +* prelude module containing traits and structs that should be sufficient for most basic mediasoup-based apps. * Dominant Speaker Event (PR #603 by @SteveMcFarlin). ### 0.8.2 -* Support for optional fixed port on transports +* Support for optional fixed port on transports. ### 0.8.1 -* Add convenience methods for getting information from `TransportTuple` enum, especially local IP/port +* Add convenience methods for getting information from `TransportTuple` enum, especially local IP/port. * Add `mid` option in `ConsumerOptions` to provide way to override MID -* Add convenience method `ConsumerStats::consumer_stat()` +* Add convenience method `ConsumerStats::consumer_stat()`. ### 0.8.0 -* `NonClosingProducer` removed (use `PipedProducer` instead, they were identical) -* `RtpHeaderExtensionUri::as_str()` now takes `self` instead of `&self` -* `kind` field of `RtpHeaderExtension` is no longer optional -* Refactor `ScalabilityMode` from being a string to enum, make sure layers are not zero on type system level -* Concrete types for info field of tracing events +* `NonClosingProducer` removed (use `PipedProducer` instead, they were identical). +* `RtpHeaderExtensionUri::as_str()` now takes `self` instead of `&self`. +* `kind` field of `RtpHeaderExtension` is no longer optional. +* Refactor `ScalabilityMode` from being a string to enum, make sure layers are not zero on type system level. +* Concrete types for info field of tracing events. ### 0.7.2 -* Thread and memory safety fixes in mediasoup-sys -* macOS support -* `NonClosingProducer` renamed into `PipedProducer` with better docs -* Internal restructuring of modules for better compatibility with IDEs -* Feature level updated to mediasoup `3.7.6` +* Thread and memory safety fixes in mediasoup-sys. +* macOS support. +* `NonClosingProducer` renamed into `PipedProducer` with better docs. +* Internal restructuring of modules for better compatibility with IDEs. +* Feature level updated to mediasoup `3.7.6`. ### 0.7.0 -* Switch from running C++ worker processes to worker threads using mediasoup-sys that wraps mediasoup-worker into library -* Simplify `WorkerManager::new()` and `WorkerManager::with_executor()` API as the result of above -* Support `rtxPacketsDiscarded` in `Producer` stats -* Enable Rust 2018 idioms warnings -* Make sure all public types have `Debug` implementation on them -* Enforce docs on public types and add missing documentation -* Remove `RtpCodecParametersParameters::new()` (`RtpCodecParametersParameters::default()` does the same thing) +* Switch from running C++ worker processes to worker threads using mediasoup-sys that wraps mediasoup-worker into library. +* Simplify `WorkerManager::new()` and `WorkerManager::with_executor()` API as the result of above. +* Support `rtxPacketsDiscarded` in `Producer` stats. +* Enable Rust 2018 idioms warnings. +* Make sure all public types have `Debug` implementation on them. +* Enforce docs on public types and add missing documentation. +* Remove `RtpCodecParametersParameters::new()` (`RtpCodecParametersParameters::default()` does the same thing). ### 0.6.0 diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 968b5e3d45..4c35295b11 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup" -version = "0.12.0" +version = "0.13.0" description = "Cutting Edge WebRTC Video Conferencing in Rust" categories = ["api-bindings", "multimedia", "network-programming"] authors = ["Nazar Mokrynskyi "] @@ -46,7 +46,7 @@ version = "0.8.1" [dependencies.mediasoup-sys] path = "../worker" -version = "0.6.0" +version = "0.7.0" [dependencies.parking_lot] version = "0.12.1" diff --git a/worker/Cargo.toml b/worker/Cargo.toml index a3a5d412ce..edf5687367 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup-sys" -version = "0.6.0" +version = "0.7.0" description = "FFI bindings to C++ libmediasoup-worker" authors = ["Nazar Mokrynskyi "] edition = "2021" From 858b27abc8fb2e749b714500e6748dace3ce3965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 4 Dec 2023 17:01:00 +0100 Subject: [PATCH 228/525] Update Cargo.lock --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 786fcb172d..25f9f06ee3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1355,7 +1355,7 @@ checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" [[package]] name = "mediasoup" -version = "0.12.0" +version = "0.13.0" dependencies = [ "actix", "actix-web", @@ -1392,7 +1392,7 @@ dependencies = [ [[package]] name = "mediasoup-sys" -version = "0.6.0" +version = "0.7.0" dependencies = [ "planus", "planus-codegen", From dba41d0a81fa9d734cbd203dea1c895eb32b6243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 4 Dec 2023 18:20:52 +0100 Subject: [PATCH 229/525] Update NPM eslint deps --- package-lock.json | 332 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 168 insertions(+), 168 deletions(-) diff --git a/package-lock.json b/package-lock.json index dbb2168b91..527b9f4462 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,8 +22,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.10", "@types/node": "^20.10.3", - "@typescript-eslint/eslint-plugin": "^6.13.1", - "@typescript-eslint/parser": "^6.13.1", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", "eslint": "^8.55.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", @@ -1661,16 +1661,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.1.tgz", - "integrity": "sha512-5bQDGkXaxD46bPvQt08BUz9YSaO4S0fB1LB5JHQuXTfkGPI3+UUeS387C/e9jRie5GqT8u5kFTrMvAjtX4O5kA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", + "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/type-utils": "6.13.1", - "@typescript-eslint/utils": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/type-utils": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1696,13 +1696,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", - "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1713,9 +1713,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", - "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1726,13 +1726,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", - "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1753,17 +1753,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", - "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" }, "engines": { @@ -1778,12 +1778,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", - "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1795,15 +1795,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.1.tgz", - "integrity": "sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", + "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4" }, "engines": { @@ -1823,13 +1823,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", - "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1840,9 +1840,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", - "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1853,13 +1853,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", - "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1880,12 +1880,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", - "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1914,13 +1914,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.1.tgz", - "integrity": "sha512-A2qPlgpxx2v//3meMqQyB1qqTg1h1dJvzca7TugM3Yc2USDY+fsRBiojAEo92HO7f5hW5mjAUF6qobOPzlBCBQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", + "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.13.1", - "@typescript-eslint/utils": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/utils": "6.13.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1941,13 +1941,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", - "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1958,9 +1958,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", - "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1971,13 +1971,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", - "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1998,17 +1998,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", - "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" }, "engines": { @@ -2023,12 +2023,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", - "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -8048,16 +8048,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.1.tgz", - "integrity": "sha512-5bQDGkXaxD46bPvQt08BUz9YSaO4S0fB1LB5JHQuXTfkGPI3+UUeS387C/e9jRie5GqT8u5kFTrMvAjtX4O5kA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", + "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/type-utils": "6.13.1", - "@typescript-eslint/utils": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/type-utils": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8067,29 +8067,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", - "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" } }, "@typescript-eslint/types": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", - "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", - "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8098,69 +8098,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", - "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", - "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.1.tgz", - "integrity": "sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", + "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", - "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" } }, "@typescript-eslint/types": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", - "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", - "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8169,12 +8169,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", - "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" } } @@ -8191,41 +8191,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.1.tgz", - "integrity": "sha512-A2qPlgpxx2v//3meMqQyB1qqTg1h1dJvzca7TugM3Yc2USDY+fsRBiojAEo92HO7f5hW5mjAUF6qobOPzlBCBQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", + "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.13.1", - "@typescript-eslint/utils": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/utils": "6.13.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", - "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" } }, "@typescript-eslint/types": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", - "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", - "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8234,27 +8234,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", - "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", - "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" } } diff --git a/package.json b/package.json index b15f2424a5..2139fe0d84 100644 --- a/package.json +++ b/package.json @@ -106,8 +106,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.10", "@types/node": "^20.10.3", - "@typescript-eslint/eslint-plugin": "^6.13.1", - "@typescript-eslint/parser": "^6.13.1", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", "eslint": "^8.55.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", From bf57b8a41f56dafb522c3d7c28363282f67dc6a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 4 Dec 2023 18:22:33 +0100 Subject: [PATCH 230/525] Node: jest, add modulePathIgnorePatters option (#1251) Since flatbuffers is a subproject in worker folder there, jest was complaining that there were two different modules for flatbuffers --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2139fe0d84..2c4e07f593 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,8 @@ "node/src/fbs", "node/src/tests" ], - "cacheDirectory": ".cache/jest" + "cacheDirectory": ".cache/jest", + "modulePathIgnorePatterns": ["worker/", "rust/"] }, "dependencies": { "debug": "^4.3.4", From b986e21e4f46a1927d7f5e15f4fa8973dc44403b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 4 Dec 2023 18:28:48 +0100 Subject: [PATCH 231/525] LibUring: Enable liburing usage for SCTP data delivery (#1249) liburing: Enable liburing usage for SCTP data delivery --- CHANGELOG.md | 5 +++++ worker/src/DepUsrSCTP.cpp | 17 +++++++++++++++++ worker/src/RTC/Router.cpp | 19 +++++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2880121d81..6d4ddc711b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### Next + +* LibUring: Enable liburing usage for SCTP data delivery ([PR 1249](https://github.com/versatica/mediasoup/pull/1249)). + + ### 3.13.7 * Update worker dependencies ([PR #1201](https://github.com/versatica/mediasoup/pull/1201)): diff --git a/worker/src/DepUsrSCTP.cpp b/worker/src/DepUsrSCTP.cpp index a19eb51a04..4eb0e40713 100644 --- a/worker/src/DepUsrSCTP.cpp +++ b/worker/src/DepUsrSCTP.cpp @@ -2,6 +2,9 @@ // #define MS_LOG_DEV_LEVEL 3 #include "DepUsrSCTP.hpp" +#ifdef MS_LIBURING_SUPPORTED +#include "DepLibUring.hpp" +#endif #include "DepLibUV.hpp" #include "Logger.hpp" #include @@ -249,7 +252,21 @@ void DepUsrSCTP::Checker::OnTimer(TimerHandle* /*timer*/) auto nowMs = DepLibUV::GetTimeMs(); const int elapsedMs = this->lastCalledAtMs ? static_cast(nowMs - this->lastCalledAtMs) : 0; +#ifdef MS_LIBURING_SUPPORTED + // Activate liburing usage. + // 'usrsctp_handle_timers()' will synchronously call the send/recv + // callbacks for the pending data. If there are multiple messages to be + // sent over the network then we will send those messages within a single + // system call. + DepLibUring::SetActive(); +#endif + usrsctp_handle_timers(elapsedMs); +#ifdef MS_LIBURING_SUPPORTED + // Submit all prepared submission entries. + DepLibUring::Submit(); +#endif + this->lastCalledAtMs = nowMs; } diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index b4e2dcc417..150d5af350 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -921,9 +921,24 @@ namespace RTC auto& dataConsumers = this->mapDataProducerDataConsumers.at(dataProducer); - for (auto* dataConsumer : dataConsumers) + if (!dataConsumers.empty()) { - dataConsumer->SendMessage(msg, len, ppid, subchannels, requiredSubchannel); +#ifdef MS_LIBURING_SUPPORTED + // Activate liburing usage. + // The effective sending could be synchronous, thus we would send those + // messages within a single system call. + DepLibUring::SetActive(); +#endif + + for (auto* dataConsumer : dataConsumers) + { + dataConsumer->SendMessage(msg, len, ppid, subchannels, requiredSubchannel); + } + +#ifdef MS_LIBURING_SUPPORTED + // Submit all prepared submission entries. + DepLibUring::Submit(); +#endif } } From 8c8c7700448189d6b6a4ae4abcdbbd5c34ca7ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Tue, 5 Dec 2023 12:27:52 +0100 Subject: [PATCH 232/525] Disable liburing by default (#1253) Disable liburing by default While investigating https://github.com/versatica/mediasoup/pull/1201, disable liburing by default. In order to enable it, use MESON_ARGS as usual. ie: MESON_ARGS=-Dms_enable_liburing=true npm install --- CHANGELOG.md | 1 + worker/meson.build | 2 +- worker/meson_options.txt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d4ddc711b..398517fc92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Next * LibUring: Enable liburing usage for SCTP data delivery ([PR 1249](https://github.com/versatica/mediasoup/pull/1249)). +* LibUring: Disable by default ([PR 1253](https://github.com/versatica/mediasoup/pull/1253)). ### 3.13.7 diff --git a/worker/meson.build b/worker/meson.build index 35a3a82874..3348adad9d 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -258,7 +258,7 @@ if host_machine.system() == 'windows' ] endif -if host_machine.system() == 'linux' +if host_machine.system() == 'linux' and get_option('ms_enable_liburing') kernel_version = run_command('uname', '-r').stdout().strip() # Enable liburing for kernel versions greather than or equal to 6. diff --git a/worker/meson_options.txt b/worker/meson_options.txt index debe84aa26..c8779fac94 100644 --- a/worker/meson_options.txt +++ b/worker/meson_options.txt @@ -1,3 +1,4 @@ option('ms_log_trace', type : 'boolean', value : false, description : 'When enabled, logs the current method/function if current log level is "debug"') option('ms_log_file_line', type : 'boolean', value : false, description : 'When enabled, all the logging macros print more verbose information, including current file and line') option('ms_rtc_logger_rtp', type : 'boolean', value : false, description : 'When enabled, prints a line with information for each RTP packet') +option('ms_enable_liburing', type : 'boolean', value : false, description : 'When enabled, enables liburing') From 5b51668ce2ffd77cc368f0a9092d3ee5d40add1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Tue, 5 Dec 2023 12:31:05 +0100 Subject: [PATCH 233/525] 3.13.8 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 398517fc92..7eff043d3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 3.13.8 * LibUring: Enable liburing usage for SCTP data delivery ([PR 1249](https://github.com/versatica/mediasoup/pull/1249)). * LibUring: Disable by default ([PR 1253](https://github.com/versatica/mediasoup/pull/1253)). diff --git a/package-lock.json b/package-lock.json index 527b9f4462..776536771b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.7", + "version": "3.13.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.7", + "version": "3.13.8", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 2c4e07f593..4f7db0c617 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.7", + "version": "3.13.8", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From bb9383df3b494059b07e65f15498a4d52cad43a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 6 Dec 2023 13:48:51 +0100 Subject: [PATCH 234/525] Update npm types/jest --- package-lock.json | 14 +++++++------- package.json | 7 +++++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 776536771b..47badc5ba2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.10", + "@types/jest": "^29.5.11", "@types/node": "^20.10.3", "@typescript-eslint/eslint-plugin": "^6.13.2", "@typescript-eslint/parser": "^6.13.2", @@ -1591,9 +1591,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.10", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", - "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -7978,9 +7978,9 @@ } }, "@types/jest": { - "version": "29.5.10", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", - "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", "dev": true, "requires": { "expect": "^29.0.0", diff --git a/package.json b/package.json index 4f7db0c617..15ded1fa8c 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,10 @@ "node/src/tests" ], "cacheDirectory": ".cache/jest", - "modulePathIgnorePatterns": ["worker/", "rust/"] + "modulePathIgnorePatterns": [ + "worker/", + "rust/" + ] }, "dependencies": { "debug": "^4.3.4", @@ -105,7 +108,7 @@ "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.10", + "@types/jest": "^29.5.11", "@types/node": "^20.10.3", "@typescript-eslint/eslint-plugin": "^6.13.2", "@typescript-eslint/parser": "^6.13.2", From 716571d6fa45174c82de077bfc908c1e8f19ebdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 6 Dec 2023 14:08:57 +0100 Subject: [PATCH 235/525] Update worker liburing dependency to 2.4-2 (#1254) --- CHANGELOG.md | 5 +++++ worker/subprojects/liburing.wrap | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eff043d3a..0cde9fde0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* Update worker liburing dependency to 2.4-2 ([PR #1254](https://github.com/versatica/mediasoup/pull/1254)): + + ### 3.13.8 * LibUring: Enable liburing usage for SCTP data delivery ([PR 1249](https://github.com/versatica/mediasoup/pull/1249)). diff --git a/worker/subprojects/liburing.wrap b/worker/subprojects/liburing.wrap index 1074fc1e75..40e019eb9c 100644 --- a/worker/subprojects/liburing.wrap +++ b/worker/subprojects/liburing.wrap @@ -3,11 +3,11 @@ directory = liburing-liburing-2.4 source_url = https://github.com/axboe/liburing/archive/refs/tags/liburing-2.4.tar.gz source_filename = liburing-2.4.tar.gz source_hash = 2398ec82d967a6f903f3ae1fd4541c754472d3a85a584dc78c5da2fabc90706b -patch_filename = liburing_2.4-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/liburing_2.4-1/get_patch -patch_hash = 0dd939828da6a7c6d22c0f4db879405e74f9ac7153927c365642a28f871c92c2 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/liburing_2.4-1/liburing-2.4.tar.gz -wrapdb_version = 2.4-1 +patch_filename = liburing_2.4-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/liburing_2.4-2/get_patch +patch_hash = 0435ae1012065fa96a22e1068c2e39e2f7c7c03b58a812774434a6e7455d7f20 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/liburing_2.4-2/liburing-2.4.tar.gz +wrapdb_version = 2.4-2 [provide] dependency_names = liburing From ad2d8146e21f6343fb8bcd189c2a9e1e5215925c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 6 Dec 2023 15:17:33 +0100 Subject: [PATCH 236/525] Enable liburing by default (#1255) - Bonus track: add explicit `--foreground-scripts` to all `npm ci` commands in CI actions - Bonus track: add `check: true` to `run_command` in our `meson.build` to avoid issue https://github.com/versatica/mediasoup/issues/1256 --- .github/workflows/mediasoup-node.yaml | 2 +- .github/workflows/mediasoup-worker-prebuild.yaml | 4 ++-- .github/workflows/mediasoup-worker.yaml | 2 +- CHANGELOG.md | 7 ++++--- worker/meson.build | 4 ++-- worker/meson_options.txt | 8 ++++---- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index f22c707306..81c11b1b03 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -50,7 +50,7 @@ jobs: # NOTE: Add --force since otherwise `npm ci` fails in Node 16 because # @octokit/auth-token dev dependency requires Node >= 16. - name: npm ci - run: npm ci --force + run: npm ci --force --foreground-scripts - name: npm run lint:node run: npm run lint:node diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index ea1491cf72..6e3f2c3606 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -51,8 +51,8 @@ jobs: node-version: ${{ matrix.node }} # We need to install some NPM production deps for npm-scripts.mjs to work. - - name: npm ci - run: npm ci --ignore-scripts --omit=dev + - name: npm ci --ignore-scripts + run: npm ci --ignore-scripts --omit=dev --foreground-scripts # However we also need to install pip invoke manually (since # `--ignore-scripts` prevented invoke from being installed). diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index ac0cb4d042..6e48e2464d 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -70,7 +70,7 @@ jobs: # We need to install npm deps of worker/scripts/package.json. - name: npm ci --prefix worker/scripts - run: npm ci --prefix worker/scripts + run: npm ci --prefix worker/scripts --foreground-scripts # TODO: Maybe fix this one day. if: runner.os != 'Windows' diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cde9fde0d..0a66a144b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,13 +3,14 @@ ### NEXT -* Update worker liburing dependency to 2.4-2 ([PR #1254](https://github.com/versatica/mediasoup/pull/1254)): +* Update worker liburing dependency to 2.4-2 ([PR #1254](https://github.com/versatica/mediasoup/pull/1254)). +* liburing: Enable by default ([PR 1255](https://github.com/versatica/mediasoup/pull/1255)). ### 3.13.8 -* LibUring: Enable liburing usage for SCTP data delivery ([PR 1249](https://github.com/versatica/mediasoup/pull/1249)). -* LibUring: Disable by default ([PR 1253](https://github.com/versatica/mediasoup/pull/1253)). +* liburing: Enable liburing usage for SCTP data delivery ([PR 1249](https://github.com/versatica/mediasoup/pull/1249)). +* liburing: Disable by default ([PR 1253](https://github.com/versatica/mediasoup/pull/1253)). ### 3.13.7 diff --git a/worker/meson.build b/worker/meson.build index 3348adad9d..13a52bc243 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -258,8 +258,8 @@ if host_machine.system() == 'windows' ] endif -if host_machine.system() == 'linux' and get_option('ms_enable_liburing') - kernel_version = run_command('uname', '-r').stdout().strip() +if host_machine.system() == 'linux' and not get_option('ms_disable_liburing') + kernel_version = run_command('uname', '-r', check: true).stdout().strip() # Enable liburing for kernel versions greather than or equal to 6. if kernel_version[0].to_int() >= 6 diff --git a/worker/meson_options.txt b/worker/meson_options.txt index c8779fac94..0d1400e97a 100644 --- a/worker/meson_options.txt +++ b/worker/meson_options.txt @@ -1,4 +1,4 @@ -option('ms_log_trace', type : 'boolean', value : false, description : 'When enabled, logs the current method/function if current log level is "debug"') -option('ms_log_file_line', type : 'boolean', value : false, description : 'When enabled, all the logging macros print more verbose information, including current file and line') -option('ms_rtc_logger_rtp', type : 'boolean', value : false, description : 'When enabled, prints a line with information for each RTP packet') -option('ms_enable_liburing', type : 'boolean', value : false, description : 'When enabled, enables liburing') +option('ms_log_trace', type : 'boolean', value : false, description : 'When set to true, logs the current method/function if current log level is "debug"') +option('ms_log_file_line', type : 'boolean', value : false, description : 'When set to true, all the logging macros print more verbose information, including current file and line') +option('ms_rtc_logger_rtp', type : 'boolean', value : false, description : 'When set to true, prints a line with information for each RTP packet') +option('ms_disable_liburing', type : 'boolean', value : false, description : 'When set to true, disables liburing integration despite current host supports it') From 23b15871a1cd854920171db7354117c8cb587f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 6 Dec 2023 15:19:25 +0100 Subject: [PATCH 237/525] 3.13.9 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a66a144b8..d4fde47497 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.13.9 * Update worker liburing dependency to 2.4-2 ([PR #1254](https://github.com/versatica/mediasoup/pull/1254)). * liburing: Enable by default ([PR 1255](https://github.com/versatica/mediasoup/pull/1255)). diff --git a/package-lock.json b/package-lock.json index 47badc5ba2..4166bfae1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.8", + "version": "3.13.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.8", + "version": "3.13.9", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 15ded1fa8c..3e79de6bed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.8", + "version": "3.13.9", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From d8b30b5be06fbe0a0503a823ef9df1313016f538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 6 Dec 2023 15:22:16 +0100 Subject: [PATCH 238/525] cosmetic --- worker/tasks.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/worker/tasks.py b/worker/tasks.py index 31e64c80f7..ea397eea3b 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -1,4 +1,4 @@ -# Ignore these pylint warnings, concentions and refactoring messages: +# Ignore these pylint warnings, conventions and refactoring messages: # - W0301: Unnecessary semicolon (unnecessary-semicolon) # - W0622: Redefining built-in 'format' (redefined-builtin) # - W0702: No exception type(s) specified (bare-except) @@ -8,11 +8,13 @@ # pylint: disable=W0301,W0622,W0702,C0114,C0301 # -# This is a tasks.py file for the pip invoke package: https://docs.pyinvoke.org/. +# This is a tasks.py file for the Python invoke package: +# https://docs.pyinvoke.org/. # # It's a replacement of our Makefile with same tasks. # # Usage: +# pip install invoke # invoke --list # From 90f7511b7f7dcf8ef562a6be33910654c8b6508a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 6 Dec 2023 15:51:40 +0100 Subject: [PATCH 239/525] Update npm h264-profile-level-id to 1.0.2 --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4166bfae1b..71277ac469 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "dependencies": { "debug": "^4.3.4", "flatbuffers": "^23.5.26", - "h264-profile-level-id": "^1.0.1", + "h264-profile-level-id": "^1.0.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0" @@ -3647,11 +3647,11 @@ "dev": true }, "node_modules/h264-profile-level-id": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.0.1.tgz", - "integrity": "sha512-D3Rln/jKNjKDW5ZTJTK3niSoOGE+pFqPvRHHVgQN3G7umcn/zWGPUo8Q8VpDj16x3hKz++zVviRNRmXu5cpN+Q==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.0.2.tgz", + "integrity": "sha512-bsSv/bHq4eIUt4iMycA9rn1C28gtXwrKLAkbpzuZmkQp4u3M6QlF5y6DlTMy5fGDkVGbMLxFGeL7Ra8JKMm4Dg==", "dependencies": { - "debug": "^4.1.1" + "debug": "^4.3.4" }, "engines": { "node": ">=8.0.0" @@ -9399,11 +9399,11 @@ "dev": true }, "h264-profile-level-id": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.0.1.tgz", - "integrity": "sha512-D3Rln/jKNjKDW5ZTJTK3niSoOGE+pFqPvRHHVgQN3G7umcn/zWGPUo8Q8VpDj16x3hKz++zVviRNRmXu5cpN+Q==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.0.2.tgz", + "integrity": "sha512-bsSv/bHq4eIUt4iMycA9rn1C28gtXwrKLAkbpzuZmkQp4u3M6QlF5y6DlTMy5fGDkVGbMLxFGeL7Ra8JKMm4Dg==", "requires": { - "debug": "^4.1.1" + "debug": "^4.3.4" } }, "hard-rejection": { diff --git a/package.json b/package.json index 3e79de6bed..1bcdcd8377 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "dependencies": { "debug": "^4.3.4", "flatbuffers": "^23.5.26", - "h264-profile-level-id": "^1.0.1", + "h264-profile-level-id": "^1.0.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0" From edc0d8cd39a1d983caa322e384d114707a27852e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 7 Dec 2023 18:26:31 +0100 Subject: [PATCH 240/525] Add --no-user in pip install commands (#1257) --- CHANGELOG.md | 5 +++++ npm-scripts.mjs | 2 +- package-lock.json | 28 ++++++++++++++-------------- package.json | 4 ++-- worker/Makefile | 2 +- worker/tasks.py | 10 ++++++---- 6 files changed, 29 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4fde47497..e850171799 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* `tasks.py`: Always include `--no-user` in `pip install` commands to avoid the "can not combine --user and --target" error in Windows ([PR #1257](https://github.com/versatica/mediasoup/pull/1257)). + + ### 3.13.9 * Update worker liburing dependency to 2.4-2 ([PR #1254](https://github.com/versatica/mediasoup/pull/1254)). diff --git a/npm-scripts.mjs b/npm-scripts.mjs index f3982f253e..d6754989fc 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -317,7 +317,7 @@ function installInvoke() // Install pip invoke into custom location, so we don't depend on system-wide // installation. executeCmd( - `"${PYTHON}" -m pip install --upgrade --target="${PIP_INVOKE_DIR}" invoke`, + `"${PYTHON}" -m pip install --upgrade --no-user --target="${PIP_INVOKE_DIR}" invoke`, /* exitOnError */ true ); } diff --git a/package-lock.json b/package-lock.json index 71277ac469..92d501c377 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.3", + "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "^6.13.2", "@typescript-eslint/parser": "^6.13.2", "eslint": "^8.55.0", @@ -32,7 +32,7 @@ "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", - "typescript": "^5.3.2" + "typescript": "^5.3.3" }, "engines": { "node": ">=16" @@ -1619,9 +1619,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", - "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -6458,9 +6458,9 @@ } }, "node_modules/typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -8006,9 +8006,9 @@ "dev": true }, "@types/node": { - "version": "20.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", - "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -11363,9 +11363,9 @@ "dev": true }, "typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true }, "undici-types": { diff --git a/package.json b/package.json index 1bcdcd8377..8885f0c1a2 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.3", + "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "^6.13.2", "@typescript-eslint/parser": "^6.13.2", "eslint": "^8.55.0", @@ -120,6 +120,6 @@ "pick-port": "^1.0.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", - "typescript": "^5.3.2" + "typescript": "^5.3.3" } } diff --git a/worker/Makefile b/worker/Makefile index fd21742768..bf5a2aba3a 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -47,7 +47,7 @@ invoke: ifeq ($(wildcard $(PIP_INVOKE_DIR)),) # Install pip invoke into custom location, so we don't depend on system-wide # installation. - $(PYTHON) -m pip install --upgrade --target="$(PIP_INVOKE_DIR)" invoke + $(PYTHON) -m pip install --upgrade --no-user --target="$(PIP_INVOKE_DIR)" invoke endif meson-ninja: invoke diff --git a/worker/tasks.py b/worker/tasks.py index ea397eea3b..e366c65d91 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -34,6 +34,8 @@ MEDIASOUP_INSTALL_DIR = os.getenv('MEDIASOUP_INSTALL_DIR') or f'{MEDIASOUP_OUT_DIR}/{MEDIASOUP_BUILDTYPE}'; BUILD_DIR = os.getenv('BUILD_DIR') or f'{MEDIASOUP_INSTALL_DIR}/build'; # Custom pip folder for invoke package. +# NOTE: We invoke `pip install` always with `--no-user` to make it not complain +# about "can not combine --user and --target". PIP_INVOKE_DIR = f'{MEDIASOUP_OUT_DIR}/pip_invoke'; # Custom pip folder for meson and ninja packages. PIP_MESON_NINJA_DIR = f'{MEDIASOUP_OUT_DIR}/pip_meson_ninja'; @@ -106,14 +108,14 @@ def meson_ninja(ctx): # fallback to command without `--system` if the first one fails. try: ctx.run( - f'"{PYTHON}" -m pip install --system --upgrade --target="{PIP_MESON_NINJA_DIR}" pip setuptools', + f'"{PYTHON}" -m pip install --system --upgrade --no-user --target="{PIP_MESON_NINJA_DIR}" pip setuptools', echo=True, hide=True, shell=SHELL ); except: ctx.run( - f'"{PYTHON}" -m pip install --upgrade --target="{PIP_MESON_NINJA_DIR}" pip setuptools', + f'"{PYTHON}" -m pip install --upgrade --no-user --target="{PIP_MESON_NINJA_DIR}" pip setuptools', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -126,7 +128,7 @@ def meson_ninja(ctx): # Install meson and ninja using pip into our custom location, so we don't # depend on system-wide installation. ctx.run( - f'"{PYTHON}" -m pip install --upgrade --target="{PIP_MESON_NINJA_DIR}" {pip_build_binaries} meson=={MESON_VERSION} ninja=={NINJA_VERSION}', + f'"{PYTHON}" -m pip install --upgrade --no-user --target="{PIP_MESON_NINJA_DIR}" {pip_build_binaries} meson=={MESON_VERSION} ninja=={NINJA_VERSION}', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -371,7 +373,7 @@ def lint(ctx): if not os.path.isdir(PIP_PYLINT_DIR): # Install pylint using pip into our custom location. ctx.run( - f'"{PYTHON}" -m pip install --upgrade --target="{PIP_PYLINT_DIR}" pylint=={PYLINT_VERSION}', + f'"{PYTHON}" -m pip install --upgrade --no-user --target="{PIP_PYLINT_DIR}" pylint=={PYLINT_VERSION}', echo=True, pty=PTY_SUPPORTED, shell=SHELL From 3fe0a1e9134c5ce5744aabf0f373b16a3a398392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 7 Dec 2023 18:29:34 +0100 Subject: [PATCH 241/525] 3.13.10 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e850171799..4b1269cf83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.13.10 * `tasks.py`: Always include `--no-user` in `pip install` commands to avoid the "can not combine --user and --target" error in Windows ([PR #1257](https://github.com/versatica/mediasoup/pull/1257)). diff --git a/package-lock.json b/package-lock.json index 92d501c377..27c691dfd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.9", + "version": "3.13.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.9", + "version": "3.13.10", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 8885f0c1a2..a4d4042b6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.9", + "version": "3.13.10", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From a68ce5d0617e35eb735510a683b71b3f76b55fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 12 Dec 2023 09:46:01 +0100 Subject: [PATCH 242/525] Update NPM dev deps --- package-lock.json | 346 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 176 insertions(+), 176 deletions(-) diff --git a/package-lock.json b/package-lock.json index 27c691dfd7..e1095508a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,12 +22,12 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.4", - "@typescript-eslint/eslint-plugin": "^6.13.2", - "@typescript-eslint/parser": "^6.13.2", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", "eslint": "^8.55.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^11.0.0", + "marked": "^11.1.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -1661,16 +1661,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", - "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.14.0.tgz", + "integrity": "sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/type-utils": "6.13.2", - "@typescript-eslint/utils": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.14.0", + "@typescript-eslint/type-utils": "6.14.0", + "@typescript-eslint/utils": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1696,13 +1696,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", - "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", + "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1713,9 +1713,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", - "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", + "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1726,13 +1726,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", - "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", + "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1753,17 +1753,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", - "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz", + "integrity": "sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/scope-manager": "6.14.0", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/typescript-estree": "6.14.0", "semver": "^7.5.4" }, "engines": { @@ -1778,12 +1778,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", - "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", + "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/types": "6.14.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1795,15 +1795,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", - "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.14.0.tgz", + "integrity": "sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.14.0", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/typescript-estree": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4" }, "engines": { @@ -1823,13 +1823,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", - "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", + "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1840,9 +1840,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", - "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", + "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1853,13 +1853,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", - "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", + "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1880,12 +1880,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", - "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", + "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/types": "6.14.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1914,13 +1914,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", - "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.14.0.tgz", + "integrity": "sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/typescript-estree": "6.14.0", + "@typescript-eslint/utils": "6.14.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1941,13 +1941,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", - "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", + "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1958,9 +1958,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", - "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", + "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1971,13 +1971,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", - "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", + "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1998,17 +1998,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", - "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz", + "integrity": "sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/scope-manager": "6.14.0", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/typescript-estree": "6.14.0", "semver": "^7.5.4" }, "engines": { @@ -2023,12 +2023,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", - "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", + "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/types": "6.14.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4849,9 +4849,9 @@ } }, "node_modules/marked": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.0.0.tgz", - "integrity": "sha512-2GsW34uXaFEGTQ/+3rCnNC6vUYTAgFuDLGl70v/aWinA5mIJtTrrFAmfbLOfVvgPyxXuDVL9He/7reCK+6j3Sw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.0.tgz", + "integrity": "sha512-fvKJWAPEafVj1dwGwcPI5mBB/0pvViL6NlCbNDG1HOIRwwAU/jeMoFxfbRLuirO1wRH7m4yPvBqD/O1wyWvayw==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -8048,16 +8048,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", - "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.14.0.tgz", + "integrity": "sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/type-utils": "6.13.2", - "@typescript-eslint/utils": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.14.0", + "@typescript-eslint/type-utils": "6.14.0", + "@typescript-eslint/utils": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8067,29 +8067,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", - "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", + "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0" } }, "@typescript-eslint/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", - "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", + "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", - "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", + "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8098,69 +8098,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", - "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz", + "integrity": "sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/scope-manager": "6.14.0", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/typescript-estree": "6.14.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", - "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", + "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/types": "6.14.0", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", - "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.14.0.tgz", + "integrity": "sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.14.0", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/typescript-estree": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", - "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", + "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0" } }, "@typescript-eslint/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", - "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", + "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", - "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", + "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8169,12 +8169,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", - "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", + "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/types": "6.14.0", "eslint-visitor-keys": "^3.4.1" } } @@ -8191,41 +8191,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", - "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.14.0.tgz", + "integrity": "sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/typescript-estree": "6.14.0", + "@typescript-eslint/utils": "6.14.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", - "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", + "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0" } }, "@typescript-eslint/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", - "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", + "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", - "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", + "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/visitor-keys": "6.14.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8234,27 +8234,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", - "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz", + "integrity": "sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/scope-manager": "6.14.0", + "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/typescript-estree": "6.14.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", - "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", + "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/types": "6.14.0", "eslint-visitor-keys": "^3.4.1" } } @@ -10280,9 +10280,9 @@ "dev": true }, "marked": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.0.0.tgz", - "integrity": "sha512-2GsW34uXaFEGTQ/+3rCnNC6vUYTAgFuDLGl70v/aWinA5mIJtTrrFAmfbLOfVvgPyxXuDVL9He/7reCK+6j3Sw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.0.tgz", + "integrity": "sha512-fvKJWAPEafVj1dwGwcPI5mBB/0pvViL6NlCbNDG1HOIRwwAU/jeMoFxfbRLuirO1wRH7m4yPvBqD/O1wyWvayw==", "dev": true }, "meow": { diff --git a/package.json b/package.json index a4d4042b6b..0f8ba679d8 100644 --- a/package.json +++ b/package.json @@ -110,12 +110,12 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.4", - "@typescript-eslint/eslint-plugin": "^6.13.2", - "@typescript-eslint/parser": "^6.13.2", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", "eslint": "^8.55.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^11.0.0", + "marked": "^11.1.0", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From b2508b1bf49c8d58a78f55ab3a1b9757ec99e835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Tue, 12 Dec 2023 11:15:22 +0100 Subject: [PATCH 243/525] liburing: avoid extra memcpy on RTP (#1258) liburing: avoid extra memcpy on RTP Use an already allocated send buffer to directly encrypt the RTP rather than using the static EncryptBuffer that needs to be memcpy-ed before sending. If there are no send buffers available, the EncryptBuffer will be used. --- CHANGELOG.md | 5 ++ worker/include/DepLibUring.hpp | 37 ++++++++++++--- worker/src/DepLibUring.cpp | 87 ++++++++++++++++++++++++++++------ worker/src/RTC/SrtpSession.cpp | 30 ++++++++++-- 4 files changed, 134 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b1269cf83..14540ae398 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* liburing: avoid extra memcpy on RTP ([PR #1258](https://github.com/versatica/mediasoup/pull/1258)). + + ### 3.13.10 * `tasks.py`: Always include `--no-user` in `pip install` commands to avoid the "can not combine --user and --target" error in Windows ([PR #1257](https://github.com/versatica/mediasoup/pull/1257)). diff --git a/worker/include/DepLibUring.hpp b/worker/include/DepLibUring.hpp index 5c2481736c..7d3d3848e4 100644 --- a/worker/include/DepLibUring.hpp +++ b/worker/include/DepLibUring.hpp @@ -15,13 +15,23 @@ class DepLibUring /* Struct for the user data field of SQE and CQE. */ struct UserData { - uint8_t store[1500]{}; + // Pointer to send buffer. + uint8_t* store{ nullptr }; + // Frame len buffer for TCP. + uint8_t frameLen[2] = { 0 }; + // iovec for TCP, first item for framing, second item for payload. + struct iovec iov[2]; + // Send callback. onSendCallback* cb{ nullptr }; + // Index in userDatas array. size_t idx{ 0 }; }; /* Number of submission queue entries (SQE). */ static constexpr size_t QueueDepth{ 1024 * 4 }; + static constexpr size_t SendBufferSize{ 1500 }; + + using SendBuffer = uint8_t[SendBufferSize]; static bool IsRuntimeSupported(); static void ClassInit(); @@ -29,10 +39,11 @@ class DepLibUring static flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder); static void StartPollingCQEs(); static void StopPollingCQEs(); + static uint8_t* GetSendBuffer(); static bool PrepareSend( - int sockfd, const void* data, size_t len, const struct sockaddr* addr, onSendCallback* cb); + int sockfd, const uint8_t* data, size_t len, const struct sockaddr* addr, onSendCallback* cb); static bool PrepareWrite( - int sockfd, const void* data1, size_t len1, const void* data2, size_t len2, onSendCallback* cb); + int sockfd, const uint8_t* data1, size_t len1, const uint8_t* data2, size_t len2, onSendCallback* cb); static void Submit(); static void SetActive(); static bool IsActive(); @@ -50,10 +61,16 @@ class DepLibUring flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; void StartPollingCQEs(); void StopPollingCQEs(); + uint8_t* GetSendBuffer(); bool PrepareSend( - int sockfd, const void* data, size_t len, const struct sockaddr* addr, onSendCallback* cb); + int sockfd, const uint8_t* data, size_t len, const struct sockaddr* addr, onSendCallback* cb); bool PrepareWrite( - int sockfd, const void* data1, size_t len1, const void* data2, size_t len2, onSendCallback* cb); + int sockfd, + const uint8_t* data1, + size_t len1, + const uint8_t* data2, + size_t len2, + onSendCallback* cb); void Submit(); void SetActive() { @@ -78,6 +95,10 @@ class DepLibUring private: UserData* GetUserData(); + bool IsDataInSendBuffers(const uint8_t* data) const + { + return data >= this->sendBuffers[0] && data <= this->sendBuffers[DepLibUring::QueueDepth - 1]; + } private: // io_uring instance. @@ -88,10 +109,12 @@ class DepLibUring uv_poll_t* uvHandle{ nullptr }; // Whether we are currently sending RTP over io_uring. bool active{ false }; - // Pre-allocated UserData entries. - UserData userDataBuffer[QueueDepth]{}; + // Pre-allocated UserData's. + UserData userDatas[QueueDepth]{}; // Indexes of available UserData entries. std::queue availableUserDataEntries; + // Pre-allocated SendBuffer's. + SendBuffer sendBuffers[QueueDepth]; // Submission queue entry process count. uint64_t sqeProcessCount{ 0u }; // Submission queue entry miss count. diff --git a/worker/src/DepLibUring.cpp b/worker/src/DepLibUring.cpp index 627da3ecf0..a2c9226769 100644 --- a/worker/src/DepLibUring.cpp +++ b/worker/src/DepLibUring.cpp @@ -151,8 +151,17 @@ void DepLibUring::StopPollingCQEs() DepLibUring::liburing->StopPollingCQEs(); } +uint8_t* DepLibUring::GetSendBuffer() +{ + MS_TRACE(); + + MS_ASSERT(DepLibUring::liburing, "DepLibUring::liburing is not set"); + + return DepLibUring::liburing->GetSendBuffer(); +} + bool DepLibUring::PrepareSend( - int sockfd, const void* data, size_t len, const struct sockaddr* addr, onSendCallback* cb) + int sockfd, const uint8_t* data, size_t len, const struct sockaddr* addr, onSendCallback* cb) { MS_TRACE(); @@ -162,7 +171,7 @@ bool DepLibUring::PrepareSend( } bool DepLibUring::PrepareWrite( - int sockfd, const void* data1, size_t len1, const void* data2, size_t len2, onSendCallback* cb) + int sockfd, const uint8_t* data1, size_t len1, const uint8_t* data2, size_t len2, onSendCallback* cb) { MS_TRACE(); @@ -246,6 +255,7 @@ DepLibUring::LibUring::LibUring() // Initialize available UserData entries. for (size_t i{ 0 }; i < DepLibUring::QueueDepth; ++i) { + this->userDatas[i].store = this->sendBuffers[i]; this->availableUserDataEntries.push(i); } } @@ -319,8 +329,24 @@ void DepLibUring::LibUring::StopPollingCQEs() uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseFd)); } +uint8_t* DepLibUring::LibUring::GetSendBuffer() +{ + MS_TRACE(); + + if (this->availableUserDataEntries.empty()) + { + MS_DEBUG_DEV("no user data entry available"); + + return nullptr; + } + + auto idx = this->availableUserDataEntries.front(); + + return this->userDatas[idx].store; +} + bool DepLibUring::LibUring::PrepareSend( - int sockfd, const void* data, size_t len, const struct sockaddr* addr, onSendCallback* cb) + int sockfd, const uint8_t* data, size_t len, const struct sockaddr* addr, onSendCallback* cb) { MS_TRACE(); @@ -328,7 +354,7 @@ bool DepLibUring::LibUring::PrepareSend( if (!userData) { - MS_WARN_DEV("no user data entry available"); + MS_DEBUG_DEV("no user data entry available"); this->userDataMissCount++; @@ -339,16 +365,25 @@ bool DepLibUring::LibUring::PrepareSend( if (!sqe) { - MS_WARN_DEV("no sqe available"); + MS_DEBUG_DEV("no sqe available"); this->sqeMissCount++; return false; } - std::memcpy(userData->store, data, len); userData->cb = cb; + // The send data buffer belongs to us, no need to memcpy. + if (this->IsDataInSendBuffers(data)) + { + MS_ASSERT(data == userData->store, "send buffer does not match userData store"); + } + else + { + std::memcpy(userData->store, data, len); + } + io_uring_sqe_set_data(sqe, userData); socklen_t addrlen = 0; @@ -370,7 +405,7 @@ bool DepLibUring::LibUring::PrepareSend( } bool DepLibUring::LibUring::PrepareWrite( - int sockfd, const void* data1, size_t len1, const void* data2, size_t len2, onSendCallback* cb) + int sockfd, const uint8_t* data1, size_t len1, const uint8_t* data2, size_t len2, onSendCallback* cb) { MS_TRACE(); @@ -378,7 +413,7 @@ bool DepLibUring::LibUring::PrepareWrite( if (!userData) { - MS_WARN_DEV("no user data entry available"); + MS_DEBUG_DEV("no user data entry available"); this->userDataMissCount++; @@ -389,19 +424,43 @@ bool DepLibUring::LibUring::PrepareWrite( if (!sqe) { - MS_WARN_DEV("no sqe available"); + MS_DEBUG_DEV("no sqe available"); this->sqeMissCount++; return false; } - std::memcpy(userData->store, data1, len1); - std::memcpy(userData->store + len1, data2, len2); + // The send data buffer belongs to us, no need to memcpy. + // NOTE: data1 contains the TCP framing buffer and data2 the actual payload. + if (this->IsDataInSendBuffers(data2)) + { + MS_ASSERT(data2 == userData->store, "send buffer does not match userData store"); + + // Always memcpy the frame len as it resides in the stack memory. + std::memcpy(userData->frameLen, data1, len1); + + userData->iov[0].iov_base = userData->frameLen; + userData->iov[0].iov_len = len1; + userData->iov[1].iov_base = userData->store; + userData->iov[1].iov_len = len2; + } + else + { + std::memcpy(userData->store, data1, len1); + std::memcpy(userData->store + len1, data2, len2); + + userData->iov[0].iov_base = userData->store; + userData->iov[0].iov_len = len1; + userData->iov[1].iov_base = userData->store + len1; + userData->iov[1].iov_len = len2; + } + userData->cb = cb; io_uring_sqe_set_data(sqe, userData); - io_uring_prep_write(sqe, sockfd, userData->store, len1 + len2, 0); + + io_uring_prep_writev(sqe, sockfd, userData->iov, 2, 0); this->sqeProcessCount++; @@ -433,8 +492,6 @@ DepLibUring::UserData* DepLibUring::LibUring::GetUserData() if (this->availableUserDataEntries.empty()) { - MS_WARN_DEV("no user data entry available"); - return nullptr; } @@ -442,7 +499,7 @@ DepLibUring::UserData* DepLibUring::LibUring::GetUserData() this->availableUserDataEntries.pop(); - auto* userData = std::addressof(this->userDataBuffer[idx]); + auto* userData = std::addressof(this->userDatas[idx]); userData->idx = idx; return userData; diff --git a/worker/src/RTC/SrtpSession.cpp b/worker/src/RTC/SrtpSession.cpp index 0a136d4e31..5c2c810e0f 100644 --- a/worker/src/RTC/SrtpSession.cpp +++ b/worker/src/RTC/SrtpSession.cpp @@ -3,6 +3,9 @@ #include "RTC/SrtpSession.hpp" #include "DepLibSRTP.hpp" +#ifdef MS_LIBURING_SUPPORTED +#include "DepLibUring.hpp" +#endif #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include // std::memset(), std::memcpy() @@ -198,9 +201,30 @@ namespace RTC return false; } - std::memcpy(EncryptBuffer, *data, *len); + uint8_t* encryptBuffer = EncryptBuffer; - const srtp_err_status_t err = srtp_protect(this->session, static_cast(EncryptBuffer), len); +#ifdef MS_LIBURING_SUPPORTED + { + if (!DepLibUring::IsActive()) + { + goto protect; + } + + // Use a preallocated buffer, if available. + auto* sendBuffer = DepLibUring::GetSendBuffer(); + + if (sendBuffer) + { + encryptBuffer = sendBuffer; + } + } + + protect: +#endif + + std::memcpy(encryptBuffer, *data, *len); + + const srtp_err_status_t err = srtp_protect(this->session, static_cast(encryptBuffer), len); if (DepLibSRTP::IsError(err)) { @@ -210,7 +234,7 @@ namespace RTC } // Update the given data pointer. - *data = (const uint8_t*)EncryptBuffer; + *data = const_cast(encryptBuffer); return true; } From 042b7f5ba1ce41cdf0236070b027a6ee7e1f9a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Tue, 12 Dec 2023 13:14:56 +0100 Subject: [PATCH 244/525] libsrtp: use our own fork (#1260) libsrtp: use our own fork It uses a list hash rather than a single list to store stream contexts. By distributing the stream contexts in multiple lists (32) we enhance the list traversal time for the stream we are looking, by 32 times in the best case. --- CHANGELOG.md | 1 + worker/subprojects/libsrtp2.wrap | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14540ae398..e545dd3208 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### NEXT * liburing: avoid extra memcpy on RTP ([PR #1258](https://github.com/versatica/mediasoup/pull/1258)). +* libsrtp: use our own fork ([PR #1260](https://github.com/versatica/mediasoup/pull/1260)). ### 3.13.10 diff --git a/worker/subprojects/libsrtp2.wrap b/worker/subprojects/libsrtp2.wrap index fac0fc01eb..aa1b767f2d 100644 --- a/worker/subprojects/libsrtp2.wrap +++ b/worker/subprojects/libsrtp2.wrap @@ -1,9 +1,8 @@ [wrap-file] -directory = libsrtp-2.5.0 -source_url = https://github.com/cisco/libsrtp/archive/refs/tags/v2.5.0.tar.gz -source_filename = libsrtp-2.5.0.tar.gz -source_hash = 8a43ef8e9ae2b665292591af62aa1a4ae41e468b6d98d8258f91478735da4e09 -wrapdb_version = 2.5.0-1 +directory = libsrtp-4c9f0956f2933ac0650208d69c8d897625ba6301 +source_url = https://github.com/versatica/libsrtp/archive/4c9f0956f2933ac0650208d69c8d897625ba6301.zip +source_filename = libsrtp-4c9f0956f2933ac0650208d69c8d897625ba6301.zip +source_hash = 4f3af61e26df398569605fc4bcf377587ca2d8bd34b2b4bf9cdb9590cadbd662 [provide] libsrtp2 = libsrtp2_dep From eccc173bdb3646db10fbe3a57e1325c1dae104ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 12 Dec 2023 19:12:03 +0100 Subject: [PATCH 245/525] Fix Rust DataConsumer (#1262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Luis Millán --- CHANGELOG.md | 1 + node/src/tests/test-DataConsumer.ts | 6 +++-- rust/src/router/data_consumer.rs | 31 +++++++++++----------- rust/tests/integration/data_consumer.rs | 25 +++++++++++++++++ rust/tests/integration/direct_transport.rs | 4 +-- 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e545dd3208..b0be793ad4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * liburing: avoid extra memcpy on RTP ([PR #1258](https://github.com/versatica/mediasoup/pull/1258)). * libsrtp: use our own fork ([PR #1260](https://github.com/versatica/mediasoup/pull/1260)). +* Fix Rust `DataConsumer` ([PR #1262](https://github.com/versatica/mediasoup/pull/1262)). ### 3.13.10 diff --git a/node/src/tests/test-DataConsumer.ts b/node/src/tests/test-DataConsumer.ts index 5bbf33fa0c..44cdab5884 100644 --- a/node/src/tests/test-DataConsumer.ts +++ b/node/src/tests/test-DataConsumer.ts @@ -71,7 +71,8 @@ test('transport.consumeData() succeeds', async () => expect(dataConsumer1.label).toBe('foo'); expect(dataConsumer1.protocol).toBe('bar'); expect(dataConsumer1.paused).toBe(false); - expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 0, 1, 2, 100, 65535 ]); + expect(dataConsumer1.subchannels.sort((a, b) => a - b)) + .toEqual([ 0, 1, 2, 100, 65535 ]); expect(dataConsumer1.appData).toEqual({ baz: 'LOL' }); const dump = await router.dump(); @@ -134,7 +135,8 @@ test('dataConsumer.setSubchannels() succeeds', async () => { await dataConsumer1.setSubchannels([ 999, 999, 998, 65536 ]); - expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 0, 998, 999 ]); + expect(dataConsumer1.subchannels.sort((a, b) => a - b)) + .toEqual([ 0, 998, 999 ]); }, 2000); test('transport.consumeData() on a DirectTransport succeeds', async () => diff --git a/rust/src/router/data_consumer.rs b/rust/src/router/data_consumer.rs index d235f4c894..003a7f03cc 100644 --- a/rust/src/router/data_consumer.rs +++ b/rust/src/router/data_consumer.rs @@ -381,6 +381,7 @@ impl fmt::Debug for RegularDataConsumer { .field("data_producer_id", &self.inner.data_producer_id) .field("paused", &self.inner.paused) .field("data_producer_paused", &self.inner.data_producer_paused) + .field("subchannels", &self.inner.subchannels) .field("transport", &self.inner.transport) .field("closed", &self.inner.closed) .finish() @@ -411,6 +412,7 @@ impl fmt::Debug for DirectDataConsumer { .field("data_producer_id", &self.inner.data_producer_id) .field("paused", &self.inner.paused) .field("data_producer_paused", &self.inner.data_producer_paused) + .field("subchannels", &self.inner.subchannels) .field("transport", &self.inner.transport) .field("closed", &self.inner.closed) .finish() @@ -788,6 +790,19 @@ impl DataConsumer { .await } + /// Sets subchannels to the worker DataConsumer. + pub async fn set_subchannels(&self, subchannels: Vec) -> Result<(), RequestError> { + let response = self + .inner() + .channel + .request(self.id(), DataConsumerSetSubchannelsRequest { subchannels }) + .await?; + + *self.inner().subchannels.lock() = response.subchannels; + + Ok(()) + } + /// Callback is called when a message has been received from the corresponding data producer. /// /// # Notes on usage @@ -918,22 +933,6 @@ impl DirectDataConsumer { ) .await } - - /// Sets subchannels to the worker DataConsumer. - pub async fn set_subchannels(&self, subchannels: Vec) -> Result<(), RequestError> { - let response = self - .inner - .channel - .request( - self.inner.id, - DataConsumerSetSubchannelsRequest { subchannels }, - ) - .await?; - - *self.inner.subchannels.lock() = response.subchannels; - - Ok(()) - } } /// [`WeakDataConsumer`] doesn't own data consumer instance on mediasoup-worker and will not prevent diff --git a/rust/tests/integration/data_consumer.rs b/rust/tests/integration/data_consumer.rs index 3d0894fcc7..11e3255c92 100644 --- a/rust/tests/integration/data_consumer.rs +++ b/rust/tests/integration/data_consumer.rs @@ -321,6 +321,31 @@ fn get_stats_succeeds() { }); } +#[test] +fn set_subchannels() { + future::block_on(async move { + let (_worker, _router, transport1, data_producer) = init().await; + + let data_consumer = transport1 + .consume_data(DataConsumerOptions::new_sctp_unordered_with_life_time( + data_producer.id(), + 4000, + )) + .await + .expect("Failed to consume data"); + + data_consumer + .set_subchannels([999, 999, 998, 0].to_vec()) + .await + .expect("Failed to set data consumer subchannels"); + + let mut sorted_subchannels = data_consumer.subchannels(); + sorted_subchannels.sort(); + + assert_eq!(sorted_subchannels, [0, 998, 999]); + }); +} + #[test] fn consume_data_on_direct_transport_succeeds() { future::block_on(async move { diff --git a/rust/tests/integration/direct_transport.rs b/rust/tests/integration/direct_transport.rs index 380f3e1b3e..6053de0208 100644 --- a/rust/tests/integration/direct_transport.rs +++ b/rust/tests/integration/direct_transport.rs @@ -430,7 +430,7 @@ fn send_with_subchannels_succeeds() { } }; - let direct_data_consumer_2 = match &data_consumer_2 { + let _ = match &data_consumer_2 { DataConsumer::Direct(direct_data_consumer) => direct_data_consumer, _ => { panic!("Expected direct data consumer") @@ -514,7 +514,7 @@ fn send_with_subchannels_succeeds() { let mut subchannels = data_consumer_2.subchannels(); subchannels.push(1); - direct_data_consumer_2 + data_consumer_2 .set_subchannels(subchannels) .await .expect("Failed to set subchannels"); From e2e0622b85069faef5254ba9261bb790e0fbfb3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 12 Dec 2023 20:56:15 +0100 Subject: [PATCH 246/525] DataConsumer: Add addSubchannel() and removeSubchannel() (#1263) --- CHANGELOG.md | 5 +- node/src/DataConsumer.ts | 55 +++++++++++++ node/src/tests/test-DataConsumer.ts | 24 ++++++ rust/src/messages.rs | 100 ++++++++++++++++++++++++ rust/src/router/data_consumer.rs | 37 ++++++++- rust/tests/integration/data_consumer.rs | 86 ++++++++++++++++++++ worker/fbs/dataConsumer.fbs | 16 ++++ worker/fbs/request.fbs | 4 + worker/fbs/response.fbs | 2 + worker/src/Channel/ChannelRequest.cpp | 2 + worker/src/RTC/DataConsumer.cpp | 48 ++++++++++++ 11 files changed, 373 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0be793ad4..306202a174 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,10 @@ ### NEXT -* liburing: avoid extra memcpy on RTP ([PR #1258](https://github.com/versatica/mediasoup/pull/1258)). -* libsrtp: use our own fork ([PR #1260](https://github.com/versatica/mediasoup/pull/1260)). +* liburing: Avoid extra memcpy on RTP ([PR #1258](https://github.com/versatica/mediasoup/pull/1258)). +* libsrtp: Use our own fork ([PR #1260](https://github.com/versatica/mediasoup/pull/1260)). * Fix Rust `DataConsumer` ([PR #1262](https://github.com/versatica/mediasoup/pull/1262)). +* `DataConsumer`: Add `addSubchannel()` and `removeSubchannel()` methods ([PR #1263](https://github.com/versatica/mediasoup/pull/1263)). ### 3.13.10 diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 12b7e5db68..52ccd0284b 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -586,6 +586,61 @@ export class DataConsumer this.#subchannels = utils.parseVector(data, 'subchannels'); } + /** + * Add a subchannel. + */ + async addSubchannel(subchannel: number): Promise + { + logger.debug('addSubchannel()'); + + /* Build Request. */ + const requestOffset = + FbsDataConsumer.AddSubchannelRequest.createAddSubchannelRequest( + this.#channel.bufferBuilder, subchannel); + + const response = await this.#channel.request( + FbsRequest.Method.DATACONSUMER_ADD_SUBCHANNEL, + FbsRequest.Body.DataConsumer_AddSubchannelRequest, + requestOffset, + this.#internal.dataConsumerId + ); + + /* Decode Response. */ + const data = new FbsDataConsumer.AddSubchannelResponse(); + + response.body(data); + + // Update subchannels. + this.#subchannels = utils.parseVector(data, 'subchannels'); + } + + /** + * Remove a subchannel. + */ + async removeSubchannel(subchannel: number): Promise + { + logger.debug('removeSubchannel()'); + + /* Build Request. */ + const requestOffset = FbsDataConsumer.RemoveSubchannelRequest. + createRemoveSubchannelRequest(this.#channel.bufferBuilder, subchannel); + + const response = await this.#channel.request( + FbsRequest.Method.DATACONSUMER_REMOVE_SUBCHANNEL, + FbsRequest.Body.DataConsumer_RemoveSubchannelRequest, + requestOffset, + this.#internal.dataConsumerId + ); + + /* Decode Response. */ + const data = new FbsDataConsumer.RemoveSubchannelResponse(); + + response.body(data); + + // Update subchannels. + this.#subchannels = utils.parseVector(data, 'subchannels'); + } + private handleWorkerNotifications(): void { this.#channel.on(this.#internal.dataConsumerId, (event: Event, data?: Notification) => diff --git a/node/src/tests/test-DataConsumer.ts b/node/src/tests/test-DataConsumer.ts index 44cdab5884..66bfae338b 100644 --- a/node/src/tests/test-DataConsumer.ts +++ b/node/src/tests/test-DataConsumer.ts @@ -139,6 +139,30 @@ test('dataConsumer.setSubchannels() succeeds', async () => .toEqual([ 0, 998, 999 ]); }, 2000); +test('dataConsumer.addSubchannel() and .removeSubchannel() succeed', async () => +{ + await dataConsumer1.setSubchannels([ ]); + expect(dataConsumer1.subchannels).toEqual([ ]); + + await dataConsumer1.addSubchannel(5); + expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 5 ]); + + await dataConsumer1.addSubchannel(10); + expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 5, 10 ]); + + await dataConsumer1.addSubchannel(5); + expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 5, 10 ]); + + await dataConsumer1.removeSubchannel(666); + expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 5, 10 ]); + + await dataConsumer1.removeSubchannel(5); + expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 10 ]); + + await dataConsumer1.setSubchannels([ ]); + expect(dataConsumer1.subchannels).toEqual([ ]); +}, 2000); + test('transport.consumeData() on a DirectTransport succeeds', async () => { const onObserverNewDataConsumer = jest.fn(); diff --git a/rust/src/messages.rs b/rust/src/messages.rs index e92b8521ac..1eb50f46cc 100644 --- a/rust/src/messages.rs +++ b/rust/src/messages.rs @@ -3260,6 +3260,106 @@ impl Request for DataConsumerSetSubchannelsRequest { } } +#[derive(Debug, Clone, Serialize)] +pub(crate) struct DataConsumerAddSubchannelRequest { + pub(crate) subchannel: u16, +} + +#[derive(Debug, Clone, Serialize)] +pub(crate) struct DataConsumerAddSubchannelResponse { + pub(crate) subchannels: Vec, +} + +impl Request for DataConsumerAddSubchannelRequest { + const METHOD: request::Method = request::Method::DataconsumerAddSubchannel; + type HandlerId = DataConsumerId; + type Response = DataConsumerAddSubchannelResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = data_consumer::AddSubchannelRequest::create(&mut builder, self.subchannel); + let request_body = + request::Body::create_data_consumer_add_subchannel_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::DataConsumerAddSubchannelResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = data_consumer::AddSubchannelResponse::try_from(data)?; + + Ok(DataConsumerAddSubchannelResponse { + subchannels: data.subchannels, + }) + } +} + +#[derive(Debug, Clone, Serialize)] +pub(crate) struct DataConsumerRemoveSubchannelRequest { + pub(crate) subchannel: u16, +} + +#[derive(Debug, Clone, Serialize)] +pub(crate) struct DataConsumerRemoveSubchannelResponse { + pub(crate) subchannels: Vec, +} + +impl Request for DataConsumerRemoveSubchannelRequest { + const METHOD: request::Method = request::Method::DataconsumerRemoveSubchannel; + type HandlerId = DataConsumerId; + type Response = DataConsumerRemoveSubchannelResponse; + + fn into_bytes(self, id: u32, handler_id: Self::HandlerId) -> Vec { + let mut builder = Builder::new(); + + let data = data_consumer::RemoveSubchannelRequest::create(&mut builder, self.subchannel); + let request_body = + request::Body::create_data_consumer_remove_subchannel_request(&mut builder, data); + + let request = request::Request::create( + &mut builder, + id, + Self::METHOD, + handler_id.to_string(), + Some(request_body), + ); + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message_body); + + builder.finish(message, None).to_vec() + } + + fn convert_response( + response: Option>, + ) -> Result> { + let Some(response::BodyRef::DataConsumerRemoveSubchannelResponse(data)) = response else { + panic!("Wrong message from worker: {response:?}"); + }; + + let data = data_consumer::RemoveSubchannelResponse::try_from(data)?; + + Ok(DataConsumerRemoveSubchannelResponse { + subchannels: data.subchannels, + }) + } +} + #[derive(Debug)] pub(crate) struct RtpObserverCloseRequest { pub(crate) rtp_observer_id: RtpObserverId, diff --git a/rust/src/router/data_consumer.rs b/rust/src/router/data_consumer.rs index 003a7f03cc..88ca1a5742 100644 --- a/rust/src/router/data_consumer.rs +++ b/rust/src/router/data_consumer.rs @@ -4,10 +4,10 @@ mod tests; use crate::data_producer::{DataProducer, DataProducerId, WeakDataProducer}; use crate::data_structures::{AppData, WebRtcMessage}; use crate::messages::{ - DataConsumerCloseRequest, DataConsumerDumpRequest, DataConsumerGetBufferedAmountRequest, - DataConsumerGetStatsRequest, DataConsumerPauseRequest, DataConsumerResumeRequest, - DataConsumerSendRequest, DataConsumerSetBufferedAmountLowThresholdRequest, - DataConsumerSetSubchannelsRequest, + DataConsumerAddSubchannelRequest, DataConsumerCloseRequest, DataConsumerDumpRequest, + DataConsumerGetBufferedAmountRequest, DataConsumerGetStatsRequest, DataConsumerPauseRequest, + DataConsumerRemoveSubchannelRequest, DataConsumerResumeRequest, DataConsumerSendRequest, + DataConsumerSetBufferedAmountLowThresholdRequest, DataConsumerSetSubchannelsRequest, }; use crate::sctp_parameters::SctpStreamParameters; use crate::transport::Transport; @@ -803,6 +803,35 @@ impl DataConsumer { Ok(()) } + /// Adds a subchannel to the worker DataConsumer. + pub async fn add_subchannel(&self, subchannel: u16) -> Result<(), RequestError> { + let response = self + .inner() + .channel + .request(self.id(), DataConsumerAddSubchannelRequest { subchannel }) + .await?; + + *self.inner().subchannels.lock() = response.subchannels; + + Ok(()) + } + + /// Removes a subchannel to the worker DataConsumer. + pub async fn remove_subchannel(&self, subchannel: u16) -> Result<(), RequestError> { + let response = self + .inner() + .channel + .request( + self.id(), + DataConsumerRemoveSubchannelRequest { subchannel }, + ) + .await?; + + *self.inner().subchannels.lock() = response.subchannels; + + Ok(()) + } + /// Callback is called when a message has been received from the corresponding data producer. /// /// # Notes on usage diff --git a/rust/tests/integration/data_consumer.rs b/rust/tests/integration/data_consumer.rs index 11e3255c92..d18e21d540 100644 --- a/rust/tests/integration/data_consumer.rs +++ b/rust/tests/integration/data_consumer.rs @@ -346,6 +346,92 @@ fn set_subchannels() { }); } +#[test] +fn add_and_remove_subchannel() { + future::block_on(async move { + let (_worker, _router, transport1, data_producer) = init().await; + + let data_consumer = transport1 + .consume_data(DataConsumerOptions::new_sctp_unordered_with_life_time( + data_producer.id(), + 4000, + )) + .await + .expect("Failed to consume data"); + + data_consumer + .set_subchannels([].to_vec()) + .await + .expect("Failed to set data consumer subchannels"); + + assert_eq!(data_consumer.subchannels(), []); + + data_consumer + .add_subchannel(5) + .await + .expect("Failed to add data consumer subchannel"); + + assert_eq!(data_consumer.subchannels(), [5]); + + data_consumer + .add_subchannel(10) + .await + .expect("Failed to add data consumer subchannel"); + + let mut sorted_subchannels = data_consumer.subchannels(); + sorted_subchannels.sort(); + + assert_eq!(sorted_subchannels, [5, 10]); + + data_consumer + .add_subchannel(5) + .await + .expect("Failed to add data consumer subchannel"); + + sorted_subchannels = data_consumer.subchannels(); + sorted_subchannels.sort(); + + assert_eq!(sorted_subchannels, [5, 10]); + + data_consumer + .remove_subchannel(666) + .await + .expect("Failed to remove data consumer subchannel"); + + sorted_subchannels = data_consumer.subchannels(); + sorted_subchannels.sort(); + + assert_eq!(sorted_subchannels, [5, 10]); + + data_consumer + .remove_subchannel(5) + .await + .expect("Failed to remove data consumer subchannel"); + + sorted_subchannels = data_consumer.subchannels(); + sorted_subchannels.sort(); + + assert_eq!(sorted_subchannels, [10]); + + data_consumer + .add_subchannel(5) + .await + .expect("Failed to add data consumer subchannel"); + + sorted_subchannels = data_consumer.subchannels(); + sorted_subchannels.sort(); + + assert_eq!(sorted_subchannels, [5, 10]); + + data_consumer + .set_subchannels([].to_vec()) + .await + .expect("Failed to set data consumer subchannels"); + + assert_eq!(data_consumer.subchannels(), []); + }); +} + #[test] fn consume_data_on_direct_transport_succeeds() { future::block_on(async move { diff --git a/worker/fbs/dataConsumer.fbs b/worker/fbs/dataConsumer.fbs index 2bebe33191..2670288a58 100644 --- a/worker/fbs/dataConsumer.fbs +++ b/worker/fbs/dataConsumer.fbs @@ -47,6 +47,22 @@ table SetSubchannelsResponse { subchannels: [uint16] (required); } +table AddSubchannelRequest { + subchannel: uint16; +} + +table AddSubchannelResponse { + subchannels: [uint16] (required); +} + +table RemoveSubchannelRequest { + subchannel: uint16; +} + +table RemoveSubchannelResponse { + subchannels: [uint16] (required); +} + // Notifications from Worker. table BufferedAmountLowNotification { diff --git a/worker/fbs/request.fbs b/worker/fbs/request.fbs index 56eca5674d..d9f869e878 100644 --- a/worker/fbs/request.fbs +++ b/worker/fbs/request.fbs @@ -72,6 +72,8 @@ enum Method: uint8 { DATACONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, DATACONSUMER_SEND, DATACONSUMER_SET_SUBCHANNELS, + DATACONSUMER_ADD_SUBCHANNEL, + DATACONSUMER_REMOVE_SUBCHANNEL, RTPOBSERVER_PAUSE, RTPOBSERVER_RESUME, RTPOBSERVER_ADD_PRODUCER, @@ -114,6 +116,8 @@ union Body { DataConsumer_SetBufferedAmountLowThresholdRequest: FBS.DataConsumer.SetBufferedAmountLowThresholdRequest, DataConsumer_SendRequest: FBS.DataConsumer.SendRequest, DataConsumer_SetSubchannelsRequest: FBS.DataConsumer.SetSubchannelsRequest, + DataConsumer_AddSubchannelRequest: FBS.DataConsumer.AddSubchannelRequest, + DataConsumer_RemoveSubchannelRequest: FBS.DataConsumer.RemoveSubchannelRequest, RtpObserver_AddProducerRequest: FBS.RtpObserver.AddProducerRequest, RtpObserver_RemoveProducerRequest: FBS.RtpObserver.RemoveProducerRequest, } diff --git a/worker/fbs/response.fbs b/worker/fbs/response.fbs index 539d36a72a..707e5750ef 100644 --- a/worker/fbs/response.fbs +++ b/worker/fbs/response.fbs @@ -40,6 +40,8 @@ union Body { DataConsumer_DumpResponse: FBS.DataConsumer.DumpResponse, DataConsumer_GetStatsResponse: FBS.DataConsumer.GetStatsResponse, DataConsumer_SetSubchannelsResponse: FBS.DataConsumer.SetSubchannelsResponse, + DataConsumer_AddSubchannelResponse: FBS.DataConsumer.AddSubchannelResponse, + DataConsumer_RemoveSubchannelResponse: FBS.DataConsumer.RemoveSubchannelResponse } table Response { diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index adf62ba28e..ed1ef58395 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -75,6 +75,8 @@ namespace Channel { FBS::Request::Method::DATACONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, "dataConsumer.setBufferedAmountLowThreshold" }, { FBS::Request::Method::DATACONSUMER_SEND, "dataConsumer.send" }, { FBS::Request::Method::DATACONSUMER_SET_SUBCHANNELS, "dataConsumer.setSubchannels" }, + { FBS::Request::Method::DATACONSUMER_ADD_SUBCHANNEL, "dataConsumer.addSubchannel" }, + { FBS::Request::Method::DATACONSUMER_REMOVE_SUBCHANNEL, "dataConsumer.removeSubchannel" }, { FBS::Request::Method::RTPOBSERVER_PAUSE, "rtpObserver.pause" }, { FBS::Request::Method::RTPOBSERVER_RESUME, "rtpObserver.resume" }, { FBS::Request::Method::RTPOBSERVER_ADD_PRODUCER, "rtpObserver.addProducer" }, diff --git a/worker/src/RTC/DataConsumer.cpp b/worker/src/RTC/DataConsumer.cpp index 3f5fd69ffd..fdabc812a5 100644 --- a/worker/src/RTC/DataConsumer.cpp +++ b/worker/src/RTC/DataConsumer.cpp @@ -339,6 +339,54 @@ namespace RTC break; } + case Channel::ChannelRequest::Method::DATACONSUMER_ADD_SUBCHANNEL: + { + const auto* body = request->data->body_as(); + + this->subchannels.insert(body->subchannel()); + + std::vector subchannels; + + subchannels.reserve(this->subchannels.size()); + + for (auto subchannel : this->subchannels) + { + subchannels.emplace_back(subchannel); + } + + // Create response. + auto responseOffset = FBS::DataConsumer::CreateAddSubchannelResponseDirect( + request->GetBufferBuilder(), std::addressof(subchannels)); + + request->Accept(FBS::Response::Body::DataConsumer_AddSubchannelResponse, responseOffset); + + break; + } + + case Channel::ChannelRequest::Method::DATACONSUMER_REMOVE_SUBCHANNEL: + { + const auto* body = request->data->body_as(); + + this->subchannels.erase(body->subchannel()); + + std::vector subchannels; + + subchannels.reserve(this->subchannels.size()); + + for (auto subchannel : this->subchannels) + { + subchannels.emplace_back(subchannel); + } + + // Create response. + auto responseOffset = FBS::DataConsumer::CreateRemoveSubchannelResponseDirect( + request->GetBufferBuilder(), std::addressof(subchannels)); + + request->Accept(FBS::Response::Body::DataConsumer_RemoveSubchannelResponse, responseOffset); + + break; + } + default: { MS_THROW_ERROR("unknown method '%s'", request->methodCStr); From 32c37ff19d6b5afb0521013e87abd4644f09a5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 13 Dec 2023 10:02:53 +0100 Subject: [PATCH 247/525] 3.13.11 --- CHANGELOG.md | 6 +++--- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 306202a174..41176905bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,12 @@ # Changelog -### NEXT +### 3.13.11 * liburing: Avoid extra memcpy on RTP ([PR #1258](https://github.com/versatica/mediasoup/pull/1258)). -* libsrtp: Use our own fork ([PR #1260](https://github.com/versatica/mediasoup/pull/1260)). -* Fix Rust `DataConsumer` ([PR #1262](https://github.com/versatica/mediasoup/pull/1262)). +* libsrtp: Use our own fork with performance gain ([PR #1260](https://github.com/versatica/mediasoup/pull/1260)). * `DataConsumer`: Add `addSubchannel()` and `removeSubchannel()` methods ([PR #1263](https://github.com/versatica/mediasoup/pull/1263)). +* Fix Rust `DataConsumer` ([PR #1262](https://github.com/versatica/mediasoup/pull/1262)). ### 3.13.10 diff --git a/package-lock.json b/package-lock.json index e1095508a2..e2b9f758c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.10", + "version": "3.13.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.10", + "version": "3.13.11", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 0f8ba679d8..b31d3cfda5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.10", + "version": "3.13.11", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From fb83d4f4e430c14aa766ede8d02496aa1f3ec7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Thu, 14 Dec 2023 16:40:32 +0100 Subject: [PATCH 248/525] worker: disable RtcLogger usage if not enabled (#1264) worker: disable RtcLogger usage if not enabled --- CHANGELOG.md | 5 +++++ worker/include/RTC/RtpPacket.hpp | 4 ++++ worker/src/RTC/PipeConsumer.cpp | 10 ++++++++++ worker/src/RTC/Producer.cpp | 8 ++++++++ worker/src/RTC/Router.cpp | 2 ++ worker/src/RTC/RtcLogger.cpp | 2 -- worker/src/RTC/SimpleConsumer.cpp | 12 ++++++++++++ worker/src/RTC/SimulcastConsumer.cpp | 24 ++++++++++++++++++++++++ worker/src/RTC/SvcConsumer.cpp | 14 ++++++++++++++ worker/src/RTC/Transport.cpp | 6 ++++++ 10 files changed, 85 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41176905bf..782d84724e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* worker: Disable RtcLogger usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). + + ### 3.13.11 * liburing: Avoid extra memcpy on RTP ([PR #1258](https://github.com/versatica/mediasoup/pull/1258)). diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index 3c72e7b2a8..0ff85ed150 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -5,7 +5,9 @@ #include "Utils.hpp" #include "FBS/rtpPacket.h" #include "RTC/Codecs/PayloadDescriptorHandler.hpp" +#ifdef MS_RTC_LOGGER_RTP #include "RTC/RtcLogger.hpp" +#endif #include #include #include @@ -649,8 +651,10 @@ namespace RTC void ShiftPayload(size_t payloadOffset, size_t shift, bool expand = true); +#ifdef MS_RTC_LOGGER_RTP public: RtcLogger::RtpPacket logger; +#endif private: void ParseExtensions(); diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index 5ac3f65c09..4b43242ce7 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -219,11 +219,15 @@ namespace RTC { MS_TRACE(); +#ifdef MS_RTC_LOGGER_RTP packet->logger.consumerId = this->id; +#endif if (!IsActive()) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::CONSUMER_INACTIVE); +#endif return; } @@ -236,7 +240,9 @@ namespace RTC { MS_DEBUG_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType); +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE); +#endif return; } @@ -250,7 +256,9 @@ namespace RTC // the packet. if (syncRequired && this->keyFrameSupported && !packet->IsKeyFrame()) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); +#endif return; } @@ -284,8 +292,10 @@ namespace RTC packet->SetSsrc(ssrc); packet->SetSequenceNumber(seq); +#ifdef MS_RTC_LOGGER_RTP packet->logger.sendRtpTimestamp = packet->GetTimestamp(); packet->logger.sendSeqNumber = seq; +#endif if (isSyncPacket) { diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index 6c5f7a8951..d8bd6a1f2c 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -562,7 +562,9 @@ namespace RTC { MS_TRACE(); +#ifdef MS_RTC_LOGGER_RTP packet->logger.producerId = this->id; +#endif // Reset current packet. this->currentRtpPacket = nullptr; @@ -576,7 +578,9 @@ namespace RTC { MS_WARN_TAG(rtp, "no stream found for received packet [ssrc:%" PRIu32 "]", packet->GetSsrc()); +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_NOT_FOUND); +#endif return ReceiveRtpPacketResult::DISCARDED; } @@ -601,7 +605,9 @@ namespace RTC NotifyNewRtpStream(rtpStream); } +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_DISCARDED); +#endif return result; } @@ -615,7 +621,9 @@ namespace RTC // Process the packet. if (!rtpStream->ReceiveRtxPacket(packet)) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_NOT_FOUND); +#endif return result; } diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index 150d5af350..d5fe22e621 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -652,7 +652,9 @@ namespace RTC { MS_TRACE(); +#ifdef MS_RTC_LOGGER_RTP packet->logger.routerId = this->id; +#endif auto& consumers = this->mapProducerConsumers.at(producer); diff --git a/worker/src/RTC/RtcLogger.cpp b/worker/src/RTC/RtcLogger.cpp index 1301fd5292..96f6809246 100644 --- a/worker/src/RTC/RtcLogger.cpp +++ b/worker/src/RTC/RtcLogger.cpp @@ -49,7 +49,6 @@ namespace RTC void RtpPacket::Log() const { -#ifdef MS_RTC_LOGGER_RTP MS_TRACE(); std::cout << "{"; @@ -83,7 +82,6 @@ namespace RTC std::cout << ", \"dropped\": " << (this->dropped ? "true" : "false"); std::cout << ", \"dropReason\": '" << dropReason2String[this->dropReason] << "'"; std::cout << "}" << std::endl; -#endif } void RtpPacket::Clear() diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index 6488e776d2..9523ce3f71 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -301,11 +301,15 @@ namespace RTC { MS_TRACE(); +#ifdef MS_RTC_LOGGER_RTP packet->logger.consumerId = this->id; +#endif if (!IsActive()) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::CONSUMER_INACTIVE); +#endif return; } @@ -318,7 +322,9 @@ namespace RTC { MS_DEBUG_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType); +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE); +#endif return; } @@ -336,7 +342,9 @@ namespace RTC this->rtpSeqManager.Drop(packet->GetSequenceNumber()); +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC); +#endif return; } @@ -345,7 +353,9 @@ namespace RTC // the packet. if (this->syncRequired && this->keyFrameSupported && !packet->IsKeyFrame()) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); +#endif return; } @@ -379,8 +389,10 @@ namespace RTC packet->SetSsrc(this->rtpParameters.encodings[0].ssrc); packet->SetSequenceNumber(seq); +#ifdef MS_RTC_LOGGER_RTP packet->logger.sendRtpTimestamp = packet->GetTimestamp(); packet->logger.sendSeqNumber = seq; +#endif if (isSyncPacket) { diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index cbafc1d05d..c17c15dde4 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -712,18 +712,24 @@ namespace RTC { MS_TRACE(); +#ifdef MS_RTC_LOGGER_RTP packet->logger.consumerId = this->id; +#endif if (!IsActive()) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::CONSUMER_INACTIVE); +#endif return; } if (this->targetTemporalLayer == -1) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::INVALID_TARGET_LAYER); +#endif return; } @@ -736,7 +742,9 @@ namespace RTC { MS_DEBUG_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType); +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE); +#endif return; } @@ -751,7 +759,9 @@ namespace RTC // Ignore if not a key frame. if (!packet->IsKeyFrame()) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); +#endif return; } @@ -766,7 +776,9 @@ namespace RTC // drop it. else if (spatialLayer != this->currentSpatialLayer) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::SPATIAL_LAYER_MISMATCH); +#endif return; } @@ -774,7 +786,9 @@ namespace RTC // If we need to sync and this is not a key frame, ignore the packet. if (this->syncRequired && !packet->IsKeyFrame()) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); +#endif return; } @@ -890,7 +904,9 @@ namespace RTC this->syncRequired = false; this->spatialLayerToSync = -1; +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::TOO_HIGH_TIMESTAMP_EXTRA_NEEDED); +#endif return; } @@ -932,8 +948,10 @@ namespace RTC if (SeqManager::IsSeqLowerThan( packet->GetSequenceNumber(), this->snReferenceSpatialLayer)) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped( RtcLogger::RtpPacket::DropReason::PACKET_PREVIOUS_TO_SPATIAL_LAYER_SWITCH); +#endif return; } @@ -979,7 +997,9 @@ namespace RTC { this->rtpSeqManager.Drop(packet->GetSequenceNumber()); +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC); +#endif return; } @@ -1006,8 +1026,10 @@ namespace RTC packet->SetSequenceNumber(seq); packet->SetTimestamp(timestamp); +#ifdef MS_RTC_LOGGER_RTP packet->logger.sendRtpTimestamp = timestamp; packet->logger.sendSeqNumber = seq; +#endif if (isSyncPacket) { @@ -1050,7 +1072,9 @@ namespace RTC origSeq, origTimestamp); +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::SEND_RTP_STREAM_DISCARDED); +#endif } // Restore packet fields. diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index 9e86e867b2..1140d0c517 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -627,11 +627,15 @@ namespace RTC { MS_TRACE(); +#ifdef MS_RTC_LOGGER_RTP packet->logger.consumerId = this->id; +#endif if (!IsActive()) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::CONSUMER_INACTIVE); +#endif return; } @@ -643,7 +647,9 @@ namespace RTC ) // clang-format on { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::INVALID_TARGET_LAYER); +#endif return; } @@ -656,7 +662,9 @@ namespace RTC { MS_DEBUG_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType); +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE); +#endif return; } @@ -664,7 +672,9 @@ namespace RTC // If we need to sync and this is not a key frame, ignore the packet. if (this->syncRequired && !packet->IsKeyFrame()) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); +#endif return; } @@ -696,7 +706,9 @@ namespace RTC { this->rtpSeqManager.Drop(packet->GetSequenceNumber()); +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC); +#endif return; } @@ -725,8 +737,10 @@ namespace RTC packet->SetSsrc(this->rtpParameters.encodings[0].ssrc); packet->SetSequenceNumber(seq); +#ifdef MS_RTC_LOGGER_RTP packet->logger.sendRtpTimestamp = packet->GetTimestamp(); packet->logger.sendSeqNumber = seq; +#endif if (marker) { diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index d697a17fac..e76d9adad0 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -1546,7 +1546,9 @@ namespace RTC { MS_TRACE(); +#ifdef MS_RTC_LOGGER_RTP packet->logger.recvTransportId = this->id; +#endif // Apply the Transport RTP header extension ids so the RTP listener can use them. packet->SetMidExtensionId(this->recvRtpHeaderExtensionIds.mid); @@ -1568,7 +1570,9 @@ namespace RTC if (!producer) { +#ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::PRODUCER_NOT_FOUND); +#endif MS_WARN_TAG( rtp, @@ -2442,8 +2446,10 @@ namespace RTC { MS_TRACE(); +#ifdef MS_RTC_LOGGER_RTP packet->logger.sendTransportId = this->id; packet->logger.Sent(); +#endif // Update abs-send-time if present. packet->UpdateAbsSendTime(DepLibUV::GetTimeMs()); From bc55f22ccb3e028d15258dd8154ae142ecea60bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 14 Dec 2023 20:22:24 +0100 Subject: [PATCH 249/525] npm installation: Don't require Python if valid worker prebuilt binary is fetched (#1265) --- CHANGELOG.md | 3 ++- npm-scripts.mjs | 31 ++++++++++++++++++++----------- package.json | 1 - 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 782d84724e..4690870b50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ### NEXT -* worker: Disable RtcLogger usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). +* worker: Disable `RtcLogger` usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). +* npm installation: Don't require Python if valid worker prebuilt binary is fetched ([PR #1265](https://github.com/versatica/mediasoup/pull/1265)). ### 3.13.11 diff --git a/npm-scripts.mjs b/npm-scripts.mjs index d6754989fc..25c1928a72 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -47,13 +47,6 @@ async function run() { switch (task) { - case 'preinstall': - { - installInvoke(); - - break; - } - // As per NPM documentation (https://docs.npmjs.com/cli/v9/using-npm/scripts) // `prepare` script: // @@ -167,6 +160,8 @@ async function run() case 'format:worker': { + installInvoke(); + executeCmd(`"${PYTHON}" -m invoke -r worker format`); break; @@ -351,6 +346,8 @@ function buildWorker() { logInfo('buildWorker()'); + installInvoke(); + executeCmd(`"${PYTHON}" -m invoke -r worker mediasoup-worker`); } @@ -358,6 +355,8 @@ function cleanWorkerArtifacts() { logInfo('cleanWorkerArtifacts()'); + installInvoke(); + // Clean build artifacts except `mediasoup-worker`. executeCmd(`"${PYTHON}" -m invoke -r worker clean-build`); // Clean downloaded dependencies. @@ -377,6 +376,8 @@ function lintWorker() { logInfo('lintWorker()'); + installInvoke(); + executeCmd(`"${PYTHON}" -m invoke -r worker lint`); } @@ -384,6 +385,8 @@ function flatcNode() { logInfo('flatcNode()'); + installInvoke(); + // Build flatc if needed. executeCmd(`"${PYTHON}" -m invoke -r worker flatc`); @@ -410,6 +413,8 @@ function flatcWorker() { logInfo('flatcWorker()'); + installInvoke(); + executeCmd(`"${PYTHON}" -m invoke -r worker flatc`); } @@ -431,6 +436,8 @@ function testWorker() { logInfo('testWorker()'); + installInvoke(); + executeCmd(`"${PYTHON}" -m invoke -r worker test`); } @@ -575,6 +582,8 @@ async function downloadPrebuiltWorker() { const resolvedBinPath = path.resolve(WORKER_RELEASE_BIN_PATH); + // This will always fail on purpose, but if status code is 41 then + // it's good. execSync( `"${resolvedBinPath}"`, { @@ -583,15 +592,15 @@ async function downloadPrebuiltWorker() env : {} } ); - - logInfo( - 'downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary is valid for current host' - ); } catch (error) { if (error.status === 41) { + logInfo( + 'downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary is valid for current host' + ); + resolve(true); } else diff --git a/package.json b/package.json index b31d3cfda5..dcfbfe77ea 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,6 @@ "nodejs" ], "scripts": { - "preinstall": "node npm-scripts.mjs preinstall", "prepare": "node npm-scripts.mjs prepare", "postinstall": "node npm-scripts.mjs postinstall", "typescript:build": "node npm-scripts.mjs typescript:build", From 553ef36aa80de32b3742b44c475a9a806a97ff13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 18 Dec 2023 12:07:45 +0100 Subject: [PATCH 250/525] JS: Require curly braces in switch cases (#1268) --- node/.eslintrc.js | 8 ++++ node/src/Channel.ts | 22 +++++++++- node/src/Consumer.ts | 34 +++++++++++++++ node/src/DataConsumer.ts | 13 ++++++ node/src/DataProducer.ts | 13 ++++++ node/src/Producer.ts | 48 +++++++++++++++++++++ node/src/RtpParameters.ts | 67 +++++++++++++++++++++++++++++ node/src/SrtpParameters.ts | 18 ++++++++ node/src/Transport.ts | 39 +++++++++++++++++ node/src/WebRtcTransport.ts | 84 +++++++++++++++++++++++++++++++++++++ node/src/utils.ts | 6 +++ 11 files changed, 351 insertions(+), 1 deletion(-) diff --git a/node/.eslintrc.js b/node/.eslintrc.js index e541c5acd6..1d0f1e8728 100644 --- a/node/.eslintrc.js +++ b/node/.eslintrc.js @@ -45,6 +45,14 @@ const eslintConfig = 'computed-property-spacing' : 2, 'constructor-super' : 2, 'curly' : [ 2, 'all' ], + // Unfortunatelly `curly` does not apply to blocks in `switch` cases so + // this is needed. + 'no-restricted-syntax' : [ 2, + { + 'selector' : 'SwitchCase > *.consequent[type!="BlockStatement"]', + 'message' : 'Switch cases without blocks are disallowed' + } + ], 'func-call-spacing' : 2, 'generator-star-spacing' : 2, 'guard-for-in' : 2, diff --git a/node/src/Channel.ts b/node/src/Channel.ts index 654c588b32..7f41ca9f2f 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -164,10 +164,13 @@ export class Channel extends EnhancedEventEmitter } default: + { // eslint-disable-next-line no-console console.warn( `worker[pid:${pid}] unexpected data: %s`, - payload.toString('utf8', 1)); + payload.toString('utf8', 1) + ); + } } } catch (error) @@ -432,11 +435,16 @@ export class Channel extends EnhancedEventEmitter switch (response.error()!) { case 'TypeError': + { sent.reject(new TypeError(response.reason()!)); + break; + } default: + { sent.reject(new Error(response.reason()!)); + } } } else @@ -470,24 +478,36 @@ export class Channel extends EnhancedEventEmitter { // 'D' (a debug log). case 'D': + { logger.debug(`[pid:${pid}] ${logData.slice(1)}`); + break; + } // 'W' (a warn log). case 'W': + { logger.warn(`[pid:${pid}] ${logData.slice(1)}`); + break; + } // 'E' (a error log). case 'E': + { logger.error(`[pid:${pid}] ${logData.slice(1)}`); + break; + } // 'X' (a dump log). case 'X': + { // eslint-disable-next-line no-console console.log(logData.slice(1)); + break; + } } } } diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index e8d9a5981d..e2ab1167e7 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -999,17 +999,34 @@ function consumerTraceEventTypeToFbs(eventType: ConsumerTraceEventType) switch (eventType) { case 'keyframe': + { return FbsConsumer.TraceEventType.KEYFRAME; + } + case 'fir': + { return FbsConsumer.TraceEventType.FIR; + } + case 'nack': + { return FbsConsumer.TraceEventType.NACK; + } + case 'pli': + { return FbsConsumer.TraceEventType.PLI; + } + case 'rtp': + { return FbsConsumer.TraceEventType.RTP; + } + default: + { throw new TypeError(`invalid ConsumerTraceEventType: ${eventType}`); + } } } @@ -1019,17 +1036,34 @@ function consumerTraceEventTypeFromFbs(traceType: FbsConsumer.TraceEventType) switch (traceType) { case FbsConsumer.TraceEventType.KEYFRAME: + { return 'keyframe'; + } + case FbsConsumer.TraceEventType.FIR: + { return 'fir'; + } + case FbsConsumer.TraceEventType.NACK: + { return 'nack'; + } + case FbsConsumer.TraceEventType.PLI: + { return 'pli'; + } + case FbsConsumer.TraceEventType.RTP: + { return 'rtp'; + } + default: + { throw new TypeError(`invalid FbsConsumer.TraceEventType: ${traceType}`); + } } } diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 52ccd0284b..799001cef0 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -762,11 +762,19 @@ export function dataConsumerTypeToFbs(type: DataConsumerType): FbsDataProducer.T switch (type) { case 'sctp': + { return FbsDataProducer.Type.SCTP; + } + case 'direct': + { return FbsDataProducer.Type.DIRECT; + } + default: + { throw new TypeError('invalid DataConsumerType: ${type}'); + } } } @@ -775,9 +783,14 @@ export function dataConsumerTypeFromFbs(type: FbsDataProducer.Type): DataConsume switch (type) { case FbsDataProducer.Type.SCTP: + { return 'sctp'; + } + case FbsDataProducer.Type.DIRECT: + { return 'direct'; + } } } diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 94ffccf5cf..ee3cf29ef8 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -475,11 +475,19 @@ export function dataProducerTypeToFbs(type: DataProducerType): FbsDataProducer.T switch (type) { case 'sctp': + { return FbsDataProducer.Type.SCTP; + } + case 'direct': + { return FbsDataProducer.Type.DIRECT; + } + default: + { throw new TypeError('invalid DataConsumerType: ${type}'); + } } } @@ -488,9 +496,14 @@ export function dataProducerTypeFromFbs(type: FbsDataProducer.Type): DataProduce switch (type) { case FbsDataProducer.Type.SCTP: + { return 'sctp'; + } + case FbsDataProducer.Type.DIRECT: + { return 'direct'; + } } } diff --git a/node/src/Producer.ts b/node/src/Producer.ts index d45c1d1be7..dcae6545ea 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -630,13 +630,24 @@ export function producerTypeFromFbs(type: FbsRtpParameters.Type): ProducerType switch (type) { case FbsRtpParameters.Type.SIMPLE: + { return 'simple'; + } + case FbsRtpParameters.Type.SIMULCAST: + { return 'simulcast'; + } + case FbsRtpParameters.Type.SVC: + { return 'svc'; + } + default: + { throw new TypeError(`invalid FbsRtpParameters.Type: ${type}`); + } } } @@ -645,13 +656,19 @@ export function producerTypeToFbs(type: ProducerType): FbsRtpParameters.Type switch (type) { case 'simple': + { return FbsRtpParameters.Type.SIMPLE; + } case 'simulcast': + { return FbsRtpParameters.Type.SIMULCAST; + } case 'svc': + { return FbsRtpParameters.Type.SVC; + } } } @@ -661,17 +678,34 @@ function producerTraceEventTypeToFbs(eventType: ProducerTraceEventType) switch (eventType) { case 'keyframe': + { return FbsProducer.TraceEventType.KEYFRAME; + } + case 'fir': + { return FbsProducer.TraceEventType.FIR; + } + case 'nack': + { return FbsProducer.TraceEventType.NACK; + } + case 'pli': + { return FbsProducer.TraceEventType.PLI; + } + case 'rtp': + { return FbsProducer.TraceEventType.RTP; + } + default: + { throw new TypeError(`invalid ProducerTraceEventType: ${eventType}`); + } } } @@ -681,15 +715,29 @@ function producerTraceEventTypeFromFbs(eventType: FbsProducer.TraceEventType) switch (eventType) { case FbsProducer.TraceEventType.KEYFRAME: + { return 'keyframe'; + } + case FbsProducer.TraceEventType.FIR: + { return 'fir'; + } + case FbsProducer.TraceEventType.NACK: + { return 'nack'; + } + case FbsProducer.TraceEventType.PLI: + { return 'pli'; + } + case FbsProducer.TraceEventType.RTP: + { return 'rtp'; + } } } diff --git a/node/src/RtpParameters.ts b/node/src/RtpParameters.ts index 95308b7a29..99e9f528ed 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/RtpParameters.ts @@ -709,27 +709,59 @@ export function rtpHeaderExtensionUriFromFbs(uri: FbsRtpHeaderExtensionUri): Rtp switch (uri) { case FbsRtpHeaderExtensionUri.Mid: + { return 'urn:ietf:params:rtp-hdrext:sdes:mid'; + } + case FbsRtpHeaderExtensionUri.RtpStreamId: + { return 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id'; + } + case FbsRtpHeaderExtensionUri.RepairRtpStreamId: + { return 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id'; + } + case FbsRtpHeaderExtensionUri.FrameMarkingDraft07: + { return 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07'; + } + case FbsRtpHeaderExtensionUri.FrameMarking: + { return 'urn:ietf:params:rtp-hdrext:framemarking'; + } + case FbsRtpHeaderExtensionUri.AudioLevel: + { return 'urn:ietf:params:rtp-hdrext:ssrc-audio-level'; + } + case FbsRtpHeaderExtensionUri.VideoOrientation: + { return 'urn:3gpp:video-orientation'; + } + case FbsRtpHeaderExtensionUri.TimeOffset: + { return 'urn:ietf:params:rtp-hdrext:toffset'; + } + case FbsRtpHeaderExtensionUri.TransportWideCcDraft01: + { return 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01'; + } + case FbsRtpHeaderExtensionUri.AbsSendTime: + { return 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time'; + } + case FbsRtpHeaderExtensionUri.AbsCaptureTime: + { return 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time'; + } } } @@ -738,29 +770,64 @@ export function rtpHeaderExtensionUriToFbs(uri: RtpHeaderExtensionUri): FbsRtpHe switch (uri) { case 'urn:ietf:params:rtp-hdrext:sdes:mid': + { return FbsRtpHeaderExtensionUri.Mid; + } + case 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id': + { return FbsRtpHeaderExtensionUri.RtpStreamId; + } + case 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id': + { return FbsRtpHeaderExtensionUri.RepairRtpStreamId; + } + case 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07': + { return FbsRtpHeaderExtensionUri.FrameMarkingDraft07; + } + case 'urn:ietf:params:rtp-hdrext:framemarking': + { return FbsRtpHeaderExtensionUri.FrameMarking; + } + case 'urn:ietf:params:rtp-hdrext:ssrc-audio-level': + { return FbsRtpHeaderExtensionUri.AudioLevel; + } + case 'urn:3gpp:video-orientation': + { return FbsRtpHeaderExtensionUri.VideoOrientation; + } + case 'urn:ietf:params:rtp-hdrext:toffset': + { return FbsRtpHeaderExtensionUri.TimeOffset; + } + case 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01': + { return FbsRtpHeaderExtensionUri.TransportWideCcDraft01; + } + case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time': + { return FbsRtpHeaderExtensionUri.AbsSendTime; + } + case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time': + { return FbsRtpHeaderExtensionUri.AbsCaptureTime; + } + default: + { throw new TypeError(`invalid RtpHeaderExtensionUri: ${uri}`); + } } } diff --git a/node/src/SrtpParameters.ts b/node/src/SrtpParameters.ts index 7c5937c05e..87470bb5a4 100644 --- a/node/src/SrtpParameters.ts +++ b/node/src/SrtpParameters.ts @@ -31,16 +31,24 @@ export function cryptoSuiteFromFbs(binary: FbsSrtpParameters.SrtpCryptoSuite): S switch (binary) { case FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_256_GCM: + { return 'AEAD_AES_256_GCM'; + } case FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_128_GCM: + { return 'AEAD_AES_128_GCM'; + } case FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80: + { return 'AES_CM_128_HMAC_SHA1_80'; + } case FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32: + { return 'AES_CM_128_HMAC_SHA1_32'; + } } } @@ -50,19 +58,29 @@ export function cryptoSuiteToFbs(cryptoSuite: SrtpCryptoSuite) switch (cryptoSuite) { case 'AEAD_AES_256_GCM': + { return FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_256_GCM; + } case 'AEAD_AES_128_GCM': + { return FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_128_GCM; + } case 'AES_CM_128_HMAC_SHA1_80': + { return FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80; + } case 'AES_CM_128_HMAC_SHA1_32': + { return FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32; + } default: + { throw new TypeError(`invalid SrtpCryptoSuite: ${cryptoSuite}`); + } } } diff --git a/node/src/Transport.ts b/node/src/Transport.ts index a0e3449a62..7c68ad0143 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -1321,11 +1321,19 @@ function transportTraceEventTypeToFbs(eventType: TransportTraceEventType) switch (eventType) { case 'probation': + { return FbsTransport.TraceEventType.PROBATION; + } + case 'bwe': + { return FbsTransport.TraceEventType.BWE; + } + default: + { throw new TypeError(`invalid TransportTraceEventType: ${eventType}`); + } } } @@ -1335,9 +1343,15 @@ function transportTraceEventTypeFromFbs(eventType: FbsTransport.TraceEventType) switch (eventType) { case FbsTransport.TraceEventType.PROBATION: + { return 'probation'; + } + case FbsTransport.TraceEventType.BWE: + { return 'bwe'; + } + } } @@ -1346,17 +1360,34 @@ export function parseSctpState(fbsSctpState: FbsSctpState): SctpState switch (fbsSctpState) { case FbsSctpState.NEW: + { return 'new'; + } + case FbsSctpState.CONNECTING: + { return 'connecting'; + } + case FbsSctpState.CONNECTED: + { return 'connected'; + } + case FbsSctpState.FAILED: + { return 'failed'; + } + case FbsSctpState.CLOSED: + { return 'closed'; + } + default: + { throw new TypeError(`invalid SctpState: ${fbsSctpState}`); + } } } @@ -1365,10 +1396,14 @@ export function parseProtocol(protocol: FbsTransport.Protocol): TransportProtoco switch (protocol) { case FbsTransport.Protocol.UDP: + { return 'udp'; + } case FbsTransport.Protocol.TCP: + { return 'tcp'; + } } } @@ -1377,10 +1412,14 @@ export function serializeProtocol(protocol: TransportProtocol): FbsTransport.Pro switch (protocol) { case 'udp': + { return FbsTransport.Protocol.UDP; + } case 'tcp': + { return FbsTransport.Protocol.TCP; + } } } diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 96b5165035..64fec095e0 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -650,13 +650,24 @@ function iceStateFromFbs(fbsIceState: FbsIceState): IceState switch (fbsIceState) { case FbsIceState.NEW: + { return 'new'; + } + case FbsIceState.CONNECTED: + { return 'connected'; + } + case FbsIceState.COMPLETED: + { return 'completed'; + } + case FbsIceState.DISCONNECTED: + { return 'disconnected'; + } } } @@ -665,9 +676,14 @@ function iceRoleFromFbs(role: FbsIceRole): IceRole switch (role) { case FbsIceRole.CONTROLLED: + { return 'controlled'; + } + case FbsIceRole.CONTROLLING: + { return 'controlling'; + } } } @@ -676,7 +692,9 @@ function iceCandidateTypeFromFbs(type: FbsIceCandidateType): IceCandidateType switch (type) { case FbsIceCandidateType.HOST: + { return 'host'; + } } } @@ -685,7 +703,9 @@ function iceCandidateTcpTypeFromFbs(type: FbsIceCandidateTcpType): IceCandidateT switch (type) { case FbsIceCandidateTcpType.PASSIVE: + { return 'passive'; + } } } @@ -694,15 +714,29 @@ function dtlsStateFromFbs(fbsDtlsState: FbsDtlsState): DtlsState switch (fbsDtlsState) { case FbsDtlsState.NEW: + { return 'new'; + } + case FbsDtlsState.CONNECTING: + { return 'connecting'; + } + case FbsDtlsState.CONNECTED: + { return 'connected'; + } + case FbsDtlsState.FAILED: + { return 'failed'; + } + case FbsDtlsState.CLOSED: + { return 'closed'; + } } } @@ -711,11 +745,19 @@ function dtlsRoleFromFbs(role: FbsDtlsRole): DtlsRole switch (role) { case FbsDtlsRole.AUTO: + { return 'auto'; + } + case FbsDtlsRole.CLIENT: + { return 'client'; + } + case FbsDtlsRole.SERVER: + { return 'server'; + } } } @@ -725,15 +767,29 @@ function fingerprintAlgorithmsFromFbs(algorithm: FbsFingerprintAlgorithm) switch (algorithm) { case FbsFingerprintAlgorithm.SHA1: + { return 'sha-1'; + } + case FbsFingerprintAlgorithm.SHA224: + { return 'sha-224'; + } + case FbsFingerprintAlgorithm.SHA256: + { return 'sha-256'; + } + case FbsFingerprintAlgorithm.SHA384: + { return 'sha-384'; + } + case FbsFingerprintAlgorithm.SHA512: + { return 'sha-512'; + } } } @@ -743,17 +799,34 @@ function fingerprintAlgorithmToFbs(algorithm: FingerprintAlgorithm) switch (algorithm) { case 'sha-1': + { return FbsFingerprintAlgorithm.SHA1; + } + case 'sha-224': + { return FbsFingerprintAlgorithm.SHA224; + } + case 'sha-256': + { return FbsFingerprintAlgorithm.SHA256; + } + case 'sha-384': + { return FbsFingerprintAlgorithm.SHA384; + } + case 'sha-512': + { return FbsFingerprintAlgorithm.SHA512; + } + default: + { throw new TypeError(`invalid FingerprintAlgorithm: ${algorithm}`); + } } } @@ -762,13 +835,24 @@ function dtlsRoleToFbs(role: DtlsRole): FbsDtlsRole switch (role) { case 'auto': + { return FbsDtlsRole.AUTO; + } + case 'client': + { return FbsDtlsRole.CLIENT; + } + case 'server': + { return FbsDtlsRole.SERVER; + } + default: + { throw new TypeError(`invalid DtlsRole: ${role}`); + } } } diff --git a/node/src/utils.ts b/node/src/utils.ts index 6f9ad900d2..439f1fcaaf 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -57,13 +57,19 @@ export function getRtpParametersType( switch (producerType) { case 'simple': + { return FbsRtpParametersType.SIMPLE; + } case 'simulcast': + { return FbsRtpParametersType.SIMULCAST; + } case 'svc': + { return FbsRtpParametersType.SVC; + } } } From d7bee8a34cf0880de6508fc57be1c049375e88fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 18 Dec 2023 16:56:33 +0100 Subject: [PATCH 251/525] 3.13.12 --- CHANGELOG.md | 3 ++- package-lock.json | 64 +++++++++++++++++++++++------------------------ package.json | 8 +++--- 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4690870b50..370e19885b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ # Changelog -### NEXT +### 3.13.12 * worker: Disable `RtcLogger` usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). * npm installation: Don't require Python if valid worker prebuilt binary is fetched ([PR #1265](https://github.com/versatica/mediasoup/pull/1265)). +* Update h264-profile-level-id NPM dependency to 1.1.0. ### 3.13.11 diff --git a/package-lock.json b/package-lock.json index e2b9f758c5..0bc80cc4df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "mediasoup", - "version": "3.13.11", + "version": "3.13.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.11", + "version": "3.13.12", "hasInstallScript": true, "license": "ISC", "dependencies": { "debug": "^4.3.4", "flatbuffers": "^23.5.26", - "h264-profile-level-id": "^1.0.2", + "h264-profile-level-id": "^1.1.0", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0" @@ -21,10 +21,10 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.4", + "@types/node": "^20.10.5", "@typescript-eslint/eslint-plugin": "^6.14.0", "@typescript-eslint/parser": "^6.14.0", - "eslint": "^8.55.0", + "eslint": "^8.56.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", "marked": "^11.1.0", @@ -765,9 +765,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", - "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1619,9 +1619,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3023,15 +3023,15 @@ } }, "node_modules/eslint": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", - "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.55.0", + "@eslint/js": "8.56.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -3647,14 +3647,14 @@ "dev": true }, "node_modules/h264-profile-level-id": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.0.2.tgz", - "integrity": "sha512-bsSv/bHq4eIUt4iMycA9rn1C28gtXwrKLAkbpzuZmkQp4u3M6QlF5y6DlTMy5fGDkVGbMLxFGeL7Ra8JKMm4Dg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.1.0.tgz", + "integrity": "sha512-kASSjiJii6zPurTkCyaxxw3IaI1ahnylJNpdcxRhpUebHy/jpyjgIZ+8YcqjYaX+HtAPlpw9rKbvWBLc4jRjPw==", "dependencies": { "debug": "^4.3.4" }, "engines": { - "node": ">=8.0.0" + "node": ">=10.0.0" } }, "node_modules/hard-rejection": { @@ -7301,9 +7301,9 @@ } }, "@eslint/js": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", - "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true }, "@humanwhocodes/config-array": { @@ -8006,9 +8006,9 @@ "dev": true }, "@types/node": { - "version": "20.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -8949,15 +8949,15 @@ "dev": true }, "eslint": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", - "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.55.0", + "@eslint/js": "8.56.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -9399,9 +9399,9 @@ "dev": true }, "h264-profile-level-id": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.0.2.tgz", - "integrity": "sha512-bsSv/bHq4eIUt4iMycA9rn1C28gtXwrKLAkbpzuZmkQp4u3M6QlF5y6DlTMy5fGDkVGbMLxFGeL7Ra8JKMm4Dg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.1.0.tgz", + "integrity": "sha512-kASSjiJii6zPurTkCyaxxw3IaI1ahnylJNpdcxRhpUebHy/jpyjgIZ+8YcqjYaX+HtAPlpw9rKbvWBLc4jRjPw==", "requires": { "debug": "^4.3.4" } diff --git a/package.json b/package.json index dcfbfe77ea..31b18d59e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.11", + "version": "3.13.12", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -99,7 +99,7 @@ "dependencies": { "debug": "^4.3.4", "flatbuffers": "^23.5.26", - "h264-profile-level-id": "^1.0.2", + "h264-profile-level-id": "^1.1.0", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0" @@ -108,10 +108,10 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.4", + "@types/node": "^20.10.5", "@typescript-eslint/eslint-plugin": "^6.14.0", "@typescript-eslint/parser": "^6.14.0", - "eslint": "^8.55.0", + "eslint": "^8.56.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", "marked": "^11.1.0", From f9c081c41e90a84d837d2a26b700d1fee84430c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 18 Dec 2023 19:21:58 +0100 Subject: [PATCH 252/525] Rust: Update h264-profile-level-id dependency to 0.2.0 --- rust/CHANGELOG.md | 4 ++++ rust/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index 4697ba666e..c00c8ae3d8 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +# NEXT + +* Update h264-profile-level-id dependency to 0.2.0. + # 0.13.0 * Updates from mediasoup TypeScript `3.13.0..=3.13.7`. diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 4c35295b11..3ccbd1e8c1 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -30,7 +30,7 @@ atomic-take = "1.0.0" event-listener-primitives = "2.0.1" fastrand = "1.8.0" futures-lite = "1.12.0" -h264-profile-level-id = "0.1.1" +h264-profile-level-id = "0.2.0" hash_hasher = "2.0.3" log = "0.4.17" nohash-hasher = "0.2.0" From c5eb1b40534b5fa2ce991f17df2a5947378004bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 18 Dec 2023 23:01:34 +0100 Subject: [PATCH 253/525] Fix Rust docs build (#1271) --- .github/workflows/mediasoup-rust.yaml | 7 +++++++ Cargo.lock | 5 ++--- rust/CHANGELOG.md | 2 ++ rust/src/data_structures.rs | 2 +- rust/src/router/data_consumer.rs | 5 ++++- worker/build.rs | 10 +++++----- 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index 0778129e84..f89b64b9ab 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -46,3 +46,10 @@ jobs: - name: cargo test run: cargo test --verbose + + - name: cargo doc + run: cargo doc --locked --all --no-deps --lib + env: + DOCS_RS: '1' + RUSTDOCFLAGS: '-D rustdoc::broken-intra-doc-links -D rustdoc::private_intra_doc_links' + diff --git a/Cargo.lock b/Cargo.lock index 25f9f06ee3..7a0eadf2d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1028,13 +1028,12 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "h264-profile-level-id" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12ebc03fc4f14b7ddc94da90cfb28ba3edee2d926798a9eef89f8a27bbdbca5" +checksum = "45d0dbf6a9847b64c9b06938660891f983434dcc009b5ae6a58f5e34af74a649" dependencies = [ "bitpattern", "log", - "once_cell", "thiserror", ] diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index c00c8ae3d8..dad75c4f0f 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -3,6 +3,8 @@ # NEXT * Update h264-profile-level-id dependency to 0.2.0. +* Fix docs build (PR #1271). +* Rename `data_consumer::on_producer_resume` to `data_consumer::on_data_producer_resume` (PR #1271). # 0.13.0 diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index d1940de235..a5c2cc1856 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -45,7 +45,7 @@ impl AppData { } } -/// Listening protocol, IP and port for [`WebRtcServer`] to listen on. +/// Listening protocol, IP and port for [`WebRtcServer`](crate::webrtc_server::WebRtcServer) to listen on. /// /// # Notes on usage /// If you use "0.0.0.0" or "::" as ip value, then you need to also provide `announced_ip`. diff --git a/rust/src/router/data_consumer.rs b/rust/src/router/data_consumer.rs index 88ca1a5742..bafaffd240 100644 --- a/rust/src/router/data_consumer.rs +++ b/rust/src/router/data_consumer.rs @@ -903,7 +903,10 @@ impl DataConsumer { } /// Callback is called when the associated data producer is resumed. - pub fn on_producer_resume(&self, callback: F) -> HandlerId { + pub fn on_data_producer_resume( + &self, + callback: F, + ) -> HandlerId { self.inner() .handlers .data_producer_resume diff --git a/worker/build.rs b/worker/build.rs index 5139edef80..920d185d7b 100644 --- a/worker/build.rs +++ b/worker/build.rs @@ -2,11 +2,6 @@ use std::process::Command; use std::{env, fs}; fn main() { - if env::var("DOCS_RS").is_ok() { - // Skip everything when building docs on docs.rs - return; - } - // On Windows Rust always links against release version of MSVC runtime, thus requires // Release build here let build_type = if cfg!(all(debug_assertions, not(windows))) { @@ -45,6 +40,11 @@ fn main() { ) .expect("Failed to write generated Rust flatbuffers into fbs.rs"); + if env::var("DOCS_RS").is_ok() { + // Skip everything when building docs on docs.rs + return; + } + // Force forward slashes on Windows too so that is plays well with our tasks.py let mediasoup_out_dir = format!("{}/out", out_dir.replace('\\', "/")); From c2c4323da4a90817d2e1ee14ff45b2188d67f2b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 18 Dec 2023 23:21:25 +0100 Subject: [PATCH 254/525] Update Rust versions (#1272) --- Cargo.lock | 4 ++-- rust/CHANGELOG.md | 3 ++- rust/Cargo.toml | 4 ++-- worker/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7a0eadf2d9..aa5dfcfb45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1354,7 +1354,7 @@ checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" [[package]] name = "mediasoup" -version = "0.13.0" +version = "0.14.0" dependencies = [ "actix", "actix-web", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "mediasoup-sys" -version = "0.7.0" +version = "0.7.1" dependencies = [ "planus", "planus-codegen", diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index dad75c4f0f..c6148b0170 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog -# NEXT +# 0.14.0 +* Updates from mediasoup TypeScript `3.13.8..=3.13.12`. * Update h264-profile-level-id dependency to 0.2.0. * Fix docs build (PR #1271). * Rename `data_consumer::on_producer_resume` to `data_consumer::on_data_producer_resume` (PR #1271). diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 3ccbd1e8c1..66ed81c861 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup" -version = "0.13.0" +version = "0.14.0" description = "Cutting Edge WebRTC Video Conferencing in Rust" categories = ["api-bindings", "multimedia", "network-programming"] authors = ["Nazar Mokrynskyi "] @@ -46,7 +46,7 @@ version = "0.8.1" [dependencies.mediasoup-sys] path = "../worker" -version = "0.7.0" +version = "0.7.1" [dependencies.parking_lot] version = "0.12.1" diff --git a/worker/Cargo.toml b/worker/Cargo.toml index edf5687367..c3911071e9 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup-sys" -version = "0.7.0" +version = "0.7.1" description = "FFI bindings to C++ libmediasoup-worker" authors = ["Nazar Mokrynskyi "] edition = "2021" From 8365c62fde60337d8bffd56ee414ef2eab45b676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Wed, 20 Dec 2023 20:15:52 +0100 Subject: [PATCH 255/525] worker: Do not use references for async callbacks (#1274) * worker: Do not use references for async callbacks If the callback is not executed in the same uv_loop iteration, the access to such values upon executing the callback is undefined. * Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ worker/include/RTC/SenderBandwidthEstimator.hpp | 2 +- .../include/RTC/TransportCongestionControlClient.hpp | 2 +- worker/src/RTC/SenderBandwidthEstimator.cpp | 2 +- worker/src/RTC/Transport.cpp | 12 ++++++------ worker/src/RTC/TransportCongestionControlClient.cpp | 3 ++- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 370e19885b..24a5e5405b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). + + ### 3.13.12 * worker: Disable `RtcLogger` usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). diff --git a/worker/include/RTC/SenderBandwidthEstimator.hpp b/worker/include/RTC/SenderBandwidthEstimator.hpp index b25f5df385..208b188f93 100644 --- a/worker/include/RTC/SenderBandwidthEstimator.hpp +++ b/worker/include/RTC/SenderBandwidthEstimator.hpp @@ -89,7 +89,7 @@ namespace RTC public: void TransportConnected(); void TransportDisconnected(); - void RtpPacketSent(SentInfo& sentInfo); + void RtpPacketSent(const SentInfo& sentInfo); void ReceiveRtcpTransportFeedback(const RTC::RTCP::FeedbackRtpTransportPacket* feedback); void EstimateAvailableBitrate(CummulativeResult& cummulativeResult); void UpdateRtt(float rtt); diff --git a/worker/include/RTC/TransportCongestionControlClient.hpp b/worker/include/RTC/TransportCongestionControlClient.hpp index 1c2fb61f6c..4bd3796284 100644 --- a/worker/include/RTC/TransportCongestionControlClient.hpp +++ b/worker/include/RTC/TransportCongestionControlClient.hpp @@ -69,7 +69,7 @@ namespace RTC void TransportDisconnected(); void InsertPacket(webrtc::RtpPacketSendInfo& packetInfo); webrtc::PacedPacketInfo GetPacingInfo(); - void PacketSent(webrtc::RtpPacketSendInfo& packetInfo, int64_t nowMs); + void PacketSent(const webrtc::RtpPacketSendInfo& packetInfo, int64_t nowMs); void ReceiveEstimatedBitrate(uint32_t bitrate); void ReceiveRtcpReceiverReport(RTC::RTCP::ReceiverReportPacket* packet, float rtt, int64_t nowMs); void ReceiveRtcpTransportFeedback(const RTC::RTCP::FeedbackRtpTransportPacket* feedback); diff --git a/worker/src/RTC/SenderBandwidthEstimator.cpp b/worker/src/RTC/SenderBandwidthEstimator.cpp index 6cc7476a72..834c21ea35 100644 --- a/worker/src/RTC/SenderBandwidthEstimator.cpp +++ b/worker/src/RTC/SenderBandwidthEstimator.cpp @@ -47,7 +47,7 @@ namespace RTC this->cummulativeResult.Reset(); } - void SenderBandwidthEstimator::RtpPacketSent(SentInfo& sentInfo) + void SenderBandwidthEstimator::RtpPacketSent(const SentInfo& sentInfo) { MS_TRACE(); diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index e76d9adad0..2d1da9e623 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -2493,7 +2493,7 @@ namespace RTC sentInfo.sendingAtMs = DepLibUV::GetTimeMs(); auto* cb = new onSendCallback( - [tccClientWeakPtr, &packetInfo, senderBweWeakPtr, &sentInfo](bool sent) + [tccClientWeakPtr, packetInfo, senderBweWeakPtr, sentInfo](bool sent) { if (sent) { @@ -2517,7 +2517,7 @@ namespace RTC SendRtpPacket(consumer, packet, cb); #else const auto* cb = new onSendCallback( - [tccClientWeakPtr, &packetInfo](bool sent) + [tccClientWeakPtr, packetInfo](bool sent) { if (sent) { @@ -2582,7 +2582,7 @@ namespace RTC sentInfo.sendingAtMs = DepLibUV::GetTimeMs(); auto* cb = new onSendCallback( - [tccClientWeakPtr, &packetInfo, senderBweWeakPtr, &sentInfo](bool sent) + [tccClientWeakPtr, packetInfo, senderBweWeakPtr, sentInfo](bool sent) { if (sent) { @@ -2606,7 +2606,7 @@ namespace RTC SendRtpPacket(consumer, packet, cb); #else const auto* cb = new onSendCallback( - [tccClientWeakPtr, &packetInfo](bool sent) + [tccClientWeakPtr, packetInfo](bool sent) { if (sent) { @@ -2982,7 +2982,7 @@ namespace RTC sentInfo.sendingAtMs = DepLibUV::GetTimeMs(); auto* cb = new onSendCallback( - [tccClientWeakPtr, &packetInfo, senderBweWeakPtr, &sentInfo](bool sent) + [tccClientWeakPtr, packetInfo, senderBweWeakPtr, sentInfo](bool sent) { if (sent) { @@ -3006,7 +3006,7 @@ namespace RTC SendRtpPacket(nullptr, packet, cb); #else const auto* cb = new onSendCallback( - [tccClientWeakPtr, &packetInfo](bool sent) + [tccClientWeakPtr, packetInfo](bool sent) { if (sent) { diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index 380fb34edb..98ddd17286 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -152,7 +152,8 @@ namespace RTC return this->rtpTransportControllerSend->packet_sender()->GetPacingInfo(); } - void TransportCongestionControlClient::PacketSent(webrtc::RtpPacketSendInfo& packetInfo, int64_t nowMs) + void TransportCongestionControlClient::PacketSent( + const webrtc::RtpPacketSendInfo& packetInfo, int64_t nowMs) { MS_TRACE(); From 7ec6d293858ac66bd31aae6d32c80c08ec470bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 22 Dec 2023 10:29:56 +0100 Subject: [PATCH 256/525] Update npm h264-profile-level-id to 2.0.0 --- package-lock.json | 362 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 185 insertions(+), 183 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0bc80cc4df..6416c1a2c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "dependencies": { "debug": "^4.3.4", "flatbuffers": "^23.5.26", - "h264-profile-level-id": "^1.1.0", + "h264-profile-level-id": "^2.0.0", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0" @@ -22,8 +22,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.5", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@typescript-eslint/eslint-plugin": "^6.15.0", + "@typescript-eslint/parser": "^6.15.0", "eslint": "^8.56.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", @@ -1552,7 +1552,6 @@ "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, "dependencies": { "@types/ms": "*" } @@ -1615,8 +1614,7 @@ "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", - "dev": true + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { "version": "20.10.5", @@ -1661,16 +1659,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.14.0.tgz", - "integrity": "sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.15.0.tgz", + "integrity": "sha512-j5qoikQqPccq9QoBAupOP+CBu8BaJ8BLjaXSioDISeTZkVO3ig7oSIKh3H+rEpee7xCXtWwSB4KIL5l6hWZzpg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/type-utils": "6.14.0", - "@typescript-eslint/utils": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/type-utils": "6.15.0", + "@typescript-eslint/utils": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1696,13 +1694,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", - "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", + "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0" + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1713,9 +1711,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", - "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", + "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1726,13 +1724,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", - "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", + "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1753,17 +1751,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz", - "integrity": "sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", + "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/typescript-estree": "6.14.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", "semver": "^7.5.4" }, "engines": { @@ -1778,12 +1776,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", - "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", + "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/types": "6.15.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1795,15 +1793,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.14.0.tgz", - "integrity": "sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz", + "integrity": "sha512-MkgKNnsjC6QwcMdlNAel24jjkEO/0hQaMDLqP4S9zq5HBAUJNQB6y+3DwLjX7b3l2b37eNAxMPLwb3/kh8VKdA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/typescript-estree": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4" }, "engines": { @@ -1823,13 +1821,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", - "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", + "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0" + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1840,9 +1838,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", - "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", + "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1853,13 +1851,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", - "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", + "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1880,12 +1878,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", - "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", + "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/types": "6.15.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1914,13 +1912,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.14.0.tgz", - "integrity": "sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.15.0.tgz", + "integrity": "sha512-CnmHKTfX6450Bo49hPg2OkIm/D/TVYV7jO1MCfPYGwf6x3GO0VU8YMO5AYMn+u3X05lRRxA4fWCz87GFQV6yVQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.14.0", - "@typescript-eslint/utils": "6.14.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/utils": "6.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1941,13 +1939,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", - "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", + "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0" + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1958,9 +1956,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", - "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", + "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1971,13 +1969,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", - "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", + "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1998,17 +1996,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz", - "integrity": "sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", + "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/typescript-estree": "6.14.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", "semver": "^7.5.4" }, "engines": { @@ -2023,12 +2021,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", - "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", + "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/types": "6.15.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3647,14 +3645,19 @@ "dev": true }, "node_modules/h264-profile-level-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.1.0.tgz", - "integrity": "sha512-kASSjiJii6zPurTkCyaxxw3IaI1ahnylJNpdcxRhpUebHy/jpyjgIZ+8YcqjYaX+HtAPlpw9rKbvWBLc4jRjPw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-2.0.0.tgz", + "integrity": "sha512-X4CLryVbVA0CtjTExS4G5U1gb2Z4wa32AF8ukVmFuLdw2JRq2aHisor7SY5SYTUUrUSqq0KdPIO18sql6IWIQw==", "dependencies": { + "@types/debug": "^4.1.12", "debug": "^4.3.4" }, "engines": { - "node": ">=10.0.0" + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mediasoup" } }, "node_modules/hard-rejection": { @@ -7939,7 +7942,6 @@ "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, "requires": { "@types/ms": "*" } @@ -8002,8 +8004,7 @@ "@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", - "dev": true + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { "version": "20.10.5", @@ -8048,16 +8049,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.14.0.tgz", - "integrity": "sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.15.0.tgz", + "integrity": "sha512-j5qoikQqPccq9QoBAupOP+CBu8BaJ8BLjaXSioDISeTZkVO3ig7oSIKh3H+rEpee7xCXtWwSB4KIL5l6hWZzpg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/type-utils": "6.14.0", - "@typescript-eslint/utils": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/type-utils": "6.15.0", + "@typescript-eslint/utils": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8067,29 +8068,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", - "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", + "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0" + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0" } }, "@typescript-eslint/types": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", - "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", + "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", - "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", + "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", "dev": true, "requires": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8098,69 +8099,69 @@ } }, "@typescript-eslint/utils": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz", - "integrity": "sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", + "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/typescript-estree": "6.14.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", - "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", + "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/types": "6.15.0", "eslint-visitor-keys": "^3.4.1" } } } }, "@typescript-eslint/parser": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.14.0.tgz", - "integrity": "sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz", + "integrity": "sha512-MkgKNnsjC6QwcMdlNAel24jjkEO/0hQaMDLqP4S9zq5HBAUJNQB6y+3DwLjX7b3l2b37eNAxMPLwb3/kh8VKdA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/typescript-estree": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", - "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", + "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0" + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0" } }, "@typescript-eslint/types": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", - "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", + "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", - "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", + "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", "dev": true, "requires": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8169,12 +8170,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", - "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", + "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/types": "6.15.0", "eslint-visitor-keys": "^3.4.1" } } @@ -8191,41 +8192,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.14.0.tgz", - "integrity": "sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.15.0.tgz", + "integrity": "sha512-CnmHKTfX6450Bo49hPg2OkIm/D/TVYV7jO1MCfPYGwf6x3GO0VU8YMO5AYMn+u3X05lRRxA4fWCz87GFQV6yVQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.14.0", - "@typescript-eslint/utils": "6.14.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/utils": "6.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", - "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", + "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0" + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0" } }, "@typescript-eslint/types": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", - "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", + "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", - "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", + "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", "dev": true, "requires": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8234,27 +8235,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz", - "integrity": "sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", + "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/typescript-estree": "6.14.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", - "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", + "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/types": "6.15.0", "eslint-visitor-keys": "^3.4.1" } } @@ -9399,10 +9400,11 @@ "dev": true }, "h264-profile-level-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-1.1.0.tgz", - "integrity": "sha512-kASSjiJii6zPurTkCyaxxw3IaI1ahnylJNpdcxRhpUebHy/jpyjgIZ+8YcqjYaX+HtAPlpw9rKbvWBLc4jRjPw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-2.0.0.tgz", + "integrity": "sha512-X4CLryVbVA0CtjTExS4G5U1gb2Z4wa32AF8ukVmFuLdw2JRq2aHisor7SY5SYTUUrUSqq0KdPIO18sql6IWIQw==", "requires": { + "@types/debug": "^4.1.12", "debug": "^4.3.4" } }, diff --git a/package.json b/package.json index 31b18d59e3..dfefc9a71e 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "dependencies": { "debug": "^4.3.4", "flatbuffers": "^23.5.26", - "h264-profile-level-id": "^1.1.0", + "h264-profile-level-id": "^2.0.0", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0" @@ -109,8 +109,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.5", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@typescript-eslint/eslint-plugin": "^6.15.0", + "@typescript-eslint/parser": "^6.15.0", "eslint": "^8.56.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", From be90de5d6f34d390e4594ce88b9de228b1fb93af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 22 Dec 2023 10:38:04 +0100 Subject: [PATCH 257/525] Fix usage of h264-profile-level-id new API --- node/src/ortc.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/node/src/ortc.ts b/node/src/ortc.ts index dad1cf9c1b..4905708633 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -1477,7 +1477,9 @@ function matchCodecs( try { selectedProfileLevelId = - h264.generateProfileLevelIdForAnswer(aCodec.parameters, bCodec.parameters); + h264.generateProfileLevelIdStringForAnswer( + aCodec.parameters, bCodec.parameters + ); } catch (error) { From 7f2a3d21057fc4dcc6b8f307e762161759dd302c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 22 Dec 2023 11:31:11 +0100 Subject: [PATCH 258/525] invoke tasks.py: Fix 'xcode' task --- worker/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/tasks.py b/worker/tasks.py index e366c65d91..a4b3fdbfbc 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -350,7 +350,7 @@ def xcode(ctx): """ with ctx.cd(WORKER_DIR): ctx.run( - f'"{MESON}" setup --buildtype {MEDIASOUP_BUILDTYPE} --backend xcode "{MEDIASOUP_OUT_DIR}/xcode"', + f'"{MESON}" setup --buildtype {MEDIASOUP_BUILDTYPE.lower()} --backend xcode "{MEDIASOUP_OUT_DIR}/xcode"', echo=True, pty=PTY_SUPPORTED, shell=SHELL From 82ed1222abc16ae0f4f968e3f8ebf56848fa44c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 22 Dec 2023 11:42:41 +0100 Subject: [PATCH 259/525] super cosmetic --- worker/scripts/cppcheck.sh | 6 +++--- worker/scripts/flint++.sh | 4 ++-- worker/scripts/get-dep.sh | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/worker/scripts/cppcheck.sh b/worker/scripts/cppcheck.sh index 14ca7d5bd6..206355bdf8 100755 --- a/worker/scripts/cppcheck.sh +++ b/worker/scripts/cppcheck.sh @@ -29,7 +29,7 @@ CPPCHECKS="warning,style,performance,portability,unusedFunction" XML_FILE="/tmp/mediasoup-worker-cppcheck.xml" HTML_REPORT_DIR="/tmp/mediasoup-worker-cppcheck-report" -echo ">>> [INFO] running cppcheck ..." +echo ">>> [INFO] running cppcheck..." cppcheck --std=c++11 --enable=${CPPCHECKS} -v --quiet --report-progress --inline-suppr --error-exitcode=69 -I include src --xml-version=2 2> $XML_FILE # If exit code is 1 it means that some cppcheck option is wrong, so abort. @@ -40,12 +40,12 @@ fi echo ">>> [INFO] cppcheck XML report file generated in ${XML_FILE}" -echo ">>> [INFO] running cppcheck-htmlreport ..." +echo ">>> [INFO] running cppcheck-htmlreport..." cppcheck-htmlreport --title="mediasoup-worker" --file=${XML_FILE} --report-dir=${HTML_REPORT_DIR} --source-dir=. > /dev/null echo ">>> [INFO] cppcheck HTML report generated in ${HTML_REPORT_DIR}" if type "open" &> /dev/null; then - echo ">>> [INFO] opening HTML report ..." + echo ">>> [INFO] opening HTML report..." open ${HTML_REPORT_DIR}/index.html fi diff --git a/worker/scripts/flint++.sh b/worker/scripts/flint++.sh index 33a60239bb..66e1a4daf7 100755 --- a/worker/scripts/flint++.sh +++ b/worker/scripts/flint++.sh @@ -13,9 +13,9 @@ if ! type "flint++" &> /dev/null; then exit 1 fi -echo ">>> [INFO] running flint++ in src/ folder ..." +echo ">>> [INFO] running flint++ in src/ folder..." flint++ --recursive --verbose src/ echo -echo ">>> [INFO] running flint++ in include/ folder ..." +echo ">>> [INFO] running flint++ in include/ folder..." flint++ --recursive --verbose include/ diff --git a/worker/scripts/get-dep.sh b/worker/scripts/get-dep.sh index 5d6fced81f..8abe8d3bcb 100755 --- a/worker/scripts/get-dep.sh +++ b/worker/scripts/get-dep.sh @@ -17,24 +17,24 @@ function get_dep() GIT_TAG="$2" DEST="$3" - echo ">>> [INFO] getting dep '${DEP}' ..." + echo ">>> [INFO] getting dep '${DEP}'..." if [ -d "${DEST}" ] ; then - echo ">>> [INFO] deleting ${DEST} ..." + echo ">>> [INFO] deleting ${DEST}..." git rm -rf --ignore-unmatch ${DEST} > /dev/null rm -rf ${DEST} fi - echo ">>> [INFO] cloning ${GIT_REPO} ..." + echo ">>> [INFO] cloning ${GIT_REPO}..." git clone ${GIT_REPO} ${DEST} cd ${DEST} - echo ">>> [INFO] setting '${GIT_TAG}' git tag ..." + echo ">>> [INFO] setting '${GIT_TAG}' git tag..." git checkout --quiet ${GIT_TAG} set -e - echo ">>> [INFO] adding dep source code to the repository ..." + echo ">>> [INFO] adding dep source code to the repository..." rm -rf .git git add . From 3cefa117b096a5cf6cd85cc29cf411294b3d747b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Fri, 22 Dec 2023 13:16:49 +0100 Subject: [PATCH 260/525] liburing zero copy (#1273) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * liburing zero copy By pre-registering the send buffers we can make use of zero copy in order to avoid the kernel memcpy-ing the buffers. Send buffers are allocated by us and will be set as available once liburing notifies us about it. * handle feedback * handle ENOMEM error when registering buffers * fix error comparison * Cosmetic * Try to make compiled happy * Do not use errno variable name * Use error = -1 * err everywhere * remove uneeded '-1 *' to negate an int --------- Co-authored-by: Iñaki Baz Castillo --- CHANGELOG.md | 1 + worker/include/DepLibUring.hpp | 10 ++- worker/include/Utils.hpp | 2 + worker/src/DepLibUring.cpp | 133 ++++++++++++++++++++++++++++----- worker/src/Utils/IP.cpp | 23 ++++++ 5 files changed, 149 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24a5e5405b..2c0acaefc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### NEXT * worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). +* liburing: Enable zero copy ([PR #1273](https://github.com/versatica/mediasoup/pull/1273)). ### 3.13.12 diff --git a/worker/include/DepLibUring.hpp b/worker/include/DepLibUring.hpp index 7d3d3848e4..973acaff42 100644 --- a/worker/include/DepLibUring.hpp +++ b/worker/include/DepLibUring.hpp @@ -80,6 +80,10 @@ class DepLibUring { return this->active; } + bool IsZeroCopyEnabled() const + { + return this->zeroCopyEnabled; + } io_uring* GetRing() { return std::addressof(this->ring); @@ -103,18 +107,22 @@ class DepLibUring private: // io_uring instance. io_uring ring; - // Event file descriptor to watch for completions. + // Event file descriptor to watch for io_uring completions. int efd; // libuv handle used to poll io_uring completions. uv_poll_t* uvHandle{ nullptr }; // Whether we are currently sending RTP over io_uring. bool active{ false }; + // Whether Zero Copy feature is enabled. + bool zeroCopyEnabled{ true }; // Pre-allocated UserData's. UserData userDatas[QueueDepth]{}; // Indexes of available UserData entries. std::queue availableUserDataEntries; // Pre-allocated SendBuffer's. SendBuffer sendBuffers[QueueDepth]; + // iovec structs to be registered for Zero Copy. + struct iovec iovecs[QueueDepth]; // Submission queue entry process count. uint64_t sqeProcessCount{ 0u }; // Submission queue entry miss count. diff --git a/worker/include/Utils.hpp b/worker/include/Utils.hpp index b11b9a18fc..120afb0b62 100644 --- a/worker/include/Utils.hpp +++ b/worker/include/Utils.hpp @@ -23,6 +23,8 @@ namespace Utils static void GetAddressInfo(const struct sockaddr* addr, int& family, std::string& ip, uint16_t& port); + static size_t GetAddressLen(const struct sockaddr* addr); + static bool CompareAddresses(const struct sockaddr* addr1, const struct sockaddr* addr2) { // Compare family. diff --git a/worker/src/DepLibUring.cpp b/worker/src/DepLibUring.cpp index a2c9226769..bfd44aba4d 100644 --- a/worker/src/DepLibUring.cpp +++ b/worker/src/DepLibUring.cpp @@ -4,6 +4,7 @@ #include "DepLibUring.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include #include @@ -30,9 +31,13 @@ inline static void onFdEvent(uv_poll_t* handle, int status, int events) // the counter in order to avoid libuv calling this callback indefinitely. eventfd_t v; int err = eventfd_read(liburing->GetEventFd(), std::addressof(v)); + if (err < 0) { - MS_ABORT("eventfd_read() failed: %s", std::strerror(-err)); + // Get positive errno. + int error = -err; + + MS_ABORT("eventfd_read() failed: %s", std::strerror(error)); }; for (unsigned int i{ 0 }; i < count; ++i) @@ -40,27 +45,69 @@ inline static void onFdEvent(uv_poll_t* handle, int status, int events) struct io_uring_cqe* cqe = cqes[i]; auto* userData = static_cast(io_uring_cqe_get_data(cqe)); - if (cqe->res < 0) + if (liburing->IsZeroCopyEnabled()) { - MS_ERROR("sending failed: %s", std::strerror(-cqe->res)); + // CQE notification for a zero-copy submission. + if (cqe->flags & IORING_CQE_F_NOTIF) + { + // The send buffer is now in the network card, run the send callback. + if (userData->cb) + { + (*userData->cb)(true); + delete userData->cb; + userData->cb = nullptr; + } + + liburing->ReleaseUserDataEntry(userData->idx); + io_uring_cqe_seen(liburing->GetRing(), cqe); + + continue; + } + // CQE for a zero-copy submission, a CQE notification will follow. + if (cqe->flags & IORING_CQE_F_MORE) + { + if (cqe->res < 0) + { + if (userData->cb) + { + (*userData->cb)(false); + delete userData->cb; + userData->cb = nullptr; + } + } + + // NOTE: Do not release the user data as it will be done upon reception + // of CQE notification. + io_uring_cqe_seen(liburing->GetRing(), cqe); + + continue; + } + } + + // Successfull SQE. + if (cqe->res >= 0) + { if (userData->cb) { - (*userData->cb)(false); + (*userData->cb)(true); delete userData->cb; + userData->cb = nullptr; } } + // Failed SQE. else { if (userData->cb) { - (*userData->cb)(true); + (*userData->cb)(false); delete userData->cb; + userData->cb = nullptr; } } - io_uring_cqe_seen(liburing->GetRing(), cqe); liburing->ReleaseUserDataEntry(userData->idx); + io_uring_cqe_seen(liburing->GetRing(), cqe); } } @@ -234,7 +281,10 @@ DepLibUring::LibUring::LibUring() if (err < 0) { - MS_THROW_ERROR("io_uring_queue_init() failed: %s", std::strerror(-err)); + // Get positive errno. + int error = -err; + + MS_THROW_ERROR("io_uring_queue_init() failed: %s", std::strerror(error)); } // Create an eventfd instance. @@ -249,7 +299,10 @@ DepLibUring::LibUring::LibUring() if (err < 0) { - MS_THROW_ERROR("io_uring_register_eventfd() failed: %s", std::strerror(-err)); + // Get positive errno. + int error = -err; + + MS_THROW_ERROR("io_uring_register_eventfd() failed: %s", std::strerror(error)); } // Initialize available UserData entries. @@ -258,6 +311,35 @@ DepLibUring::LibUring::LibUring() this->userDatas[i].store = this->sendBuffers[i]; this->availableUserDataEntries.push(i); } + + // Initialize iovecs. + for (size_t i{ 0 }; i < DepLibUring::QueueDepth; ++i) + { + this->iovecs[i].iov_base = this->sendBuffers[i]; + this->iovecs[i].iov_len = DepLibUring::SendBufferSize; + } + + err = io_uring_register_buffers(std::addressof(this->ring), this->iovecs, DepLibUring::QueueDepth); + + if (err < 0) + { + // Get positive errno. + int error = -err; + + if (error == ENOMEM) + { + this->zeroCopyEnabled = false; + + MS_WARN_TAG( + info, + "io_uring_register_buffers() failed due to low memlock limit (ulimit -l), disabling zero copy: %s", + std::strerror(error)); + } + else + { + MS_THROW_ERROR("io_uring_register_buffers() failed: %s", std::strerror(error)); + } + } } DepLibUring::LibUring::~LibUring() @@ -269,7 +351,10 @@ DepLibUring::LibUring::~LibUring() if (err != 0) { - MS_ABORT("close() failed: %s", std::strerror(-err)); + // Get positive errno. + int error = -err; + + MS_ABORT("close() failed: %s", std::strerror(error)); } // Close the ring. @@ -372,8 +457,6 @@ bool DepLibUring::LibUring::PrepareSend( return false; } - userData->cb = cb; - // The send data buffer belongs to us, no need to memcpy. if (this->IsDataInSendBuffers(data)) { @@ -384,21 +467,30 @@ bool DepLibUring::LibUring::PrepareSend( std::memcpy(userData->store, data, len); } + userData->cb = cb; + io_uring_sqe_set_data(sqe, userData); - socklen_t addrlen = 0; + socklen_t addrlen = Utils::IP::GetAddressLen(addr); - if (addr->sa_family == AF_INET) + if (this->zeroCopyEnabled) { - addrlen = sizeof(struct sockaddr_in); + auto iovec = this->iovecs[userData->idx]; + iovec.iov_len = len; + + io_uring_prep_send_zc(sqe, sockfd, iovec.iov_base, iovec.iov_len, 0, 0); + io_uring_prep_send_set_addr(sqe, addr, addrlen); + + // Tell io_uring that we are providing the already registered send buffer + // for zero copy. + sqe->ioprio |= IORING_RECVSEND_FIXED_BUF; + sqe->buf_index = userData->idx; } - else if (addr->sa_family == AF_INET6) + else { - addrlen = sizeof(struct sockaddr_in6); + io_uring_prep_sendto(sqe, sockfd, userData->store, len, 0, addr, addrlen); } - io_uring_prep_sendto(sqe, sockfd, userData->store, len, 0, addr, addrlen); - this->sqeProcessCount++; return true; @@ -482,7 +574,10 @@ void DepLibUring::LibUring::Submit() } else { - MS_ERROR("io_uring_submit() failed: %s", std::strerror(-err)); + // Get positive errno. + int error = -err; + + MS_ERROR("io_uring_submit() failed: %s", std::strerror(error)); } } diff --git a/worker/src/Utils/IP.cpp b/worker/src/Utils/IP.cpp index 81a5c7e093..9460fc2488 100644 --- a/worker/src/Utils/IP.cpp +++ b/worker/src/Utils/IP.cpp @@ -91,6 +91,29 @@ namespace Utils ip.assign(ipBuffer); } + size_t IP::GetAddressLen(const struct sockaddr* addr) + { + MS_TRACE(); + + switch (addr->sa_family) + { + case AF_INET: + { + return sizeof(struct sockaddr_in); + } + + case AF_INET6: + { + return sizeof(struct sockaddr_in6); + } + + default: + { + MS_ABORT("unknown network family: %d", static_cast(addr->sa_family)); + } + } + } + void IP::NormalizeIp(std::string& ip) { MS_TRACE(); From 6007c9eb545e7dc53e1abce0095f6c3b58ba6450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 23 Dec 2023 23:36:16 +0100 Subject: [PATCH 261/525] Try GitHub CI actions v4 (#1276) --- .github/workflows/codeql.yaml | 2 +- .github/workflows/mediasoup-node.yaml | 4 ++-- .github/workflows/mediasoup-rust.yaml | 2 +- .github/workflows/mediasoup-worker-prebuild.yaml | 4 ++-- .github/workflows/mediasoup-worker.yaml | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 15c104f781..4a23647801 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -41,7 +41,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 81c11b1b03..fcb8fdb946 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -31,10 +31,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.ci.node }} diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index f89b64b9ab..ef5e95eaa6 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Configure cache uses: actions/cache@v3 diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 6e3f2c3606..99010871fd 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -43,10 +43,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 6e48e2464d..4ade2574c5 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -48,10 +48,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} From afec28ec6022eb1da1760d08684146dc32837d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 26 Dec 2023 08:33:56 +0100 Subject: [PATCH 262/525] Simplify meson setup task (#1275) --- worker/tasks.py | 71 +++++++++++++++---------------------------------- 1 file changed, 21 insertions(+), 50 deletions(-) diff --git a/worker/tasks.py b/worker/tasks.py index a4b3fdbfbc..75ac5c2bb1 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -140,59 +140,30 @@ def setup(ctx): """ Run meson setup """ - # We add --reconfigure first as a workaround for this issue: - # https://github.com/ninja-build/ninja/issues/1997 if MEDIASOUP_BUILDTYPE == 'Release': - try: - with ctx.cd(WORKER_DIR): - ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true -Db_pie=true -Db_staticpic=true --reconfigure {MESON_ARGS} "{BUILD_DIR}"', - echo=True, - pty=PTY_SUPPORTED, - shell=SHELL - ); - except: - with ctx.cd(WORKER_DIR): - ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', - echo=True, - pty=PTY_SUPPORTED, - shell=SHELL - ); + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); elif MEDIASOUP_BUILDTYPE == 'Debug': - try: - with ctx.cd(WORKER_DIR): - ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug -Db_pie=true -Db_staticpic=true --reconfigure {MESON_ARGS} "{BUILD_DIR}"', - echo=True, - pty=PTY_SUPPORTED, - shell=SHELL - ); - except: - with ctx.cd(WORKER_DIR): - ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', - echo=True, - pty=PTY_SUPPORTED, - shell=SHELL - ); + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); else: - try: - with ctx.cd(WORKER_DIR): - ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release -Db_pie=true -Db_staticpic=true --reconfigure {MESON_ARGS} "{BUILD_DIR}"', - echo=True, - pty=PTY_SUPPORTED, - shell=SHELL - ); - except: - with ctx.cd(WORKER_DIR): - ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', - echo=True, - pty=PTY_SUPPORTED, - shell=SHELL - ); + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); @task From a0485562fb89cf82b4020eae87182921d89b9efc Mon Sep 17 00:00:00 2001 From: grootgordon <5849840+grootgordon@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:42:53 +0800 Subject: [PATCH 263/525] Update: SctpAssociation::DataProducerClosed (#1278) --- worker/src/RTC/SctpAssociation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/SctpAssociation.cpp b/worker/src/RTC/SctpAssociation.cpp index 2dd56f452f..b83c740a69 100644 --- a/worker/src/RTC/SctpAssociation.cpp +++ b/worker/src/RTC/SctpAssociation.cpp @@ -503,7 +503,7 @@ namespace RTC auto streamId = dataProducer->GetSctpStreamParameters().streamId; // Send SCTP_RESET_STREAMS to the remote. - // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.7 + // https://tools.ietf.org/html/rfc8831#section-6.7 if (this->isDataChannel) { ResetSctpStream(streamId, StreamDirection::OUTGOING); From 730cb587a3b5a539ab07d7fb6a0ae2f11691516d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 27 Dec 2023 13:49:46 +0100 Subject: [PATCH 264/525] Update npm dev deps --- package-lock.json | 464 +++++++++++++++++++++++++++++----------------- package.json | 4 +- 2 files changed, 300 insertions(+), 168 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6416c1a2c8..1c663f0478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,8 +22,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.5", - "@typescript-eslint/eslint-plugin": "^6.15.0", - "@typescript-eslint/parser": "^6.15.0", + "@typescript-eslint/eslint-plugin": "^6.16.0", + "@typescript-eslint/parser": "^6.16.0", "eslint": "^8.56.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", @@ -1659,16 +1659,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.15.0.tgz", - "integrity": "sha512-j5qoikQqPccq9QoBAupOP+CBu8BaJ8BLjaXSioDISeTZkVO3ig7oSIKh3H+rEpee7xCXtWwSB4KIL5l6hWZzpg==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.16.0.tgz", + "integrity": "sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.15.0", - "@typescript-eslint/type-utils": "6.15.0", - "@typescript-eslint/utils": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/scope-manager": "6.16.0", + "@typescript-eslint/type-utils": "6.16.0", + "@typescript-eslint/utils": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1694,13 +1694,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", - "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", + "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0" + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1711,9 +1711,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", - "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", + "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1724,16 +1724,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", - "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", + "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -1751,17 +1752,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", - "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz", + "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.15.0", - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/scope-manager": "6.16.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/typescript-estree": "6.16.0", "semver": "^7.5.4" }, "engines": { @@ -1776,12 +1777,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", - "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", + "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/types": "6.16.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1792,16 +1793,40 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz", - "integrity": "sha512-MkgKNnsjC6QwcMdlNAel24jjkEO/0hQaMDLqP4S9zq5HBAUJNQB6y+3DwLjX7b3l2b37eNAxMPLwb3/kh8VKdA==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.16.0.tgz", + "integrity": "sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.15.0", - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/typescript-estree": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/scope-manager": "6.16.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/typescript-estree": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4" }, "engines": { @@ -1821,13 +1846,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", - "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", + "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0" + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1838,9 +1863,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", - "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", + "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1851,16 +1876,17 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", - "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", + "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -1878,12 +1904,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", - "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", + "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/types": "6.16.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1894,6 +1920,30 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", @@ -1912,13 +1962,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.15.0.tgz", - "integrity": "sha512-CnmHKTfX6450Bo49hPg2OkIm/D/TVYV7jO1MCfPYGwf6x3GO0VU8YMO5AYMn+u3X05lRRxA4fWCz87GFQV6yVQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.16.0.tgz", + "integrity": "sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.15.0", - "@typescript-eslint/utils": "6.15.0", + "@typescript-eslint/typescript-estree": "6.16.0", + "@typescript-eslint/utils": "6.16.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1939,13 +1989,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", - "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", + "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0" + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1956,9 +2006,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", - "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", + "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1969,16 +2019,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", - "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", + "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -1996,17 +2047,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", - "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz", + "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.15.0", - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/scope-manager": "6.16.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/typescript-estree": "6.16.0", "semver": "^7.5.4" }, "engines": { @@ -2021,12 +2072,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", - "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", + "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/types": "6.16.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2037,6 +2088,30 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/types": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", @@ -8049,16 +8124,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.15.0.tgz", - "integrity": "sha512-j5qoikQqPccq9QoBAupOP+CBu8BaJ8BLjaXSioDISeTZkVO3ig7oSIKh3H+rEpee7xCXtWwSB4KIL5l6hWZzpg==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.16.0.tgz", + "integrity": "sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.15.0", - "@typescript-eslint/type-utils": "6.15.0", - "@typescript-eslint/utils": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/scope-manager": "6.16.0", + "@typescript-eslint/type-utils": "6.16.0", + "@typescript-eslint/utils": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8068,116 +8143,154 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", - "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", + "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0" + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0" } }, "@typescript-eslint/types": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", - "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", + "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", - "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", + "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/utils": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", - "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz", + "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.15.0", - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/scope-manager": "6.16.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/typescript-estree": "6.16.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", - "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", + "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/types": "6.16.0", "eslint-visitor-keys": "^3.4.1" } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } } } }, "@typescript-eslint/parser": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz", - "integrity": "sha512-MkgKNnsjC6QwcMdlNAel24jjkEO/0hQaMDLqP4S9zq5HBAUJNQB6y+3DwLjX7b3l2b37eNAxMPLwb3/kh8VKdA==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.16.0.tgz", + "integrity": "sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.15.0", - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/typescript-estree": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/scope-manager": "6.16.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/typescript-estree": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", - "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", + "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0" + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0" } }, "@typescript-eslint/types": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", - "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", + "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", - "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", + "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/visitor-keys": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", - "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", + "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/types": "6.16.0", "eslint-visitor-keys": "^3.4.1" } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } } } }, @@ -8192,72 +8305,91 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.15.0.tgz", - "integrity": "sha512-CnmHKTfX6450Bo49hPg2OkIm/D/TVYV7jO1MCfPYGwf6x3GO0VU8YMO5AYMn+u3X05lRRxA4fWCz87GFQV6yVQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.16.0.tgz", + "integrity": "sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.15.0", - "@typescript-eslint/utils": "6.15.0", + "@typescript-eslint/typescript-estree": "6.16.0", + "@typescript-eslint/utils": "6.16.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", - "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", + "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0" + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0" } }, "@typescript-eslint/types": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", - "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", + "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", - "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", + "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/visitor-keys": "6.15.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/visitor-keys": "6.16.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/utils": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", - "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz", + "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.15.0", - "@typescript-eslint/types": "6.15.0", - "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/scope-manager": "6.16.0", + "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/typescript-estree": "6.16.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", - "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", + "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/types": "6.16.0", "eslint-visitor-keys": "^3.4.1" } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } } } }, diff --git a/package.json b/package.json index dfefc9a71e..0ac7030e6b 100644 --- a/package.json +++ b/package.json @@ -109,8 +109,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.5", - "@typescript-eslint/eslint-plugin": "^6.15.0", - "@typescript-eslint/parser": "^6.15.0", + "@typescript-eslint/eslint-plugin": "^6.16.0", + "@typescript-eslint/parser": "^6.16.0", "eslint": "^8.56.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", From 675e9be844e972f8b6db870479553e9df0feac41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 27 Dec 2023 20:15:39 +0100 Subject: [PATCH 265/525] And env variables to Dockerfiles --- worker/Dockerfile | 3 +++ worker/Dockerfile.alpine | 3 +++ 2 files changed, 6 insertions(+) diff --git a/worker/Dockerfile b/worker/Dockerfile index 81f4294115..37ab88d260 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -26,6 +26,9 @@ ENV LANG="C.UTF-8" ENV CC="clang" ENV CXX="clang++" +ENV MEDIASOUP_LOCAL_DEV=true +ENV KEEP_BUILD_ARTIFACTS=1 + WORKDIR /mediasoup CMD ["bash"] diff --git a/worker/Dockerfile.alpine b/worker/Dockerfile.alpine index d1b31a6062..c90d2b82a4 100644 --- a/worker/Dockerfile.alpine +++ b/worker/Dockerfile.alpine @@ -9,6 +9,9 @@ ENV LANG="C.UTF-8" ENV CC="gcc" ENV CXX="g++" +ENV MEDIASOUP_LOCAL_DEV=true +ENV KEEP_BUILD_ARTIFACTS=1 + WORKDIR /mediasoup CMD ["ash"] From 4620783ae02abdd14e2c1ea831105affeeadfea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 28 Dec 2023 22:08:07 +0100 Subject: [PATCH 266/525] Dockerfile.alpine: Install linux-headers package --- worker/Dockerfile.alpine | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/Dockerfile.alpine b/worker/Dockerfile.alpine index c90d2b82a4..bde3577dcc 100644 --- a/worker/Dockerfile.alpine +++ b/worker/Dockerfile.alpine @@ -2,7 +2,7 @@ FROM alpine # Install dependencies. RUN set -x \ - && apk add gcc g++ nodejs-current npm python3 py3-pip + && apk add gcc g++ nodejs-current npm python3 py3-pip linux-headers # Make CC and CXX point to gcc/g++. ENV LANG="C.UTF-8" From 76d429ac9dfc49fe2dd0e2f059467ea47c7e6db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 29 Dec 2023 10:43:04 +0100 Subject: [PATCH 267/525] Improvements in CI files (#1281) --- .github/workflows/codeql.yaml | 21 +++++++++---------- .../workflows/mediasoup-worker-prebuild.yaml | 5 ++--- .github/workflows/mediasoup-worker.yaml | 1 - .github/workflows/pull-request-stats.yml | 18 ---------------- 4 files changed, 12 insertions(+), 33 deletions(-) delete mode 100644 .github/workflows/pull-request-stats.yml diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 4a23647801..8170e2f783 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -9,16 +9,15 @@ # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # -name: "CodeQL" +name: CodeQL -on: - push: - branches: [ "v3" ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ "v3" ] - schedule: - - cron: '37 9 * * 5' +on: [push, pull_request] + +concurrency: + # Cancel a currently running workflow from the same PR, branch or tag when a + # new workflow is triggered. + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: analyze: @@ -37,7 +36,7 @@ jobs: # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support env: - MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: "true" + MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' steps: - name: Checkout repository @@ -77,4 +76,4 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: - category: "/language:${{matrix.language}}" + category: '/language:${{matrix.language}}' diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 99010871fd..141e31343a 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -4,7 +4,7 @@ on: push: # Only trigger for production releases. tags: - - "*.*.*" + - '*.*.*' # Only trigger when other workflows succeeded. workflow_run: @@ -15,7 +15,6 @@ on: jobs: ci: strategy: - fail-fast: false matrix: build: # For Linux let's use an old version of Ubuntu (20.04) that builds the @@ -39,7 +38,7 @@ jobs: env: CC: ${{ matrix.build.cc }} CXX: ${{ matrix.build.cxx }} - MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: "true" + MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' steps: - name: Checkout diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 4ade2574c5..ffa8b70160 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -11,7 +11,6 @@ concurrency: jobs: ci: strategy: - fail-fast: false matrix: build: - os: ubuntu-20.04 diff --git a/.github/workflows/pull-request-stats.yml b/.github/workflows/pull-request-stats.yml deleted file mode 100644 index af1e612f02..0000000000 --- a/.github/workflows/pull-request-stats.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Pull Request Stats - -on: - # Run it every Monday at 1PM UTC. - schedule: - - cron: "0 13 * * 1" - -jobs: - stats: - runs-on: ubuntu-latest - steps: - - name: Run pull request stats - uses: flowwer-dev/pull-request-stats@master - with: - period: 365 - charts: true - disable-links: false - sort-by: 'REVIEWS' From 2966c5248e8e3fe7feb4502b9fde7e41488148bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 29 Dec 2023 11:53:12 +0100 Subject: [PATCH 268/525] Make mediasoup-worker-prebuild CI job only run on GH releases --- .github/workflows/mediasoup-worker-prebuild.yaml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 141e31343a..b399fbe89d 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -1,16 +1,9 @@ name: mediasoup-worker-prebuild +# Only trigger on GitHub releases. on: - push: - # Only trigger for production releases. - tags: - - '*.*.*' - - # Only trigger when other workflows succeeded. - workflow_run: - workflows: [mediasoup-worker, mediasoup-node, mediasoup-rust] - types: - - completed + release: + types: [published] jobs: ci: From 779af189c7595e154f44e6d203e0c38683a20ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 29 Dec 2023 11:57:41 +0100 Subject: [PATCH 269/525] Fix build on musl based systems (such as Alpine Linux) (#1279) --- CHANGELOG.md | 1 + worker/meson.build | 106 ++++++++++++++++++++++++++------------------- 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c0acaefc2..71a03e5d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). * liburing: Enable zero copy ([PR #1273](https://github.com/versatica/mediasoup/pull/1273)). +* Fix build on musl based systems (such as Alpine Linux) ([PR #1279](https://github.com/versatica/mediasoup/pull/1279)). ### 3.13.12 diff --git a/worker/meson.build b/worker/meson.build index 13a52bc243..e2c294ce9f 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -44,6 +44,18 @@ if get_option('ms_rtc_logger_rtp') ] endif +cpp = meson.get_compiler('cpp') + +# This is a workaround to define FLATBUFFERS_LOCALE_INDEPENDENT=0 outside +# flatbuffers project, which is needed in case the current arch doesn't support +# strtoll_l or strtoull_l (such as musl in Alpine Linux). Problem is that +# flatbuffers build system not only defines it for its own usage but also relies +# on it in its include/flatbuffers/util.h file, and if such a file is included +# by mediasoup source files (and it is included) build fails with "error: +# 'strtoull_l' was not declared in this scope". +# See issue: https://github.com/versatica/mediasoup/issues/1223 +add_project_arguments('-DFLATBUFFERS_LOCALE_INDEPENDENT=@0@'.format(cpp.has_function('strtoull_l')), language: 'cpp') + common_sources = [ 'src/lib.cpp', 'src/DepLibSRTP.cpp', @@ -163,14 +175,13 @@ common_sources = [ 'src/RTC/RTCP/XrReceiverReferenceTime.cpp', ] -cpp = meson.get_compiler('cpp') - openssl_proj = subproject( 'openssl', default_options: [ 'warning_level=0', ], ) + libuv_proj = subproject( 'libuv', default_options: [ @@ -179,6 +190,7 @@ libuv_proj = subproject( 'build_benchmarks=false', ], ) + libsrtp2_proj = subproject( 'libsrtp2', default_options: [ @@ -188,6 +200,7 @@ libsrtp2_proj = subproject( 'tests=disabled', ], ) + usrsctp_proj = subproject( 'usrsctp', default_options: [ @@ -195,6 +208,7 @@ usrsctp_proj = subproject( 'sctp_build_programs=false', ], ) + abseil_cpp_proj = subproject( 'abseil-cpp', default_options: [ @@ -202,20 +216,24 @@ abseil_cpp_proj = subproject( 'cpp_std=c++17', ], ) + catch2_proj = subproject( 'catch2', default_options: [ 'warning_level=0', ], ) + flatbuffers_proj = subproject( 'flatbuffers', default_options: [ 'warning_level=0', ], ) + # flatbuffers schemas subdirectory. subdir('fbs') + # Add current build directory so libwebrtc has access to FBS folder. libwebrtc_include_directories = include_directories('include', 'fbs') subdir('deps/libwebrtc') @@ -305,48 +323,48 @@ executable( ) test_sources = [ - 'test/src/tests.cpp', - 'test/src/RTC/TestKeyFrameRequestManager.cpp', - 'test/src/RTC/TestNackGenerator.cpp', - 'test/src/RTC/TestRateCalculator.cpp', - 'test/src/RTC/TestRtpPacket.cpp', - 'test/src/RTC/TestRtpPacketH264Svc.cpp', - 'test/src/RTC/TestRtpRetransmissionBuffer.cpp', - 'test/src/RTC/TestRtpStreamSend.cpp', - 'test/src/RTC/TestRtpStreamRecv.cpp', - 'test/src/RTC/TestSeqManager.cpp', - 'test/src/RTC/TestTrendCalculator.cpp', - 'test/src/RTC/TestRtpEncodingParameters.cpp', - 'test/src/RTC/Codecs/TestVP8.cpp', - 'test/src/RTC/Codecs/TestVP9.cpp', - 'test/src/RTC/Codecs/TestH264.cpp', - 'test/src/RTC/Codecs/TestH264_SVC.cpp', - 'test/src/RTC/RTCP/TestFeedbackPsAfb.cpp', - 'test/src/RTC/RTCP/TestFeedbackPsFir.cpp', - 'test/src/RTC/RTCP/TestFeedbackPsLei.cpp', - 'test/src/RTC/RTCP/TestFeedbackPsPli.cpp', - 'test/src/RTC/RTCP/TestFeedbackPsRemb.cpp', - 'test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp', - 'test/src/RTC/RTCP/TestFeedbackPsSli.cpp', - 'test/src/RTC/RTCP/TestFeedbackPsTst.cpp', - 'test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp', - 'test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp', - 'test/src/RTC/RTCP/TestFeedbackRtpNack.cpp', - 'test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp', - 'test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp', - 'test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp', - 'test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp', - 'test/src/RTC/RTCP/TestBye.cpp', - 'test/src/RTC/RTCP/TestReceiverReport.cpp', - 'test/src/RTC/RTCP/TestSdes.cpp', - 'test/src/RTC/RTCP/TestSenderReport.cpp', - 'test/src/RTC/RTCP/TestPacket.cpp', - 'test/src/RTC/RTCP/TestXr.cpp', - 'test/src/Utils/TestBits.cpp', - 'test/src/Utils/TestByte.cpp', - 'test/src/Utils/TestIP.cpp', - 'test/src/Utils/TestString.cpp', - 'test/src/Utils/TestTime.cpp', + 'test/src/tests.cpp', + 'test/src/RTC/TestKeyFrameRequestManager.cpp', + 'test/src/RTC/TestNackGenerator.cpp', + 'test/src/RTC/TestRateCalculator.cpp', + 'test/src/RTC/TestRtpPacket.cpp', + 'test/src/RTC/TestRtpPacketH264Svc.cpp', + 'test/src/RTC/TestRtpRetransmissionBuffer.cpp', + 'test/src/RTC/TestRtpStreamSend.cpp', + 'test/src/RTC/TestRtpStreamRecv.cpp', + 'test/src/RTC/TestSeqManager.cpp', + 'test/src/RTC/TestTrendCalculator.cpp', + 'test/src/RTC/TestRtpEncodingParameters.cpp', + 'test/src/RTC/Codecs/TestVP8.cpp', + 'test/src/RTC/Codecs/TestVP9.cpp', + 'test/src/RTC/Codecs/TestH264.cpp', + 'test/src/RTC/Codecs/TestH264_SVC.cpp', + 'test/src/RTC/RTCP/TestFeedbackPsAfb.cpp', + 'test/src/RTC/RTCP/TestFeedbackPsFir.cpp', + 'test/src/RTC/RTCP/TestFeedbackPsLei.cpp', + 'test/src/RTC/RTCP/TestFeedbackPsPli.cpp', + 'test/src/RTC/RTCP/TestFeedbackPsRemb.cpp', + 'test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp', + 'test/src/RTC/RTCP/TestFeedbackPsSli.cpp', + 'test/src/RTC/RTCP/TestFeedbackPsTst.cpp', + 'test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp', + 'test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp', + 'test/src/RTC/RTCP/TestFeedbackRtpNack.cpp', + 'test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp', + 'test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp', + 'test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp', + 'test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp', + 'test/src/RTC/RTCP/TestBye.cpp', + 'test/src/RTC/RTCP/TestReceiverReport.cpp', + 'test/src/RTC/RTCP/TestSdes.cpp', + 'test/src/RTC/RTCP/TestSenderReport.cpp', + 'test/src/RTC/RTCP/TestPacket.cpp', + 'test/src/RTC/RTCP/TestXr.cpp', + 'test/src/Utils/TestBits.cpp', + 'test/src/Utils/TestByte.cpp', + 'test/src/Utils/TestIP.cpp', + 'test/src/Utils/TestString.cpp', + 'test/src/Utils/TestTime.cpp', ] mediasoup_worker_test = executable( From f4931c66e6ada68dccdeb85047e7c84caf036308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 29 Dec 2023 12:39:01 +0100 Subject: [PATCH 270/525] 3.13.13 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71a03e5d75..fff82c0c37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.13.13 * worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). * liburing: Enable zero copy ([PR #1273](https://github.com/versatica/mediasoup/pull/1273)). diff --git a/package-lock.json b/package-lock.json index 1c663f0478..04e61f2f6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.12", + "version": "3.13.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.12", + "version": "3.13.13", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 0ac7030e6b..1de04ddf4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.12", + "version": "3.13.13", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From ee2654baf56c80022f3204db6dd40b467efc0590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 30 Dec 2023 11:30:33 +0100 Subject: [PATCH 271/525] mediasoup-worker linux prebuilt with io-uring support (part 1) (#1283) --- npm-scripts.mjs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 25c1928a72..6dab36a258 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -16,7 +16,7 @@ const WORKER_RELEASE_DIR = 'worker/out/Release'; const WORKER_RELEASE_BIN = IS_WINDOWS ? 'mediasoup-worker.exe' : 'mediasoup-worker'; const WORKER_RELEASE_BIN_PATH = `${WORKER_RELEASE_DIR}/${WORKER_RELEASE_BIN}`; const WORKER_PREBUILD_DIR = 'worker/prebuild'; -const WORKER_PREBUILD_TAR = `mediasoup-worker-${PKG.version}-${os.platform()}-${os.arch()}.tgz`; +const WORKER_PREBUILD_TAR = getWorkerPrebuildTarName(); const WORKER_PREBUILD_TAR_PATH = `${WORKER_PREBUILD_DIR}/${WORKER_PREBUILD_TAR}`; const GH_OWNER = 'versatica'; const GH_REPO = 'mediasoup'; @@ -300,6 +300,22 @@ function getPython() return python; } +function getWorkerPrebuildTarName() +{ + let name = `mediasoup-worker-${PKG.version}-${os.platform()}-${os.arch()}`; + + // In Linux we want to know about kernel version since kernel >= 6 supports + // io-uring. + if (os.platform() === 'linux') + { + const kernelMajorVersion = Number(os.release().split('.')[0]); + + name += `-kernel${kernelMajorVersion}`; + } + + return `${name}.tgz`; +} + function installInvoke() { if (fs.existsSync(PIP_INVOKE_DIR)) From 2b0f46928fd382cab683b5e02a52bdaa40369fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 30 Dec 2023 11:32:32 +0100 Subject: [PATCH 272/525] Update types/node --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 04e61f2f6b..5e0d48269b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.5", + "@types/node": "^20.10.6", "@typescript-eslint/eslint-plugin": "^6.16.0", "@typescript-eslint/parser": "^6.16.0", "eslint": "^8.56.0", @@ -1617,9 +1617,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", - "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "version": "20.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", + "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -8082,9 +8082,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", - "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "version": "20.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", + "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", "dev": true, "requires": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index 1de04ddf4e..26941b9403 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.5", + "@types/node": "^20.10.6", "@typescript-eslint/eslint-plugin": "^6.16.0", "@typescript-eslint/parser": "^6.16.0", "eslint": "^8.56.0", From 90fff361620a15a25bc3c42069a9b21952810670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 30 Dec 2023 16:34:03 +0100 Subject: [PATCH 273/525] Avoid modification of user input data (#1285) --- node/src/Transport.ts | 64 +- node/src/Worker.ts | 21 +- node/src/index.ts | 2 +- node/src/ortc.ts | 2032 +++++++++++++++++------------------ node/src/tests/test-ortc.ts | 5 +- 5 files changed, 1032 insertions(+), 1092 deletions(-) diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 7c68ad0143..7ae79d39df 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -714,17 +714,20 @@ export class Transport throw new TypeError('if given, appData must be an object'); } + // Clone given RTP parameters to not modify input data. + const clonedRtpParameters = utils.clone(rtpParameters); + // This may throw. - ortc.validateRtpParameters(rtpParameters); + ortc.validateRtpParameters(clonedRtpParameters); // If missing or empty encodings, add one. if ( - !rtpParameters.encodings || - !Array.isArray(rtpParameters.encodings) || - rtpParameters.encodings.length === 0 + !clonedRtpParameters.encodings || + !Array.isArray(clonedRtpParameters.encodings) || + clonedRtpParameters.encodings.length === 0 ) { - rtpParameters.encodings = [ {} ]; + clonedRtpParameters.encodings = [ {} ]; } // Don't do this in PipeTransports since there we must keep CNAME value in @@ -733,9 +736,13 @@ export class Transport { // If CNAME is given and we don't have yet a CNAME for Producers in this // Transport, take it. - if (!this.#cnameForProducers && rtpParameters.rtcp && rtpParameters.rtcp.cname) + if ( + !this.#cnameForProducers && + clonedRtpParameters.rtcp && + clonedRtpParameters.rtcp.cname + ) { - this.#cnameForProducers = rtpParameters.rtcp.cname; + this.#cnameForProducers = clonedRtpParameters.rtcp.cname; } // Otherwise if we don't have yet a CNAME for Producers and the RTP // parameters do not include CNAME, create a random one. @@ -745,26 +752,26 @@ export class Transport } // Override Producer's CNAME. - rtpParameters.rtcp = rtpParameters.rtcp || {}; - rtpParameters.rtcp.cname = this.#cnameForProducers; + clonedRtpParameters.rtcp = clonedRtpParameters.rtcp ?? {}; + clonedRtpParameters.rtcp.cname = this.#cnameForProducers; } const routerRtpCapabilities = this.#getRouterRtpCapabilities(); // This may throw. const rtpMapping = ortc.getProducerRtpParametersMapping( - rtpParameters, routerRtpCapabilities); + clonedRtpParameters, routerRtpCapabilities); // This may throw. const consumableRtpParameters = ortc.getConsumableRtpParameters( - kind, rtpParameters, routerRtpCapabilities, rtpMapping); + kind, clonedRtpParameters, routerRtpCapabilities, rtpMapping); const producerId = id || utils.generateUUIDv4(); const requestOffset = createProduceRequest({ - builder : this.channel.bufferBuilder, + builder : this.channel.bufferBuilder, producerId, kind, - rtpParameters, + rtpParameters : clonedRtpParameters, rtpMapping, keyFrameRequestDelay, paused @@ -787,8 +794,8 @@ export class Transport const data = { kind, - rtpParameters, - type : producerTypeFromFbs(status.type), + rtpParameters : clonedRtpParameters, + type : producerTypeFromFbs(status.type), consumableRtpParameters }; @@ -800,7 +807,7 @@ export class Transport producerId }, data, - channel : this.channel, + channel : this.channel, appData, paused }); @@ -854,8 +861,11 @@ export class Transport throw new TypeError('if given, mid must be non empty string'); } + // Clone given RTP capabilities to not modify input data. + const clonedRtpCapabilities = utils.clone(rtpCapabilities); + // This may throw. - ortc.validateRtpCapabilities(rtpCapabilities!); + ortc.validateRtpCapabilities(clonedRtpCapabilities); const producer = this.getProducerById(producerId); @@ -874,7 +884,7 @@ export class Transport const rtpParameters = ortc.getConsumerRtpParameters( { consumableRtpParameters : producer.consumableRtpParameters, - remoteRtpCapabilities : rtpCapabilities!, + remoteRtpCapabilities : clonedRtpCapabilities, pipe, enableRtx } @@ -996,13 +1006,17 @@ export class Transport let type: DataProducerType; + // Clone given SCTP stream parameters to not modify input data. + let clonedSctpStreamParameters + = utils.clone(sctpStreamParameters); + // If this is not a DirectTransport, sctpStreamParameters are required. if (this.constructor.name !== 'DirectTransport') { type = 'sctp'; // This may throw. - ortc.validateSctpStreamParameters(sctpStreamParameters!); + ortc.validateSctpStreamParameters(clonedSctpStreamParameters!); } // If this is a DirectTransport, sctpStreamParameters must not be given. else @@ -1013,15 +1027,17 @@ export class Transport { logger.warn( 'produceData() | sctpStreamParameters are ignored when producing data on a DirectTransport'); + + clonedSctpStreamParameters = undefined; } } const dataProducerId = id || utils.generateUUIDv4(); const requestOffset = createProduceDataRequest({ - builder : this.channel.bufferBuilder, + builder : this.channel.bufferBuilder, dataProducerId, type, - sctpStreamParameters, + sctpStreamParameters : clonedSctpStreamParameters, label, protocol, paused @@ -1117,8 +1133,10 @@ export class Transport if (this.constructor.name !== 'DirectTransport') { type = 'sctp'; - sctpStreamParameters = - (utils.clone(dataProducer.sctpStreamParameters) ?? {}) as SctpStreamParameters; + + sctpStreamParameters = utils.clone( + dataProducer.sctpStreamParameters + ) ?? {} as SctpStreamParameters; // Override if given. if (ordered !== undefined) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 62c7c5334e..44cee98b4b 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -8,8 +8,9 @@ import * as ortc from './ortc'; import { Channel } from './Channel'; import { Router, RouterOptions } from './Router'; import { WebRtcServer, WebRtcServerOptions } from './WebRtcServer'; +import { RtpCodecCapability } from './RtpParameters'; import { AppData } from './types'; -import { generateUUIDv4, parseVector } from './utils'; +import * as utils from './utils'; import { Event } from './fbs/notification'; import * as FbsRequest from './fbs/request'; import * as FbsWorker from './fbs/worker'; @@ -703,7 +704,7 @@ export class Worker ); } - const webRtcServerId = generateUUIDv4(); + const webRtcServerId = utils.generateUUIDv4(); const createWebRtcServerRequestOffset = new FbsWorker.CreateWebRtcServerRequestT( webRtcServerId, fbsListenInfos @@ -747,10 +748,14 @@ export class Worker throw new TypeError('if given, appData must be an object'); } + // Clone given media codecs to not modify input data. + const clonedMediaCodecs = + utils.clone(mediaCodecs); + // This may throw. - const rtpCapabilities = ortc.generateRouterRtpCapabilities(mediaCodecs); + const rtpCapabilities = ortc.generateRouterRtpCapabilities(clonedMediaCodecs); - const routerId = generateUUIDv4(); + const routerId = utils.generateUUIDv4(); // Get flatbuffer builder. const createRouterRequestOffset = @@ -822,12 +827,12 @@ export function parseWorkerDumpResponse( { const dump: WorkerDump = { pid : binary.pid()!, - webRtcServerIds : parseVector(binary, 'webRtcServerIds'), - routerIds : parseVector(binary, 'routerIds'), + webRtcServerIds : utils.parseVector(binary, 'webRtcServerIds'), + routerIds : utils.parseVector(binary, 'routerIds'), channelMessageHandlers : { - channelRequestHandlers : parseVector(binary.channelMessageHandlers()!, 'channelRequestHandlers'), - channelNotificationHandlers : parseVector(binary.channelMessageHandlers()!, 'channelNotificationHandlers') + channelRequestHandlers : utils.parseVector(binary.channelMessageHandlers()!, 'channelRequestHandlers'), + channelNotificationHandlers : utils.parseVector(binary.channelMessageHandlers()!, 'channelNotificationHandlers') } }; diff --git a/node/src/index.ts b/node/src/index.ts index faf33812a7..08666f51f9 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -95,5 +95,5 @@ export async function createWorker(supportedRtpCapabilities); } diff --git a/node/src/ortc.ts b/node/src/ortc.ts index 4905708633..c36e4ba10e 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -14,12 +14,7 @@ import { RtpHeaderExtensionParameters, RtcpParameters } from './RtpParameters'; -import { - SctpCapabilities, - NumSctpStreams, - SctpParameters, - SctpStreamParameters -} from './SctpParameters'; +import { SctpStreamParameters } from './SctpParameters'; import * as utils from './utils'; import { UnsupportedError } from './errors'; import * as FbsRtpParameters from './fbs/rtp-parameters'; @@ -91,181 +86,6 @@ export function validateRtpCapabilities(caps: RtpCapabilities): void } } -/** - * Validates RtpCodecCapability. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. - */ -export function validateRtpCodecCapability(codec: RtpCodecCapability): void -{ - const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i'); - - if (typeof codec !== 'object') - { - throw new TypeError('codec is not an object'); - } - - // mimeType is mandatory. - if (!codec.mimeType || typeof codec.mimeType !== 'string') - { - throw new TypeError('missing codec.mimeType'); - } - - const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType); - - if (!mimeTypeMatch) - { - throw new TypeError('invalid codec.mimeType'); - } - - // Just override kind with media component of mimeType. - codec.kind = mimeTypeMatch[1].toLowerCase() as MediaKind; - - // preferredPayloadType is optional. - if (codec.preferredPayloadType && typeof codec.preferredPayloadType !== 'number') - { - throw new TypeError('invalid codec.preferredPayloadType'); - } - - // clockRate is mandatory. - if (typeof codec.clockRate !== 'number') - { - throw new TypeError('missing codec.clockRate'); - } - - // channels is optional. If unset, set it to 1 (just if audio). - if (codec.kind === 'audio') - { - if (typeof codec.channels !== 'number') - { - codec.channels = 1; - } - } - else - { - delete codec.channels; - } - - // parameters is optional. If unset, set it to an empty object. - if (!codec.parameters || typeof codec.parameters !== 'object') - { - codec.parameters = {}; - } - - for (const key of Object.keys(codec.parameters)) - { - let value = codec.parameters[key]; - - if (value === undefined) - { - codec.parameters[key] = ''; - value = ''; - } - - if (typeof value !== 'string' && typeof value !== 'number') - { - throw new TypeError( - `invalid codec parameter [key:${key}s, value:${value}]`); - } - - // Specific parameters validation. - if (key === 'apt') - { - if (typeof value !== 'number') - { - throw new TypeError('invalid codec apt parameter'); - } - } - } - - // rtcpFeedback is optional. If unset, set it to an empty array. - if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) - { - codec.rtcpFeedback = []; - } - - for (const fb of codec.rtcpFeedback) - { - validateRtcpFeedback(fb); - } -} - -/** - * Validates RtcpFeedback. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. - */ -export function validateRtcpFeedback(fb: RtcpFeedback): void -{ - if (typeof fb !== 'object') - { - throw new TypeError('fb is not an object'); - } - - // type is mandatory. - if (!fb.type || typeof fb.type !== 'string') - { - throw new TypeError('missing fb.type'); - } - - // parameter is optional. If unset set it to an empty string. - if (!fb.parameter || typeof fb.parameter !== 'string') - { - fb.parameter = ''; - } -} - -/** - * Validates RtpHeaderExtension. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. - */ -export function validateRtpHeaderExtension(ext: RtpHeaderExtension): void -{ - - if (typeof ext !== 'object') - { - throw new TypeError('ext is not an object'); - } - - if (ext.kind !== 'audio' && ext.kind !== 'video') - { - throw new TypeError('invalid ext.kind'); - } - - // uri is mandatory. - if (!ext.uri || typeof ext.uri !== 'string') - { - throw new TypeError('missing ext.uri'); - } - - // preferredId is mandatory. - if (typeof ext.preferredId !== 'number') - { - throw new TypeError('missing ext.preferredId'); - } - - // preferredEncrypt is optional. If unset set it to false. - if (ext.preferredEncrypt && typeof ext.preferredEncrypt !== 'boolean') - { - throw new TypeError('invalid ext.preferredEncrypt'); - } - else if (!ext.preferredEncrypt) - { - ext.preferredEncrypt = false; - } - - // direction is optional. If unset set it to sendrecv. - if (ext.direction && typeof ext.direction !== 'string') - { - throw new TypeError('invalid ext.direction'); - } - else if (!ext.direction) - { - ext.direction = 'sendrecv'; - } -} - /** * Validates RtpParameters. It may modify given data by adding missing * fields with default values. @@ -339,1221 +159,1317 @@ export function validateRtpParameters(params: RtpParameters): void } /** - * Validates RtpCodecParameters. It may modify given data by adding missing + * Validates SctpStreamParameters. It may modify given data by adding missing * fields with default values. * It throws if invalid. */ -export function validateRtpCodecParameters(codec: RtpCodecParameters): void +export function validateSctpStreamParameters(params: SctpStreamParameters): void { - const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i'); - - if (typeof codec !== 'object') + if (typeof params !== 'object') { - throw new TypeError('codec is not an object'); + throw new TypeError('params is not an object'); } - // mimeType is mandatory. - if (!codec.mimeType || typeof codec.mimeType !== 'string') + // streamId is mandatory. + if (typeof params.streamId !== 'number') { - throw new TypeError('missing codec.mimeType'); + throw new TypeError('missing params.streamId'); } - const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType); + // ordered is optional. + let orderedGiven = false; - if (!mimeTypeMatch) + if (typeof params.ordered === 'boolean') { - throw new TypeError('invalid codec.mimeType'); + orderedGiven = true; + } + else + { + params.ordered = true; } - // payloadType is mandatory. - if (typeof codec.payloadType !== 'number') + // maxPacketLifeTime is optional. + if (params.maxPacketLifeTime && typeof params.maxPacketLifeTime !== 'number') { - throw new TypeError('missing codec.payloadType'); + throw new TypeError('invalid params.maxPacketLifeTime'); } - // clockRate is mandatory. - if (typeof codec.clockRate !== 'number') + // maxRetransmits is optional. + if (params.maxRetransmits && typeof params.maxRetransmits !== 'number') { - throw new TypeError('missing codec.clockRate'); + throw new TypeError('invalid params.maxRetransmits'); } - const kind = mimeTypeMatch[1].toLowerCase() as MediaKind; + if (params.maxPacketLifeTime && params.maxRetransmits) + { + throw new TypeError('cannot provide both maxPacketLifeTime and maxRetransmits'); + } - // channels is optional. If unset, set it to 1 (just if audio). - if (kind === 'audio') + if ( + orderedGiven && + params.ordered && + (params.maxPacketLifeTime || params.maxRetransmits) + ) { - if (typeof codec.channels !== 'number') - { - codec.channels = 1; - } + throw new TypeError('cannot be ordered with maxPacketLifeTime or maxRetransmits'); } - else + else if (!orderedGiven && (params.maxPacketLifeTime || params.maxRetransmits)) { - delete codec.channels; + params.ordered = false; } +} - // parameters is optional. If unset, set it to an empty object. - if (!codec.parameters || typeof codec.parameters !== 'object') +/** + * Generate RTP capabilities for the Router based on the given media codecs and + * mediasoup supported RTP capabilities. + */ +export function generateRouterRtpCapabilities( + mediaCodecs: RtpCodecCapability[] = [] +): RtpCapabilities +{ + // Normalize supported RTP capabilities. + validateRtpCapabilities(supportedRtpCapabilities); + + if (!Array.isArray(mediaCodecs)) { - codec.parameters = {}; + throw new TypeError('mediaCodecs must be an Array'); } - for (const key of Object.keys(codec.parameters)) + const clonedSupportedRtpCapabilities = + utils.clone(supportedRtpCapabilities); + const dynamicPayloadTypes = utils.clone(DynamicPayloadTypes); + const caps: RtpCapabilities = { - let value = codec.parameters[key]; + codecs : [], + headerExtensions : clonedSupportedRtpCapabilities.headerExtensions + }; - if (value === undefined) + for (const mediaCodec of mediaCodecs) + { + // This may throw. + validateRtpCodecCapability(mediaCodec); + + const matchedSupportedCodec = clonedSupportedRtpCapabilities + .codecs! + .find((supportedCodec) => ( + matchCodecs(mediaCodec, supportedCodec, { strict: false })) + ); + + if (!matchedSupportedCodec) { - codec.parameters[key] = ''; - value = ''; + throw new UnsupportedError( + `media codec not supported [mimeType:${mediaCodec.mimeType}]`); } - if (typeof value !== 'string' && typeof value !== 'number') + // Clone the supported codec. + const codec = utils.clone(matchedSupportedCodec); + + // If the given media codec has preferredPayloadType, keep it. + if (typeof mediaCodec.preferredPayloadType === 'number') { - throw new TypeError( - `invalid codec parameter [key:${key}s, value:${value}]`); - } + codec.preferredPayloadType = mediaCodec.preferredPayloadType; - // Specific parameters validation. - if (key === 'apt') + // Also remove the pt from the list of available dynamic values. + const idx = dynamicPayloadTypes.indexOf(codec.preferredPayloadType); + + if (idx > -1) + { + dynamicPayloadTypes.splice(idx, 1); + } + } + // Otherwise if the supported codec has preferredPayloadType, use it. + else if (typeof codec.preferredPayloadType === 'number') { - if (typeof value !== 'number') + // No need to remove it from the list since it's not a dynamic value. + } + // Otherwise choose a dynamic one. + else + { + // Take the first available pt and remove it from the list. + const pt = dynamicPayloadTypes.shift(); + + if (!pt) { - throw new TypeError('invalid codec apt parameter'); + throw new Error('cannot allocate more dynamic codec payload types'); } + + codec.preferredPayloadType = pt; } - } - // rtcpFeedback is optional. If unset, set it to an empty array. - if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) - { - codec.rtcpFeedback = []; - } + // Ensure there is not duplicated preferredPayloadType values. + if (caps.codecs!.some((c) => c.preferredPayloadType === codec.preferredPayloadType)) + { + throw new TypeError('duplicated codec.preferredPayloadType'); + } - for (const fb of codec.rtcpFeedback) - { - validateRtcpFeedback(fb); + // Merge the media codec parameters. + codec.parameters = { ...codec.parameters, ...mediaCodec.parameters }; + + // Append to the codec list. + caps.codecs!.push(codec); + + // Add a RTX video codec if video. + if (codec.kind === 'video') + { + // Take the first available pt and remove it from the list. + const pt = dynamicPayloadTypes.shift(); + + if (!pt) + { + throw new Error('cannot allocate more dynamic codec payload types'); + } + + const rtxCodec: RtpCodecCapability = + { + kind : codec.kind, + mimeType : `${codec.kind}/rtx`, + preferredPayloadType : pt, + clockRate : codec.clockRate, + parameters : + { + apt : codec.preferredPayloadType + }, + rtcpFeedback : [] + }; + + // Append to the codec list. + caps.codecs!.push(rtxCodec); + } } + + return caps; } /** - * Validates RtpHeaderExtensionParameteters. It may modify given data by adding - * missing fields with default values. It throws if invalid. + * Get a mapping of codec payloads and encodings of the given Producer RTP + * parameters as values expected by the Router. + * + * It may throw if invalid or non supported RTP parameters are given. */ -export function validateRtpHeaderExtensionParameters( - ext: RtpHeaderExtensionParameters -): void +export function getProducerRtpParametersMapping( + params: RtpParameters, + caps: RtpCapabilities +): RtpMapping { - - if (typeof ext !== 'object') + const rtpMapping: RtpMapping = { - throw new TypeError('ext is not an object'); - } + codecs : [], + encodings : [] + }; - // uri is mandatory. - if (!ext.uri || typeof ext.uri !== 'string') - { - throw new TypeError('missing ext.uri'); - } + // Match parameters media codecs to capabilities media codecs. + const codecToCapCodec: Map = new Map(); - // id is mandatory. - if (typeof ext.id !== 'number') + for (const codec of params.codecs) { - throw new TypeError('missing ext.id'); - } + if (isRtxCodec(codec)) + { + continue; + } - // encrypt is optional. If unset set it to false. - if (ext.encrypt && typeof ext.encrypt !== 'boolean') - { - throw new TypeError('invalid ext.encrypt'); - } - else if (!ext.encrypt) - { - ext.encrypt = false; - } + // Search for the same media codec in capabilities. + const matchedCapCodec = caps.codecs! + .find((capCodec) => ( + matchCodecs(codec, capCodec, { strict: true, modify: true })) + ); - // parameters is optional. If unset, set it to an empty object. - if (!ext.parameters || typeof ext.parameters !== 'object') - { - ext.parameters = {}; + if (!matchedCapCodec) + { + throw new UnsupportedError( + `unsupported codec [mimeType:${codec.mimeType}, payloadType:${codec.payloadType}]`); + } + + codecToCapCodec.set(codec, matchedCapCodec); } - for (const key of Object.keys(ext.parameters)) + // Match parameters RTX codecs to capabilities RTX codecs. + for (const codec of params.codecs) { - let value = ext.parameters[key]; + if (!isRtxCodec(codec)) + { + continue; + } - if (value === undefined) + // Search for the associated media codec. + const associatedMediaCodec = params.codecs + .find((mediaCodec) => mediaCodec.payloadType === codec.parameters.apt); + + if (!associatedMediaCodec) { - ext.parameters[key] = ''; - value = ''; + throw new TypeError( + `missing media codec found for RTX PT ${codec.payloadType}`); } - if (typeof value !== 'string' && typeof value !== 'number') + const capMediaCodec = codecToCapCodec.get(associatedMediaCodec); + + // Ensure that the capabilities media codec has a RTX codec. + const associatedCapRtxCodec = caps.codecs! + .find((capCodec) => ( + isRtxCodec(capCodec) && + capCodec.parameters.apt === capMediaCodec!.preferredPayloadType + )); + + if (!associatedCapRtxCodec) { - throw new TypeError('invalid header extension parameter'); + throw new UnsupportedError( + `no RTX codec for capability codec PT ${capMediaCodec!.preferredPayloadType}`); } - } -} -/** - * Validates RtpEncodingParameters. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. - */ -export function validateRtpEncodingParameters(encoding: RtpEncodingParameters): void -{ - if (typeof encoding !== 'object') - { - throw new TypeError('encoding is not an object'); + codecToCapCodec.set(codec, associatedCapRtxCodec); } - // ssrc is optional. - if (encoding.ssrc && typeof encoding.ssrc !== 'number') + // Generate codecs mapping. + for (const [ codec, capCodec ] of codecToCapCodec) { - throw new TypeError('invalid encoding.ssrc'); + rtpMapping.codecs.push( + { + payloadType : codec.payloadType, + mappedPayloadType : capCodec.preferredPayloadType! + }); } - // rid is optional. - if (encoding.rid && typeof encoding.rid !== 'string') - { - throw new TypeError('invalid encoding.rid'); - } + // Generate encodings mapping. + let mappedSsrc = utils.generateRandomNumber(); - // rtx is optional. - if (encoding.rtx && typeof encoding.rtx !== 'object') - { - throw new TypeError('invalid encoding.rtx'); - } - else if (encoding.rtx) + for (const encoding of params.encodings!) { - // RTX ssrc is mandatory if rtx is present. - if (typeof encoding.rtx.ssrc !== 'number') + const mappedEncoding: any = {}; + + mappedEncoding.mappedSsrc = mappedSsrc++; + + if (encoding.rid) { - throw new TypeError('missing encoding.rtx.ssrc'); + mappedEncoding.rid = encoding.rid; + } + if (encoding.ssrc) + { + mappedEncoding.ssrc = encoding.ssrc; + } + if (encoding.scalabilityMode) + { + mappedEncoding.scalabilityMode = encoding.scalabilityMode; } - } - // dtx is optional. If unset set it to false. - if (!encoding.dtx || typeof encoding.dtx !== 'boolean') - { - encoding.dtx = false; + rtpMapping.encodings.push(mappedEncoding); } - // scalabilityMode is optional. - if (encoding.scalabilityMode && typeof encoding.scalabilityMode !== 'string') - { - throw new TypeError('invalid encoding.scalabilityMode'); - } + return rtpMapping; } /** - * Validates RtcpParameters. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. + * Generate RTP parameters to be internally used by Consumers given the RTP + * parameters of a Producer and the RTP capabilities of the Router. */ -export function validateRtcpParameters(rtcp: RtcpParameters): void +export function getConsumableRtpParameters( + kind: string, + params: RtpParameters, + caps: RtpCapabilities, + rtpMapping: RtpMapping +): RtpParameters { - if (typeof rtcp !== 'object') + const consumableParams: RtpParameters = { - throw new TypeError('rtcp is not an object'); - } + codecs : [], + headerExtensions : [], + encodings : [], + rtcp : {} + }; - // cname is optional. - if (rtcp.cname && typeof rtcp.cname !== 'string') + for (const codec of params.codecs) { - throw new TypeError('invalid rtcp.cname'); - } + if (isRtxCodec(codec)) + { + continue; + } - // reducedSize is optional. If unset set it to true. - if (!rtcp.reducedSize || typeof rtcp.reducedSize !== 'boolean') - { - rtcp.reducedSize = true; - } -} + const consumableCodecPt = rtpMapping.codecs + .find((entry) => entry.payloadType === codec.payloadType)! + .mappedPayloadType; -/** - * Validates SctpCapabilities. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. - */ -export function validateSctpCapabilities(caps: SctpCapabilities): void -{ - if (typeof caps !== 'object') - { - throw new TypeError('caps is not an object'); - } + const matchedCapCodec = caps.codecs! + .find((capCodec) => capCodec.preferredPayloadType === consumableCodecPt)!; - // numStreams is mandatory. - if (!caps.numStreams || typeof caps.numStreams !== 'object') - { - throw new TypeError('missing caps.numStreams'); - } + const consumableCodec: RtpCodecParameters = + { + mimeType : matchedCapCodec.mimeType, + payloadType : matchedCapCodec.preferredPayloadType!, + clockRate : matchedCapCodec.clockRate, + channels : matchedCapCodec.channels, + parameters : codec.parameters, // Keep the Producer codec parameters. + rtcpFeedback : matchedCapCodec.rtcpFeedback + }; - validateNumSctpStreams(caps.numStreams); -} + consumableParams.codecs.push(consumableCodec); -/** - * Validates NumSctpStreams. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. - */ -export function validateNumSctpStreams(numStreams: NumSctpStreams): void -{ - if (typeof numStreams !== 'object') - { - throw new TypeError('numStreams is not an object'); - } + const consumableCapRtxCodec = caps.codecs! + .find((capRtxCodec) => ( + isRtxCodec(capRtxCodec) && + capRtxCodec.parameters.apt === consumableCodec.payloadType + )); - // OS is mandatory. - if (typeof numStreams.OS !== 'number') - { - throw new TypeError('missing numStreams.OS'); - } + if (consumableCapRtxCodec) + { + const consumableRtxCodec: RtpCodecParameters = + { + mimeType : consumableCapRtxCodec.mimeType, + payloadType : consumableCapRtxCodec.preferredPayloadType!, + clockRate : consumableCapRtxCodec.clockRate, + parameters : consumableCapRtxCodec.parameters, + rtcpFeedback : consumableCapRtxCodec.rtcpFeedback + }; - // MIS is mandatory. - if (typeof numStreams.MIS !== 'number') - { - throw new TypeError('missing numStreams.MIS'); + consumableParams.codecs.push(consumableRtxCodec); + } } -} -/** - * Validates SctpParameters. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. - */ -export function validateSctpParameters(params: SctpParameters): void -{ - if (typeof params !== 'object') + for (const capExt of caps.headerExtensions!) { - throw new TypeError('params is not an object'); - } - // port is mandatory. - if (typeof params.port !== 'number') - { - throw new TypeError('missing params.port'); - } + // Just take RTP header extension that can be used in Consumers. + if ( + capExt.kind !== kind || + (capExt.direction !== 'sendrecv' && capExt.direction !== 'sendonly') + ) + { + continue; + } - // OS is mandatory. - if (typeof params.OS !== 'number') - { - throw new TypeError('missing params.OS'); + const consumableExt = + { + uri : capExt.uri, + id : capExt.preferredId, + encrypt : capExt.preferredEncrypt, + parameters : {} + }; + + consumableParams.headerExtensions!.push(consumableExt); } - // MIS is mandatory. - if (typeof params.MIS !== 'number') + // Clone Producer encodings since we'll mangle them. + const consumableEncodings = + utils.clone(params.encodings) ?? []; + + for (let i = 0; i < consumableEncodings.length; ++i) { - throw new TypeError('missing params.MIS'); + const consumableEncoding = consumableEncodings[i]; + const { mappedSsrc } = rtpMapping.encodings[i]; + + // Remove useless fields. + delete consumableEncoding.rid; + delete consumableEncoding.rtx; + delete consumableEncoding.codecPayloadType; + + // Set the mapped ssrc. + consumableEncoding.ssrc = mappedSsrc; + + consumableParams.encodings!.push(consumableEncoding); } - // maxMessageSize is mandatory. - if (typeof params.maxMessageSize !== 'number') + consumableParams.rtcp = { - throw new TypeError('missing params.maxMessageSize'); - } + cname : params.rtcp!.cname, + reducedSize : true + }; + + return consumableParams; } /** - * Validates SctpStreamParameters. It may modify given data by adding missing - * fields with default values. - * It throws if invalid. + * Check whether the given RTP capabilities can consume the given Producer. */ -export function validateSctpStreamParameters(params: SctpStreamParameters): void +export function canConsume( + consumableParams: RtpParameters, + caps: RtpCapabilities +): boolean { - if (typeof params !== 'object') - { - throw new TypeError('params is not an object'); - } - - // streamId is mandatory. - if (typeof params.streamId !== 'number') - { - throw new TypeError('missing params.streamId'); - } + // This may throw. + validateRtpCapabilities(caps); - // ordered is optional. - let orderedGiven = false; + const matchingCodecs: RtpCodecParameters[] = []; - if (typeof params.ordered === 'boolean') - { - orderedGiven = true; - } - else + for (const codec of consumableParams.codecs) { - params.ordered = true; - } + const matchedCapCodec = caps.codecs! + .find((capCodec) => matchCodecs(capCodec, codec, { strict: true })); - // maxPacketLifeTime is optional. - if (params.maxPacketLifeTime && typeof params.maxPacketLifeTime !== 'number') - { - throw new TypeError('invalid params.maxPacketLifeTime'); - } + if (!matchedCapCodec) + { + continue; + } - // maxRetransmits is optional. - if (params.maxRetransmits && typeof params.maxRetransmits !== 'number') - { - throw new TypeError('invalid params.maxRetransmits'); + matchingCodecs.push(codec); } - if (params.maxPacketLifeTime && params.maxRetransmits) + // Ensure there is at least one media codec. + if (matchingCodecs.length === 0 || isRtxCodec(matchingCodecs[0])) { - throw new TypeError('cannot provide both maxPacketLifeTime and maxRetransmits'); + return false; } - if ( - orderedGiven && - params.ordered && - (params.maxPacketLifeTime || params.maxRetransmits) - ) - { - throw new TypeError('cannot be ordered with maxPacketLifeTime or maxRetransmits'); - } - else if (!orderedGiven && (params.maxPacketLifeTime || params.maxRetransmits)) - { - params.ordered = false; - } + return true; } /** - * Generate RTP capabilities for the Router based on the given media codecs and - * mediasoup supported RTP capabilities. + * Generate RTP parameters for a specific Consumer. + * + * It reduces encodings to just one and takes into account given RTP + * capabilities to reduce codecs, codecs' RTCP feedback and header extensions, + * and also enables or disables RTX. */ -export function generateRouterRtpCapabilities( - mediaCodecs: RtpCodecCapability[] = [] -): RtpCapabilities -{ - // Normalize supported RTP capabilities. - validateRtpCapabilities(supportedRtpCapabilities); - - if (!Array.isArray(mediaCodecs)) +export function getConsumerRtpParameters( { - throw new TypeError('mediaCodecs must be an Array'); + consumableRtpParameters, + remoteRtpCapabilities, + pipe, + enableRtx + }: + { + consumableRtpParameters: RtpParameters; + remoteRtpCapabilities: RtpCapabilities; + pipe: boolean; + enableRtx: boolean; } - - const clonedSupportedRtpCapabilities = - utils.clone(supportedRtpCapabilities) as RtpCapabilities; - const dynamicPayloadTypes = utils.clone(DynamicPayloadTypes) as number[]; - const caps: RtpCapabilities = +): RtpParameters +{ + const consumerParams: RtpParameters = { codecs : [], - headerExtensions : clonedSupportedRtpCapabilities.headerExtensions + headerExtensions : [], + encodings : [], + rtcp : consumableRtpParameters.rtcp }; - for (const mediaCodec of mediaCodecs) + for (const capCodec of remoteRtpCapabilities.codecs!) { - // This may throw. - validateRtpCodecCapability(mediaCodec); + validateRtpCodecCapability(capCodec); + } - const matchedSupportedCodec = clonedSupportedRtpCapabilities - .codecs! - .find((supportedCodec) => ( - matchCodecs(mediaCodec, supportedCodec, { strict: false })) - ); + const consumableCodecs = + utils.clone(consumableRtpParameters.codecs) ?? []; - if (!matchedSupportedCodec) + let rtxSupported = false; + + for (const codec of consumableCodecs) + { + if (!enableRtx && isRtxCodec(codec)) { - throw new UnsupportedError( - `media codec not supported [mimeType:${mediaCodec.mimeType}]`); + continue; } - // Clone the supported codec. - const codec = utils.clone(matchedSupportedCodec) as RtpCodecCapability; + const matchedCapCodec = remoteRtpCapabilities.codecs! + .find((capCodec) => matchCodecs(capCodec, codec, { strict: true })); - // If the given media codec has preferredPayloadType, keep it. - if (typeof mediaCodec.preferredPayloadType === 'number') + if (!matchedCapCodec) { - codec.preferredPayloadType = mediaCodec.preferredPayloadType; + continue; + } - // Also remove the pt from the list of available dynamic values. - const idx = dynamicPayloadTypes.indexOf(codec.preferredPayloadType); + codec.rtcpFeedback = matchedCapCodec.rtcpFeedback! + .filter((fb) => ( + (enableRtx || fb.type !== 'nack' || fb.parameter) + )); - if (idx > -1) + consumerParams.codecs.push(codec); + } + + // Must sanitize the list of matched codecs by removing useless RTX codecs. + for (let idx = consumerParams.codecs.length - 1; idx >= 0; --idx) + { + const codec = consumerParams.codecs[idx]; + + if (isRtxCodec(codec)) + { + // Search for the associated media codec. + const associatedMediaCodec = consumerParams.codecs + .find((mediaCodec) => mediaCodec.payloadType === codec.parameters.apt); + + if (associatedMediaCodec) { - dynamicPayloadTypes.splice(idx, 1); + rtxSupported = true; + } + else + { + consumerParams.codecs.splice(idx, 1); } } - // Otherwise if the supported codec has preferredPayloadType, use it. - else if (typeof codec.preferredPayloadType === 'number') + } + + // Ensure there is at least one media codec. + if (consumerParams.codecs.length === 0 || isRtxCodec(consumerParams.codecs[0])) + { + throw new UnsupportedError('no compatible media codecs'); + } + + consumerParams.headerExtensions = consumableRtpParameters.headerExtensions! + .filter((ext) => ( + remoteRtpCapabilities.headerExtensions! + .some((capExt) => ( + capExt.preferredId === ext.id && + capExt.uri === ext.uri + )) + )); + + // Reduce codecs' RTCP feedback. Use Transport-CC if available, REMB otherwise. + if ( + consumerParams.headerExtensions.some((ext) => ( + ext.uri === 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' + )) + ) + { + for (const codec of consumerParams.codecs) { - // No need to remove it from the list since it's not a dynamic value. + codec.rtcpFeedback = codec.rtcpFeedback! + .filter((fb) => fb.type !== 'goog-remb'); } - // Otherwise choose a dynamic one. - else + } + else if ( + consumerParams.headerExtensions.some((ext) => ( + ext.uri === 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' + )) + ) + { + for (const codec of consumerParams.codecs) { - // Take the first available pt and remove it from the list. - const pt = dynamicPayloadTypes.shift(); + codec.rtcpFeedback = codec.rtcpFeedback! + .filter((fb) => fb.type !== 'transport-cc'); + } + } + else + { + for (const codec of consumerParams.codecs) + { + codec.rtcpFeedback = codec.rtcpFeedback! + .filter((fb) => ( + fb.type !== 'transport-cc' && + fb.type !== 'goog-remb' + )); + } + } - if (!pt) - { - throw new Error('cannot allocate more dynamic codec payload types'); - } + if (!pipe) + { + const consumerEncoding: RtpEncodingParameters = + { + ssrc : utils.generateRandomNumber() + }; - codec.preferredPayloadType = pt; + if (rtxSupported) + { + consumerEncoding.rtx = { ssrc: consumerEncoding.ssrc! + 1 }; } - // Ensure there is not duplicated preferredPayloadType values. - if (caps.codecs!.some((c) => c.preferredPayloadType === codec.preferredPayloadType)) + // If any of the consumableRtpParameters.encodings has scalabilityMode, + // process it (assume all encodings have the same value). + const encodingWithScalabilityMode = + consumableRtpParameters.encodings!.find((encoding) => encoding.scalabilityMode); + + let scalabilityMode = encodingWithScalabilityMode + ? encodingWithScalabilityMode.scalabilityMode + : undefined; + + // If there is simulast, mangle spatial layers in scalabilityMode. + if (consumableRtpParameters.encodings!.length > 1) { - throw new TypeError('duplicated codec.preferredPayloadType'); + const { temporalLayers } = parseScalabilityMode(scalabilityMode); + + scalabilityMode = `L${consumableRtpParameters.encodings!.length}T${temporalLayers}`; } - // Merge the media codec parameters. - codec.parameters = { ...codec.parameters, ...mediaCodec.parameters }; + if (scalabilityMode) + { + consumerEncoding.scalabilityMode = scalabilityMode; + } - // Append to the codec list. - caps.codecs!.push(codec); + // Use the maximum maxBitrate in any encoding and honor it in the Consumer's + // encoding. + const maxEncodingMaxBitrate = + consumableRtpParameters.encodings!.reduce((maxBitrate, encoding) => ( + encoding.maxBitrate && encoding.maxBitrate > maxBitrate + ? encoding.maxBitrate + : maxBitrate + ), 0); - // Add a RTX video codec if video. - if (codec.kind === 'video') + if (maxEncodingMaxBitrate) { - // Take the first available pt and remove it from the list. - const pt = dynamicPayloadTypes.shift(); + consumerEncoding.maxBitrate = maxEncodingMaxBitrate; + } - if (!pt) + // Set a single encoding for the Consumer. + consumerParams.encodings!.push(consumerEncoding); + } + else + { + const consumableEncodings = + utils.clone(consumableRtpParameters.encodings) ?? []; + const baseSsrc = utils.generateRandomNumber(); + const baseRtxSsrc = utils.generateRandomNumber(); + + for (let i = 0; i < consumableEncodings.length; ++i) + { + const encoding = consumableEncodings[i]; + + encoding.ssrc = baseSsrc + i; + + if (rtxSupported) { - throw new Error('cannot allocate more dynamic codec payload types'); + encoding.rtx = { ssrc: baseRtxSsrc + i }; } - - const rtxCodec: RtpCodecCapability = + else { - kind : codec.kind, - mimeType : `${codec.kind}/rtx`, - preferredPayloadType : pt, - clockRate : codec.clockRate, - parameters : - { - apt : codec.preferredPayloadType - }, - rtcpFeedback : [] - }; + delete encoding.rtx; + } - // Append to the codec list. - caps.codecs!.push(rtxCodec); + consumerParams.encodings!.push(encoding); } } - return caps; + return consumerParams; } /** - * Get a mapping of codec payloads and encodings of the given Producer RTP - * parameters as values expected by the Router. + * Generate RTP parameters for a pipe Consumer. * - * It may throw if invalid or non supported RTP parameters are given. + * It keeps all original consumable encodings and removes support for BWE. If + * enableRtx is false, it also removes RTX and NACK support. */ -export function getProducerRtpParametersMapping( - params: RtpParameters, - caps: RtpCapabilities -): RtpMapping +export function getPipeConsumerRtpParameters( + { + consumableRtpParameters, + enableRtx + }: + { + consumableRtpParameters: RtpParameters; + enableRtx: boolean; + } +): RtpParameters { - const rtpMapping: RtpMapping = + const consumerParams: RtpParameters = { - codecs : [], - encodings : [] + codecs : [], + headerExtensions : [], + encodings : [], + rtcp : consumableRtpParameters.rtcp }; - // Match parameters media codecs to capabilities media codecs. - const codecToCapCodec: Map = new Map(); + const consumableCodecs = + utils.clone(consumableRtpParameters.codecs) ?? []; - for (const codec of params.codecs) + for (const codec of consumableCodecs) { - if (isRtxCodec(codec)) + if (!enableRtx && isRtxCodec(codec)) { continue; } - // Search for the same media codec in capabilities. - const matchedCapCodec = caps.codecs! - .find((capCodec) => ( - matchCodecs(codec, capCodec, { strict: true, modify: true })) - ); - - if (!matchedCapCodec) - { - throw new UnsupportedError( - `unsupported codec [mimeType:${codec.mimeType}, payloadType:${codec.payloadType}]`); - } + codec.rtcpFeedback = codec.rtcpFeedback! + .filter((fb) => ( + (fb.type === 'nack' && fb.parameter === 'pli') || + (fb.type === 'ccm' && fb.parameter === 'fir') || + (enableRtx && fb.type === 'nack' && !fb.parameter) + )); - codecToCapCodec.set(codec, matchedCapCodec); + consumerParams.codecs.push(codec); } - // Match parameters RTX codecs to capabilities RTX codecs. - for (const codec of params.codecs) - { - if (!isRtxCodec(codec)) - { - continue; - } - - // Search for the associated media codec. - const associatedMediaCodec = params.codecs - .find((mediaCodec) => mediaCodec.payloadType === codec.parameters.apt); - - if (!associatedMediaCodec) - { - throw new TypeError( - `missing media codec found for RTX PT ${codec.payloadType}`); - } - - const capMediaCodec = codecToCapCodec.get(associatedMediaCodec); - - // Ensure that the capabilities media codec has a RTX codec. - const associatedCapRtxCodec = caps.codecs! - .find((capCodec) => ( - isRtxCodec(capCodec) && - capCodec.parameters.apt === capMediaCodec!.preferredPayloadType - )); - - if (!associatedCapRtxCodec) - { - throw new UnsupportedError( - `no RTX codec for capability codec PT ${capMediaCodec!.preferredPayloadType}`); - } - - codecToCapCodec.set(codec, associatedCapRtxCodec); - } - - // Generate codecs mapping. - for (const [ codec, capCodec ] of codecToCapCodec) - { - rtpMapping.codecs.push( - { - payloadType : codec.payloadType, - mappedPayloadType : capCodec.preferredPayloadType! - }); - } + // Reduce RTP extensions by disabling transport MID and BWE related ones. + consumerParams.headerExtensions = consumableRtpParameters.headerExtensions! + .filter((ext) => ( + ext.uri !== 'urn:ietf:params:rtp-hdrext:sdes:mid' && + ext.uri !== 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' && + ext.uri !== 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' + )); - // Generate encodings mapping. - let mappedSsrc = utils.generateRandomNumber(); + const consumableEncodings = + utils.clone(consumableRtpParameters.encodings) ?? []; + const baseSsrc = utils.generateRandomNumber(); + const baseRtxSsrc = utils.generateRandomNumber(); - for (const encoding of params.encodings!) + for (let i = 0; i < consumableEncodings.length; ++i) { - const mappedEncoding: any = {}; + const encoding = consumableEncodings[i]; - mappedEncoding.mappedSsrc = mappedSsrc++; + encoding.ssrc = baseSsrc + i; - if (encoding.rid) - { - mappedEncoding.rid = encoding.rid; - } - if (encoding.ssrc) + if (enableRtx) { - mappedEncoding.ssrc = encoding.ssrc; + encoding.rtx = { ssrc: baseRtxSsrc + i }; } - if (encoding.scalabilityMode) + else { - mappedEncoding.scalabilityMode = encoding.scalabilityMode; + delete encoding.rtx; } - rtpMapping.encodings.push(mappedEncoding); + consumerParams.encodings!.push(encoding); } - return rtpMapping; + return consumerParams; } -/** - * Generate RTP parameters to be internally used by Consumers given the RTP - * parameters of a Producer and the RTP capabilities of the Router. - */ -export function getConsumableRtpParameters( - kind: string, - params: RtpParameters, - caps: RtpCapabilities, - rtpMapping: RtpMapping -): RtpParameters +function isRtxCodec(codec: RtpCodecCapability | RtpCodecParameters): boolean { - const consumableParams: RtpParameters = - { - codecs : [], - headerExtensions : [], - encodings : [], - rtcp : {} - }; + return /.+\/rtx$/i.test(codec.mimeType); +} - for (const codec of params.codecs) +function matchCodecs( + aCodec: RtpCodecCapability | RtpCodecParameters, + bCodec: RtpCodecCapability | RtpCodecParameters, + { strict = false, modify = false } = {} +): boolean +{ + const aMimeType = aCodec.mimeType.toLowerCase(); + const bMimeType = bCodec.mimeType.toLowerCase(); + + if (aMimeType !== bMimeType) { - if (isRtxCodec(codec)) - { - continue; - } + return false; + } - const consumableCodecPt = rtpMapping.codecs - .find((entry) => entry.payloadType === codec.payloadType)! - .mappedPayloadType; + if (aCodec.clockRate !== bCodec.clockRate) + { + return false; + } - const matchedCapCodec = caps.codecs! - .find((capCodec) => capCodec.preferredPayloadType === consumableCodecPt)!; + if (aCodec.channels !== bCodec.channels) + { + return false; + } - const consumableCodec: RtpCodecParameters = + // Per codec special checks. + switch (aMimeType) + { + case 'audio/multiopus': { - mimeType : matchedCapCodec.mimeType, - payloadType : matchedCapCodec.preferredPayloadType!, - clockRate : matchedCapCodec.clockRate, - channels : matchedCapCodec.channels, - parameters : codec.parameters, // Keep the Producer codec parameters. - rtcpFeedback : matchedCapCodec.rtcpFeedback - }; + const aNumStreams = aCodec.parameters['num_streams']; + const bNumStreams = bCodec.parameters['num_streams']; - consumableParams.codecs.push(consumableCodec); + if (aNumStreams !== bNumStreams) + { + return false; + } - const consumableCapRtxCodec = caps.codecs! - .find((capRtxCodec) => ( - isRtxCodec(capRtxCodec) && - capRtxCodec.parameters.apt === consumableCodec.payloadType - )); + const aCoupledStreams = aCodec.parameters['coupled_streams']; + const bCoupledStreams = bCodec.parameters['coupled_streams']; - if (consumableCapRtxCodec) - { - const consumableRtxCodec: RtpCodecParameters = + if (aCoupledStreams !== bCoupledStreams) { - mimeType : consumableCapRtxCodec.mimeType, - payloadType : consumableCapRtxCodec.preferredPayloadType!, - clockRate : consumableCapRtxCodec.clockRate, - parameters : consumableCapRtxCodec.parameters, - rtcpFeedback : consumableCapRtxCodec.rtcpFeedback - }; + return false; + } - consumableParams.codecs.push(consumableRtxCodec); + break; } - } - - for (const capExt of caps.headerExtensions!) - { - // Just take RTP header extension that can be used in Consumers. - if ( - capExt.kind !== kind || - (capExt.direction !== 'sendrecv' && capExt.direction !== 'sendonly') - ) + case 'video/h264': + case 'video/h264-svc': { - continue; - } + if (strict) + { + const aPacketizationMode = aCodec.parameters['packetization-mode'] || 0; + const bPacketizationMode = bCodec.parameters['packetization-mode'] || 0; - const consumableExt = - { - uri : capExt.uri, - id : capExt.preferredId, - encrypt : capExt.preferredEncrypt, - parameters : {} - }; + if (aPacketizationMode !== bPacketizationMode) + { + return false; + } - consumableParams.headerExtensions!.push(consumableExt); - } + if (!h264.isSameProfile(aCodec.parameters, bCodec.parameters)) + { + return false; + } - // Clone Producer encodings since we'll mangle them. - const consumableEncodings = - (utils.clone(params.encodings) ?? []) as RtpEncodingParameters[]; + let selectedProfileLevelId; - for (let i = 0; i < consumableEncodings.length; ++i) - { - const consumableEncoding = consumableEncodings[i]; - const { mappedSsrc } = rtpMapping.encodings[i]; + try + { + selectedProfileLevelId = + h264.generateProfileLevelIdStringForAnswer( + aCodec.parameters, bCodec.parameters + ); + } + catch (error) + { + return false; + } - // Remove useless fields. - delete consumableEncoding.rid; - delete consumableEncoding.rtx; - delete consumableEncoding.codecPayloadType; + if (modify) + { + if (selectedProfileLevelId) + { + aCodec.parameters['profile-level-id'] = selectedProfileLevelId; + } + else + { + delete aCodec.parameters['profile-level-id']; + } + } + } - // Set the mapped ssrc. - consumableEncoding.ssrc = mappedSsrc; + break; + } - consumableParams.encodings!.push(consumableEncoding); - } + case 'video/vp9': + { + if (strict) + { + const aProfileId = aCodec.parameters['profile-id'] || 0; + const bProfileId = bCodec.parameters['profile-id'] || 0; - consumableParams.rtcp = - { - cname : params.rtcp!.cname, - reducedSize : true - }; + if (aProfileId !== bProfileId) + { + return false; + } + } - return consumableParams; + break; + } + } + + return true; } -/** - * Check whether the given RTP capabilities can consume the given Producer. - */ -export function canConsume( - consumableParams: RtpParameters, - caps: RtpCapabilities -): boolean +export function serializeRtpMapping( + builder: flatbuffers.Builder, rtpMapping: RtpMapping +): number { - // This may throw. - validateRtpCapabilities(caps); - - const matchingCodecs: RtpCodecParameters[] = []; + const codecs: number[] = []; - for (const codec of consumableParams.codecs) + for (const codec of rtpMapping.codecs) { - const matchedCapCodec = caps.codecs! - .find((capCodec) => matchCodecs(capCodec, codec, { strict: true })); - - if (!matchedCapCodec) - { - continue; - } - - matchingCodecs.push(codec); + codecs.push( + FbsRtpParameters.CodecMapping.createCodecMapping( + builder, codec.payloadType, codec.mappedPayloadType + ) + ); } + const codecsOffset = + FbsRtpParameters.RtpMapping.createCodecsVector(builder, codecs); - // Ensure there is at least one media codec. - if (matchingCodecs.length === 0 || isRtxCodec(matchingCodecs[0])) + const encodings: number[] = []; + + for (const encoding of rtpMapping.encodings) { - return false; + encodings.push( + FbsRtpParameters.EncodingMapping.createEncodingMapping( + builder, + builder.createString(encoding.rid), + encoding.ssrc ?? null, + builder.createString(encoding.scalabilityMode), + encoding.mappedSsrc + ) + ); } - return true; + const encodingsOffset = + FbsRtpParameters.RtpMapping.createEncodingsVector(builder, encodings); + + return FbsRtpParameters.RtpMapping.createRtpMapping( + builder, codecsOffset, encodingsOffset + ); } /** - * Generate RTP parameters for a specific Consumer. - * - * It reduces encodings to just one and takes into account given RTP capabilities - * to reduce codecs, codecs' RTCP feedback and header extensions, and also enables - * or disables RTX. + * Validates RtpCodecCapability. It may modify given data by adding missing + * fields with default values. + * It throws if invalid. */ -export function getConsumerRtpParameters( - { - consumableRtpParameters, - remoteRtpCapabilities, - pipe, - enableRtx - }: - { - consumableRtpParameters: RtpParameters; - remoteRtpCapabilities: RtpCapabilities; - pipe: boolean; - enableRtx: boolean; - } -): RtpParameters +function validateRtpCodecCapability(codec: RtpCodecCapability): void { - const consumerParams: RtpParameters = - { - codecs : [], - headerExtensions : [], - encodings : [], - rtcp : consumableRtpParameters.rtcp - }; + const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i'); - for (const capCodec of remoteRtpCapabilities.codecs!) + if (typeof codec !== 'object') { - validateRtpCodecCapability(capCodec); + throw new TypeError('codec is not an object'); } - const consumableCodecs = - (utils.clone(consumableRtpParameters.codecs) ?? []) as RtpCodecParameters[]; - - let rtxSupported = false; - - for (const codec of consumableCodecs) + // mimeType is mandatory. + if (!codec.mimeType || typeof codec.mimeType !== 'string') { - if (!enableRtx && isRtxCodec(codec)) - { - continue; - } - - const matchedCapCodec = remoteRtpCapabilities.codecs! - .find((capCodec) => matchCodecs(capCodec, codec, { strict: true })); - - if (!matchedCapCodec) - { - continue; - } - - codec.rtcpFeedback = matchedCapCodec.rtcpFeedback! - .filter((fb) => ( - (enableRtx || fb.type !== 'nack' || fb.parameter) - )); - - consumerParams.codecs.push(codec); + throw new TypeError('missing codec.mimeType'); } - // Must sanitize the list of matched codecs by removing useless RTX codecs. - for (let idx = consumerParams.codecs.length - 1; idx >= 0; --idx) - { - const codec = consumerParams.codecs[idx]; - - if (isRtxCodec(codec)) - { - // Search for the associated media codec. - const associatedMediaCodec = consumerParams.codecs - .find((mediaCodec) => mediaCodec.payloadType === codec.parameters.apt); + const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType); - if (associatedMediaCodec) - { - rtxSupported = true; - } - else - { - consumerParams.codecs.splice(idx, 1); - } - } + if (!mimeTypeMatch) + { + throw new TypeError('invalid codec.mimeType'); } - // Ensure there is at least one media codec. - if (consumerParams.codecs.length === 0 || isRtxCodec(consumerParams.codecs[0])) + // Just override kind with media component of mimeType. + codec.kind = mimeTypeMatch[1].toLowerCase() as MediaKind; + + // preferredPayloadType is optional. + if (codec.preferredPayloadType && typeof codec.preferredPayloadType !== 'number') { - throw new UnsupportedError('no compatible media codecs'); + throw new TypeError('invalid codec.preferredPayloadType'); } - consumerParams.headerExtensions = consumableRtpParameters.headerExtensions! - .filter((ext) => ( - remoteRtpCapabilities.headerExtensions! - .some((capExt) => ( - capExt.preferredId === ext.id && - capExt.uri === ext.uri - )) - )); - - // Reduce codecs' RTCP feedback. Use Transport-CC if available, REMB otherwise. - if ( - consumerParams.headerExtensions.some((ext) => ( - ext.uri === 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' - )) - ) + // clockRate is mandatory. + if (typeof codec.clockRate !== 'number') { - for (const codec of consumerParams.codecs) - { - codec.rtcpFeedback = codec.rtcpFeedback! - .filter((fb) => fb.type !== 'goog-remb'); - } + throw new TypeError('missing codec.clockRate'); } - else if ( - consumerParams.headerExtensions.some((ext) => ( - ext.uri === 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' - )) - ) + + // channels is optional. If unset, set it to 1 (just if audio). + if (codec.kind === 'audio') { - for (const codec of consumerParams.codecs) + if (typeof codec.channels !== 'number') { - codec.rtcpFeedback = codec.rtcpFeedback! - .filter((fb) => fb.type !== 'transport-cc'); + codec.channels = 1; } } else { - for (const codec of consumerParams.codecs) - { - codec.rtcpFeedback = codec.rtcpFeedback! - .filter((fb) => ( - fb.type !== 'transport-cc' && - fb.type !== 'goog-remb' - )); - } + delete codec.channels; } - if (!pipe) + // parameters is optional. If unset, set it to an empty object. + if (!codec.parameters || typeof codec.parameters !== 'object') { - const consumerEncoding: RtpEncodingParameters = - { - ssrc : utils.generateRandomNumber() - }; + codec.parameters = {}; + } - if (rtxSupported) + for (const key of Object.keys(codec.parameters)) + { + let value = codec.parameters[key]; + + if (value === undefined) { - consumerEncoding.rtx = { ssrc: consumerEncoding.ssrc! + 1 }; + codec.parameters[key] = ''; + value = ''; } - // If any of the consumableRtpParameters.encodings has scalabilityMode, - // process it (assume all encodings have the same value). - const encodingWithScalabilityMode = - consumableRtpParameters.encodings!.find((encoding) => encoding.scalabilityMode); - - let scalabilityMode = encodingWithScalabilityMode - ? encodingWithScalabilityMode.scalabilityMode - : undefined; - - // If there is simulast, mangle spatial layers in scalabilityMode. - if (consumableRtpParameters.encodings!.length > 1) + if (typeof value !== 'string' && typeof value !== 'number') { - const { temporalLayers } = parseScalabilityMode(scalabilityMode); - - scalabilityMode = `L${consumableRtpParameters.encodings!.length}T${temporalLayers}`; + throw new TypeError( + `invalid codec parameter [key:${key}s, value:${value}]`); } - if (scalabilityMode) + // Specific parameters validation. + if (key === 'apt') { - consumerEncoding.scalabilityMode = scalabilityMode; + if (typeof value !== 'number') + { + throw new TypeError('invalid codec apt parameter'); + } } + } - // Use the maximum maxBitrate in any encoding and honor it in the Consumer's - // encoding. - const maxEncodingMaxBitrate = - consumableRtpParameters.encodings!.reduce((maxBitrate, encoding) => ( - encoding.maxBitrate && encoding.maxBitrate > maxBitrate - ? encoding.maxBitrate - : maxBitrate - ), 0); + // rtcpFeedback is optional. If unset, set it to an empty array. + if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) + { + codec.rtcpFeedback = []; + } - if (maxEncodingMaxBitrate) - { - consumerEncoding.maxBitrate = maxEncodingMaxBitrate; - } + for (const fb of codec.rtcpFeedback) + { + validateRtcpFeedback(fb); + } +} - // Set a single encoding for the Consumer. - consumerParams.encodings!.push(consumerEncoding); +/** + * Validates RtcpFeedback. It may modify given data by adding missing + * fields with default values. + * It throws if invalid. + */ +function validateRtcpFeedback(fb: RtcpFeedback): void +{ + if (typeof fb !== 'object') + { + throw new TypeError('fb is not an object'); } - else + + // type is mandatory. + if (!fb.type || typeof fb.type !== 'string') { - const consumableEncodings = - (utils.clone(consumableRtpParameters.encodings) ?? []) as RtpEncodingParameters[]; - const baseSsrc = utils.generateRandomNumber(); - const baseRtxSsrc = utils.generateRandomNumber(); + throw new TypeError('missing fb.type'); + } - for (let i = 0; i < consumableEncodings.length; ++i) - { - const encoding = consumableEncodings[i]; + // parameter is optional. If unset set it to an empty string. + if (!fb.parameter || typeof fb.parameter !== 'string') + { + fb.parameter = ''; + } +} - encoding.ssrc = baseSsrc + i; +/** + * Validates RtpHeaderExtension. It may modify given data by adding missing + * fields with default values. + * It throws if invalid. + */ +function validateRtpHeaderExtension(ext: RtpHeaderExtension): void +{ - if (rtxSupported) - { - encoding.rtx = { ssrc: baseRtxSsrc + i }; - } - else - { - delete encoding.rtx; - } + if (typeof ext !== 'object') + { + throw new TypeError('ext is not an object'); + } - consumerParams.encodings!.push(encoding); - } + if (ext.kind !== 'audio' && ext.kind !== 'video') + { + throw new TypeError('invalid ext.kind'); } - return consumerParams; + // uri is mandatory. + if (!ext.uri || typeof ext.uri !== 'string') + { + throw new TypeError('missing ext.uri'); + } + + // preferredId is mandatory. + if (typeof ext.preferredId !== 'number') + { + throw new TypeError('missing ext.preferredId'); + } + + // preferredEncrypt is optional. If unset set it to false. + if (ext.preferredEncrypt && typeof ext.preferredEncrypt !== 'boolean') + { + throw new TypeError('invalid ext.preferredEncrypt'); + } + else if (!ext.preferredEncrypt) + { + ext.preferredEncrypt = false; + } + + // direction is optional. If unset set it to sendrecv. + if (ext.direction && typeof ext.direction !== 'string') + { + throw new TypeError('invalid ext.direction'); + } + else if (!ext.direction) + { + ext.direction = 'sendrecv'; + } } /** - * Generate RTP parameters for a pipe Consumer. - * - * It keeps all original consumable encodings and removes support for BWE. If - * enableRtx is false, it also removes RTX and NACK support. + * Validates RtpCodecParameters. It may modify given data by adding missing + * fields with default values. + * It throws if invalid. */ -export function getPipeConsumerRtpParameters( - { - consumableRtpParameters, - enableRtx - }: +function validateRtpCodecParameters(codec: RtpCodecParameters): void +{ + const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i'); + + if (typeof codec !== 'object') { - consumableRtpParameters: RtpParameters; - enableRtx: boolean; + throw new TypeError('codec is not an object'); } -): RtpParameters -{ - const consumerParams: RtpParameters = + + // mimeType is mandatory. + if (!codec.mimeType || typeof codec.mimeType !== 'string') { - codecs : [], - headerExtensions : [], - encodings : [], - rtcp : consumableRtpParameters.rtcp - }; + throw new TypeError('missing codec.mimeType'); + } - const consumableCodecs = - (utils.clone(consumableRtpParameters.codecs) ?? []) as RtpCodecParameters[]; + const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType); - for (const codec of consumableCodecs) + if (!mimeTypeMatch) { - if (!enableRtx && isRtxCodec(codec)) - { - continue; - } + throw new TypeError('invalid codec.mimeType'); + } - codec.rtcpFeedback = codec.rtcpFeedback! - .filter((fb) => ( - (fb.type === 'nack' && fb.parameter === 'pli') || - (fb.type === 'ccm' && fb.parameter === 'fir') || - (enableRtx && fb.type === 'nack' && !fb.parameter) - )); + // payloadType is mandatory. + if (typeof codec.payloadType !== 'number') + { + throw new TypeError('missing codec.payloadType'); + } - consumerParams.codecs.push(codec); + // clockRate is mandatory. + if (typeof codec.clockRate !== 'number') + { + throw new TypeError('missing codec.clockRate'); } - // Reduce RTP extensions by disabling transport MID and BWE related ones. - consumerParams.headerExtensions = consumableRtpParameters.headerExtensions! - .filter((ext) => ( - ext.uri !== 'urn:ietf:params:rtp-hdrext:sdes:mid' && - ext.uri !== 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' && - ext.uri !== 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' - )); + const kind = mimeTypeMatch[1].toLowerCase() as MediaKind; - const consumableEncodings = - (utils.clone(consumableRtpParameters.encodings) ?? []) as RtpEncodingParameters[]; - const baseSsrc = utils.generateRandomNumber(); - const baseRtxSsrc = utils.generateRandomNumber(); + // channels is optional. If unset, set it to 1 (just if audio). + if (kind === 'audio') + { + if (typeof codec.channels !== 'number') + { + codec.channels = 1; + } + } + else + { + delete codec.channels; + } - for (let i = 0; i < consumableEncodings.length; ++i) + // parameters is optional. If unset, set it to an empty object. + if (!codec.parameters || typeof codec.parameters !== 'object') { - const encoding = consumableEncodings[i]; + codec.parameters = {}; + } - encoding.ssrc = baseSsrc + i; + for (const key of Object.keys(codec.parameters)) + { + let value = codec.parameters[key]; - if (enableRtx) + if (value === undefined) { - encoding.rtx = { ssrc: baseRtxSsrc + i }; + codec.parameters[key] = ''; + value = ''; } - else + + if (typeof value !== 'string' && typeof value !== 'number') { - delete encoding.rtx; + throw new TypeError( + `invalid codec parameter [key:${key}s, value:${value}]`); } - consumerParams.encodings!.push(encoding); + // Specific parameters validation. + if (key === 'apt') + { + if (typeof value !== 'number') + { + throw new TypeError('invalid codec apt parameter'); + } + } } - return consumerParams; -} + // rtcpFeedback is optional. If unset, set it to an empty array. + if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) + { + codec.rtcpFeedback = []; + } -function isRtxCodec(codec: RtpCodecCapability | RtpCodecParameters): boolean -{ - return /.+\/rtx$/i.test(codec.mimeType); + for (const fb of codec.rtcpFeedback) + { + validateRtcpFeedback(fb); + } } -function matchCodecs( - aCodec: RtpCodecCapability | RtpCodecParameters, - bCodec: RtpCodecCapability | RtpCodecParameters, - { strict = false, modify = false } = {} -): boolean +/** + * Validates RtpHeaderExtensionParameteters. It may modify given data by adding + * missing fields with default values. It throws if invalid. + */ +function validateRtpHeaderExtensionParameters( + ext: RtpHeaderExtensionParameters +): void { - const aMimeType = aCodec.mimeType.toLowerCase(); - const bMimeType = bCodec.mimeType.toLowerCase(); - if (aMimeType !== bMimeType) + if (typeof ext !== 'object') { - return false; + throw new TypeError('ext is not an object'); } - if (aCodec.clockRate !== bCodec.clockRate) + // uri is mandatory. + if (!ext.uri || typeof ext.uri !== 'string') { - return false; + throw new TypeError('missing ext.uri'); } - if (aCodec.channels !== bCodec.channels) + // id is mandatory. + if (typeof ext.id !== 'number') { - return false; + throw new TypeError('missing ext.id'); } - // Per codec special checks. - switch (aMimeType) + // encrypt is optional. If unset set it to false. + if (ext.encrypt && typeof ext.encrypt !== 'boolean') { - case 'audio/multiopus': - { - const aNumStreams = aCodec.parameters['num_streams']; - const bNumStreams = bCodec.parameters['num_streams']; - - if (aNumStreams !== bNumStreams) - { - return false; - } + throw new TypeError('invalid ext.encrypt'); + } + else if (!ext.encrypt) + { + ext.encrypt = false; + } - const aCoupledStreams = aCodec.parameters['coupled_streams']; - const bCoupledStreams = bCodec.parameters['coupled_streams']; + // parameters is optional. If unset, set it to an empty object. + if (!ext.parameters || typeof ext.parameters !== 'object') + { + ext.parameters = {}; + } - if (aCoupledStreams !== bCoupledStreams) - { - return false; - } + for (const key of Object.keys(ext.parameters)) + { + let value = ext.parameters[key]; - break; + if (value === undefined) + { + ext.parameters[key] = ''; + value = ''; } - case 'video/h264': - case 'video/h264-svc': + if (typeof value !== 'string' && typeof value !== 'number') { - if (strict) - { - const aPacketizationMode = aCodec.parameters['packetization-mode'] || 0; - const bPacketizationMode = bCodec.parameters['packetization-mode'] || 0; - - if (aPacketizationMode !== bPacketizationMode) - { - return false; - } - - if (!h264.isSameProfile(aCodec.parameters, bCodec.parameters)) - { - return false; - } - - let selectedProfileLevelId; + throw new TypeError('invalid header extension parameter'); + } + } +} - try - { - selectedProfileLevelId = - h264.generateProfileLevelIdStringForAnswer( - aCodec.parameters, bCodec.parameters - ); - } - catch (error) - { - return false; - } +/** + * Validates RtpEncodingParameters. It may modify given data by adding missing + * fields with default values. + * It throws if invalid. + */ +function validateRtpEncodingParameters(encoding: RtpEncodingParameters): void +{ + if (typeof encoding !== 'object') + { + throw new TypeError('encoding is not an object'); + } - if (modify) - { - if (selectedProfileLevelId) - { - aCodec.parameters['profile-level-id'] = selectedProfileLevelId; - } - else - { - delete aCodec.parameters['profile-level-id']; - } - } - } + // ssrc is optional. + if (encoding.ssrc && typeof encoding.ssrc !== 'number') + { + throw new TypeError('invalid encoding.ssrc'); + } - break; - } + // rid is optional. + if (encoding.rid && typeof encoding.rid !== 'string') + { + throw new TypeError('invalid encoding.rid'); + } - case 'video/vp9': + // rtx is optional. + if (encoding.rtx && typeof encoding.rtx !== 'object') + { + throw new TypeError('invalid encoding.rtx'); + } + else if (encoding.rtx) + { + // RTX ssrc is mandatory if rtx is present. + if (typeof encoding.rtx.ssrc !== 'number') { - if (strict) - { - const aProfileId = aCodec.parameters['profile-id'] || 0; - const bProfileId = bCodec.parameters['profile-id'] || 0; - - if (aProfileId !== bProfileId) - { - return false; - } - } - - break; + throw new TypeError('missing encoding.rtx.ssrc'); } } - return true; + // dtx is optional. If unset set it to false. + if (!encoding.dtx || typeof encoding.dtx !== 'boolean') + { + encoding.dtx = false; + } + + // scalabilityMode is optional. + if (encoding.scalabilityMode && typeof encoding.scalabilityMode !== 'string') + { + throw new TypeError('invalid encoding.scalabilityMode'); + } } -export function serializeRtpMapping( - builder: flatbuffers.Builder, rtpMapping: RtpMapping -): number +/** + * Validates RtcpParameters. It may modify given data by adding missing + * fields with default values. + * It throws if invalid. + */ +function validateRtcpParameters(rtcp: RtcpParameters): void { - const codecs: number[] = []; - - for (const codec of rtpMapping.codecs) + if (typeof rtcp !== 'object') { - codecs.push( - FbsRtpParameters.CodecMapping.createCodecMapping( - builder, codec.payloadType, codec.mappedPayloadType) - ); + throw new TypeError('rtcp is not an object'); } - const codecsOffset = - FbsRtpParameters.RtpMapping.createCodecsVector(builder, codecs); - - const encodings: number[] = []; - for (const encoding of rtpMapping.encodings) + // cname is optional. + if (rtcp.cname && typeof rtcp.cname !== 'string') { - encodings.push( - FbsRtpParameters.EncodingMapping.createEncodingMapping( - builder, - builder.createString(encoding.rid), - encoding.ssrc ?? null, - builder.createString(encoding.scalabilityMode), - encoding.mappedSsrc) - ); + throw new TypeError('invalid rtcp.cname'); } - const encodingsOffset = - FbsRtpParameters.RtpMapping.createEncodingsVector(builder, encodings); - return FbsRtpParameters.RtpMapping.createRtpMapping( - builder, codecsOffset, encodingsOffset); + // reducedSize is optional. If unset set it to true. + if (!rtcp.reducedSize || typeof rtcp.reducedSize !== 'boolean') + { + rtcp.reducedSize = true; + } } diff --git a/node/src/tests/test-ortc.ts b/node/src/tests/test-ortc.ts index b1c4d4ca16..40801e3e9c 100644 --- a/node/src/tests/test-ortc.ts +++ b/node/src/tests/test-ortc.ts @@ -604,6 +604,7 @@ test('getProducerRtpParametersMapping() with incompatible params throws Unsuppor }; expect( - () => ortc.getProducerRtpParametersMapping(rtpParameters, routerRtpCapabilities)) - .toThrow(UnsupportedError); + () => ortc.getProducerRtpParametersMapping( + rtpParameters, routerRtpCapabilities + )).toThrow(UnsupportedError); }); From a6b6babe1ff699c7f01614e50869d69189b0d3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 30 Dec 2023 16:34:37 +0100 Subject: [PATCH 274/525] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fff82c0c37..f24bb46fc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### NEXT + +* Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). + + ### 3.13.13 * worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). From a1b385a42baa761c20f532e813c75d1360d4996d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 30 Dec 2023 16:39:20 +0100 Subject: [PATCH 275/525] CI jobs: use `on: [pull_request, workflow_dispatch]` to avoid duplicate executions of each job --- .github/workflows/codeql.yaml | 2 +- .github/workflows/mediasoup-node.yaml | 2 +- .github/workflows/mediasoup-rust.yaml | 2 +- .github/workflows/mediasoup-worker.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 8170e2f783..16625708a3 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -11,7 +11,7 @@ # name: CodeQL -on: [push, pull_request] +on: [pull_request, workflow_dispatch] concurrency: # Cancel a currently running workflow from the same PR, branch or tag when a diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index fcb8fdb946..5e61e6bc1a 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -1,6 +1,6 @@ name: mediasoup-node -on: [push, pull_request] +on: [pull_request, workflow_dispatch] concurrency: # Cancel a currently running workflow from the same PR, branch or tag when a diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index ef5e95eaa6..f9d77fef18 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -1,6 +1,6 @@ name: mediasoup-rust -on: [push, pull_request] +on: [pull_request, workflow_dispatch] concurrency: # Cancel a currently running workflow from the same PR, branch or tag when a diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index ffa8b70160..5405601601 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -1,6 +1,6 @@ name: mediasoup-worker -on: [push, pull_request] +on: [pull_request, workflow_dispatch] concurrency: # Cancel a currently running workflow from the same PR, branch or tag when a From e4f499116b3816df16e1750a2343245fe6e61b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jan 2024 12:44:42 +0100 Subject: [PATCH 276/525] Update marked NPM dep --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5e0d48269b..b78c5d146a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "eslint": "^8.56.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^11.1.0", + "marked": "^11.1.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", @@ -4927,9 +4927,9 @@ } }, "node_modules/marked": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.0.tgz", - "integrity": "sha512-fvKJWAPEafVj1dwGwcPI5mBB/0pvViL6NlCbNDG1HOIRwwAU/jeMoFxfbRLuirO1wRH7m4yPvBqD/O1wyWvayw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", + "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -10414,9 +10414,9 @@ "dev": true }, "marked": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.0.tgz", - "integrity": "sha512-fvKJWAPEafVj1dwGwcPI5mBB/0pvViL6NlCbNDG1HOIRwwAU/jeMoFxfbRLuirO1wRH7m4yPvBqD/O1wyWvayw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", + "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==", "dev": true }, "meow": { diff --git a/package.json b/package.json index 26941b9403..e0ca6a86ae 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "eslint": "^8.56.0", "eslint-plugin-jest": "^27.6.0", "jest": "^29.7.0", - "marked": "^11.1.0", + "marked": "^11.1.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", From 28ff4a731b4f1e90d7e2d41d80c0c5b9a1e7f5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jan 2024 14:35:32 +0100 Subject: [PATCH 277/525] Update Catch2 to version 3.4.0 (#1287) --- worker/subprojects/catch2.wrap | 15 +++++----- worker/tasks.py | 29 +++++++------------ .../TestPayloadChannelNotification.cpp | 2 +- .../TestPayloadChannelRequest.cpp | 2 +- worker/test/src/RTC/Codecs/TestH264.cpp | 2 +- worker/test/src/RTC/Codecs/TestH264_SVC.cpp | 2 +- worker/test/src/RTC/Codecs/TestVP8.cpp | 2 +- worker/test/src/RTC/Codecs/TestVP9.cpp | 2 +- worker/test/src/RTC/RTCP/TestBye.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackPsAfb.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackPsFir.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackPsLei.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackPsPli.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackPsRemb.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackPsSli.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackPsTst.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackRtpNack.cpp | 2 +- .../src/RTC/RTCP/TestFeedbackRtpSrReq.cpp | 2 +- .../src/RTC/RTCP/TestFeedbackRtpTllei.cpp | 2 +- .../test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp | 2 +- .../src/RTC/RTCP/TestFeedbackRtpTransport.cpp | 2 +- worker/test/src/RTC/RTCP/TestPacket.cpp | 2 +- .../test/src/RTC/RTCP/TestReceiverReport.cpp | 2 +- worker/test/src/RTC/RTCP/TestSdes.cpp | 2 +- worker/test/src/RTC/RTCP/TestSenderReport.cpp | 2 +- worker/test/src/RTC/RTCP/TestXr.cpp | 2 +- .../src/RTC/TestKeyFrameRequestManager.cpp | 2 +- worker/test/src/RTC/TestNackGenerator.cpp | 2 +- worker/test/src/RTC/TestRateCalculator.cpp | 2 +- .../src/RTC/TestRtpEncodingParameters.cpp | 2 +- worker/test/src/RTC/TestRtpPacket.cpp | 2 +- worker/test/src/RTC/TestRtpPacketH264Svc.cpp | 2 +- .../src/RTC/TestRtpRetransmissionBuffer.cpp | 2 +- worker/test/src/RTC/TestRtpStreamRecv.cpp | 2 +- worker/test/src/RTC/TestRtpStreamSend.cpp | 2 +- worker/test/src/RTC/TestSeqManager.cpp | 2 +- worker/test/src/RTC/TestTrendCalculator.cpp | 2 +- worker/test/src/Utils/TestBits.cpp | 2 +- worker/test/src/Utils/TestByte.cpp | 2 +- worker/test/src/Utils/TestIP.cpp | 2 +- worker/test/src/Utils/TestString.cpp | 2 +- worker/test/src/Utils/TestTime.cpp | 2 +- worker/test/src/tests.cpp | 8 ++--- 46 files changed, 65 insertions(+), 73 deletions(-) diff --git a/worker/subprojects/catch2.wrap b/worker/subprojects/catch2.wrap index c82b310fb0..691d39c858 100644 --- a/worker/subprojects/catch2.wrap +++ b/worker/subprojects/catch2.wrap @@ -1,12 +1,11 @@ [wrap-file] -directory = Catch2-2.13.7 -source_url = https://github.com/catchorg/Catch2/archive/v2.13.7.zip -source_filename = Catch2-2.13.7.zip -source_hash = 3f3ccd90ad3a8fbb1beeb15e6db440ccdcbebe378dfd125d07a1f9a587a927e9 -patch_filename = catch2_2.13.7-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/catch2_2.13.7-1/get_patch -patch_hash = 2f7369645d747e5bd866317ac1dd4c3d04dc97d3aad4fc6b864bdf75d3b57158 +directory = Catch2-3.4.0 +source_url = https://github.com/catchorg/Catch2/archive/v3.4.0.tar.gz +source_filename = Catch2-3.4.0.tar.gz +source_hash = 122928b814b75717316c71af69bd2b43387643ba076a6ec16e7882bfb2dfacbb +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.4.0-1/Catch2-3.4.0.tar.gz +wrapdb_version = 3.4.0-1 [provide] catch2 = catch2_dep - +catch2-with-main = catch2_with_main_dep diff --git a/worker/tasks.py b/worker/tasks.py index 75ac5c2bb1..a04b031edb 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -393,32 +393,25 @@ def test(ctx): shell=SHELL ); + mediasoup_worker_test = 'mediasoup-worker-test.exe' if os.name == 'nt' else 'mediasoup-worker-test'; mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or ''; - # On Windows lcov doesn't work (at least not yet) and we need to add .exe to - # the binary path. - if os.name == 'nt': - with ctx.cd(WORKER_DIR): - ctx.run( - f'"{BUILD_DIR}/mediasoup-worker-test.exe" --invisibles --use-colour=yes {mediasoup_test_tags}', - echo=True, - pty=PTY_SUPPORTED, - shell=SHELL - ); - else: + # On Windows lcov doesn't work (at least not yet). + if os.name != 'nt': ctx.run( f'"{LCOV}" --directory "{WORKER_DIR}" --zerocounters', echo=True, pty=PTY_SUPPORTED, shell=SHELL ); - with ctx.cd(WORKER_DIR): - ctx.run( - f'"{BUILD_DIR}/mediasoup-worker-test" --invisibles --use-colour=yes {mediasoup_test_tags}', - echo=True, - pty=PTY_SUPPORTED, - shell=SHELL - ); + + with ctx.cd(WORKER_DIR): + ctx.run( + f'"{BUILD_DIR}/{mediasoup_worker_test}" --invisibles --colour-mode=ansi {mediasoup_test_tags}', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); @task(pre=[setup, flatc]) diff --git a/worker/test/src/PayloadChannel/TestPayloadChannelNotification.cpp b/worker/test/src/PayloadChannel/TestPayloadChannelNotification.cpp index 0fb6a865cc..2a929f7745 100644 --- a/worker/test/src/PayloadChannel/TestPayloadChannelNotification.cpp +++ b/worker/test/src/PayloadChannel/TestPayloadChannelNotification.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "PayloadChannel/PayloadChannelNotification.hpp" -#include +#include SCENARIO("PayloadChannelNotification", "[channel][notification]") { diff --git a/worker/test/src/PayloadChannel/TestPayloadChannelRequest.cpp b/worker/test/src/PayloadChannel/TestPayloadChannelRequest.cpp index 5b1299fba1..302c9d6378 100644 --- a/worker/test/src/PayloadChannel/TestPayloadChannelRequest.cpp +++ b/worker/test/src/PayloadChannel/TestPayloadChannelRequest.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "PayloadChannel/PayloadChannelRequest.hpp" -#include +#include SCENARIO("PayloadChannelRequest", "[channel][request]") { diff --git a/worker/test/src/RTC/Codecs/TestH264.cpp b/worker/test/src/RTC/Codecs/TestH264.cpp index 4f50fb6689..67b573682f 100644 --- a/worker/test/src/RTC/Codecs/TestH264.cpp +++ b/worker/test/src/RTC/Codecs/TestH264.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/Codecs/H264.hpp" -#include +#include #include // std::memcmp() using namespace RTC; diff --git a/worker/test/src/RTC/Codecs/TestH264_SVC.cpp b/worker/test/src/RTC/Codecs/TestH264_SVC.cpp index 9af9b71c62..16c5726ac6 100644 --- a/worker/test/src/RTC/Codecs/TestH264_SVC.cpp +++ b/worker/test/src/RTC/Codecs/TestH264_SVC.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/Codecs/H264_SVC.hpp" -#include +#include #include // std::memcmp() using namespace RTC; diff --git a/worker/test/src/RTC/Codecs/TestVP8.cpp b/worker/test/src/RTC/Codecs/TestVP8.cpp index dd1c6d3333..545240d78c 100644 --- a/worker/test/src/RTC/Codecs/TestVP8.cpp +++ b/worker/test/src/RTC/Codecs/TestVP8.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/Codecs/VP8.hpp" -#include +#include #include // std::memcmp(), std::memcpy() using namespace RTC; diff --git a/worker/test/src/RTC/Codecs/TestVP9.cpp b/worker/test/src/RTC/Codecs/TestVP9.cpp index 0a94ac1988..77dec6365c 100644 --- a/worker/test/src/RTC/Codecs/TestVP9.cpp +++ b/worker/test/src/RTC/Codecs/TestVP9.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/Codecs/VP9.hpp" -#include +#include #include // std::memcmp() using namespace RTC; diff --git a/worker/test/src/RTC/RTCP/TestBye.cpp b/worker/test/src/RTC/RTCP/TestBye.cpp index a7825a01c5..fa77458c35 100644 --- a/worker/test/src/RTC/RTCP/TestBye.cpp +++ b/worker/test/src/RTC/RTCP/TestBye.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/Bye.hpp" -#include +#include #include // std::memcmp() #include diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsAfb.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsAfb.cpp index e6112b70cf..cbea3a75cd 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsAfb.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsAfb.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackPsAfb.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsFir.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsFir.cpp index 1a182e2958..7bd3a71585 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsFir.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsFir.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackPsFir.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsLei.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsLei.cpp index 4d092ffb5e..98196a2e0e 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsLei.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsLei.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackPsLei.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsPli.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsPli.cpp index 1d3d83e25f..3182ddcf04 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsPli.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsPli.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackPsPli.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp index cbea39771e..c0c9b21f88 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackPsRemb.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp index 8447af6f53..796868ad50 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackPsRpsi.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsSli.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsSli.cpp index 56eba471bc..f01999a39d 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsSli.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsSli.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackPsSli.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsTst.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsTst.cpp index 859c7564dc..de8fc4d1ef 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsTst.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsTst.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackPsTst.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp index d8f8c3a585..3067c7367c 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackPsVbcm.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp index 3cad5af92a..06c1d93dd9 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackRtpEcn.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpNack.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpNack.cpp index 7c48a03b4d..64ed4ee994 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpNack.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpNack.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackRtpNack.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp index 0608823c6b..8b1e4036cd 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackRtpSrReq.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp index 08e3c97d8f..654a11d251 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackRtpTllei.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp index c5ae5e5478..fc17fcf23f 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/FeedbackRtpTmmb.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp index e61be9cee9..e34c99ae8e 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "Logger.hpp" #include "RTC/RTCP/FeedbackRtpTransport.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestPacket.cpp b/worker/test/src/RTC/RTCP/TestPacket.cpp index 63ceddb861..7755e0be38 100644 --- a/worker/test/src/RTC/RTCP/TestPacket.cpp +++ b/worker/test/src/RTC/RTCP/TestPacket.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/Packet.hpp" -#include +#include using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestReceiverReport.cpp b/worker/test/src/RTC/RTCP/TestReceiverReport.cpp index 879ab0c080..a184856ab6 100644 --- a/worker/test/src/RTC/RTCP/TestReceiverReport.cpp +++ b/worker/test/src/RTC/RTCP/TestReceiverReport.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "RTC/RTCP/ReceiverReport.hpp" #include "RTC/RTCP/SenderReport.hpp" // sizeof(SenderReport::Header) -#include +#include using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestSdes.cpp b/worker/test/src/RTC/RTCP/TestSdes.cpp index 9edc5e2a22..a875dbf2ba 100644 --- a/worker/test/src/RTC/RTCP/TestSdes.cpp +++ b/worker/test/src/RTC/RTCP/TestSdes.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "RTC/RTCP/Packet.hpp" #include "RTC/RTCP/Sdes.hpp" -#include +#include #include // std::memcmp() #include diff --git a/worker/test/src/RTC/RTCP/TestSenderReport.cpp b/worker/test/src/RTC/RTCP/TestSenderReport.cpp index 48862861a0..38f7862e8f 100644 --- a/worker/test/src/RTC/RTCP/TestSenderReport.cpp +++ b/worker/test/src/RTC/RTCP/TestSenderReport.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/RTCP/SenderReport.hpp" -#include +#include #include // std::memcmp() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/RTCP/TestXr.cpp b/worker/test/src/RTC/RTCP/TestXr.cpp index 6580208b52..b047d32389 100644 --- a/worker/test/src/RTC/RTCP/TestXr.cpp +++ b/worker/test/src/RTC/RTCP/TestXr.cpp @@ -2,7 +2,7 @@ #include "RTC/RTCP/XR.hpp" #include "RTC/RTCP/XrDelaySinceLastRr.hpp" #include "RTC/RTCP/XrReceiverReferenceTime.hpp" -#include +#include #include // std::memcmp(), std::memcpy() using namespace RTC::RTCP; diff --git a/worker/test/src/RTC/TestKeyFrameRequestManager.cpp b/worker/test/src/RTC/TestKeyFrameRequestManager.cpp index 0fdc8449a3..69d459037a 100644 --- a/worker/test/src/RTC/TestKeyFrameRequestManager.cpp +++ b/worker/test/src/RTC/TestKeyFrameRequestManager.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "DepLibUV.hpp" #include "RTC/KeyFrameRequestManager.hpp" -#include +#include using namespace RTC; diff --git a/worker/test/src/RTC/TestNackGenerator.cpp b/worker/test/src/RTC/TestNackGenerator.cpp index e1c6b090eb..bb9744188b 100644 --- a/worker/test/src/RTC/TestNackGenerator.cpp +++ b/worker/test/src/RTC/TestNackGenerator.cpp @@ -3,7 +3,7 @@ #include "RTC/Codecs/PayloadDescriptorHandler.hpp" #include "RTC/NackGenerator.hpp" #include "RTC/RtpPacket.hpp" -#include +#include #include using namespace RTC; diff --git a/worker/test/src/RTC/TestRateCalculator.cpp b/worker/test/src/RTC/TestRateCalculator.cpp index ae566fe53e..6a27abaf06 100644 --- a/worker/test/src/RTC/TestRateCalculator.cpp +++ b/worker/test/src/RTC/TestRateCalculator.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "DepLibUV.hpp" #include "RTC/RateCalculator.hpp" -#include +#include #include using namespace RTC; diff --git a/worker/test/src/RTC/TestRtpEncodingParameters.cpp b/worker/test/src/RTC/TestRtpEncodingParameters.cpp index 98eb329a63..2de9089972 100644 --- a/worker/test/src/RTC/TestRtpEncodingParameters.cpp +++ b/worker/test/src/RTC/TestRtpEncodingParameters.cpp @@ -1,5 +1,5 @@ #include "common.hpp" -#include +#include #include static const std::regex ScalabilityModeRegex( diff --git a/worker/test/src/RTC/TestRtpPacket.cpp b/worker/test/src/RTC/TestRtpPacket.cpp index 2eea35b8b0..ade9004564 100644 --- a/worker/test/src/RTC/TestRtpPacket.cpp +++ b/worker/test/src/RTC/TestRtpPacket.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "helpers.hpp" #include "RTC/RtpPacket.hpp" -#include +#include #include // std::memset() #include #include diff --git a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp index 68b3c0033f..e2407ff1ff 100644 --- a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp +++ b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp @@ -2,7 +2,7 @@ #include "helpers.hpp" #include "RTC/Codecs/H264_SVC.hpp" #include "RTC/RtpPacket.hpp" -#include +#include #include // std::memset() #include #include diff --git a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp index 411db9fcac..ab038ba0e7 100644 --- a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp +++ b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "RTC/RtpPacket.hpp" #include "RTC/RtpRetransmissionBuffer.hpp" -#include +#include #include using namespace RTC; diff --git a/worker/test/src/RTC/TestRtpStreamRecv.cpp b/worker/test/src/RTC/TestRtpStreamRecv.cpp index d1d67cf489..feaf8e7c03 100644 --- a/worker/test/src/RTC/TestRtpStreamRecv.cpp +++ b/worker/test/src/RTC/TestRtpStreamRecv.cpp @@ -3,7 +3,7 @@ #include "RTC/RtpPacket.hpp" #include "RTC/RtpStream.hpp" #include "RTC/RtpStreamRecv.hpp" -#include +#include #include using namespace RTC; diff --git a/worker/test/src/RTC/TestRtpStreamSend.cpp b/worker/test/src/RTC/TestRtpStreamSend.cpp index b1182ca4e0..8e61af7bd6 100644 --- a/worker/test/src/RTC/TestRtpStreamSend.cpp +++ b/worker/test/src/RTC/TestRtpStreamSend.cpp @@ -3,7 +3,7 @@ #include "RTC/RtpPacket.hpp" #include "RTC/RtpStream.hpp" #include "RTC/RtpStreamSend.hpp" -#include +#include #include // #define PERFORMANCE_TEST 1 diff --git a/worker/test/src/RTC/TestSeqManager.cpp b/worker/test/src/RTC/TestSeqManager.cpp index 2e393a7923..564547b76a 100644 --- a/worker/test/src/RTC/TestSeqManager.cpp +++ b/worker/test/src/RTC/TestSeqManager.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/SeqManager.hpp" -#include +#include #include #include diff --git a/worker/test/src/RTC/TestTrendCalculator.cpp b/worker/test/src/RTC/TestTrendCalculator.cpp index f4dcf09591..bd466e63a7 100644 --- a/worker/test/src/RTC/TestTrendCalculator.cpp +++ b/worker/test/src/RTC/TestTrendCalculator.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "RTC/TrendCalculator.hpp" -#include +#include using namespace RTC; diff --git a/worker/test/src/Utils/TestBits.cpp b/worker/test/src/Utils/TestBits.cpp index c8217d6825..f388e4cb63 100644 --- a/worker/test/src/Utils/TestBits.cpp +++ b/worker/test/src/Utils/TestBits.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "Utils.hpp" -#include +#include SCENARIO("Utils::Bits::CountSetBits()") { diff --git a/worker/test/src/Utils/TestByte.cpp b/worker/test/src/Utils/TestByte.cpp index d25d2647c5..43cc193ed5 100644 --- a/worker/test/src/Utils/TestByte.cpp +++ b/worker/test/src/Utils/TestByte.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "Utils.hpp" -#include +#include SCENARIO("Utils::Byte") { diff --git a/worker/test/src/Utils/TestIP.cpp b/worker/test/src/Utils/TestIP.cpp index 201c83caa3..154be007e1 100644 --- a/worker/test/src/Utils/TestIP.cpp +++ b/worker/test/src/Utils/TestIP.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" -#include +#include #include // std::memset() #ifdef _WIN32 #include diff --git a/worker/test/src/Utils/TestString.cpp b/worker/test/src/Utils/TestString.cpp index 99fe49e751..2c02ca3323 100644 --- a/worker/test/src/Utils/TestString.cpp +++ b/worker/test/src/Utils/TestString.cpp @@ -1,6 +1,6 @@ #include "common.hpp" #include "Utils.hpp" -#include +#include #include // std::memcmp() using namespace Utils; diff --git a/worker/test/src/Utils/TestTime.cpp b/worker/test/src/Utils/TestTime.cpp index 25112ffd27..7fcf0d04ff 100644 --- a/worker/test/src/Utils/TestTime.cpp +++ b/worker/test/src/Utils/TestTime.cpp @@ -1,7 +1,7 @@ #include "common.hpp" #include "DepLibUV.hpp" #include "Utils.hpp" -#include +#include using namespace Utils; diff --git a/worker/test/src/tests.cpp b/worker/test/src/tests.cpp index 6584789af6..b42ef7ad44 100644 --- a/worker/test/src/tests.cpp +++ b/worker/test/src/tests.cpp @@ -1,5 +1,3 @@ -#define CATCH_CONFIG_RUNNER - #include "DepLibSRTP.hpp" #include "DepLibUV.hpp" #include "DepLibWebRTC.hpp" @@ -8,7 +6,7 @@ #include "LogLevel.hpp" #include "Settings.hpp" #include "Utils.hpp" -#include +#include #include // std::getenv() int main(int argc, char* argv[]) @@ -53,7 +51,9 @@ int main(int argc, char* argv[]) DepLibWebRTC::ClassInit(); Utils::Crypto::ClassInit(); - int status = Catch::Session().run(argc, argv); + Catch::Session session; + + int status = session.run(argc, argv); // Free static stuff. DepLibSRTP::ClassDestroy(); From c4f56e5ba0c5e0045b41b14a956fe7e3666c07e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jan 2024 16:25:46 +0100 Subject: [PATCH 278/525] Remove lcov dep from the repo (#1288) --- .gitignore | 2 + worker/deps/lcov/.gitignore | 6 - worker/deps/lcov/CONTRIBUTING | 93 - worker/deps/lcov/COPYING | 339 - worker/deps/lcov/Makefile | 122 - worker/deps/lcov/README | 135 - worker/deps/lcov/bin/copy_dates.sh | 36 - worker/deps/lcov/bin/gendesc | 226 - worker/deps/lcov/bin/genhtml | 5978 ----------------- worker/deps/lcov/bin/geninfo | 4593 ------------- worker/deps/lcov/bin/genpng | 389 -- worker/deps/lcov/bin/get_changes.sh | 13 - worker/deps/lcov/bin/get_version.sh | 34 - worker/deps/lcov/bin/install.sh | 76 - worker/deps/lcov/bin/lcov | 4329 ------------ worker/deps/lcov/bin/updateversion.pl | 194 - worker/deps/lcov/example/Makefile | 98 - worker/deps/lcov/example/README | 6 - worker/deps/lcov/example/descriptions.txt | 10 - worker/deps/lcov/example/example.c | 60 - worker/deps/lcov/example/gauss.h | 6 - worker/deps/lcov/example/iterate.h | 6 - worker/deps/lcov/example/methods/gauss.c | 48 - worker/deps/lcov/example/methods/iterate.c | 45 - worker/deps/lcov/lcovrc | 172 - worker/deps/lcov/man/gendesc.1 | 78 - worker/deps/lcov/man/genhtml.1 | 601 -- worker/deps/lcov/man/geninfo.1 | 578 -- worker/deps/lcov/man/genpng.1 | 101 - worker/deps/lcov/man/lcov.1 | 930 --- worker/deps/lcov/man/lcovrc.5 | 937 --- worker/deps/lcov/rpm/lcov.spec | 59 - worker/deps/lcov/test/Makefile | 27 - worker/deps/lcov/test/bin/common | 103 - worker/deps/lcov/test/bin/mkinfo | 952 --- worker/deps/lcov/test/bin/norminfo | 243 - worker/deps/lcov/test/bin/test_run | 99 - worker/deps/lcov/test/bin/test_skip | 19 - worker/deps/lcov/test/bin/testsuite_exit | 71 - worker/deps/lcov/test/bin/testsuite_init | 28 - worker/deps/lcov/test/common.mak | 50 - worker/deps/lcov/test/genhtml_output/Makefile | 31 - .../lcov/test/genhtml_output/genhtml_test | 36 - worker/deps/lcov/test/lcov_add_files/Makefile | 47 - worker/deps/lcov/test/lcov_add_files/add_test | 46 - worker/deps/lcov/test/lcov_diff/Makefile | 9 - worker/deps/lcov/test/lcov_diff/diff_test | 35 - worker/deps/lcov/test/lcov_diff/new/Makefile | 17 - worker/deps/lcov/test/lcov_diff/new/prog.c | 41 - worker/deps/lcov/test/lcov_diff/old/Makefile | 17 - worker/deps/lcov/test/lcov_diff/old/prog.c | 22 - worker/deps/lcov/test/lcov_misc/Makefile | 5 - worker/deps/lcov/test/lcov_summary/Makefile | 41 - .../deps/lcov/test/lcov_summary/check_counts | 70 - worker/deps/lcov/test/lcovrc | 4 - worker/deps/lcov/test/profiles/large | 51 - worker/deps/lcov/test/profiles/medium | 51 - worker/deps/lcov/test/profiles/small | 51 - worker/scripts/lcov.sh | 12 +- worker/tasks.py | 10 - 60 files changed, 7 insertions(+), 22481 deletions(-) delete mode 100644 worker/deps/lcov/.gitignore delete mode 100644 worker/deps/lcov/CONTRIBUTING delete mode 100644 worker/deps/lcov/COPYING delete mode 100644 worker/deps/lcov/Makefile delete mode 100644 worker/deps/lcov/README delete mode 100755 worker/deps/lcov/bin/copy_dates.sh delete mode 100755 worker/deps/lcov/bin/gendesc delete mode 100755 worker/deps/lcov/bin/genhtml delete mode 100755 worker/deps/lcov/bin/geninfo delete mode 100755 worker/deps/lcov/bin/genpng delete mode 100755 worker/deps/lcov/bin/get_changes.sh delete mode 100755 worker/deps/lcov/bin/get_version.sh delete mode 100755 worker/deps/lcov/bin/install.sh delete mode 100755 worker/deps/lcov/bin/lcov delete mode 100755 worker/deps/lcov/bin/updateversion.pl delete mode 100644 worker/deps/lcov/example/Makefile delete mode 100644 worker/deps/lcov/example/README delete mode 100644 worker/deps/lcov/example/descriptions.txt delete mode 100644 worker/deps/lcov/example/example.c delete mode 100644 worker/deps/lcov/example/gauss.h delete mode 100644 worker/deps/lcov/example/iterate.h delete mode 100644 worker/deps/lcov/example/methods/gauss.c delete mode 100644 worker/deps/lcov/example/methods/iterate.c delete mode 100644 worker/deps/lcov/lcovrc delete mode 100644 worker/deps/lcov/man/gendesc.1 delete mode 100644 worker/deps/lcov/man/genhtml.1 delete mode 100644 worker/deps/lcov/man/geninfo.1 delete mode 100644 worker/deps/lcov/man/genpng.1 delete mode 100644 worker/deps/lcov/man/lcov.1 delete mode 100644 worker/deps/lcov/man/lcovrc.5 delete mode 100644 worker/deps/lcov/rpm/lcov.spec delete mode 100644 worker/deps/lcov/test/Makefile delete mode 100644 worker/deps/lcov/test/bin/common delete mode 100755 worker/deps/lcov/test/bin/mkinfo delete mode 100755 worker/deps/lcov/test/bin/norminfo delete mode 100755 worker/deps/lcov/test/bin/test_run delete mode 100755 worker/deps/lcov/test/bin/test_skip delete mode 100755 worker/deps/lcov/test/bin/testsuite_exit delete mode 100755 worker/deps/lcov/test/bin/testsuite_init delete mode 100644 worker/deps/lcov/test/common.mak delete mode 100644 worker/deps/lcov/test/genhtml_output/Makefile delete mode 100755 worker/deps/lcov/test/genhtml_output/genhtml_test delete mode 100644 worker/deps/lcov/test/lcov_add_files/Makefile delete mode 100755 worker/deps/lcov/test/lcov_add_files/add_test delete mode 100644 worker/deps/lcov/test/lcov_diff/Makefile delete mode 100755 worker/deps/lcov/test/lcov_diff/diff_test delete mode 100644 worker/deps/lcov/test/lcov_diff/new/Makefile delete mode 100644 worker/deps/lcov/test/lcov_diff/new/prog.c delete mode 100644 worker/deps/lcov/test/lcov_diff/old/Makefile delete mode 100644 worker/deps/lcov/test/lcov_diff/old/prog.c delete mode 100644 worker/deps/lcov/test/lcov_misc/Makefile delete mode 100644 worker/deps/lcov/test/lcov_summary/Makefile delete mode 100755 worker/deps/lcov/test/lcov_summary/check_counts delete mode 100644 worker/deps/lcov/test/lcovrc delete mode 100644 worker/deps/lcov/test/profiles/large delete mode 100644 worker/deps/lcov/test/profiles/medium delete mode 100644 worker/deps/lcov/test/profiles/small diff --git a/.gitignore b/.gitignore index e2f65fca29..027c5a99f3 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,8 @@ # Ignore all fuzzer generated test inputs. /worker/fuzzer/new-corpus/* !/worker/fuzzer/new-corpus/.placeholder +# lcov is just for local usage. +/worker/lcov ## Others. /coverage diff --git a/worker/deps/lcov/.gitignore b/worker/deps/lcov/.gitignore deleted file mode 100644 index 51f952052d..0000000000 --- a/worker/deps/lcov/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.version -*.gcda -*.gcno -*.info -*.tar.gz -*.rpm diff --git a/worker/deps/lcov/CONTRIBUTING b/worker/deps/lcov/CONTRIBUTING deleted file mode 100644 index 6890789bd1..0000000000 --- a/worker/deps/lcov/CONTRIBUTING +++ /dev/null @@ -1,93 +0,0 @@ -Contributing to LCOV -==================== - -Please read this document if you would like to help improving the LTP GCOV -extension (LCOV). In general, all types of contributions are welcome, for -example: - - * Fixes for code or documentation - * Performance and compatibility improvements - * Functional enhancements - -There are some rules that these contributions must follow to be acceptable for -inclusion: - - 1. The contribution must align with the project goals of LCOV. - 2. The contribution must follow a particular format. - 3. The contribution must be signed. - -Once you have made sure that your contribution follows these rules, send it via -e-mail to the LTP coverage mailing list [1]. - - -Signing your work -================= - -All contributions to LCOV must be signed by putting the following line at the -end of the explanation of a patch: - - Signed-off-by: Your Name - -By signing a patch, you certify the following: - - By making a contribution to the LTP GCOV extension (LCOV) on - http://ltp.sourceforge.net, I certify that: - - a) The contribution was created by me and I have the right to submit it - under the terms and conditions of the open source license - "GNU General Public License, version 2 or later". - (http://www.gnu.org/licenses/old-licenses/gpl-2.0.html). - - b) The contribution is made free of any other party's intellectual property - claims or rights. - - c) I understand and agree that this project and the contribution are public - and that a record of the contribution (including all personal information - I submit with it, including my sign-off) is maintained indefinitely and - may be redistributed consistent with this project or the open source - license(s) involved. - - -Project goals -============= - -The goal of LCOV is to provide a set of command line tools that can be used to -collect, process and visualize code coverage data as produced by the gcov tool -that is part of the GNU Compiler Collection (GCC) [2]. - -If you have an idea for a contribution but are unsure if it aligns with the -project goals, feel free to discuss the idea on the LTP coverage mailing -list [1]. - - -Contribution format -=================== - -To contribute a change, please create a patch using 'git format-patch'. -Alternatively you can use the diff utility with the following command line -options: - - diff -Naurp - -Please base your changes on the most current version of LCOV. You can use the -following command line to obtain this version from the lcov Git repository: - - git clone https://github.com/linux-test-project/lcov.git - -Add a meaningful description of the contribution to the top of the patch. The -description should follow this format: - - component: short description - - detailed description - - Signed-off-by: Your Name - -With your Signed-off-by, you certify the rules stated in section -"Signing your work". - - --- - -[1] ltp-coverage@lists.sourceforge.net -[2] http://gcc.gnu.org diff --git a/worker/deps/lcov/COPYING b/worker/deps/lcov/COPYING deleted file mode 100644 index d511905c16..0000000000 --- a/worker/deps/lcov/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/worker/deps/lcov/Makefile b/worker/deps/lcov/Makefile deleted file mode 100644 index 1207cb19ad..0000000000 --- a/worker/deps/lcov/Makefile +++ /dev/null @@ -1,122 +0,0 @@ -# -# Makefile for LCOV -# -# Make targets: -# - install: install LCOV tools and man pages on the system -# - uninstall: remove tools and man pages from the system -# - dist: create files required for distribution, i.e. the lcov.tar.gz -# and the lcov.rpm file. Just make sure to adjust the VERSION -# and RELEASE variables below - both version and date strings -# will be updated in all necessary files. -# - clean: remove all generated files -# - -VERSION := $(shell bin/get_version.sh --version) -RELEASE := $(shell bin/get_version.sh --release) -FULL := $(shell bin/get_version.sh --full) - -# Set this variable during 'make install' to specify the Perl interpreter used in -# installed scripts, or leave empty to keep the current interpreter. -export LCOV_PERL_PATH := /usr/bin/perl - -PREFIX := /usr/local - -CFG_DIR := $(PREFIX)/etc -BIN_DIR := $(PREFIX)/bin -MAN_DIR := $(PREFIX)/share/man -TMP_DIR := $(shell mktemp -d) -FILES := $(wildcard bin/*) $(wildcard man/*) README Makefile \ - $(wildcard rpm/*) lcovrc - -.PHONY: all info clean install uninstall rpms test - -all: info - -info: - @echo "Available make targets:" - @echo " install : install binaries and man pages in DESTDIR (default /)" - @echo " uninstall : delete binaries and man pages from DESTDIR (default /)" - @echo " dist : create packages (RPM, tarball) ready for distribution" - @echo " test : perform self-tests" - -clean: - rm -f lcov-*.tar.gz - rm -f lcov-*.rpm - make -C example clean - make -C test -s clean - -install: - bin/install.sh bin/lcov $(DESTDIR)$(BIN_DIR)/lcov -m 755 - bin/install.sh bin/genhtml $(DESTDIR)$(BIN_DIR)/genhtml -m 755 - bin/install.sh bin/geninfo $(DESTDIR)$(BIN_DIR)/geninfo -m 755 - bin/install.sh bin/genpng $(DESTDIR)$(BIN_DIR)/genpng -m 755 - bin/install.sh bin/gendesc $(DESTDIR)$(BIN_DIR)/gendesc -m 755 - bin/install.sh man/lcov.1 $(DESTDIR)$(MAN_DIR)/man1/lcov.1 -m 644 - bin/install.sh man/genhtml.1 $(DESTDIR)$(MAN_DIR)/man1/genhtml.1 -m 644 - bin/install.sh man/geninfo.1 $(DESTDIR)$(MAN_DIR)/man1/geninfo.1 -m 644 - bin/install.sh man/genpng.1 $(DESTDIR)$(MAN_DIR)/man1/genpng.1 -m 644 - bin/install.sh man/gendesc.1 $(DESTDIR)$(MAN_DIR)/man1/gendesc.1 -m 644 - bin/install.sh man/lcovrc.5 $(DESTDIR)$(MAN_DIR)/man5/lcovrc.5 -m 644 - bin/install.sh lcovrc $(DESTDIR)$(CFG_DIR)/lcovrc -m 644 - bin/updateversion.pl $(DESTDIR)$(BIN_DIR)/lcov $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(BIN_DIR)/genhtml $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(BIN_DIR)/geninfo $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(BIN_DIR)/genpng $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(BIN_DIR)/gendesc $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(MAN_DIR)/man1/lcov.1 $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(MAN_DIR)/man1/genhtml.1 $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(MAN_DIR)/man1/geninfo.1 $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(MAN_DIR)/man1/genpng.1 $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(MAN_DIR)/man1/gendesc.1 $(VERSION) $(RELEASE) $(FULL) - bin/updateversion.pl $(DESTDIR)$(MAN_DIR)/man5/lcovrc.5 $(VERSION) $(RELEASE) $(FULL) - -uninstall: - bin/install.sh --uninstall bin/lcov $(DESTDIR)$(BIN_DIR)/lcov - bin/install.sh --uninstall bin/genhtml $(DESTDIR)$(BIN_DIR)/genhtml - bin/install.sh --uninstall bin/geninfo $(DESTDIR)$(BIN_DIR)/geninfo - bin/install.sh --uninstall bin/genpng $(DESTDIR)$(BIN_DIR)/genpng - bin/install.sh --uninstall bin/gendesc $(DESTDIR)$(BIN_DIR)/gendesc - bin/install.sh --uninstall man/lcov.1 $(DESTDIR)$(MAN_DIR)/man1/lcov.1 - bin/install.sh --uninstall man/genhtml.1 $(DESTDIR)$(MAN_DIR)/man1/genhtml.1 - bin/install.sh --uninstall man/geninfo.1 $(DESTDIR)$(MAN_DIR)/man1/geninfo.1 - bin/install.sh --uninstall man/genpng.1 $(DESTDIR)$(MAN_DIR)/man1/genpng.1 - bin/install.sh --uninstall man/gendesc.1 $(DESTDIR)$(MAN_DIR)/man1/gendesc.1 - bin/install.sh --uninstall man/lcovrc.5 $(DESTDIR)$(MAN_DIR)/man5/lcovrc.5 - bin/install.sh --uninstall lcovrc $(DESTDIR)$(CFG_DIR)/lcovrc - -dist: lcov-$(VERSION).tar.gz lcov-$(VERSION)-$(RELEASE).noarch.rpm \ - lcov-$(VERSION)-$(RELEASE).src.rpm - -lcov-$(VERSION).tar.gz: $(FILES) - mkdir $(TMP_DIR)/lcov-$(VERSION) - cp -r * $(TMP_DIR)/lcov-$(VERSION) - bin/copy_dates.sh . $(TMP_DIR)/lcov-$(VERSION) - make -C $(TMP_DIR)/lcov-$(VERSION) clean - bin/updateversion.pl $(TMP_DIR)/lcov-$(VERSION) $(VERSION) $(RELEASE) $(FULL) - bin/get_changes.sh > $(TMP_DIR)/lcov-$(VERSION)/CHANGES - cd $(TMP_DIR) ; \ - tar cfz $(TMP_DIR)/lcov-$(VERSION).tar.gz lcov-$(VERSION) - mv $(TMP_DIR)/lcov-$(VERSION).tar.gz . - rm -rf $(TMP_DIR) - -lcov-$(VERSION)-$(RELEASE).noarch.rpm: rpms -lcov-$(VERSION)-$(RELEASE).src.rpm: rpms - -rpms: lcov-$(VERSION).tar.gz - mkdir $(TMP_DIR) - mkdir $(TMP_DIR)/BUILD - mkdir $(TMP_DIR)/RPMS - mkdir $(TMP_DIR)/SOURCES - mkdir $(TMP_DIR)/SRPMS - cp lcov-$(VERSION).tar.gz $(TMP_DIR)/SOURCES - cd $(TMP_DIR)/BUILD ; \ - tar xfz $(TMP_DIR)/SOURCES/lcov-$(VERSION).tar.gz \ - lcov-$(VERSION)/rpm/lcov.spec - rpmbuild --define '_topdir $(TMP_DIR)' \ - -ba $(TMP_DIR)/BUILD/lcov-$(VERSION)/rpm/lcov.spec - mv $(TMP_DIR)/RPMS/noarch/lcov-$(VERSION)-$(RELEASE).noarch.rpm . - mv $(TMP_DIR)/SRPMS/lcov-$(VERSION)-$(RELEASE).src.rpm . - rm -rf $(TMP_DIR) - -test: - @make -C test -s all diff --git a/worker/deps/lcov/README b/worker/deps/lcov/README deleted file mode 100644 index bd3c4f2af9..0000000000 --- a/worker/deps/lcov/README +++ /dev/null @@ -1,135 +0,0 @@ -------------------------------------------------- -- README file for the LTP GCOV extension (LCOV) - -- Last changes: 2016-12-19 - -------------------------------------------------- - -Description ------------ - LCOV is an extension of GCOV, a GNU tool which provides information about - what parts of a program are actually executed (i.e. "covered") while running - a particular test case. The extension consists of a set of Perl scripts - which build on the textual GCOV output to implement the following enhanced - functionality: - - * HTML based output: coverage rates are additionally indicated using bar - graphs and specific colors. - - * Support for large projects: overview pages allow quick browsing of - coverage data by providing three levels of detail: directory view, - file view and source code view. - - LCOV was initially designed to support Linux kernel coverage measurements, - but works as well for coverage measurements on standard user space - applications. - - -Further README contents ------------------------ - 1. Included files - 2. Installing LCOV - 3. An example of how to access kernel coverage data - 4. An example of how to access coverage data for a user space program - 5. Questions and Comments - - - -1. Important files ------------------- - README - This README file - CHANGES - List of changes between releases - bin/lcov - Tool for capturing LCOV coverage data - bin/genhtml - Tool for creating HTML output from LCOV data - bin/gendesc - Tool for creating description files as used by genhtml - bin/geninfo - Internal tool (creates LCOV data files) - bin/genpng - Internal tool (creates png overviews of source files) - bin/install.sh - Internal tool (takes care of un-/installing) - man - Directory containing man pages for included tools - example - Directory containing an example to demonstrate LCOV - lcovrc - LCOV configuration file - Makefile - Makefile providing 'install' and 'uninstall' targets - - -2. Installing LCOV ------------------- -The LCOV package is available as either RPM or tarball from: - - http://ltp.sourceforge.net/coverage/lcov.php - -To install the tarball, unpack it to a directory and run: - - make install - -Use Git for the most recent (but possibly unstable) version: - - git clone https://github.com/linux-test-project/lcov.git - -Change to the resulting lcov directory and type: - - make install - - -3. An example of how to access kernel coverage data ---------------------------------------------------- -Requirements: get and install the gcov-kernel package from - - http://sourceforge.net/projects/ltp - -Copy the resulting gcov kernel module file to either the system wide modules -directory or the same directory as the Perl scripts. As root, do the following: - - a) Resetting counters - - lcov --zerocounters - - b) Capturing the current coverage state to a file - - lcov --capture --output-file kernel.info - - c) Getting HTML output - - genhtml kernel.info - -Point the web browser of your choice to the resulting index.html file. - - -4. An example of how to access coverage data for a user space program ---------------------------------------------------------------------- -Requirements: compile the program in question using GCC with the options --fprofile-arcs and -ftest-coverage. During linking, make sure to specify --lgcov or -coverage. - -Assuming the compile directory is called "appdir", do the following: - - a) Resetting counters - - lcov --directory appdir --zerocounters - - b) Capturing the current coverage state to a file - - lcov --directory appdir --capture --output-file app.info - - Note that this step only works after the application has - been started and stopped at least once. Otherwise lcov will - abort with an error mentioning that there are no data/.gcda files. - - c) Getting HTML output - - genhtml app.info - -Point the web browser of your choice to the resulting index.html file. - -Please note that independently of where the application is installed or -from which directory it is run, the --directory statement needs to -point to the directory in which the application was compiled. - -For further information on the gcc profiling mechanism, please also -consult the gcov man page. - - -5. Questions and comments -------------------------- -See the included man pages for more information on how to use the LCOV tools. - -Please email further questions or comments regarding this tool to the -LTP Mailing list at ltp-coverage@lists.sourceforge.net - diff --git a/worker/deps/lcov/bin/copy_dates.sh b/worker/deps/lcov/bin/copy_dates.sh deleted file mode 100755 index aef5f5ed36..0000000000 --- a/worker/deps/lcov/bin/copy_dates.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -# -# Usage: copy_dates.sh SOURCE TARGET -# -# For each file found in SOURCE, set the modification time of the copy of that -# file in TARGET to either the time of the latest Git commit (if SOURCE contains -# a Git repository and the file was not modified after the last commit), or the -# modification time of the original file. - -SOURCE="$1" -TARGET="$2" - -if [ -z "$SOURCE" -o -z "$TARGET" ] ; then - echo "Usage: $0 SOURCE TARGET" >&2 - exit 1 -fi - -[ -d "$SOURCE/.git" ] ; NOGIT=$? - -echo "Copying modification/commit times from $SOURCE to $TARGET" - -cd "$SOURCE" || exit 1 -find * -type f | while read FILENAME ; do - [ ! -e "$TARGET/$FILENAME" ] && continue - - # Copy modification time - touch -m "$TARGET/$FILENAME" -r "$FILENAME" - - [ $NOGIT -eq 1 ] && continue # No Git - git diff --quiet -- "$FILENAME" || continue # Modified - git diff --quiet --cached -- "$FILENAME" || continue # Modified - - # Apply modification time from Git commit time - TIME=$(git log --pretty=format:%cd -n 1 --date=iso -- "$FILENAME") - [ -n "$TIME" ] && touch -m "$TARGET/$FILENAME" --date "$TIME" -done diff --git a/worker/deps/lcov/bin/gendesc b/worker/deps/lcov/bin/gendesc deleted file mode 100755 index ea07b4e9b7..0000000000 --- a/worker/deps/lcov/bin/gendesc +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright (c) International Business Machines Corp., 2002 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# -# gendesc -# -# This script creates a description file as understood by genhtml. -# Input file format: -# -# For each test case: -# -# -# -# Actual description may consist of several lines. By default, output is -# written to stdout. Test names consist of alphanumeric characters -# including _ and -. -# -# -# History: -# 2002-09-02: created by Peter Oberparleiter -# - -use strict; -use warnings; -use File::Basename; -use Getopt::Long; -use Cwd qw/abs_path/; - - -# Constants -our $tool_dir = abs_path(dirname($0)); -our $lcov_version = 'LCOV version '.`$tool_dir/get_version.sh --full`; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; -our $tool_name = basename($0); - - -# Prototypes -sub print_usage(*); -sub gen_desc(); -sub warn_handler($); -sub die_handler($); - - -# Global variables -our $help; -our $version; -our $output_filename; -our $input_filename; - - -# -# Code entry point -# - -$SIG{__WARN__} = \&warn_handler; -$SIG{__DIE__} = \&die_handler; - -# Parse command line options -if (!GetOptions("output-filename=s" => \$output_filename, - "version" =>\$version, - "help|?" => \$help - )) -{ - print(STDERR "Use $tool_name --help to get usage information\n"); - exit(1); -} - -$input_filename = $ARGV[0]; - -# Check for help option -if ($help) -{ - print_usage(*STDOUT); - exit(0); -} - -# Check for version option -if ($version) -{ - print("$tool_name: $lcov_version\n"); - exit(0); -} - - -# Check for input filename -if (!$input_filename) -{ - die("No input filename specified\n". - "Use $tool_name --help to get usage information\n"); -} - -# Do something -gen_desc(); - - -# -# print_usage(handle) -# -# Write out command line usage information to given filehandle. -# - -sub print_usage(*) -{ - local *HANDLE = $_[0]; - - print(HANDLE < -# TD: -# -# If defined, write output to OUTPUT_FILENAME, otherwise to stdout. -# -# Die on error. -# - -sub gen_desc() -{ - local *INPUT_HANDLE; - local *OUTPUT_HANDLE; - my $empty_line = "ignore"; - - open(INPUT_HANDLE, "<", $input_filename) - or die("ERROR: cannot open $input_filename!\n"); - - # Open output file for writing - if ($output_filename) - { - open(OUTPUT_HANDLE, ">", $output_filename) - or die("ERROR: cannot create $output_filename!\n"); - } - else - { - *OUTPUT_HANDLE = *STDOUT; - } - - # Process all lines in input file - while () - { - chomp($_); - - if (/^(\w[\w-]*)(\s*)$/) - { - # Matched test name - # Name starts with alphanum or _, continues with - # alphanum, _ or - - print(OUTPUT_HANDLE "TN: $1\n"); - $empty_line = "ignore"; - } - elsif (/^(\s+)(\S.*?)\s*$/) - { - # Matched test description - if ($empty_line eq "insert") - { - # Write preserved empty line - print(OUTPUT_HANDLE "TD: \n"); - } - print(OUTPUT_HANDLE "TD: $2\n"); - $empty_line = "observe"; - } - elsif (/^\s*$/) - { - # Matched empty line to preserve paragraph separation - # inside description text - if ($empty_line eq "observe") - { - $empty_line = "insert"; - } - } - } - - # Close output file if defined - if ($output_filename) - { - close(OUTPUT_HANDLE); - } - - close(INPUT_HANDLE); -} - -sub warn_handler($) -{ - my ($msg) = @_; - - warn("$tool_name: $msg"); -} - -sub die_handler($) -{ - my ($msg) = @_; - - die("$tool_name: $msg"); -} diff --git a/worker/deps/lcov/bin/genhtml b/worker/deps/lcov/bin/genhtml deleted file mode 100755 index 578c66ef6b..0000000000 --- a/worker/deps/lcov/bin/genhtml +++ /dev/null @@ -1,5978 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright (c) International Business Machines Corp., 2002,2012 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# -# genhtml -# -# This script generates HTML output from .info files as created by the -# geninfo script. Call it with --help and refer to the genhtml man page -# to get information on usage and available options. -# -# -# History: -# 2002-08-23 created by Peter Oberparleiter -# IBM Lab Boeblingen -# based on code by Manoj Iyer and -# Megan Bock -# IBM Austin -# 2002-08-27 / Peter Oberparleiter: implemented frame view -# 2002-08-29 / Peter Oberparleiter: implemented test description filtering -# so that by default only descriptions for test cases which -# actually hit some source lines are kept -# 2002-09-05 / Peter Oberparleiter: implemented --no-sourceview -# 2002-09-05 / Mike Kobler: One of my source file paths includes a "+" in -# the directory name. I found that genhtml.pl died when it -# encountered it. I was able to fix the problem by modifying -# the string with the escape character before parsing it. -# 2002-10-26 / Peter Oberparleiter: implemented --num-spaces -# 2003-04-07 / Peter Oberparleiter: fixed bug which resulted in an error -# when trying to combine .info files containing data without -# a test name -# 2003-04-10 / Peter Oberparleiter: extended fix by Mike to also cover -# other special characters -# 2003-04-30 / Peter Oberparleiter: made info write to STDERR, not STDOUT -# 2003-07-10 / Peter Oberparleiter: added line checksum support -# 2004-08-09 / Peter Oberparleiter: added configuration file support -# 2005-03-04 / Cal Pierog: added legend to HTML output, fixed coloring of -# "good coverage" background -# 2006-03-18 / Marcus Boerger: added --custom-intro, --custom-outro and -# overwrite --no-prefix if --prefix is present -# 2006-03-20 / Peter Oberparleiter: changes to custom_* function (rename -# to html_prolog/_epilog, minor modifications to implementation), -# changed prefix/noprefix handling to be consistent with current -# logic -# 2006-03-20 / Peter Oberparleiter: added --html-extension option -# 2008-07-14 / Tom Zoerner: added --function-coverage command line option; -# added function table to source file page -# 2008-08-13 / Peter Oberparleiter: modified function coverage -# implementation (now enabled per default), -# introduced sorting option (enabled per default) -# - -use strict; -use warnings; -use File::Basename; -use File::Temp qw(tempfile); -use Getopt::Long; -use Digest::MD5 qw(md5_base64); -use Cwd qw/abs_path cwd/; - - -# Global constants -our $title = "LCOV - code coverage report"; -our $tool_dir = abs_path(dirname($0)); -our $lcov_version = 'LCOV version '.`$tool_dir/get_version.sh --full`; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; -our $tool_name = basename($0); - -# Specify coverage rate default precision -our $default_precision = 1; - -# Specify coverage rate limits (in %) for classifying file entries -# HI: $hi_limit <= rate <= 100 graph color: green -# MED: $med_limit <= rate < $hi_limit graph color: orange -# LO: 0 <= rate < $med_limit graph color: red - -# For line coverage/all coverage types if not specified -our $hi_limit = 90; -our $med_limit = 75; - -# For function coverage -our $fn_hi_limit; -our $fn_med_limit; - -# For branch coverage -our $br_hi_limit; -our $br_med_limit; - -# Width of overview image -our $overview_width = 80; - -# Resolution of overview navigation: this number specifies the maximum -# difference in lines between the position a user selected from the overview -# and the position the source code window is scrolled to. -our $nav_resolution = 4; - -# Clicking a line in the overview image should show the source code view at -# a position a bit further up so that the requested line is not the first -# line in the window. This number specifies that offset in lines. -our $nav_offset = 10; - -# Clicking on a function name should show the source code at a position a -# few lines before the first line of code of that function. This number -# specifies that offset in lines. -our $func_offset = 2; - -our $overview_title = "top level"; - -# Width for line coverage information in the source code view -our $line_field_width = 12; - -# Width for branch coverage information in the source code view -our $br_field_width = 16; - -# Internal Constants - -# Header types -our $HDR_DIR = 0; -our $HDR_FILE = 1; -our $HDR_SOURCE = 2; -our $HDR_TESTDESC = 3; -our $HDR_FUNC = 4; - -# Sort types -our $SORT_FILE = 0; -our $SORT_LINE = 1; -our $SORT_FUNC = 2; -our $SORT_BRANCH = 3; - -# Fileview heading types -our $HEAD_NO_DETAIL = 1; -our $HEAD_DETAIL_HIDDEN = 2; -our $HEAD_DETAIL_SHOWN = 3; - -# Additional offsets used when converting branch coverage data to HTML -our $BR_LEN = 3; -our $BR_OPEN = 4; -our $BR_CLOSE = 5; - -# Branch data combination types -our $BR_SUB = 0; -our $BR_ADD = 1; - -# Block value used for unnamed blocks -our $UNNAMED_BLOCK = vec(pack('b*', 1 x 32), 0, 32); - -# Error classes which users may specify to ignore during processing -our $ERROR_SOURCE = 0; -our %ERROR_ID = ( - "source" => $ERROR_SOURCE, -); - -# Data related prototypes -sub print_usage(*); -sub gen_html(); -sub html_create($$); -sub process_dir($); -sub process_file($$$); -sub info(@); -sub read_info_file($); -sub get_info_entry($); -sub set_info_entry($$$$$$$$$;$$$$$$); -sub get_prefix($@); -sub shorten_prefix($); -sub get_dir_list(@); -sub get_relative_base_path($); -sub read_testfile($); -sub get_date_string(); -sub create_sub_dir($); -sub subtract_counts($$); -sub add_counts($$); -sub apply_baseline($$); -sub remove_unused_descriptions(); -sub get_found_and_hit($); -sub get_affecting_tests($$$); -sub combine_info_files($$); -sub merge_checksums($$$); -sub combine_info_entries($$$); -sub apply_prefix($@); -sub system_no_output($@); -sub read_config($); -sub apply_config($); -sub get_html_prolog($); -sub get_html_epilog($); -sub write_dir_page($$$$$$$$$$$$$$$$$); -sub classify_rate($$$$); -sub combine_brcount($$$;$); -sub get_br_found_and_hit($); -sub warn_handler($); -sub die_handler($); -sub parse_ignore_errors(@); -sub parse_dir_prefix(@); -sub rate($$;$$$); - - -# HTML related prototypes -sub escape_html($); -sub get_bar_graph_code($$$); - -sub write_png_files(); -sub write_htaccess_file(); -sub write_css_file(); -sub write_description_file($$$$$$$); -sub write_function_table(*$$$$$$$$$$); - -sub write_html(*$); -sub write_html_prolog(*$$); -sub write_html_epilog(*$;$); - -sub write_header(*$$$$$$$$$$); -sub write_header_prolog(*$); -sub write_header_line(*@); -sub write_header_epilog(*$); - -sub write_file_table(*$$$$$$$); -sub write_file_table_prolog(*$@); -sub write_file_table_entry(*$$$@); -sub write_file_table_detail_entry(*$@); -sub write_file_table_epilog(*); - -sub write_test_table_prolog(*$); -sub write_test_table_entry(*$$); -sub write_test_table_epilog(*); - -sub write_source($$$$$$$); -sub write_source_prolog(*); -sub write_source_line(*$$$$$); -sub write_source_epilog(*); - -sub write_frameset(*$$$); -sub write_overview_line(*$$$); -sub write_overview(*$$$$); - -# External prototype (defined in genpng) -sub gen_png($$$@); - - -# Global variables & initialization -our %info_data; # Hash containing all data from .info file -our @opt_dir_prefix; # Array of prefixes to remove from all sub directories -our @dir_prefix; -our %test_description; # Hash containing test descriptions if available -our $date = get_date_string(); - -our @info_filenames; # List of .info files to use as data source -our $test_title; # Title for output as written to each page header -our $output_directory; # Name of directory in which to store output -our $base_filename; # Optional name of file containing baseline data -our $desc_filename; # Name of file containing test descriptions -our $css_filename; # Optional name of external stylesheet file to use -our $quiet; # If set, suppress information messages -our $help; # Help option flag -our $version; # Version option flag -our $show_details; # If set, generate detailed directory view -our $no_prefix; # If set, do not remove filename prefix -our $func_coverage; # If set, generate function coverage statistics -our $no_func_coverage; # Disable func_coverage -our $br_coverage; # If set, generate branch coverage statistics -our $no_br_coverage; # Disable br_coverage -our $sort = 1; # If set, provide directory listings with sorted entries -our $no_sort; # Disable sort -our $frames; # If set, use frames for source code view -our $keep_descriptions; # If set, do not remove unused test case descriptions -our $no_sourceview; # If set, do not create a source code view for each file -our $highlight; # If set, highlight lines covered by converted data only -our $legend; # If set, include legend in output -our $tab_size = 8; # Number of spaces to use in place of tab -our $config; # Configuration file contents -our $html_prolog_file; # Custom HTML prolog file (up to and including ) -our $html_epilog_file; # Custom HTML epilog file (from onwards) -our $html_prolog; # Actual HTML prolog -our $html_epilog; # Actual HTML epilog -our $html_ext = "html"; # Extension for generated HTML files -our $html_gzip = 0; # Compress with gzip -our $demangle_cpp = 0; # Demangle C++ function names -our @opt_ignore_errors; # Ignore certain error classes during processing -our @ignore; -our $opt_config_file; # User-specified configuration file location -our %opt_rc; -our $opt_missed; # List/sort lines by missed counts -our $charset = "UTF-8"; # Default charset for HTML pages -our @fileview_sortlist; -our @fileview_sortname = ("", "-sort-l", "-sort-f", "-sort-b"); -our @funcview_sortlist; -our @rate_name = ("Lo", "Med", "Hi"); -our @rate_png = ("ruby.png", "amber.png", "emerald.png"); -our $lcov_func_coverage = 1; -our $lcov_branch_coverage = 0; -our $rc_desc_html = 0; # lcovrc: genhtml_desc_html - -our $cwd = cwd(); # Current working directory - - -# -# Code entry point -# - -$SIG{__WARN__} = \&warn_handler; -$SIG{__DIE__} = \&die_handler; - -# Check command line for a configuration file name -Getopt::Long::Configure("pass_through", "no_auto_abbrev"); -GetOptions("config-file=s" => \$opt_config_file, - "rc=s%" => \%opt_rc); -Getopt::Long::Configure("default"); - -{ - # Remove spaces around rc options - my %new_opt_rc; - - while (my ($key, $value) = each(%opt_rc)) { - $key =~ s/^\s+|\s+$//g; - $value =~ s/^\s+|\s+$//g; - - $new_opt_rc{$key} = $value; - } - %opt_rc = %new_opt_rc; -} - -# Read configuration file if available -if (defined($opt_config_file)) { - $config = read_config($opt_config_file); -} elsif (defined($ENV{"HOME"}) && (-r $ENV{"HOME"}."/.lcovrc")) -{ - $config = read_config($ENV{"HOME"}."/.lcovrc"); -} -elsif (-r "/etc/lcovrc") -{ - $config = read_config("/etc/lcovrc"); -} elsif (-r "/usr/local/etc/lcovrc") -{ - $config = read_config("/usr/local/etc/lcovrc"); -} - -if ($config || %opt_rc) -{ - # Copy configuration file and --rc values to variables - apply_config({ - "genhtml_css_file" => \$css_filename, - "genhtml_hi_limit" => \$hi_limit, - "genhtml_med_limit" => \$med_limit, - "genhtml_line_field_width" => \$line_field_width, - "genhtml_overview_width" => \$overview_width, - "genhtml_nav_resolution" => \$nav_resolution, - "genhtml_nav_offset" => \$nav_offset, - "genhtml_keep_descriptions" => \$keep_descriptions, - "genhtml_no_prefix" => \$no_prefix, - "genhtml_no_source" => \$no_sourceview, - "genhtml_num_spaces" => \$tab_size, - "genhtml_highlight" => \$highlight, - "genhtml_legend" => \$legend, - "genhtml_html_prolog" => \$html_prolog_file, - "genhtml_html_epilog" => \$html_epilog_file, - "genhtml_html_extension" => \$html_ext, - "genhtml_html_gzip" => \$html_gzip, - "genhtml_precision" => \$default_precision, - "genhtml_function_hi_limit" => \$fn_hi_limit, - "genhtml_function_med_limit" => \$fn_med_limit, - "genhtml_function_coverage" => \$func_coverage, - "genhtml_branch_hi_limit" => \$br_hi_limit, - "genhtml_branch_med_limit" => \$br_med_limit, - "genhtml_branch_coverage" => \$br_coverage, - "genhtml_branch_field_width" => \$br_field_width, - "genhtml_sort" => \$sort, - "genhtml_charset" => \$charset, - "genhtml_desc_html" => \$rc_desc_html, - "genhtml_demangle_cpp" => \$demangle_cpp, - "genhtml_missed" => \$opt_missed, - "lcov_function_coverage" => \$lcov_func_coverage, - "lcov_branch_coverage" => \$lcov_branch_coverage, - }); -} - -# Copy related values if not specified -$fn_hi_limit = $hi_limit if (!defined($fn_hi_limit)); -$fn_med_limit = $med_limit if (!defined($fn_med_limit)); -$br_hi_limit = $hi_limit if (!defined($br_hi_limit)); -$br_med_limit = $med_limit if (!defined($br_med_limit)); -$func_coverage = $lcov_func_coverage if (!defined($func_coverage)); -$br_coverage = $lcov_branch_coverage if (!defined($br_coverage)); - -# Parse command line options -if (!GetOptions("output-directory|o=s" => \$output_directory, - "title|t=s" => \$test_title, - "description-file|d=s" => \$desc_filename, - "keep-descriptions|k" => \$keep_descriptions, - "css-file|c=s" => \$css_filename, - "baseline-file|b=s" => \$base_filename, - "prefix|p=s" => \@opt_dir_prefix, - "num-spaces=i" => \$tab_size, - "no-prefix" => \$no_prefix, - "no-sourceview" => \$no_sourceview, - "show-details|s" => \$show_details, - "frames|f" => \$frames, - "highlight" => \$highlight, - "legend" => \$legend, - "quiet|q" => \$quiet, - "help|h|?" => \$help, - "version|v" => \$version, - "html-prolog=s" => \$html_prolog_file, - "html-epilog=s" => \$html_epilog_file, - "html-extension=s" => \$html_ext, - "html-gzip" => \$html_gzip, - "function-coverage" => \$func_coverage, - "no-function-coverage" => \$no_func_coverage, - "branch-coverage" => \$br_coverage, - "no-branch-coverage" => \$no_br_coverage, - "sort" => \$sort, - "no-sort" => \$no_sort, - "demangle-cpp" => \$demangle_cpp, - "ignore-errors=s" => \@opt_ignore_errors, - "config-file=s" => \$opt_config_file, - "rc=s%" => \%opt_rc, - "precision=i" => \$default_precision, - "missed" => \$opt_missed, - )) -{ - print(STDERR "Use $tool_name --help to get usage information\n"); - exit(1); -} else { - # Merge options - if ($no_func_coverage) { - $func_coverage = 0; - } - if ($no_br_coverage) { - $br_coverage = 0; - } - - # Merge sort options - if ($no_sort) { - $sort = 0; - } -} - -@info_filenames = @ARGV; - -# Check for help option -if ($help) -{ - print_usage(*STDOUT); - exit(0); -} - -# Check for version option -if ($version) -{ - print("$tool_name: $lcov_version\n"); - exit(0); -} - -# Determine which errors the user wants us to ignore -parse_ignore_errors(@opt_ignore_errors); - -# Split the list of prefixes if needed -parse_dir_prefix(@opt_dir_prefix); - -# Check for info filename -if (!@info_filenames) -{ - die("No filename specified\n". - "Use $tool_name --help to get usage information\n"); -} - -# Generate a title if none is specified -if (!$test_title) -{ - if (scalar(@info_filenames) == 1) - { - # Only one filename specified, use it as title - $test_title = basename($info_filenames[0]); - } - else - { - # More than one filename specified, used default title - $test_title = "unnamed"; - } -} - -# Make sure css_filename is an absolute path (in case we're changing -# directories) -if ($css_filename) -{ - if (!($css_filename =~ /^\/(.*)$/)) - { - $css_filename = $cwd."/".$css_filename; - } -} - -# Make sure tab_size is within valid range -if ($tab_size < 1) -{ - print(STDERR "ERROR: invalid number of spaces specified: ". - "$tab_size!\n"); - exit(1); -} - -# Get HTML prolog and epilog -$html_prolog = get_html_prolog($html_prolog_file); -$html_epilog = get_html_epilog($html_epilog_file); - -# Issue a warning if --no-sourceview is enabled together with --frames -if ($no_sourceview && defined($frames)) -{ - warn("WARNING: option --frames disabled because --no-sourceview ". - "was specified!\n"); - $frames = undef; -} - -# Issue a warning if --no-prefix is enabled together with --prefix -if ($no_prefix && @dir_prefix) -{ - warn("WARNING: option --prefix disabled because --no-prefix was ". - "specified!\n"); - @dir_prefix = undef; -} - -@fileview_sortlist = ($SORT_FILE); -@funcview_sortlist = ($SORT_FILE); - -if ($sort) { - push(@fileview_sortlist, $SORT_LINE); - push(@fileview_sortlist, $SORT_FUNC) if ($func_coverage); - push(@fileview_sortlist, $SORT_BRANCH) if ($br_coverage); - push(@funcview_sortlist, $SORT_LINE); -} - -if ($frames) -{ - # Include genpng code needed for overview image generation - do("$tool_dir/genpng"); -} - -# Ensure that the c++filt tool is available when using --demangle-cpp -if ($demangle_cpp) -{ - if (system_no_output(3, "c++filt", "--version")) { - die("ERROR: could not find c++filt tool needed for ". - "--demangle-cpp\n"); - } -} - -# Make sure precision is within valid range -if ($default_precision < 1 || $default_precision > 4) -{ - die("ERROR: specified precision is out of range (1 to 4)\n"); -} - - -# Make sure output_directory exists, create it if necessary -if ($output_directory) -{ - stat($output_directory); - - if (! -e _) - { - create_sub_dir($output_directory); - } -} - -# Do something -gen_html(); - -exit(0); - - - -# -# print_usage(handle) -# -# Print usage information. -# - -sub print_usage(*) -{ - local *HANDLE = $_[0]; - - print(HANDLE <{$filename}; - my $funcdata = $data->{"func"}; - my $sumfnccount = $data->{"sumfnc"}; - - if (defined($funcdata)) { - foreach my $func_name (keys(%{$funcdata})) { - $fns{$func_name} = 1; - } - } - - if (defined($sumfnccount)) { - foreach my $func_name (keys(%{$sumfnccount})) { - $fns{$func_name} = 1; - } - } - } - - @result = keys(%fns); - - return \@result; -} - -# -# rename_functions(info, conv) -# -# Rename all function names in INFO according to CONV: OLD_NAME -> NEW_NAME. -# In case two functions demangle to the same name, assume that they are -# different object code implementations for the same source function. -# - -sub rename_functions($$) -{ - my ($info, $conv) = @_; - - foreach my $filename (keys(%{$info})) { - my $data = $info->{$filename}; - my $funcdata; - my $testfncdata; - my $sumfnccount; - my %newfuncdata; - my %newsumfnccount; - my $f_found; - my $f_hit; - - # funcdata: function name -> line number - $funcdata = $data->{"func"}; - foreach my $fn (keys(%{$funcdata})) { - my $cn = $conv->{$fn}; - - # Abort if two functions on different lines map to the - # same demangled name. - if (defined($newfuncdata{$cn}) && - $newfuncdata{$cn} != $funcdata->{$fn}) { - die("ERROR: Demangled function name $cn ". - "maps to different lines (". - $newfuncdata{$cn}." vs ". - $funcdata->{$fn}.") in $filename\n"); - } - $newfuncdata{$cn} = $funcdata->{$fn}; - } - $data->{"func"} = \%newfuncdata; - - # testfncdata: test name -> testfnccount - # testfnccount: function name -> execution count - $testfncdata = $data->{"testfnc"}; - foreach my $tn (keys(%{$testfncdata})) { - my $testfnccount = $testfncdata->{$tn}; - my %newtestfnccount; - - foreach my $fn (keys(%{$testfnccount})) { - my $cn = $conv->{$fn}; - - # Add counts for different functions that map - # to the same name. - $newtestfnccount{$cn} += - $testfnccount->{$fn}; - } - $testfncdata->{$tn} = \%newtestfnccount; - } - - # sumfnccount: function name -> execution count - $sumfnccount = $data->{"sumfnc"}; - foreach my $fn (keys(%{$sumfnccount})) { - my $cn = $conv->{$fn}; - - # Add counts for different functions that map - # to the same name. - $newsumfnccount{$cn} += $sumfnccount->{$fn}; - } - $data->{"sumfnc"} = \%newsumfnccount; - - # Update function found and hit counts since they may have - # changed - $f_found = 0; - $f_hit = 0; - foreach my $fn (keys(%newsumfnccount)) { - $f_found++; - $f_hit++ if ($newsumfnccount{$fn} > 0); - } - $data->{"f_found"} = $f_found; - $data->{"f_hit"} = $f_hit; - } -} - -# -# gen_html() -# -# Generate a set of HTML pages from contents of .info file INFO_FILENAME. -# Files will be written to the current directory. If provided, test case -# descriptions will be read from .tests file TEST_FILENAME and included -# in ouput. -# -# Die on error. -# - -sub gen_html() -{ - local *HTML_HANDLE; - my %overview; - my %base_data; - my $lines_found; - my $lines_hit; - my $fn_found; - my $fn_hit; - my $br_found; - my $br_hit; - my $overall_found = 0; - my $overall_hit = 0; - my $total_fn_found = 0; - my $total_fn_hit = 0; - my $total_br_found = 0; - my $total_br_hit = 0; - my $dir_name; - my $link_name; - my @dir_list; - my %new_info; - - # Read in all specified .info files - foreach (@info_filenames) - { - %new_info = %{read_info_file($_)}; - - # Combine %new_info with %info_data - %info_data = %{combine_info_files(\%info_data, \%new_info)}; - } - - info("Found %d entries.\n", scalar(keys(%info_data))); - - # Read and apply baseline data if specified - if ($base_filename) - { - # Read baseline file - info("Reading baseline file $base_filename\n"); - %base_data = %{read_info_file($base_filename)}; - info("Found %d entries.\n", scalar(keys(%base_data))); - - # Apply baseline - info("Subtracting baseline data.\n"); - %info_data = %{apply_baseline(\%info_data, \%base_data)}; - } - - @dir_list = get_dir_list(keys(%info_data)); - - if ($no_prefix) - { - # User requested that we leave filenames alone - info("User asked not to remove filename prefix\n"); - } - elsif (! @dir_prefix) - { - # Get prefix common to most directories in list - my $prefix = get_prefix(1, keys(%info_data)); - - if ($prefix) - { - info("Found common filename prefix \"$prefix\"\n"); - $dir_prefix[0] = $prefix; - - } - else - { - info("No common filename prefix found!\n"); - $no_prefix=1; - } - } - else - { - my $msg = "Using user-specified filename prefix "; - for my $i (0 .. $#dir_prefix) - { - $dir_prefix[$i] =~ s/\/+$//; - $msg .= ", " unless 0 == $i; - $msg .= "\"" . $dir_prefix[$i] . "\""; - } - info($msg . "\n"); - } - - - # Read in test description file if specified - if ($desc_filename) - { - info("Reading test description file $desc_filename\n"); - %test_description = %{read_testfile($desc_filename)}; - - # Remove test descriptions which are not referenced - # from %info_data if user didn't tell us otherwise - if (!$keep_descriptions) - { - remove_unused_descriptions(); - } - } - - # Change to output directory if specified - if ($output_directory) - { - chdir($output_directory) - or die("ERROR: cannot change to directory ". - "$output_directory!\n"); - } - - info("Writing .css and .png files.\n"); - write_css_file(); - write_png_files(); - - if ($html_gzip) - { - info("Writing .htaccess file.\n"); - write_htaccess_file(); - } - - info("Generating output.\n"); - - # Process each subdirectory and collect overview information - foreach $dir_name (@dir_list) - { - ($lines_found, $lines_hit, $fn_found, $fn_hit, - $br_found, $br_hit) - = process_dir($dir_name); - - # Handle files in root directory gracefully - $dir_name = "root" if ($dir_name eq ""); - - # Remove prefix if applicable - if (!$no_prefix && @dir_prefix) - { - # Match directory names beginning with one of @dir_prefix - $dir_name = apply_prefix($dir_name,@dir_prefix); - } - - # Generate name for directory overview HTML page - if ($dir_name =~ /^\/(.*)$/) - { - $link_name = substr($dir_name, 1)."/index.$html_ext"; - } - else - { - $link_name = $dir_name."/index.$html_ext"; - } - - $overview{$dir_name} = [$lines_found, $lines_hit, $fn_found, - $fn_hit, $br_found, $br_hit, $link_name, - get_rate($lines_found, $lines_hit), - get_rate($fn_found, $fn_hit), - get_rate($br_found, $br_hit)]; - $overall_found += $lines_found; - $overall_hit += $lines_hit; - $total_fn_found += $fn_found; - $total_fn_hit += $fn_hit; - $total_br_found += $br_found; - $total_br_hit += $br_hit; - } - - # Generate overview page - info("Writing directory view page.\n"); - - # Create sorted pages - foreach (@fileview_sortlist) { - write_dir_page($fileview_sortname[$_], ".", "", $test_title, - undef, $overall_found, $overall_hit, - $total_fn_found, $total_fn_hit, $total_br_found, - $total_br_hit, \%overview, {}, {}, {}, 0, $_); - } - - # Check if there are any test case descriptions to write out - if (%test_description) - { - info("Writing test case description file.\n"); - write_description_file( \%test_description, - $overall_found, $overall_hit, - $total_fn_found, $total_fn_hit, - $total_br_found, $total_br_hit); - } - - print_overall_rate(1, $overall_found, $overall_hit, - $func_coverage, $total_fn_found, $total_fn_hit, - $br_coverage, $total_br_found, $total_br_hit); - - chdir($cwd); -} - -# -# html_create(handle, filename) -# - -sub html_create($$) -{ - my $handle = $_[0]; - my $filename = $_[1]; - - if ($html_gzip) - { - open($handle, "|-", "gzip -c >'$filename'") - or die("ERROR: cannot open $filename for writing ". - "(gzip)!\n"); - } - else - { - open($handle, ">", $filename) - or die("ERROR: cannot open $filename for writing!\n"); - } -} - -sub write_dir_page($$$$$$$$$$$$$$$$$) -{ - my ($name, $rel_dir, $base_dir, $title, $trunc_dir, $overall_found, - $overall_hit, $total_fn_found, $total_fn_hit, $total_br_found, - $total_br_hit, $overview, $testhash, $testfnchash, $testbrhash, - $view_type, $sort_type) = @_; - - # Generate directory overview page including details - html_create(*HTML_HANDLE, "$rel_dir/index$name.$html_ext"); - if (!defined($trunc_dir)) { - $trunc_dir = ""; - } - $title .= " - " if ($trunc_dir ne ""); - write_html_prolog(*HTML_HANDLE, $base_dir, "LCOV - $title$trunc_dir"); - write_header(*HTML_HANDLE, $view_type, $trunc_dir, $rel_dir, - $overall_found, $overall_hit, $total_fn_found, - $total_fn_hit, $total_br_found, $total_br_hit, $sort_type); - write_file_table(*HTML_HANDLE, $base_dir, $overview, $testhash, - $testfnchash, $testbrhash, $view_type, $sort_type); - write_html_epilog(*HTML_HANDLE, $base_dir); - close(*HTML_HANDLE); -} - - -# -# process_dir(dir_name) -# - -sub process_dir($) -{ - my $abs_dir = $_[0]; - my $trunc_dir; - my $rel_dir = $abs_dir; - my $base_dir; - my $filename; - my %overview; - my $lines_found; - my $lines_hit; - my $fn_found; - my $fn_hit; - my $br_found; - my $br_hit; - my $overall_found=0; - my $overall_hit=0; - my $total_fn_found=0; - my $total_fn_hit=0; - my $total_br_found = 0; - my $total_br_hit = 0; - my $base_name; - my $extension; - my $testdata; - my %testhash; - my $testfncdata; - my %testfnchash; - my $testbrdata; - my %testbrhash; - my @sort_list; - local *HTML_HANDLE; - - # Remove prefix if applicable - if (!$no_prefix) - { - # Match directory name beginning with one of @dir_prefix - $rel_dir = apply_prefix($rel_dir,@dir_prefix); - } - - $trunc_dir = $rel_dir; - - # Remove leading / - if ($rel_dir =~ /^\/(.*)$/) - { - $rel_dir = substr($rel_dir, 1); - } - - # Handle files in root directory gracefully - $rel_dir = "root" if ($rel_dir eq ""); - $trunc_dir = "root" if ($trunc_dir eq ""); - - $base_dir = get_relative_base_path($rel_dir); - - create_sub_dir($rel_dir); - - # Match filenames which specify files in this directory, not including - # sub-directories - foreach $filename (grep(/^\Q$abs_dir\E\/[^\/]*$/,keys(%info_data))) - { - my $page_link; - my $func_link; - - ($lines_found, $lines_hit, $fn_found, $fn_hit, $br_found, - $br_hit, $testdata, $testfncdata, $testbrdata) = - process_file($trunc_dir, $rel_dir, $filename); - - $base_name = basename($filename); - - if ($no_sourceview) { - $page_link = ""; - } elsif ($frames) { - # Link to frameset page - $page_link = "$base_name.gcov.frameset.$html_ext"; - } else { - # Link directory to source code view page - $page_link = "$base_name.gcov.$html_ext"; - } - $overview{$base_name} = [$lines_found, $lines_hit, $fn_found, - $fn_hit, $br_found, $br_hit, - $page_link, - get_rate($lines_found, $lines_hit), - get_rate($fn_found, $fn_hit), - get_rate($br_found, $br_hit)]; - - $testhash{$base_name} = $testdata; - $testfnchash{$base_name} = $testfncdata; - $testbrhash{$base_name} = $testbrdata; - - $overall_found += $lines_found; - $overall_hit += $lines_hit; - - $total_fn_found += $fn_found; - $total_fn_hit += $fn_hit; - - $total_br_found += $br_found; - $total_br_hit += $br_hit; - } - - # Create sorted pages - foreach (@fileview_sortlist) { - # Generate directory overview page (without details) - write_dir_page($fileview_sortname[$_], $rel_dir, $base_dir, - $test_title, $trunc_dir, $overall_found, - $overall_hit, $total_fn_found, $total_fn_hit, - $total_br_found, $total_br_hit, \%overview, {}, - {}, {}, 1, $_); - if (!$show_details) { - next; - } - # Generate directory overview page including details - write_dir_page("-detail".$fileview_sortname[$_], $rel_dir, - $base_dir, $test_title, $trunc_dir, - $overall_found, $overall_hit, $total_fn_found, - $total_fn_hit, $total_br_found, $total_br_hit, - \%overview, \%testhash, \%testfnchash, - \%testbrhash, 1, $_); - } - - # Calculate resulting line counts - return ($overall_found, $overall_hit, $total_fn_found, $total_fn_hit, - $total_br_found, $total_br_hit); -} - - -# -# get_converted_lines(testdata) -# -# Return hash of line numbers of those lines which were only covered in -# converted data sets. -# - -sub get_converted_lines($) -{ - my $testdata = $_[0]; - my $testcount; - my %converted; - my %nonconverted; - my $hash; - my $testcase; - my $line; - my %result; - - - # Get a hash containing line numbers with positive counts both for - # converted and original data sets - foreach $testcase (keys(%{$testdata})) - { - # Check to see if this is a converted data set - if ($testcase =~ /,diff$/) - { - $hash = \%converted; - } - else - { - $hash = \%nonconverted; - } - - $testcount = $testdata->{$testcase}; - # Add lines with a positive count to hash - foreach $line (keys%{$testcount}) - { - if ($testcount->{$line} > 0) - { - $hash->{$line} = 1; - } - } - } - - # Combine both hashes to resulting list - foreach $line (keys(%converted)) - { - if (!defined($nonconverted{$line})) - { - $result{$line} = 1; - } - } - - return \%result; -} - - -sub write_function_page($$$$$$$$$$$$$$$$$$) -{ - my ($base_dir, $rel_dir, $trunc_dir, $base_name, $title, - $lines_found, $lines_hit, $fn_found, $fn_hit, $br_found, $br_hit, - $sumcount, $funcdata, $sumfnccount, $testfncdata, $sumbrcount, - $testbrdata, $sort_type) = @_; - my $pagetitle; - my $filename; - - # Generate function table for this file - if ($sort_type == 0) { - $filename = "$rel_dir/$base_name.func.$html_ext"; - } else { - $filename = "$rel_dir/$base_name.func-sort-c.$html_ext"; - } - html_create(*HTML_HANDLE, $filename); - $pagetitle = "LCOV - $title - $trunc_dir/$base_name - functions"; - write_html_prolog(*HTML_HANDLE, $base_dir, $pagetitle); - write_header(*HTML_HANDLE, 4, "$trunc_dir/$base_name", - "$rel_dir/$base_name", $lines_found, $lines_hit, - $fn_found, $fn_hit, $br_found, $br_hit, $sort_type); - write_function_table(*HTML_HANDLE, "$base_name.gcov.$html_ext", - $sumcount, $funcdata, - $sumfnccount, $testfncdata, $sumbrcount, - $testbrdata, $base_name, - $base_dir, $sort_type); - write_html_epilog(*HTML_HANDLE, $base_dir, 1); - close(*HTML_HANDLE); -} - - -# -# process_file(trunc_dir, rel_dir, filename) -# - -sub process_file($$$) -{ - info("Processing file ".apply_prefix($_[2], @dir_prefix)."\n"); - - my $trunc_dir = $_[0]; - my $rel_dir = $_[1]; - my $filename = $_[2]; - my $base_name = basename($filename); - my $base_dir = get_relative_base_path($rel_dir); - my $testdata; - my $testcount; - my $sumcount; - my $funcdata; - my $checkdata; - my $testfncdata; - my $sumfnccount; - my $testbrdata; - my $sumbrcount; - my $lines_found; - my $lines_hit; - my $fn_found; - my $fn_hit; - my $br_found; - my $br_hit; - my $converted; - my @source; - my $pagetitle; - local *HTML_HANDLE; - - ($testdata, $sumcount, $funcdata, $checkdata, $testfncdata, - $sumfnccount, $testbrdata, $sumbrcount, $lines_found, $lines_hit, - $fn_found, $fn_hit, $br_found, $br_hit) - = get_info_entry($info_data{$filename}); - - # Return after this point in case user asked us not to generate - # source code view - if ($no_sourceview) - { - return ($lines_found, $lines_hit, $fn_found, $fn_hit, - $br_found, $br_hit, $testdata, $testfncdata, - $testbrdata); - } - - $converted = get_converted_lines($testdata); - # Generate source code view for this file - html_create(*HTML_HANDLE, "$rel_dir/$base_name.gcov.$html_ext"); - $pagetitle = "LCOV - $test_title - $trunc_dir/$base_name"; - write_html_prolog(*HTML_HANDLE, $base_dir, $pagetitle); - write_header(*HTML_HANDLE, 2, "$trunc_dir/$base_name", - "$rel_dir/$base_name", $lines_found, $lines_hit, - $fn_found, $fn_hit, $br_found, $br_hit, 0); - @source = write_source(*HTML_HANDLE, $filename, $sumcount, $checkdata, - $converted, $funcdata, $sumbrcount); - - write_html_epilog(*HTML_HANDLE, $base_dir, 1); - close(*HTML_HANDLE); - - if ($func_coverage) { - # Create function tables - foreach (@funcview_sortlist) { - write_function_page($base_dir, $rel_dir, $trunc_dir, - $base_name, $test_title, - $lines_found, $lines_hit, - $fn_found, $fn_hit, $br_found, - $br_hit, $sumcount, - $funcdata, $sumfnccount, - $testfncdata, $sumbrcount, - $testbrdata, $_); - } - } - - # Additional files are needed in case of frame output - if (!$frames) - { - return ($lines_found, $lines_hit, $fn_found, $fn_hit, - $br_found, $br_hit, $testdata, $testfncdata, - $testbrdata); - } - - # Create overview png file - gen_png("$rel_dir/$base_name.gcov.png", $overview_width, $tab_size, - @source); - - # Create frameset page - html_create(*HTML_HANDLE, - "$rel_dir/$base_name.gcov.frameset.$html_ext"); - write_frameset(*HTML_HANDLE, $base_dir, $base_name, $pagetitle); - close(*HTML_HANDLE); - - # Write overview frame - html_create(*HTML_HANDLE, - "$rel_dir/$base_name.gcov.overview.$html_ext"); - write_overview(*HTML_HANDLE, $base_dir, $base_name, $pagetitle, - scalar(@source)); - close(*HTML_HANDLE); - - return ($lines_found, $lines_hit, $fn_found, $fn_hit, $br_found, - $br_hit, $testdata, $testfncdata, $testbrdata); -} - - -sub compress_brcount($) -{ - my ($brcount) = @_; - my $db; - - $db = brcount_to_db($brcount); - return db_to_brcount($db, $brcount); -} - - -# -# read_info_file(info_filename) -# -# Read in the contents of the .info file specified by INFO_FILENAME. Data will -# be returned as a reference to a hash containing the following mappings: -# -# %result: for each filename found in file -> \%data -# -# %data: "test" -> \%testdata -# "sum" -> \%sumcount -# "func" -> \%funcdata -# "found" -> $lines_found (number of instrumented lines found in file) -# "hit" -> $lines_hit (number of executed lines in file) -# "f_found" -> $fn_found (number of instrumented functions found in file) -# "f_hit" -> $fn_hit (number of executed functions in file) -# "b_found" -> $br_found (number of instrumented branches found in file) -# "b_hit" -> $br_hit (number of executed branches in file) -# "check" -> \%checkdata -# "testfnc" -> \%testfncdata -# "sumfnc" -> \%sumfnccount -# "testbr" -> \%testbrdata -# "sumbr" -> \%sumbrcount -# -# %testdata : name of test affecting this file -> \%testcount -# %testfncdata: name of test affecting this file -> \%testfnccount -# %testbrdata: name of test affecting this file -> \%testbrcount -# -# %testcount : line number -> execution count for a single test -# %testfnccount: function name -> execution count for a single test -# %testbrcount : line number -> branch coverage data for a single test -# %sumcount : line number -> execution count for all tests -# %sumfnccount : function name -> execution count for all tests -# %sumbrcount : line number -> branch coverage data for all tests -# %funcdata : function name -> line number -# %checkdata : line number -> checksum of source code line -# $brdata : vector of items: block, branch, taken -# -# Note that .info file sections referring to the same file and test name -# will automatically be combined by adding all execution counts. -# -# Note that if INFO_FILENAME ends with ".gz", it is assumed that the file -# is compressed using GZIP. If available, GUNZIP will be used to decompress -# this file. -# -# Die on error. -# - -sub read_info_file($) -{ - my $tracefile = $_[0]; # Name of tracefile - my %result; # Resulting hash: file -> data - my $data; # Data handle for current entry - my $testdata; # " " - my $testcount; # " " - my $sumcount; # " " - my $funcdata; # " " - my $checkdata; # " " - my $testfncdata; - my $testfnccount; - my $sumfnccount; - my $testbrdata; - my $testbrcount; - my $sumbrcount; - my $line; # Current line read from .info file - my $testname; # Current test name - my $filename; # Current filename - my $hitcount; # Count for lines hit - my $count; # Execution count of current line - my $negative; # If set, warn about negative counts - my $changed_testname; # If set, warn about changed testname - my $line_checksum; # Checksum of current line - my $notified_about_relative_paths; - local *INFO_HANDLE; # Filehandle for .info file - - info("Reading data file $tracefile\n"); - - # Check if file exists and is readable - stat($_[0]); - if (!(-r _)) - { - die("ERROR: cannot read file $_[0]!\n"); - } - - # Check if this is really a plain file - if (!(-f _)) - { - die("ERROR: not a plain file: $_[0]!\n"); - } - - # Check for .gz extension - if ($_[0] =~ /\.gz$/) - { - # Check for availability of GZIP tool - system_no_output(1, "gunzip" ,"-h") - and die("ERROR: gunzip command not available!\n"); - - # Check integrity of compressed file - system_no_output(1, "gunzip", "-t", $_[0]) - and die("ERROR: integrity check failed for ". - "compressed file $_[0]!\n"); - - # Open compressed file - open(INFO_HANDLE, "-|", "gunzip -c '$_[0]'") - or die("ERROR: cannot start gunzip to decompress ". - "file $_[0]!\n"); - } - else - { - # Open decompressed file - open(INFO_HANDLE, "<", $_[0]) - or die("ERROR: cannot read file $_[0]!\n"); - } - - $testname = ""; - while () - { - chomp($_); - $line = $_; - - # Switch statement - foreach ($line) - { - /^TN:([^,]*)(,diff)?/ && do - { - # Test name information found - $testname = defined($1) ? $1 : ""; - if ($testname =~ s/\W/_/g) - { - $changed_testname = 1; - } - $testname .= $2 if (defined($2)); - last; - }; - - /^[SK]F:(.*)/ && do - { - # Filename information found - # Retrieve data for new entry - $filename = File::Spec->rel2abs($1, $cwd); - - if (!File::Spec->file_name_is_absolute($1) && - !$notified_about_relative_paths) - { - info("Resolved relative source file ". - "path \"$1\" with CWD to ". - "\"$filename\".\n"); - $notified_about_relative_paths = 1; - } - - $data = $result{$filename}; - ($testdata, $sumcount, $funcdata, $checkdata, - $testfncdata, $sumfnccount, $testbrdata, - $sumbrcount) = - get_info_entry($data); - - if (defined($testname)) - { - $testcount = $testdata->{$testname}; - $testfnccount = $testfncdata->{$testname}; - $testbrcount = $testbrdata->{$testname}; - } - else - { - $testcount = {}; - $testfnccount = {}; - $testbrcount = {}; - } - last; - }; - - /^DA:(\d+),(-?\d+)(,[^,\s]+)?/ && do - { - # Fix negative counts - $count = $2 < 0 ? 0 : $2; - if ($2 < 0) - { - $negative = 1; - } - # Execution count found, add to structure - # Add summary counts - $sumcount->{$1} += $count; - - # Add test-specific counts - if (defined($testname)) - { - $testcount->{$1} += $count; - } - - # Store line checksum if available - if (defined($3)) - { - $line_checksum = substr($3, 1); - - # Does it match a previous definition - if (defined($checkdata->{$1}) && - ($checkdata->{$1} ne - $line_checksum)) - { - die("ERROR: checksum mismatch ". - "at $filename:$1\n"); - } - - $checkdata->{$1} = $line_checksum; - } - last; - }; - - /^FN:(\d+),([^,]+)/ && do - { - last if (!$func_coverage); - - # Function data found, add to structure - $funcdata->{$2} = $1; - - # Also initialize function call data - if (!defined($sumfnccount->{$2})) { - $sumfnccount->{$2} = 0; - } - if (defined($testname)) - { - if (!defined($testfnccount->{$2})) { - $testfnccount->{$2} = 0; - } - } - last; - }; - - /^FNDA:(\d+),([^,]+)/ && do - { - last if (!$func_coverage); - # Function call count found, add to structure - # Add summary counts - $sumfnccount->{$2} += $1; - - # Add test-specific counts - if (defined($testname)) - { - $testfnccount->{$2} += $1; - } - last; - }; - - /^BRDA:(\d+),(\d+),(\d+),(\d+|-)/ && do { - # Branch coverage data found - my ($line, $block, $branch, $taken) = - ($1, $2, $3, $4); - - last if (!$br_coverage); - $block = -1 if ($block == $UNNAMED_BLOCK); - $sumbrcount->{$line} .= - "$block,$branch,$taken:"; - - # Add test-specific counts - if (defined($testname)) { - $testbrcount->{$line} .= - "$block,$branch,$taken:"; - } - last; - }; - - /^end_of_record/ && do - { - # Found end of section marker - if ($filename) - { - # Store current section data - if (defined($testname)) - { - $testdata->{$testname} = - $testcount; - $testfncdata->{$testname} = - $testfnccount; - $testbrdata->{$testname} = - $testbrcount; - } - - set_info_entry($data, $testdata, - $sumcount, $funcdata, - $checkdata, $testfncdata, - $sumfnccount, - $testbrdata, - $sumbrcount); - $result{$filename} = $data; - last; - } - }; - - # default - last; - } - } - close(INFO_HANDLE); - - # Calculate lines_found and lines_hit for each file - foreach $filename (keys(%result)) - { - $data = $result{$filename}; - - ($testdata, $sumcount, undef, undef, $testfncdata, - $sumfnccount, $testbrdata, $sumbrcount) = - get_info_entry($data); - - # Filter out empty files - if (scalar(keys(%{$sumcount})) == 0) - { - delete($result{$filename}); - next; - } - # Filter out empty test cases - foreach $testname (keys(%{$testdata})) - { - if (!defined($testdata->{$testname}) || - scalar(keys(%{$testdata->{$testname}})) == 0) - { - delete($testdata->{$testname}); - delete($testfncdata->{$testname}); - } - } - - $data->{"found"} = scalar(keys(%{$sumcount})); - $hitcount = 0; - - foreach (keys(%{$sumcount})) - { - if ($sumcount->{$_} > 0) { $hitcount++; } - } - - $data->{"hit"} = $hitcount; - - # Get found/hit values for function call data - $data->{"f_found"} = scalar(keys(%{$sumfnccount})); - $hitcount = 0; - - foreach (keys(%{$sumfnccount})) { - if ($sumfnccount->{$_} > 0) { - $hitcount++; - } - } - $data->{"f_hit"} = $hitcount; - - # Combine branch data for the same branches - (undef, $data->{"b_found"}, $data->{"b_hit"}) = - compress_brcount($sumbrcount); - foreach $testname (keys(%{$testbrdata})) { - compress_brcount($testbrdata->{$testname}); - } - } - - if (scalar(keys(%result)) == 0) - { - die("ERROR: no valid records found in tracefile $tracefile\n"); - } - if ($negative) - { - warn("WARNING: negative counts found in tracefile ". - "$tracefile\n"); - } - if ($changed_testname) - { - warn("WARNING: invalid characters removed from testname in ". - "tracefile $tracefile\n"); - } - - return(\%result); -} - - -# -# get_info_entry(hash_ref) -# -# Retrieve data from an entry of the structure generated by read_info_file(). -# Return a list of references to hashes: -# (test data hash ref, sum count hash ref, funcdata hash ref, checkdata hash -# ref, testfncdata hash ref, sumfnccount hash ref, lines found, lines hit, -# functions found, functions hit) -# - -sub get_info_entry($) -{ - my $testdata_ref = $_[0]->{"test"}; - my $sumcount_ref = $_[0]->{"sum"}; - my $funcdata_ref = $_[0]->{"func"}; - my $checkdata_ref = $_[0]->{"check"}; - my $testfncdata = $_[0]->{"testfnc"}; - my $sumfnccount = $_[0]->{"sumfnc"}; - my $testbrdata = $_[0]->{"testbr"}; - my $sumbrcount = $_[0]->{"sumbr"}; - my $lines_found = $_[0]->{"found"}; - my $lines_hit = $_[0]->{"hit"}; - my $fn_found = $_[0]->{"f_found"}; - my $fn_hit = $_[0]->{"f_hit"}; - my $br_found = $_[0]->{"b_found"}; - my $br_hit = $_[0]->{"b_hit"}; - - return ($testdata_ref, $sumcount_ref, $funcdata_ref, $checkdata_ref, - $testfncdata, $sumfnccount, $testbrdata, $sumbrcount, - $lines_found, $lines_hit, $fn_found, $fn_hit, - $br_found, $br_hit); -} - - -# -# set_info_entry(hash_ref, testdata_ref, sumcount_ref, funcdata_ref, -# checkdata_ref, testfncdata_ref, sumfcncount_ref, -# testbrdata_ref, sumbrcount_ref[,lines_found, -# lines_hit, f_found, f_hit, $b_found, $b_hit]) -# -# Update the hash referenced by HASH_REF with the provided data references. -# - -sub set_info_entry($$$$$$$$$;$$$$$$) -{ - my $data_ref = $_[0]; - - $data_ref->{"test"} = $_[1]; - $data_ref->{"sum"} = $_[2]; - $data_ref->{"func"} = $_[3]; - $data_ref->{"check"} = $_[4]; - $data_ref->{"testfnc"} = $_[5]; - $data_ref->{"sumfnc"} = $_[6]; - $data_ref->{"testbr"} = $_[7]; - $data_ref->{"sumbr"} = $_[8]; - - if (defined($_[9])) { $data_ref->{"found"} = $_[9]; } - if (defined($_[10])) { $data_ref->{"hit"} = $_[10]; } - if (defined($_[11])) { $data_ref->{"f_found"} = $_[11]; } - if (defined($_[12])) { $data_ref->{"f_hit"} = $_[12]; } - if (defined($_[13])) { $data_ref->{"b_found"} = $_[13]; } - if (defined($_[14])) { $data_ref->{"b_hit"} = $_[14]; } -} - - -# -# add_counts(data1_ref, data2_ref) -# -# DATA1_REF and DATA2_REF are references to hashes containing a mapping -# -# line number -> execution count -# -# Return a list (RESULT_REF, LINES_FOUND, LINES_HIT) where RESULT_REF -# is a reference to a hash containing the combined mapping in which -# execution counts are added. -# - -sub add_counts($$) -{ - my $data1_ref = $_[0]; # Hash 1 - my $data2_ref = $_[1]; # Hash 2 - my %result; # Resulting hash - my $line; # Current line iteration scalar - my $data1_count; # Count of line in hash1 - my $data2_count; # Count of line in hash2 - my $found = 0; # Total number of lines found - my $hit = 0; # Number of lines with a count > 0 - - foreach $line (keys(%$data1_ref)) - { - $data1_count = $data1_ref->{$line}; - $data2_count = $data2_ref->{$line}; - - # Add counts if present in both hashes - if (defined($data2_count)) { $data1_count += $data2_count; } - - # Store sum in %result - $result{$line} = $data1_count; - - $found++; - if ($data1_count > 0) { $hit++; } - } - - # Add lines unique to data2_ref - foreach $line (keys(%$data2_ref)) - { - # Skip lines already in data1_ref - if (defined($data1_ref->{$line})) { next; } - - # Copy count from data2_ref - $result{$line} = $data2_ref->{$line}; - - $found++; - if ($result{$line} > 0) { $hit++; } - } - - return (\%result, $found, $hit); -} - - -# -# merge_checksums(ref1, ref2, filename) -# -# REF1 and REF2 are references to hashes containing a mapping -# -# line number -> checksum -# -# Merge checksum lists defined in REF1 and REF2 and return reference to -# resulting hash. Die if a checksum for a line is defined in both hashes -# but does not match. -# - -sub merge_checksums($$$) -{ - my $ref1 = $_[0]; - my $ref2 = $_[1]; - my $filename = $_[2]; - my %result; - my $line; - - foreach $line (keys(%{$ref1})) - { - if (defined($ref2->{$line}) && - ($ref1->{$line} ne $ref2->{$line})) - { - die("ERROR: checksum mismatch at $filename:$line\n"); - } - $result{$line} = $ref1->{$line}; - } - - foreach $line (keys(%{$ref2})) - { - $result{$line} = $ref2->{$line}; - } - - return \%result; -} - - -# -# merge_func_data(funcdata1, funcdata2, filename) -# - -sub merge_func_data($$$) -{ - my ($funcdata1, $funcdata2, $filename) = @_; - my %result; - my $func; - - if (defined($funcdata1)) { - %result = %{$funcdata1}; - } - - foreach $func (keys(%{$funcdata2})) { - my $line1 = $result{$func}; - my $line2 = $funcdata2->{$func}; - - if (defined($line1) && ($line1 != $line2)) { - warn("WARNING: function data mismatch at ". - "$filename:$line2\n"); - next; - } - $result{$func} = $line2; - } - - return \%result; -} - - -# -# add_fnccount(fnccount1, fnccount2) -# -# Add function call count data. Return list (fnccount_added, f_found, f_hit) -# - -sub add_fnccount($$) -{ - my ($fnccount1, $fnccount2) = @_; - my %result; - my $fn_found; - my $fn_hit; - my $function; - - if (defined($fnccount1)) { - %result = %{$fnccount1}; - } - foreach $function (keys(%{$fnccount2})) { - $result{$function} += $fnccount2->{$function}; - } - $fn_found = scalar(keys(%result)); - $fn_hit = 0; - foreach $function (keys(%result)) { - if ($result{$function} > 0) { - $fn_hit++; - } - } - - return (\%result, $fn_found, $fn_hit); -} - -# -# add_testfncdata(testfncdata1, testfncdata2) -# -# Add function call count data for several tests. Return reference to -# added_testfncdata. -# - -sub add_testfncdata($$) -{ - my ($testfncdata1, $testfncdata2) = @_; - my %result; - my $testname; - - foreach $testname (keys(%{$testfncdata1})) { - if (defined($testfncdata2->{$testname})) { - my $fnccount; - - # Function call count data for this testname exists - # in both data sets: add - ($fnccount) = add_fnccount( - $testfncdata1->{$testname}, - $testfncdata2->{$testname}); - $result{$testname} = $fnccount; - next; - } - # Function call count data for this testname is unique to - # data set 1: copy - $result{$testname} = $testfncdata1->{$testname}; - } - - # Add count data for testnames unique to data set 2 - foreach $testname (keys(%{$testfncdata2})) { - if (!defined($result{$testname})) { - $result{$testname} = $testfncdata2->{$testname}; - } - } - return \%result; -} - - -# -# brcount_to_db(brcount) -# -# Convert brcount data to the following format: -# -# db: line number -> block hash -# block hash: block number -> branch hash -# branch hash: branch number -> taken value -# - -sub brcount_to_db($) -{ - my ($brcount) = @_; - my $line; - my $db; - - # Add branches to database - foreach $line (keys(%{$brcount})) { - my $brdata = $brcount->{$line}; - - foreach my $entry (split(/:/, $brdata)) { - my ($block, $branch, $taken) = split(/,/, $entry); - my $old = $db->{$line}->{$block}->{$branch}; - - if (!defined($old) || $old eq "-") { - $old = $taken; - } elsif ($taken ne "-") { - $old += $taken; - } - - $db->{$line}->{$block}->{$branch} = $old; - } - } - - return $db; -} - - -# -# db_to_brcount(db[, brcount]) -# -# Convert branch coverage data back to brcount format. If brcount is specified, -# the converted data is directly inserted in brcount. -# - -sub db_to_brcount($;$) -{ - my ($db, $brcount) = @_; - my $line; - my $br_found = 0; - my $br_hit = 0; - - # Convert database back to brcount format - foreach $line (sort({$a <=> $b} keys(%{$db}))) { - my $ldata = $db->{$line}; - my $brdata; - my $block; - - foreach $block (sort({$a <=> $b} keys(%{$ldata}))) { - my $bdata = $ldata->{$block}; - my $branch; - - foreach $branch (sort({$a <=> $b} keys(%{$bdata}))) { - my $taken = $bdata->{$branch}; - - $br_found++; - $br_hit++ if ($taken ne "-" && $taken > 0); - $brdata .= "$block,$branch,$taken:"; - } - } - $brcount->{$line} = $brdata; - } - - return ($brcount, $br_found, $br_hit); -} - - -# -# brcount_db_combine(db1, db2, op) -# -# db1 := db1 op db2, where -# db1, db2: brcount data as returned by brcount_to_db -# op: one of $BR_ADD and BR_SUB -# -sub brcount_db_combine($$$) -{ - my ($db1, $db2, $op) = @_; - - foreach my $line (keys(%{$db2})) { - my $ldata = $db2->{$line}; - - foreach my $block (keys(%{$ldata})) { - my $bdata = $ldata->{$block}; - - foreach my $branch (keys(%{$bdata})) { - my $taken = $bdata->{$branch}; - my $new = $db1->{$line}->{$block}->{$branch}; - - if (!defined($new) || $new eq "-") { - $new = $taken; - } elsif ($taken ne "-") { - if ($op == $BR_ADD) { - $new += $taken; - } elsif ($op == $BR_SUB) { - $new -= $taken; - $new = 0 if ($new < 0); - } - } - - $db1->{$line}->{$block}->{$branch} = $new; - } - } - } -} - - -# -# brcount_db_get_found_and_hit(db) -# -# Return (br_found, br_hit) for db. -# - -sub brcount_db_get_found_and_hit($) -{ - my ($db) = @_; - my ($br_found , $br_hit) = (0, 0); - - foreach my $line (keys(%{$db})) { - my $ldata = $db->{$line}; - - foreach my $block (keys(%{$ldata})) { - my $bdata = $ldata->{$block}; - - foreach my $branch (keys(%{$bdata})) { - my $taken = $bdata->{$branch}; - - $br_found++; - $br_hit++ if ($taken ne "-" && $taken > 0); - } - } - } - - return ($br_found, $br_hit); -} - - -# combine_brcount(brcount1, brcount2, type, inplace) -# -# If add is BR_ADD, add branch coverage data and return list brcount_added. -# If add is BR_SUB, subtract the taken values of brcount2 from brcount1 and -# return brcount_sub. If inplace is set, the result is inserted into brcount1. -# - -sub combine_brcount($$$;$) -{ - my ($brcount1, $brcount2, $type, $inplace) = @_; - my ($db1, $db2); - - $db1 = brcount_to_db($brcount1); - $db2 = brcount_to_db($brcount2); - brcount_db_combine($db1, $db2, $type); - - return db_to_brcount($db1, $inplace ? $brcount1 : undef); -} - - -# -# add_testbrdata(testbrdata1, testbrdata2) -# -# Add branch coverage data for several tests. Return reference to -# added_testbrdata. -# - -sub add_testbrdata($$) -{ - my ($testbrdata1, $testbrdata2) = @_; - my %result; - my $testname; - - foreach $testname (keys(%{$testbrdata1})) { - if (defined($testbrdata2->{$testname})) { - my $brcount; - - # Branch coverage data for this testname exists - # in both data sets: add - ($brcount) = combine_brcount($testbrdata1->{$testname}, - $testbrdata2->{$testname}, $BR_ADD); - $result{$testname} = $brcount; - next; - } - # Branch coverage data for this testname is unique to - # data set 1: copy - $result{$testname} = $testbrdata1->{$testname}; - } - - # Add count data for testnames unique to data set 2 - foreach $testname (keys(%{$testbrdata2})) { - if (!defined($result{$testname})) { - $result{$testname} = $testbrdata2->{$testname}; - } - } - return \%result; -} - - -# -# combine_info_entries(entry_ref1, entry_ref2, filename) -# -# Combine .info data entry hashes referenced by ENTRY_REF1 and ENTRY_REF2. -# Return reference to resulting hash. -# - -sub combine_info_entries($$$) -{ - my $entry1 = $_[0]; # Reference to hash containing first entry - my $testdata1; - my $sumcount1; - my $funcdata1; - my $checkdata1; - my $testfncdata1; - my $sumfnccount1; - my $testbrdata1; - my $sumbrcount1; - - my $entry2 = $_[1]; # Reference to hash containing second entry - my $testdata2; - my $sumcount2; - my $funcdata2; - my $checkdata2; - my $testfncdata2; - my $sumfnccount2; - my $testbrdata2; - my $sumbrcount2; - - my %result; # Hash containing combined entry - my %result_testdata; - my $result_sumcount = {}; - my $result_funcdata; - my $result_testfncdata; - my $result_sumfnccount; - my $result_testbrdata; - my $result_sumbrcount; - my $lines_found; - my $lines_hit; - my $fn_found; - my $fn_hit; - my $br_found; - my $br_hit; - - my $testname; - my $filename = $_[2]; - - # Retrieve data - ($testdata1, $sumcount1, $funcdata1, $checkdata1, $testfncdata1, - $sumfnccount1, $testbrdata1, $sumbrcount1) = get_info_entry($entry1); - ($testdata2, $sumcount2, $funcdata2, $checkdata2, $testfncdata2, - $sumfnccount2, $testbrdata2, $sumbrcount2) = get_info_entry($entry2); - - # Merge checksums - $checkdata1 = merge_checksums($checkdata1, $checkdata2, $filename); - - # Combine funcdata - $result_funcdata = merge_func_data($funcdata1, $funcdata2, $filename); - - # Combine function call count data - $result_testfncdata = add_testfncdata($testfncdata1, $testfncdata2); - ($result_sumfnccount, $fn_found, $fn_hit) = - add_fnccount($sumfnccount1, $sumfnccount2); - - # Combine branch coverage data - $result_testbrdata = add_testbrdata($testbrdata1, $testbrdata2); - ($result_sumbrcount, $br_found, $br_hit) = - combine_brcount($sumbrcount1, $sumbrcount2, $BR_ADD); - - # Combine testdata - foreach $testname (keys(%{$testdata1})) - { - if (defined($testdata2->{$testname})) - { - # testname is present in both entries, requires - # combination - ($result_testdata{$testname}) = - add_counts($testdata1->{$testname}, - $testdata2->{$testname}); - } - else - { - # testname only present in entry1, add to result - $result_testdata{$testname} = $testdata1->{$testname}; - } - - # update sum count hash - ($result_sumcount, $lines_found, $lines_hit) = - add_counts($result_sumcount, - $result_testdata{$testname}); - } - - foreach $testname (keys(%{$testdata2})) - { - # Skip testnames already covered by previous iteration - if (defined($testdata1->{$testname})) { next; } - - # testname only present in entry2, add to result hash - $result_testdata{$testname} = $testdata2->{$testname}; - - # update sum count hash - ($result_sumcount, $lines_found, $lines_hit) = - add_counts($result_sumcount, - $result_testdata{$testname}); - } - - # Calculate resulting sumcount - - # Store result - set_info_entry(\%result, \%result_testdata, $result_sumcount, - $result_funcdata, $checkdata1, $result_testfncdata, - $result_sumfnccount, $result_testbrdata, - $result_sumbrcount, $lines_found, $lines_hit, - $fn_found, $fn_hit, $br_found, $br_hit); - - return(\%result); -} - - -# -# combine_info_files(info_ref1, info_ref2) -# -# Combine .info data in hashes referenced by INFO_REF1 and INFO_REF2. Return -# reference to resulting hash. -# - -sub combine_info_files($$) -{ - my %hash1 = %{$_[0]}; - my %hash2 = %{$_[1]}; - my $filename; - - foreach $filename (keys(%hash2)) - { - if ($hash1{$filename}) - { - # Entry already exists in hash1, combine them - $hash1{$filename} = - combine_info_entries($hash1{$filename}, - $hash2{$filename}, - $filename); - } - else - { - # Entry is unique in both hashes, simply add to - # resulting hash - $hash1{$filename} = $hash2{$filename}; - } - } - - return(\%hash1); -} - - -# -# get_prefix(min_dir, filename_list) -# -# Search FILENAME_LIST for a directory prefix which is common to as many -# list entries as possible, so that removing this prefix will minimize the -# sum of the lengths of all resulting shortened filenames while observing -# that no filename has less than MIN_DIR parent directories. -# - -sub get_prefix($@) -{ - my ($min_dir, @filename_list) = @_; - my %prefix; # mapping: prefix -> sum of lengths - my $current; # Temporary iteration variable - - # Find list of prefixes - foreach (@filename_list) - { - # Need explicit assignment to get a copy of $_ so that - # shortening the contained prefix does not affect the list - $current = $_; - while ($current = shorten_prefix($current)) - { - $current .= "/"; - - # Skip rest if the remaining prefix has already been - # added to hash - if (exists($prefix{$current})) { last; } - - # Initialize with 0 - $prefix{$current}="0"; - } - - } - - # Remove all prefixes that would cause filenames to have less than - # the minimum number of parent directories - foreach my $filename (@filename_list) { - my $dir = dirname($filename); - - for (my $i = 0; $i < $min_dir; $i++) { - delete($prefix{$dir."/"}); - $dir = shorten_prefix($dir); - } - } - - # Check if any prefix remains - return undef if (!%prefix); - - # Calculate sum of lengths for all prefixes - foreach $current (keys(%prefix)) - { - foreach (@filename_list) - { - # Add original length - $prefix{$current} += length($_); - - # Check whether prefix matches - if (substr($_, 0, length($current)) eq $current) - { - # Subtract prefix length for this filename - $prefix{$current} -= length($current); - } - } - } - - # Find and return prefix with minimal sum - $current = (keys(%prefix))[0]; - - foreach (keys(%prefix)) - { - if ($prefix{$_} < $prefix{$current}) - { - $current = $_; - } - } - - $current =~ s/\/$//; - - return($current); -} - - -# -# shorten_prefix(prefix) -# -# Return PREFIX shortened by last directory component. -# - -sub shorten_prefix($) -{ - my @list = split("/", $_[0]); - - pop(@list); - return join("/", @list); -} - - - -# -# get_dir_list(filename_list) -# -# Return sorted list of directories for each entry in given FILENAME_LIST. -# - -sub get_dir_list(@) -{ - my %result; - - foreach (@_) - { - $result{shorten_prefix($_)} = ""; - } - - return(sort(keys(%result))); -} - - -# -# get_relative_base_path(subdirectory) -# -# Return a relative path string which references the base path when applied -# in SUBDIRECTORY. -# -# Example: get_relative_base_path("fs/mm") -> "../../" -# - -sub get_relative_base_path($) -{ - my $result = ""; - my $index; - - # Make an empty directory path a special case - if (!$_[0]) { return(""); } - - # Count number of /s in path - $index = ($_[0] =~ s/\//\//g); - - # Add a ../ to $result for each / in the directory path + 1 - for (; $index>=0; $index--) - { - $result .= "../"; - } - - return $result; -} - - -# -# read_testfile(test_filename) -# -# Read in file TEST_FILENAME which contains test descriptions in the format: -# -# TN: -# TD: -# -# for each test case. Return a reference to a hash containing a mapping -# -# test name -> test description. -# -# Die on error. -# - -sub read_testfile($) -{ - my %result; - my $test_name; - my $changed_testname; - local *TEST_HANDLE; - - open(TEST_HANDLE, "<", $_[0]) - or die("ERROR: cannot open $_[0]!\n"); - - while () - { - chomp($_); - - # Match lines beginning with TN: - if (/^TN:\s+(.*?)\s*$/) - { - # Store name for later use - $test_name = $1; - if ($test_name =~ s/\W/_/g) - { - $changed_testname = 1; - } - } - - # Match lines beginning with TD: - if (/^TD:\s+(.*?)\s*$/) - { - if (!defined($test_name)) { - die("ERROR: Found test description without prior test name in $_[0]:$.\n"); - } - # Check for empty line - if ($1) - { - # Add description to hash - $result{$test_name} .= " $1"; - } - else - { - # Add empty line - $result{$test_name} .= "\n\n"; - } - } - } - - close(TEST_HANDLE); - - if ($changed_testname) - { - warn("WARNING: invalid characters removed from testname in ". - "descriptions file $_[0]\n"); - } - - return \%result; -} - - -# -# escape_html(STRING) -# -# Return a copy of STRING in which all occurrences of HTML special characters -# are escaped. -# - -sub escape_html($) -{ - my $string = $_[0]; - - if (!$string) { return ""; } - - $string =~ s/&/&/g; # & -> & - $string =~ s/ < - $string =~ s/>/>/g; # > -> > - $string =~ s/\"/"/g; # " -> " - - while ($string =~ /^([^\t]*)(\t)/) - { - my $replacement = " "x($tab_size - (length($1) % $tab_size)); - $string =~ s/^([^\t]*)(\t)/$1$replacement/; - } - - $string =~ s/\n/
/g; # \n ->
- - return $string; -} - - -# -# get_date_string() -# -# Return the current date in the form: yyyy-mm-dd -# - -sub get_date_string() -{ - my $year; - my $month; - my $day; - my $hour; - my $min; - my $sec; - my @timeresult; - - if (defined $ENV{'SOURCE_DATE_EPOCH'}) - { - @timeresult = gmtime($ENV{'SOURCE_DATE_EPOCH'}); - } - else - { - @timeresult = localtime(); - } - ($year, $month, $day, $hour, $min, $sec) = - @timeresult[5, 4, 3, 2, 1, 0]; - - return sprintf("%d-%02d-%02d %02d:%02d:%02d", $year+1900, $month+1, - $day, $hour, $min, $sec); -} - - -# -# create_sub_dir(dir_name) -# -# Create subdirectory DIR_NAME if it does not already exist, including all its -# parent directories. -# -# Die on error. -# - -sub create_sub_dir($) -{ - my ($dir) = @_; - - system("mkdir", "-p" ,$dir) - and die("ERROR: cannot create directory $dir!\n"); -} - - -# -# write_description_file(descriptions, overall_found, overall_hit, -# total_fn_found, total_fn_hit, total_br_found, -# total_br_hit) -# -# Write HTML file containing all test case descriptions. DESCRIPTIONS is a -# reference to a hash containing a mapping -# -# test case name -> test case description -# -# Die on error. -# - -sub write_description_file($$$$$$$) -{ - my %description = %{$_[0]}; - my $found = $_[1]; - my $hit = $_[2]; - my $fn_found = $_[3]; - my $fn_hit = $_[4]; - my $br_found = $_[5]; - my $br_hit = $_[6]; - my $test_name; - local *HTML_HANDLE; - - html_create(*HTML_HANDLE,"descriptions.$html_ext"); - write_html_prolog(*HTML_HANDLE, "", "LCOV - test case descriptions"); - write_header(*HTML_HANDLE, 3, "", "", $found, $hit, $fn_found, - $fn_hit, $br_found, $br_hit, 0); - - write_test_table_prolog(*HTML_HANDLE, - "Test case descriptions - alphabetical list"); - - foreach $test_name (sort(keys(%description))) - { - my $desc = $description{$test_name}; - - $desc = escape_html($desc) if (!$rc_desc_html); - write_test_table_entry(*HTML_HANDLE, $test_name, $desc); - } - - write_test_table_epilog(*HTML_HANDLE); - write_html_epilog(*HTML_HANDLE, ""); - - close(*HTML_HANDLE); -} - - - -# -# write_png_files() -# -# Create all necessary .png files for the HTML-output in the current -# directory. .png-files are used as bar graphs. -# -# Die on error. -# - -sub write_png_files() -{ - my %data; - local *PNG_HANDLE; - - $data{"ruby.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, - 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, - 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f, 0x18, 0x10, 0x5d, 0x57, - 0x34, 0x6e, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, - 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, - 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, - 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, - 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x35, 0x2f, - 0x00, 0x00, 0x00, 0xd0, 0x33, 0x9a, 0x9d, 0x00, 0x00, 0x00, - 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82]; - $data{"amber.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, - 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, - 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f, 0x28, 0x04, 0x98, 0xcb, - 0xd6, 0xe0, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, - 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, - 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, - 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, - 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xe0, 0x50, - 0x00, 0x00, 0x00, 0xa2, 0x7a, 0xda, 0x7e, 0x00, 0x00, 0x00, - 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82]; - $data{"emerald.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, - 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, - 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f, 0x22, 0x2b, 0xc9, 0xf5, - 0x03, 0x33, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, - 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, - 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, - 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, - 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0x1b, 0xea, 0x59, - 0x0a, 0x0a, 0x0a, 0x0f, 0xba, 0x50, 0x83, 0x00, 0x00, 0x00, - 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82]; - $data{"snow.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, - 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, - 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f, 0x1e, 0x1d, 0x75, 0xbc, - 0xef, 0x55, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, - 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, - 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, - 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, - 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x55, 0xc2, 0xd3, 0x7e, 0x00, 0x00, 0x00, - 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82]; - $data{"glass.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, - 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, - 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, - 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x55, 0xc2, 0xd3, 0x7e, 0x00, 0x00, 0x00, - 0x01, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x40, 0xe6, 0xd8, 0x66, - 0x00, 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x00, 0x88, - 0x05, 0x1d, 0x48, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, - 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, - 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, - 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x13, 0x0f, 0x08, 0x19, 0xc4, - 0x40, 0x56, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, - 0x54, 0x78, 0x9c, 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x01, 0x48, 0xaf, 0xa4, 0x71, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]; - $data{"updown.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x00, 0x0e, 0x08, 0x06, 0x00, 0x00, 0x00, 0x16, - 0xa3, 0x8d, 0xab, 0x00, 0x00, 0x00, 0x3c, 0x49, 0x44, 0x41, - 0x54, 0x28, 0xcf, 0x63, 0x60, 0x40, 0x03, 0xff, 0xa1, 0x00, - 0x5d, 0x9c, 0x11, 0x5d, 0x11, 0x8a, 0x24, 0x23, 0x23, 0x23, - 0x86, 0x42, 0x6c, 0xa6, 0x20, 0x2b, 0x66, 0xc4, 0xa7, 0x08, - 0x59, 0x31, 0x23, 0x21, 0x45, 0x30, 0xc0, 0xc4, 0x30, 0x60, - 0x80, 0xfa, 0x6e, 0x24, 0x3e, 0x78, 0x48, 0x0a, 0x70, 0x62, - 0xa2, 0x90, 0x81, 0xd8, 0x44, 0x01, 0x00, 0xe9, 0x5c, 0x2f, - 0xf5, 0xe2, 0x9d, 0x0f, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82] if ($sort); - foreach (keys(%data)) - { - open(PNG_HANDLE, ">", $_) - or die("ERROR: cannot create $_!\n"); - binmode(PNG_HANDLE); - print(PNG_HANDLE map(chr,@{$data{$_}})); - close(PNG_HANDLE); - } -} - - -# -# write_htaccess_file() -# - -sub write_htaccess_file() -{ - local *HTACCESS_HANDLE; - my $htaccess_data; - - open(*HTACCESS_HANDLE, ">", ".htaccess") - or die("ERROR: cannot open .htaccess for writing!\n"); - - $htaccess_data = (<<"END_OF_HTACCESS") -AddEncoding x-gzip .html -END_OF_HTACCESS - ; - - print(HTACCESS_HANDLE $htaccess_data); - close(*HTACCESS_HANDLE); -} - - -# -# write_css_file() -# -# Write the cascading style sheet file gcov.css to the current directory. -# This file defines basic layout attributes of all generated HTML pages. -# - -sub write_css_file() -{ - local *CSS_HANDLE; - - # Check for a specified external style sheet file - if ($css_filename) - { - # Simply copy that file - system("cp", $css_filename, "gcov.css") - and die("ERROR: cannot copy file $css_filename!\n"); - return; - } - - open(CSS_HANDLE, ">", "gcov.css") - or die ("ERROR: cannot open gcov.css for writing!\n"); - - - # ************************************************************* - - my $css_data = ($_=<<"END_OF_CSS") - /* All views: initial background and text color */ - body - { - color: #000000; - background-color: #FFFFFF; - } - - /* All views: standard link format*/ - a:link - { - color: #284FA8; - text-decoration: underline; - } - - /* All views: standard link - visited format */ - a:visited - { - color: #00CB40; - text-decoration: underline; - } - - /* All views: standard link - activated format */ - a:active - { - color: #FF0040; - text-decoration: underline; - } - - /* All views: main title format */ - td.title - { - text-align: center; - padding-bottom: 10px; - font-family: sans-serif; - font-size: 20pt; - font-style: italic; - font-weight: bold; - } - - /* All views: header item format */ - td.headerItem - { - text-align: right; - padding-right: 6px; - font-family: sans-serif; - font-weight: bold; - vertical-align: top; - white-space: nowrap; - } - - /* All views: header item value format */ - td.headerValue - { - text-align: left; - color: #284FA8; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - } - - /* All views: header item coverage table heading */ - td.headerCovTableHead - { - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - font-size: 80%; - white-space: nowrap; - } - - /* All views: header item coverage table entry */ - td.headerCovTableEntry - { - text-align: right; - color: #284FA8; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #DAE7FE; - } - - /* All views: header item coverage table entry for high coverage rate */ - td.headerCovTableEntryHi - { - text-align: right; - color: #000000; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #A7FC9D; - } - - /* All views: header item coverage table entry for medium coverage rate */ - td.headerCovTableEntryMed - { - text-align: right; - color: #000000; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #FFEA20; - } - - /* All views: header item coverage table entry for ow coverage rate */ - td.headerCovTableEntryLo - { - text-align: right; - color: #000000; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #FF0000; - } - - /* All views: header legend value for legend entry */ - td.headerValueLeg - { - text-align: left; - color: #000000; - font-family: sans-serif; - font-size: 80%; - white-space: nowrap; - padding-top: 4px; - } - - /* All views: color of horizontal ruler */ - td.ruler - { - background-color: #6688D4; - } - - /* All views: version string format */ - td.versionInfo - { - text-align: center; - padding-top: 2px; - font-family: sans-serif; - font-style: italic; - } - - /* Directory view/File view (all)/Test case descriptions: - table headline format */ - td.tableHead - { - text-align: center; - color: #FFFFFF; - background-color: #6688D4; - font-family: sans-serif; - font-size: 120%; - font-weight: bold; - white-space: nowrap; - padding-left: 4px; - padding-right: 4px; - } - - span.tableHeadSort - { - padding-right: 4px; - } - - /* Directory view/File view (all): filename entry format */ - td.coverFile - { - text-align: left; - padding-left: 10px; - padding-right: 20px; - color: #284FA8; - background-color: #DAE7FE; - font-family: monospace; - } - - /* Directory view/File view (all): bar-graph entry format*/ - td.coverBar - { - padding-left: 10px; - padding-right: 10px; - background-color: #DAE7FE; - } - - /* Directory view/File view (all): bar-graph outline color */ - td.coverBarOutline - { - background-color: #000000; - } - - /* Directory view/File view (all): percentage entry for files with - high coverage rate */ - td.coverPerHi - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #A7FC9D; - font-weight: bold; - font-family: sans-serif; - } - - /* Directory view/File view (all): line count entry for files with - high coverage rate */ - td.coverNumHi - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #A7FC9D; - white-space: nowrap; - font-family: sans-serif; - } - - /* Directory view/File view (all): percentage entry for files with - medium coverage rate */ - td.coverPerMed - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #FFEA20; - font-weight: bold; - font-family: sans-serif; - } - - /* Directory view/File view (all): line count entry for files with - medium coverage rate */ - td.coverNumMed - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #FFEA20; - white-space: nowrap; - font-family: sans-serif; - } - - /* Directory view/File view (all): percentage entry for files with - low coverage rate */ - td.coverPerLo - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #FF0000; - font-weight: bold; - font-family: sans-serif; - } - - /* Directory view/File view (all): line count entry for files with - low coverage rate */ - td.coverNumLo - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #FF0000; - white-space: nowrap; - font-family: sans-serif; - } - - /* File view (all): "show/hide details" link format */ - a.detail:link - { - color: #B8D0FF; - font-size:80%; - } - - /* File view (all): "show/hide details" link - visited format */ - a.detail:visited - { - color: #B8D0FF; - font-size:80%; - } - - /* File view (all): "show/hide details" link - activated format */ - a.detail:active - { - color: #FFFFFF; - font-size:80%; - } - - /* File view (detail): test name entry */ - td.testName - { - text-align: right; - padding-right: 10px; - background-color: #DAE7FE; - font-family: sans-serif; - } - - /* File view (detail): test percentage entry */ - td.testPer - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #DAE7FE; - font-family: sans-serif; - } - - /* File view (detail): test lines count entry */ - td.testNum - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #DAE7FE; - font-family: sans-serif; - } - - /* Test case descriptions: test name format*/ - dt - { - font-family: sans-serif; - font-weight: bold; - } - - /* Test case descriptions: description table body */ - td.testDescription - { - padding-top: 10px; - padding-left: 30px; - padding-bottom: 10px; - padding-right: 30px; - background-color: #DAE7FE; - } - - /* Source code view: function entry */ - td.coverFn - { - text-align: left; - padding-left: 10px; - padding-right: 20px; - color: #284FA8; - background-color: #DAE7FE; - font-family: monospace; - } - - /* Source code view: function entry zero count*/ - td.coverFnLo - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #FF0000; - font-weight: bold; - font-family: sans-serif; - } - - /* Source code view: function entry nonzero count*/ - td.coverFnHi - { - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #DAE7FE; - font-weight: bold; - font-family: sans-serif; - } - - /* Source code view: source code format */ - pre.source - { - font-family: monospace; - white-space: pre; - margin-top: 2px; - } - - /* Source code view: line number format */ - span.lineNum - { - background-color: #EFE383; - } - - /* Source code view: format for lines which were executed */ - td.lineCov, - span.lineCov - { - background-color: #CAD7FE; - } - - /* Source code view: format for Cov legend */ - span.coverLegendCov - { - padding-left: 10px; - padding-right: 10px; - padding-bottom: 2px; - background-color: #CAD7FE; - } - - /* Source code view: format for lines which were not executed */ - td.lineNoCov, - span.lineNoCov - { - background-color: #FF6230; - } - - /* Source code view: format for NoCov legend */ - span.coverLegendNoCov - { - padding-left: 10px; - padding-right: 10px; - padding-bottom: 2px; - background-color: #FF6230; - } - - /* Source code view (function table): standard link - visited format */ - td.lineNoCov > a:visited, - td.lineCov > a:visited - { - color: black; - text-decoration: underline; - } - - /* Source code view: format for lines which were executed only in a - previous version */ - span.lineDiffCov - { - background-color: #B5F7AF; - } - - /* Source code view: format for branches which were executed - * and taken */ - span.branchCov - { - background-color: #CAD7FE; - } - - /* Source code view: format for branches which were executed - * but not taken */ - span.branchNoCov - { - background-color: #FF6230; - } - - /* Source code view: format for branches which were not executed */ - span.branchNoExec - { - background-color: #FF6230; - } - - /* Source code view: format for the source code heading line */ - pre.sourceHeading - { - white-space: pre; - font-family: monospace; - font-weight: bold; - margin: 0px; - } - - /* All views: header legend value for low rate */ - td.headerValueLegL - { - font-family: sans-serif; - text-align: center; - white-space: nowrap; - padding-left: 4px; - padding-right: 2px; - background-color: #FF0000; - font-size: 80%; - } - - /* All views: header legend value for med rate */ - td.headerValueLegM - { - font-family: sans-serif; - text-align: center; - white-space: nowrap; - padding-left: 2px; - padding-right: 2px; - background-color: #FFEA20; - font-size: 80%; - } - - /* All views: header legend value for hi rate */ - td.headerValueLegH - { - font-family: sans-serif; - text-align: center; - white-space: nowrap; - padding-left: 2px; - padding-right: 4px; - background-color: #A7FC9D; - font-size: 80%; - } - - /* All views except source code view: legend format for low coverage */ - span.coverLegendCovLo - { - padding-left: 10px; - padding-right: 10px; - padding-top: 2px; - background-color: #FF0000; - } - - /* All views except source code view: legend format for med coverage */ - span.coverLegendCovMed - { - padding-left: 10px; - padding-right: 10px; - padding-top: 2px; - background-color: #FFEA20; - } - - /* All views except source code view: legend format for hi coverage */ - span.coverLegendCovHi - { - padding-left: 10px; - padding-right: 10px; - padding-top: 2px; - background-color: #A7FC9D; - } -END_OF_CSS - ; - - # ************************************************************* - - - # Remove leading tab from all lines - $css_data =~ s/^\t//gm; - - print(CSS_HANDLE $css_data); - - close(CSS_HANDLE); -} - - -# -# get_bar_graph_code(base_dir, cover_found, cover_hit) -# -# Return a string containing HTML code which implements a bar graph display -# for a coverage rate of cover_hit * 100 / cover_found. -# - -sub get_bar_graph_code($$$) -{ - my ($base_dir, $found, $hit) = @_; - my $rate; - my $alt; - my $width; - my $remainder; - my $png_name; - my $graph_code; - - # Check number of instrumented lines - if ($_[1] == 0) { return ""; } - - $alt = rate($hit, $found, "%"); - $width = rate($hit, $found, undef, 0); - $remainder = 100 - $width; - - # Decide which .png file to use - $png_name = $rate_png[classify_rate($found, $hit, $med_limit, - $hi_limit)]; - - if ($width == 0) - { - # Zero coverage - $graph_code = (<$alt -END_OF_HTML - ; - } - elsif ($width == 100) - { - # Full coverage - $graph_code = (<$alt -END_OF_HTML - ; - } - else - { - # Positive coverage - $graph_code = (<$alt$alt -END_OF_HTML - ; - } - - # Remove leading tabs from all lines - $graph_code =~ s/^\t+//gm; - chomp($graph_code); - - return($graph_code); -} - -# -# sub classify_rate(found, hit, med_limit, high_limit) -# -# Return 0 for low rate, 1 for medium rate and 2 for hi rate. -# - -sub classify_rate($$$$) -{ - my ($found, $hit, $med, $hi) = @_; - my $rate; - - if ($found == 0) { - return 2; - } - $rate = rate($hit, $found); - if ($rate < $med) { - return 0; - } elsif ($rate < $hi) { - return 1; - } - return 2; -} - - -# -# write_html(filehandle, html_code) -# -# Write out HTML_CODE to FILEHANDLE while removing a leading tabulator mark -# in each line of HTML_CODE. -# - -sub write_html(*$) -{ - local *HTML_HANDLE = $_[0]; - my $html_code = $_[1]; - - # Remove leading tab from all lines - $html_code =~ s/^\t//gm; - - print(HTML_HANDLE $html_code) - or die("ERROR: cannot write HTML data ($!)\n"); -} - - -# -# write_html_prolog(filehandle, base_dir, pagetitle) -# -# Write an HTML prolog common to all HTML files to FILEHANDLE. PAGETITLE will -# be used as HTML page title. BASE_DIR contains a relative path which points -# to the base directory. -# - -sub write_html_prolog(*$$) -{ - my $basedir = $_[1]; - my $pagetitle = $_[2]; - my $prolog; - - $prolog = $html_prolog; - $prolog =~ s/\@pagetitle\@/$pagetitle/g; - $prolog =~ s/\@basedir\@/$basedir/g; - - write_html($_[0], $prolog); -} - - -# -# write_header_prolog(filehandle, base_dir) -# -# Write beginning of page header HTML code. -# - -sub write_header_prolog(*$) -{ - # ************************************************************* - - write_html($_[0], < - $title - - - - - -END_OF_HTML - ; - - # ************************************************************* -} - - -# -# write_header_line(handle, content) -# -# Write a header line with the specified table contents. -# - -sub write_header_line(*@) -{ - my ($handle, @content) = @_; - my $entry; - - write_html($handle, " \n"); - foreach $entry (@content) { - my ($width, $class, $text, $colspan) = @{$entry}; - - if (defined($width)) { - $width = " width=\"$width\""; - } else { - $width = ""; - } - if (defined($class)) { - $class = " class=\"$class\""; - } else { - $class = ""; - } - if (defined($colspan)) { - $colspan = " colspan=\"$colspan\""; - } else { - $colspan = ""; - } - $text = "" if (!defined($text)); - write_html($handle, - " $text\n"); - } - write_html($handle, " \n"); -} - - -# -# write_header_epilog(filehandle, base_dir) -# -# Write end of page header HTML code. -# - -sub write_header_epilog(*$) -{ - # ************************************************************* - - write_html($_[0], < -
- - - - - - -END_OF_HTML - ; - - # ************************************************************* -} - - -# -# write_file_table_prolog(handle, file_heading, ([heading, num_cols], ...)) -# -# Write heading for file table. -# - -sub write_file_table_prolog(*$@) -{ - my ($handle, $file_heading, @columns) = @_; - my $num_columns = 0; - my $file_width; - my $col; - my $width; - - $width = 20 if (scalar(@columns) == 1); - $width = 10 if (scalar(@columns) == 2); - $width = 8 if (scalar(@columns) > 2); - - foreach $col (@columns) { - my ($heading, $cols) = @{$col}; - - $num_columns += $cols; - } - $file_width = 100 - $num_columns * $width; - - # Table definition - write_html($handle, < - - - - -END_OF_HTML - # Empty first row - foreach $col (@columns) { - my ($heading, $cols) = @{$col}; - - while ($cols-- > 0) { - write_html($handle, < -END_OF_HTML - } - } - # Next row - write_html($handle, < - - - -END_OF_HTML - # Heading row - foreach $col (@columns) { - my ($heading, $cols) = @{$col}; - my $colspan = ""; - - $colspan = " colspan=$cols" if ($cols > 1); - write_html($handle, <$heading -END_OF_HTML - } - write_html($handle, < -END_OF_HTML -} - - -# write_file_table_entry(handle, base_dir, filename, page_link, -# ([ found, hit, med_limit, hi_limit, graph ], ..) -# -# Write an entry of the file table. -# - -sub write_file_table_entry(*$$$@) -{ - my ($handle, $base_dir, $filename, $page_link, @entries) = @_; - my $file_code; - my $entry; - my $esc_filename = escape_html($filename); - - # Add link to source if provided - if (defined($page_link) && $page_link ne "") { - $file_code = "$esc_filename"; - } else { - $file_code = $esc_filename; - } - - # First column: filename - write_html($handle, < - -END_OF_HTML - # Columns as defined - foreach $entry (@entries) { - my ($found, $hit, $med, $hi, $graph) = @{$entry}; - my $bar_graph; - my $class; - my $rate; - - # Generate bar graph if requested - if ($graph) { - $bar_graph = get_bar_graph_code($base_dir, $found, - $hit); - write_html($handle, < - $bar_graph - -END_OF_HTML - } - # Get rate color and text - if ($found == 0) { - $rate = "-"; - $class = "Hi"; - } else { - $rate = rate($hit, $found, " %"); - $class = $rate_name[classify_rate($found, $hit, - $med, $hi)]; - } - if ($opt_missed) { - # Show negative number of items without coverage - $hit = -($found - $hit); - } - write_html($handle, <$rate - -END_OF_HTML - } - # End of row - write_html($handle, < -END_OF_HTML -} - - -# -# write_file_table_detail_entry(filehandle, test_name, ([found, hit], ...)) -# -# Write entry for detail section in file table. -# - -sub write_file_table_detail_entry(*$@) -{ - my ($handle, $test, @entries) = @_; - my $entry; - - if ($test eq "") { - $test = "<unnamed>"; - } elsif ($test =~ /^(.*),diff$/) { - $test = $1." (converted)"; - } - # Testname - write_html($handle, < - -END_OF_HTML - # Test data - foreach $entry (@entries) { - my ($found, $hit) = @{$entry}; - my $rate = rate($hit, $found, " %"); - - write_html($handle, <$rate - -END_OF_HTML - } - - write_html($handle, < - -END_OF_HTML - - # ************************************************************* -} - - -# -# write_file_table_epilog(filehandle) -# -# Write end of file table HTML code. -# - -sub write_file_table_epilog(*) -{ - # ************************************************************* - - write_html($_[0], < - -
- -END_OF_HTML - ; - - # ************************************************************* -} - - -# -# write_test_table_prolog(filehandle, table_heading) -# -# Write heading for test case description table. -# - -sub write_test_table_prolog(*$) -{ - # ************************************************************* - - write_html($_[0], < -

$file_heading$file_code$hit / $found$test$hit / $found
- - - - - - - - - - - - -

$_[1]
-
-END_OF_HTML - ; - - # ************************************************************* -} - - -# -# write_test_table_entry(filehandle, test_name, test_description) -# -# Write entry for the test table. -# - -sub write_test_table_entry(*$$) -{ - # ************************************************************* - - write_html($_[0], <$_[1]  -
$_[2]

-END_OF_HTML - ; - - # ************************************************************* -} - - -# -# write_test_table_epilog(filehandle) -# -# Write end of test description table HTML code. -# - -sub write_test_table_epilog(*) -{ - # ************************************************************* - - write_html($_[0], < -
- -
- -END_OF_HTML - ; - - # ************************************************************* -} - - -sub fmt_centered($$) -{ - my ($width, $text) = @_; - my $w0 = length($text); - my $w1 = $width > $w0 ? int(($width - $w0) / 2) : 0; - my $w2 = $width > $w0 ? $width - $w0 - $w1 : 0; - - return (" "x$w1).$text.(" "x$w2); -} - - -# -# write_source_prolog(filehandle) -# -# Write start of source code table. -# - -sub write_source_prolog(*) -{ - my $lineno_heading = " "; - my $branch_heading = ""; - my $line_heading = fmt_centered($line_field_width, "Line data"); - my $source_heading = " Source code"; - - if ($br_coverage) { - $branch_heading = fmt_centered($br_field_width, "Branch data"). - " "; - } - # ************************************************************* - - write_html($_[0], < - -
- - - -
${lineno_heading}${branch_heading}${line_heading} ${source_heading}
-
-END_OF_HTML
-	;
-
-	# *************************************************************
-}
-
-sub cmp_blocks($$)
-{
-	my ($a, $b) = @_;
-	my ($fa, $fb) = ($a->[0], $b->[0]);
-
-	return $fa->[0] <=> $fb->[0] if ($fa->[0] != $fb->[0]);
-	return $fa->[1] <=> $fb->[1];
-}
-
-#
-# get_branch_blocks(brdata)
-#
-# Group branches that belong to the same basic block.
-#
-# Returns: [block1, block2, ...]
-# block:   [branch1, branch2, ...]
-# branch:  [block_num, branch_num, taken_count, text_length, open, close]
-#
-
-sub get_branch_blocks($)
-{
-	my ($brdata) = @_;
-	my $last_block_num;
-	my $block = [];
-	my @blocks;
-
-	return () if (!defined($brdata));
-
-	# Group branches
-	foreach my $entry (split(/:/, $brdata)) {
-		my ($block_num, $branch, $taken) = split(/,/, $entry);
-		my $br;
-
-		if (defined($last_block_num) && $block_num != $last_block_num) {
-			push(@blocks, $block);
-			$block = [];
-		}
-		$br = [$block_num, $branch, $taken, 3, 0, 0];
-		push(@{$block}, $br);
-		$last_block_num = $block_num;
-	}
-	push(@blocks, $block) if (scalar(@{$block}) > 0);
-
-	# Add braces to first and last branch in group
-	foreach $block (@blocks) {
-		$block->[0]->[$BR_OPEN] = 1;
-		$block->[0]->[$BR_LEN]++;
-		$block->[scalar(@{$block}) - 1]->[$BR_CLOSE] = 1;
-		$block->[scalar(@{$block}) - 1]->[$BR_LEN]++;
-	}
-
-	return sort(cmp_blocks @blocks);
-}
-
-#
-# get_block_len(block)
-#
-# Calculate total text length of all branches in a block of branches.
-#
-
-sub get_block_len($)
-{
-	my ($block) = @_;
-	my $len = 0;
-	my $branch;
-
-	foreach $branch (@{$block}) {
-		$len += $branch->[$BR_LEN];
-	}
-
-	return $len;
-}
-
-
-#
-# get_branch_html(brdata)
-#
-# Return a list of HTML lines which represent the specified branch coverage
-# data in source code view.
-#
-
-sub get_branch_html($)
-{
-	my ($brdata) = @_;
-	my @blocks = get_branch_blocks($brdata);
-	my $block;
-	my $branch;
-	my $line_len = 0;
-	my $line = [];	# [branch2|" ", branch|" ", ...]
-	my @lines;	# [line1, line2, ...]
-	my @result;
-
-	# Distribute blocks to lines
-	foreach $block (@blocks) {
-		my $block_len = get_block_len($block);
-
-		# Does this block fit into the current line?
-		if ($line_len + $block_len <= $br_field_width) {
-			# Add it
-			$line_len += $block_len;
-			push(@{$line}, @{$block});
-			next;
-		} elsif ($block_len <= $br_field_width) {
-			# It would fit if the line was empty - add it to new
-			# line
-			push(@lines, $line);
-			$line_len = $block_len;
-			$line = [ @{$block} ];
-			next;
-		}
-		# Split the block into several lines
-		foreach $branch (@{$block}) {
-			if ($line_len + $branch->[$BR_LEN] >= $br_field_width) {
-				# Start a new line
-				if (($line_len + 1 <= $br_field_width) &&
-				    scalar(@{$line}) > 0 &&
-				    !$line->[scalar(@$line) - 1]->[$BR_CLOSE]) {
-					# Try to align branch symbols to be in
-					# one # row
-					push(@{$line}, " ");
-				}
-				push(@lines, $line);
-				$line_len = 0;
-				$line = [];
-			}
-			push(@{$line}, $branch);
-			$line_len += $branch->[$BR_LEN];
-		}
-	}
-	push(@lines, $line);
-
-	# Convert to HTML
-	foreach $line (@lines) {
-		my $current = "";
-		my $current_len = 0;
-
-		foreach $branch (@$line) {
-			# Skip alignment space
-			if ($branch eq " ") {
-				$current .= " ";
-				$current_len++;
-				next;
-			}
-
-			my ($block_num, $br_num, $taken, $len, $open, $close) =
-			   @{$branch};
-			my $class;
-			my $title;
-			my $text;
-
-			if ($taken eq '-') {
-				$class	= "branchNoExec";
-				$text	= " # ";
-				$title	= "Branch $br_num was not executed";
-			} elsif ($taken == 0) {
-				$class	= "branchNoCov";
-				$text	= " - ";
-				$title	= "Branch $br_num was not taken";
-			} else {
-				$class	= "branchCov";
-				$text	= " + ";
-				$title	= "Branch $br_num was taken $taken ".
-					  "time";
-				$title .= "s" if ($taken > 1);
-			}
-			$current .= "[" if ($open);
-			$current .= "";
-			$current .= $text."";
-			$current .= "]" if ($close);
-			$current_len += $len;
-		}
-
-		# Right-align result text
-		if ($current_len < $br_field_width) {
-			$current = (" "x($br_field_width - $current_len)).
-				   $current;
-		}
-		push(@result, $current);
-	}
-
-	return @result;
-}
-
-
-#
-# format_count(count, width)
-#
-# Return a right-aligned representation of count that fits in width characters.
-#
-
-sub format_count($$)
-{
-	my ($count, $width) = @_;
-	my $result;
-	my $exp;
-
-	$result = sprintf("%*.0f", $width, $count);
-	while (length($result) > $width) {
-		last if ($count < 10);
-		$exp++;
-		$count = int($count/10);
-		$result = sprintf("%*s", $width, ">$count*10^$exp");
-	}
-	return $result;
-}
-
-#
-# write_source_line(filehandle, line_num, source, hit_count, converted,
-#                   brdata)
-#
-# Write formatted source code line. Return a line in a format as needed
-# by gen_png()
-#
-
-sub write_source_line(*$$$$$)
-{
-	my ($handle, $line, $source, $count, $converted, $brdata) = @_;
-	my $source_format;
-	my $count_format;
-	my $result;
-	my $anchor_start = "";
-	my $anchor_end = "";
-	my $count_field_width = $line_field_width - 1;
-	my @br_html;
-	my $html;
-
-	# Get branch HTML data for this line
-	@br_html = get_branch_html($brdata) if ($br_coverage);
-
-	if (!defined($count)) {
-		$result		= "";
-		$source_format	= "";
-		$count_format	= " "x$count_field_width;
-	}
-	elsif ($count == 0) {
-		$result		= $count;
-		$source_format	= '';
-		$count_format	= format_count($count, $count_field_width);
-	}
-	elsif ($converted && defined($highlight)) {
-		$result		= "*".$count;
-		$source_format	= '';
-		$count_format	= format_count($count, $count_field_width);
-	}
-	else {
-		$result		= $count;
-		$source_format	= '';
-		$count_format	= format_count($count, $count_field_width);
-	}
-	$result .= ":".$source;
-
-	# Write out a line number navigation anchor every $nav_resolution
-	# lines if necessary
-	$anchor_start	= "";
-	$anchor_end	= "";
-
-
-	# *************************************************************
-
-	$html = $anchor_start;
-	$html .= "".sprintf("%8d", $line)." ";
-	$html .= shift(@br_html).":" if ($br_coverage);
-	$html .= "$source_format$count_format : ";
-	$html .= escape_html($source);
-	$html .= "" if ($source_format);
-	$html .= $anchor_end."\n";
-
-	write_html($handle, $html);
-
-	if ($br_coverage) {
-		# Add lines for overlong branch information
-		foreach (@br_html) {
-			write_html($handle, "".
-				   "         $_\n");
-		}
-	}
-	# *************************************************************
-
-	return($result);
-}
-
-
-#
-# write_source_epilog(filehandle)
-#
-# Write end of source code table.
-#
-
-sub write_source_epilog(*)
-{
-	# *************************************************************
-
-	write_html($_[0], <
-	      
-	    
-	  
-	  
- -END_OF_HTML - ; - - # ************************************************************* -} - - -# -# write_html_epilog(filehandle, base_dir[, break_frames]) -# -# Write HTML page footer to FILEHANDLE. BREAK_FRAMES should be set when -# this page is embedded in a frameset, clicking the URL link will then -# break this frameset. -# - -sub write_html_epilog(*$;$) -{ - my $basedir = $_[1]; - my $break_code = ""; - my $epilog; - - if (defined($_[2])) - { - $break_code = " target=\"_parent\""; - } - - # ************************************************************* - - write_html($_[0], < - - Generated by: $lcov_version - -
-END_OF_HTML - ; - - $epilog = $html_epilog; - $epilog =~ s/\@basedir\@/$basedir/g; - - write_html($_[0], $epilog); -} - - -# -# write_frameset(filehandle, basedir, basename, pagetitle) -# -# - -sub write_frameset(*$$$) -{ - my $frame_width = $overview_width + 40; - - # ************************************************************* - - write_html($_[0], < - - - - - - $_[3] - - - - - - - - <center>Frames not supported by your browser!<br></center> - - - - -END_OF_HTML - ; - - # ************************************************************* -} - - -# -# sub write_overview_line(filehandle, basename, line, link) -# -# - -sub write_overview_line(*$$$) -{ - my $y1 = $_[2] - 1; - my $y2 = $y1 + $nav_resolution - 1; - my $x2 = $overview_width - 1; - - # ************************************************************* - - write_html($_[0], < -END_OF_HTML - ; - - # ************************************************************* -} - - -# -# write_overview(filehandle, basedir, basename, pagetitle, lines) -# -# - -sub write_overview(*$$$$) -{ - my $index; - my $max_line = $_[4] - 1; - my $offset; - - # ************************************************************* - - write_html($_[0], < - - - - - $_[3] - - - - - - -END_OF_HTML - ; - - # ************************************************************* - - # Make $offset the next higher multiple of $nav_resolution - $offset = ($nav_offset + $nav_resolution - 1) / $nav_resolution; - $offset = sprintf("%d", $offset ) * $nav_resolution; - - # Create image map for overview image - for ($index = 1; $index <= $_[4]; $index += $nav_resolution) - { - # Enforce nav_offset - if ($index < $offset + 1) - { - write_overview_line($_[0], $_[2], $index, 1); - } - else - { - write_overview_line($_[0], $_[2], $index, $index - $offset); - } - } - - # ************************************************************* - - write_html($_[0], < - -
- Top

- Overview -
- - -END_OF_HTML - ; - - # ************************************************************* -} - - -sub max($$) -{ - my ($a, $b) = @_; - - return $a if ($a > $b); - return $b; -} - - -# -# write_header(filehandle, type, trunc_file_name, rel_file_name, lines_found, -# lines_hit, funcs_found, funcs_hit, sort_type) -# -# Write a complete standard page header. TYPE may be (0, 1, 2, 3, 4) -# corresponding to (directory view header, file view header, source view -# header, test case description header, function view header) -# - -sub write_header(*$$$$$$$$$$) -{ - local *HTML_HANDLE = $_[0]; - my $type = $_[1]; - my $trunc_name = $_[2]; - my $rel_filename = $_[3]; - my $lines_found = $_[4]; - my $lines_hit = $_[5]; - my $fn_found = $_[6]; - my $fn_hit = $_[7]; - my $br_found = $_[8]; - my $br_hit = $_[9]; - my $sort_type = $_[10]; - my $base_dir; - my $view; - my $test; - my $base_name; - my $style; - my $rate; - my @row_left; - my @row_right; - my $num_rows; - my $i; - my $esc_trunc_name = escape_html($trunc_name); - - $base_name = basename($rel_filename); - - # Prepare text for "current view" field - if ($type == $HDR_DIR) - { - # Main overview - $base_dir = ""; - $view = $overview_title; - } - elsif ($type == $HDR_FILE) - { - # Directory overview - $base_dir = get_relative_base_path($rel_filename); - $view = "". - "$overview_title - $esc_trunc_name"; - } - elsif ($type == $HDR_SOURCE || $type == $HDR_FUNC) - { - # File view - my $dir_name = dirname($rel_filename); - my $esc_base_name = escape_html($base_name); - my $esc_dir_name = escape_html($dir_name); - - $base_dir = get_relative_base_path($dir_name); - if ($frames) - { - # Need to break frameset when clicking any of these - # links - $view = "$overview_title - ". - "". - "$esc_dir_name - $esc_base_name"; - } - else - { - $view = "". - "$overview_title - ". - "". - "$esc_dir_name - $esc_base_name"; - } - - # Add function suffix - if ($func_coverage) { - $view .= ""; - if ($type == $HDR_SOURCE) { - if ($sort) { - $view .= " (source / functions)"; - } else { - $view .= " (source / functions)"; - } - } elsif ($type == $HDR_FUNC) { - $view .= " (source / functions)"; - } - $view .= ""; - } - } - elsif ($type == $HDR_TESTDESC) - { - # Test description header - $base_dir = ""; - $view = "". - "$overview_title - test case descriptions"; - } - - # Prepare text for "test" field - $test = escape_html($test_title); - - # Append link to test description page if available - if (%test_description && ($type != $HDR_TESTDESC)) - { - if ($frames && ($type == $HDR_SOURCE || $type == $HDR_FUNC)) - { - # Need to break frameset when clicking this link - $test .= " ( ". - "". - "view descriptions )"; - } - else - { - $test .= " ( ". - "". - "view descriptions )"; - } - } - - # Write header - write_header_prolog(*HTML_HANDLE, $base_dir); - - # Left row - push(@row_left, [[ "10%", "headerItem", "Current view:" ], - [ "35%", "headerValue", $view ]]); - push(@row_left, [[undef, "headerItem", "Test:"], - [undef, "headerValue", $test]]); - push(@row_left, [[undef, "headerItem", "Date:"], - [undef, "headerValue", $date]]); - - # Right row - if ($legend && ($type == $HDR_SOURCE || $type == $HDR_FUNC)) { - my $text = <hit
- not hit -END_OF_HTML - if ($br_coverage) { - $text .= <+
taken - - not taken - # not executed -END_OF_HTML - } - push(@row_left, [[undef, "headerItem", "Legend:"], - [undef, "headerValueLeg", $text]]); - } elsif ($legend && ($type != $HDR_TESTDESC)) { - my $text = <low: < $med_limit % - medium: >= $med_limit % - high: >= $hi_limit % -END_OF_HTML - push(@row_left, [[undef, "headerItem", "Legend:"], - [undef, "headerValueLeg", $text]]); - } - if ($type == $HDR_TESTDESC) { - push(@row_right, [[ "55%" ]]); - } else { - push(@row_right, [["15%", undef, undef ], - ["10%", "headerCovTableHead", "Hit" ], - ["10%", "headerCovTableHead", "Total" ], - ["15%", "headerCovTableHead", "Coverage"]]); - } - # Line coverage - $style = $rate_name[classify_rate($lines_found, $lines_hit, - $med_limit, $hi_limit)]; - $rate = rate($lines_hit, $lines_found, " %"); - push(@row_right, [[undef, "headerItem", "Lines:"], - [undef, "headerCovTableEntry", $lines_hit], - [undef, "headerCovTableEntry", $lines_found], - [undef, "headerCovTableEntry$style", $rate]]) - if ($type != $HDR_TESTDESC); - # Function coverage - if ($func_coverage) { - $style = $rate_name[classify_rate($fn_found, $fn_hit, - $fn_med_limit, $fn_hi_limit)]; - $rate = rate($fn_hit, $fn_found, " %"); - push(@row_right, [[undef, "headerItem", "Functions:"], - [undef, "headerCovTableEntry", $fn_hit], - [undef, "headerCovTableEntry", $fn_found], - [undef, "headerCovTableEntry$style", $rate]]) - if ($type != $HDR_TESTDESC); - } - # Branch coverage - if ($br_coverage) { - $style = $rate_name[classify_rate($br_found, $br_hit, - $br_med_limit, $br_hi_limit)]; - $rate = rate($br_hit, $br_found, " %"); - push(@row_right, [[undef, "headerItem", "Branches:"], - [undef, "headerCovTableEntry", $br_hit], - [undef, "headerCovTableEntry", $br_found], - [undef, "headerCovTableEntry$style", $rate]]) - if ($type != $HDR_TESTDESC); - } - - # Print rows - $num_rows = max(scalar(@row_left), scalar(@row_right)); - for ($i = 0; $i < $num_rows; $i++) { - my $left = $row_left[$i]; - my $right = $row_right[$i]; - - if (!defined($left)) { - $left = [[undef, undef, undef], [undef, undef, undef]]; - } - if (!defined($right)) { - $right = []; - } - write_header_line(*HTML_HANDLE, @{$left}, - [ $i == 0 ? "5%" : undef, undef, undef], - @{$right}); - } - - # Fourth line - write_header_epilog(*HTML_HANDLE, $base_dir); -} - -sub get_sorted_by_rate($$) -{ - my ($hash, $type) = @_; - - if ($type == $SORT_LINE) { - # Sort by line coverage - return sort({$hash->{$a}[7] <=> $hash->{$b}[7]} keys(%{$hash})); - } elsif ($type == $SORT_FUNC) { - # Sort by function coverage; - return sort({$hash->{$a}[8] <=> $hash->{$b}[8]} keys(%{$hash})); - } elsif ($type == $SORT_BRANCH) { - # Sort by br coverage; - return sort({$hash->{$a}[9] <=> $hash->{$b}[9]} keys(%{$hash})); - } -} - -sub get_sorted_by_missed($$) -{ - my ($hash, $type) = @_; - - if ($type == $SORT_LINE) { - # Sort by number of instrumented lines without coverage - return sort( - { - ($hash->{$b}[0] - $hash->{$b}[1]) <=> - ($hash->{$a}[0] - $hash->{$a}[1]) - } keys(%{$hash})); - } elsif ($type == $SORT_FUNC) { - # Sort by number of instrumented functions without coverage - return sort( - { - ($hash->{$b}[2] - $hash->{$b}[3]) <=> - ($hash->{$a}[2] - $hash->{$a}[3]) - } keys(%{$hash})); - } elsif ($type == $SORT_BRANCH) { - # Sort by number of instrumented branches without coverage - return sort( - { - ($hash->{$b}[4] - $hash->{$b}[5]) <=> - ($hash->{$a}[4] - $hash->{$a}[5]) - } keys(%{$hash})); - } -} - -# -# get_sorted_keys(hash_ref, sort_type) -# -# hash_ref: filename -> stats -# stats: [ lines_found, lines_hit, fn_found, fn_hit, br_found, br_hit, -# link_name, line_rate, fn_rate, br_rate ] -# - -sub get_sorted_keys($$) -{ - my ($hash, $type) = @_; - - if ($type == $SORT_FILE) { - # Sort by name - return sort(keys(%{$hash})); - } elsif ($opt_missed) { - return get_sorted_by_missed($hash, $type); - } else { - return get_sorted_by_rate($hash, $type); - } -} - -sub get_sort_code($$$) -{ - my ($link, $alt, $base) = @_; - my $png; - my $link_start; - my $link_end; - - if (!defined($link)) { - $png = "glass.png"; - $link_start = ""; - $link_end = ""; - } else { - $png = "updown.png"; - $link_start = ''; - $link_end = ""; - } - - return ' '.$link_start. - ''.$link_end.''; -} - -sub get_file_code($$$$) -{ - my ($type, $text, $sort_button, $base) = @_; - my $result = $text; - my $link; - - if ($sort_button) { - if ($type == $HEAD_NO_DETAIL) { - $link = "index.$html_ext"; - } else { - $link = "index-detail.$html_ext"; - } - } - $result .= get_sort_code($link, "Sort by name", $base); - - return $result; -} - -sub get_line_code($$$$$) -{ - my ($type, $sort_type, $text, $sort_button, $base) = @_; - my $result = $text; - my $sort_link; - - if ($type == $HEAD_NO_DETAIL) { - # Just text - if ($sort_button) { - $sort_link = "index-sort-l.$html_ext"; - } - } elsif ($type == $HEAD_DETAIL_HIDDEN) { - # Text + link to detail view - $result .= ' ( show details )'; - if ($sort_button) { - $sort_link = "index-sort-l.$html_ext"; - } - } else { - # Text + link to standard view - $result .= ' ( hide details )'; - if ($sort_button) { - $sort_link = "index-detail-sort-l.$html_ext"; - } - } - # Add sort button - $result .= get_sort_code($sort_link, "Sort by line coverage", $base); - - return $result; -} - -sub get_func_code($$$$) -{ - my ($type, $text, $sort_button, $base) = @_; - my $result = $text; - my $link; - - if ($sort_button) { - if ($type == $HEAD_NO_DETAIL) { - $link = "index-sort-f.$html_ext"; - } else { - $link = "index-detail-sort-f.$html_ext"; - } - } - $result .= get_sort_code($link, "Sort by function coverage", $base); - return $result; -} - -sub get_br_code($$$$) -{ - my ($type, $text, $sort_button, $base) = @_; - my $result = $text; - my $link; - - if ($sort_button) { - if ($type == $HEAD_NO_DETAIL) { - $link = "index-sort-b.$html_ext"; - } else { - $link = "index-detail-sort-b.$html_ext"; - } - } - $result .= get_sort_code($link, "Sort by branch coverage", $base); - return $result; -} - -# -# write_file_table(filehandle, base_dir, overview, testhash, testfnchash, -# testbrhash, fileview, sort_type) -# -# Write a complete file table. OVERVIEW is a reference to a hash containing -# the following mapping: -# -# filename -> "lines_found,lines_hit,funcs_found,funcs_hit,page_link, -# func_link" -# -# TESTHASH is a reference to the following hash: -# -# filename -> \%testdata -# %testdata: name of test affecting this file -> \%testcount -# %testcount: line number -> execution count for a single test -# -# Heading of first column is "Filename" if FILEVIEW is true, "Directory name" -# otherwise. -# - -sub write_file_table(*$$$$$$$) -{ - local *HTML_HANDLE = $_[0]; - my $base_dir = $_[1]; - my $overview = $_[2]; - my $testhash = $_[3]; - my $testfnchash = $_[4]; - my $testbrhash = $_[5]; - my $fileview = $_[6]; - my $sort_type = $_[7]; - my $filename; - my $bar_graph; - my $hit; - my $found; - my $fn_found; - my $fn_hit; - my $br_found; - my $br_hit; - my $page_link; - my $testname; - my $testdata; - my $testfncdata; - my $testbrdata; - my %affecting_tests; - my $line_code = ""; - my $func_code; - my $br_code; - my $file_code; - my @head_columns; - - # Determine HTML code for column headings - if (($base_dir ne "") && $show_details) - { - my $detailed = keys(%{$testhash}); - - $file_code = get_file_code($detailed ? $HEAD_DETAIL_HIDDEN : - $HEAD_NO_DETAIL, - $fileview ? "Filename" : "Directory", - $sort && $sort_type != $SORT_FILE, - $base_dir); - $line_code = get_line_code($detailed ? $HEAD_DETAIL_SHOWN : - $HEAD_DETAIL_HIDDEN, - $sort_type, - "Line Coverage", - $sort && $sort_type != $SORT_LINE, - $base_dir); - $func_code = get_func_code($detailed ? $HEAD_DETAIL_HIDDEN : - $HEAD_NO_DETAIL, - "Functions", - $sort && $sort_type != $SORT_FUNC, - $base_dir); - $br_code = get_br_code($detailed ? $HEAD_DETAIL_HIDDEN : - $HEAD_NO_DETAIL, - "Branches", - $sort && $sort_type != $SORT_BRANCH, - $base_dir); - } else { - $file_code = get_file_code($HEAD_NO_DETAIL, - $fileview ? "Filename" : "Directory", - $sort && $sort_type != $SORT_FILE, - $base_dir); - $line_code = get_line_code($HEAD_NO_DETAIL, $sort_type, "Line Coverage", - $sort && $sort_type != $SORT_LINE, - $base_dir); - $func_code = get_func_code($HEAD_NO_DETAIL, "Functions", - $sort && $sort_type != $SORT_FUNC, - $base_dir); - $br_code = get_br_code($HEAD_NO_DETAIL, "Branches", - $sort && $sort_type != $SORT_BRANCH, - $base_dir); - } - push(@head_columns, [ $line_code, 3 ]); - push(@head_columns, [ $func_code, 2]) if ($func_coverage); - push(@head_columns, [ $br_code, 2]) if ($br_coverage); - - write_file_table_prolog(*HTML_HANDLE, $file_code, @head_columns); - - foreach $filename (get_sorted_keys($overview, $sort_type)) - { - my @columns; - ($found, $hit, $fn_found, $fn_hit, $br_found, $br_hit, - $page_link) = @{$overview->{$filename}}; - - # Line coverage - push(@columns, [$found, $hit, $med_limit, $hi_limit, 1]); - # Function coverage - if ($func_coverage) { - push(@columns, [$fn_found, $fn_hit, $fn_med_limit, - $fn_hi_limit, 0]); - } - # Branch coverage - if ($br_coverage) { - push(@columns, [$br_found, $br_hit, $br_med_limit, - $br_hi_limit, 0]); - } - write_file_table_entry(*HTML_HANDLE, $base_dir, $filename, - $page_link, @columns); - - $testdata = $testhash->{$filename}; - $testfncdata = $testfnchash->{$filename}; - $testbrdata = $testbrhash->{$filename}; - - # Check whether we should write test specific coverage - # as well - if (!($show_details && $testdata)) { next; } - - # Filter out those tests that actually affect this file - %affecting_tests = %{ get_affecting_tests($testdata, - $testfncdata, $testbrdata) }; - - # Does any of the tests affect this file at all? - if (!%affecting_tests) { next; } - - foreach $testname (keys(%affecting_tests)) - { - my @results; - ($found, $hit, $fn_found, $fn_hit, $br_found, $br_hit) = - split(",", $affecting_tests{$testname}); - - # Insert link to description of available - if ($test_description{$testname}) - { - $testname = "". - "$testname"; - } - - push(@results, [$found, $hit]); - push(@results, [$fn_found, $fn_hit]) if ($func_coverage); - push(@results, [$br_found, $br_hit]) if ($br_coverage); - write_file_table_detail_entry(*HTML_HANDLE, $testname, - @results); - } - } - - write_file_table_epilog(*HTML_HANDLE); -} - - -# -# get_found_and_hit(hash) -# -# Return the count for entries (found) and entries with an execution count -# greater than zero (hit) in a hash (linenumber -> execution count) as -# a list (found, hit) -# - -sub get_found_and_hit($) -{ - my %hash = %{$_[0]}; - my $found = 0; - my $hit = 0; - - # Calculate sum - $found = 0; - $hit = 0; - - foreach (keys(%hash)) - { - $found++; - if ($hash{$_}>0) { $hit++; } - } - - return ($found, $hit); -} - - -# -# get_func_found_and_hit(sumfnccount) -# -# Return (f_found, f_hit) for sumfnccount -# - -sub get_func_found_and_hit($) -{ - my ($sumfnccount) = @_; - my $function; - my $fn_found; - my $fn_hit; - - $fn_found = scalar(keys(%{$sumfnccount})); - $fn_hit = 0; - foreach $function (keys(%{$sumfnccount})) { - if ($sumfnccount->{$function} > 0) { - $fn_hit++; - } - } - return ($fn_found, $fn_hit); -} - - -sub get_br_found_and_hit($) -{ - my ($brcount) = @_; - my $db; - - $db = brcount_to_db($brcount); - - return brcount_db_get_found_and_hit($db); -} - - -# -# get_affecting_tests(testdata, testfncdata, testbrdata) -# -# HASHREF contains a mapping filename -> (linenumber -> exec count). Return -# a hash containing mapping filename -> "lines found, lines hit" for each -# filename which has a nonzero hit count. -# - -sub get_affecting_tests($$$) -{ - my ($testdata, $testfncdata, $testbrdata) = @_; - my $testname; - my $testcount; - my $testfnccount; - my $testbrcount; - my %result; - my $found; - my $hit; - my $fn_found; - my $fn_hit; - my $br_found; - my $br_hit; - - foreach $testname (keys(%{$testdata})) - { - # Get (line number -> count) hash for this test case - $testcount = $testdata->{$testname}; - $testfnccount = $testfncdata->{$testname}; - $testbrcount = $testbrdata->{$testname}; - - # Calculate sum - ($found, $hit) = get_found_and_hit($testcount); - ($fn_found, $fn_hit) = get_func_found_and_hit($testfnccount); - ($br_found, $br_hit) = get_br_found_and_hit($testbrcount); - - if ($hit>0) - { - $result{$testname} = "$found,$hit,$fn_found,$fn_hit,". - "$br_found,$br_hit"; - } - } - - return(\%result); -} - - -sub get_hash_reverse($) -{ - my ($hash) = @_; - my %result; - - foreach (keys(%{$hash})) { - $result{$hash->{$_}} = $_; - } - - return \%result; -} - -# -# write_source(filehandle, source_filename, count_data, checksum_data, -# converted_data, func_data, sumbrcount) -# -# Write an HTML view of a source code file. Returns a list containing -# data as needed by gen_png(). -# -# Die on error. -# - -sub write_source($$$$$$$) -{ - local *HTML_HANDLE = $_[0]; - local *SOURCE_HANDLE; - my $source_filename = $_[1]; - my %count_data; - my $line_number; - my @result; - my $checkdata = $_[3]; - my $converted = $_[4]; - my $funcdata = $_[5]; - my $sumbrcount = $_[6]; - my $datafunc = get_hash_reverse($funcdata); - my @file; - - if ($_[2]) - { - %count_data = %{$_[2]}; - } - - if (!open(SOURCE_HANDLE, "<", $source_filename)) { - my @lines; - my $last_line = 0; - - if (!$ignore[$ERROR_SOURCE]) { - die("ERROR: cannot read $source_filename\n"); - } - - # Continue without source file - warn("WARNING: cannot read $source_filename!\n"); - - @lines = sort( { $a <=> $b } keys(%count_data)); - if (@lines) { - $last_line = $lines[scalar(@lines) - 1]; - } - return ( ":" ) if ($last_line < 1); - - # Simulate gcov behavior - for ($line_number = 1; $line_number <= $last_line; - $line_number++) { - push(@file, "/* EOF */"); - } - } else { - @file = ; - } - - write_source_prolog(*HTML_HANDLE); - $line_number = 0; - foreach (@file) { - $line_number++; - chomp($_); - - # Also remove CR from line-end - s/\015$//; - - # Source code matches coverage data? - if (defined($checkdata->{$line_number}) && - ($checkdata->{$line_number} ne md5_base64($_))) - { - die("ERROR: checksum mismatch at $source_filename:". - "$line_number\n"); - } - - push (@result, - write_source_line(HTML_HANDLE, $line_number, - $_, $count_data{$line_number}, - $converted->{$line_number}, - $sumbrcount->{$line_number})); - } - - close(SOURCE_HANDLE); - write_source_epilog(*HTML_HANDLE); - return(@result); -} - - -sub funcview_get_func_code($$$) -{ - my ($name, $base, $type) = @_; - my $result; - my $link; - - if ($sort && $type == 1) { - $link = "$name.func.$html_ext"; - } - $result = "Function Name"; - $result .= get_sort_code($link, "Sort by function name", $base); - - return $result; -} - -sub funcview_get_count_code($$$) -{ - my ($name, $base, $type) = @_; - my $result; - my $link; - - if ($sort && $type == 0) { - $link = "$name.func-sort-c.$html_ext"; - } - $result = "Hit count"; - $result .= get_sort_code($link, "Sort by hit count", $base); - - return $result; -} - -# -# funcview_get_sorted(funcdata, sumfncdata, sort_type) -# -# Depending on the value of sort_type, return a list of functions sorted -# by name (type 0) or by the associated call count (type 1). -# - -sub funcview_get_sorted($$$) -{ - my ($funcdata, $sumfncdata, $type) = @_; - - if ($type == 0) { - return sort(keys(%{$funcdata})); - } - return sort({ - $sumfncdata->{$b} == $sumfncdata->{$a} ? - $a cmp $b : $sumfncdata->{$a} <=> $sumfncdata->{$b} - } keys(%{$sumfncdata})); -} - -sub demangle_list($) -{ - my ($list) = @_; - my $tmpfile; - my $handle; - my %demangle; - my $demangle_arg = ""; - my %versions; - - # Write function names to file - ($handle, $tmpfile) = tempfile(); - die("ERROR: could not create temporary file") if (!defined($tmpfile)); - print($handle join("\n", @$list)); - close($handle); - - # Extra flag necessary on OS X so that symbols listed by gcov get demangled - # properly. - if ($^O eq "darwin") { - $demangle_arg = "--no-strip-underscores"; - } - - # Build translation hash from c++filt output - open($handle, "-|", "c++filt $demangle_arg < $tmpfile") or - die("ERROR: could not run c++filt: $!\n"); - foreach my $func (@$list) { - my $translated = <$handle>; - my $version; - - last if (!defined($translated)); - chomp($translated); - - $version = ++$versions{$translated}; - $translated .= ".$version" if ($version > 1); - $demangle{$func} = $translated; - } - close($handle); - - if (scalar(keys(%demangle)) != scalar(@$list)) { - die("ERROR: c++filt output not as expected (". - scalar(keys(%demangle))." vs ".scalar(@$list).") lines\n"); - } - - unlink($tmpfile) or - warn("WARNING: could not remove temporary file $tmpfile: $!\n"); - - return \%demangle; -} - -# -# write_function_table(filehandle, source_file, sumcount, funcdata, -# sumfnccount, testfncdata, sumbrcount, testbrdata, -# base_name, base_dir, sort_type) -# -# Write an HTML table listing all functions in a source file, including -# also function call counts and line coverages inside of each function. -# -# Die on error. -# - -sub write_function_table(*$$$$$$$$$$) -{ - local *HTML_HANDLE = $_[0]; - my $source = $_[1]; - my $sumcount = $_[2]; - my $funcdata = $_[3]; - my $sumfncdata = $_[4]; - my $testfncdata = $_[5]; - my $sumbrcount = $_[6]; - my $testbrdata = $_[7]; - my $name = $_[8]; - my $base = $_[9]; - my $type = $_[10]; - my $func; - my $func_code; - my $count_code; - my $demangle; - - # Get HTML code for headings - $func_code = funcview_get_func_code($name, $base, $type); - $count_code = funcview_get_count_code($name, $base, $type); - write_html(*HTML_HANDLE, < - - - - - - -END_OF_HTML - ; - - # Get demangle translation hash - if ($demangle_cpp) { - $demangle = demangle_list([ sort(keys(%{$funcdata})) ]); - } - - # Get a sorted table - foreach $func (funcview_get_sorted($funcdata, $sumfncdata, $type)) { - if (!defined($funcdata->{$func})) - { - next; - } - - my $startline = $funcdata->{$func} - $func_offset; - my $name = $func; - my $count = $sumfncdata->{$name}; - my $countstyle; - - # Replace function name with demangled version if available - $name = $demangle->{$name} if (exists($demangle->{$name})); - - # Escape special characters - $name = escape_html($name); - if ($startline < 1) { - $startline = 1; - } - if ($count == 0) { - $countstyle = "coverFnLo"; - } else { - $countstyle = "coverFnHi"; - } - - write_html(*HTML_HANDLE, < - - - -END_OF_HTML - ; - } - write_html(*HTML_HANDLE, < -
- -END_OF_HTML - ; -} - - -# -# info(printf_parameter) -# -# Use printf to write PRINTF_PARAMETER to stdout only when the $quiet flag -# is not set. -# - -sub info(@) -{ - if (!$quiet) - { - # Print info string - printf(@_); - } -} - - -# -# subtract_counts(data_ref, base_ref) -# - -sub subtract_counts($$) -{ - my %data = %{$_[0]}; - my %base = %{$_[1]}; - my $line; - my $data_count; - my $base_count; - my $hit = 0; - my $found = 0; - - foreach $line (keys(%data)) - { - $found++; - $data_count = $data{$line}; - $base_count = $base{$line}; - - if (defined($base_count)) - { - $data_count -= $base_count; - - # Make sure we don't get negative numbers - if ($data_count<0) { $data_count = 0; } - } - - $data{$line} = $data_count; - if ($data_count > 0) { $hit++; } - } - - return (\%data, $found, $hit); -} - - -# -# subtract_fnccounts(data, base) -# -# Subtract function call counts found in base from those in data. -# Return (data, f_found, f_hit). -# - -sub subtract_fnccounts($$) -{ - my %data; - my %base; - my $func; - my $data_count; - my $base_count; - my $fn_hit = 0; - my $fn_found = 0; - - %data = %{$_[0]} if (defined($_[0])); - %base = %{$_[1]} if (defined($_[1])); - foreach $func (keys(%data)) { - $fn_found++; - $data_count = $data{$func}; - $base_count = $base{$func}; - - if (defined($base_count)) { - $data_count -= $base_count; - - # Make sure we don't get negative numbers - if ($data_count < 0) { - $data_count = 0; - } - } - - $data{$func} = $data_count; - if ($data_count > 0) { - $fn_hit++; - } - } - - return (\%data, $fn_found, $fn_hit); -} - - -# -# apply_baseline(data_ref, baseline_ref) -# -# Subtract the execution counts found in the baseline hash referenced by -# BASELINE_REF from actual data in DATA_REF. -# - -sub apply_baseline($$) -{ - my %data_hash = %{$_[0]}; - my %base_hash = %{$_[1]}; - my $filename; - my $testname; - my $data; - my $data_testdata; - my $data_funcdata; - my $data_checkdata; - my $data_testfncdata; - my $data_testbrdata; - my $data_count; - my $data_testfnccount; - my $data_testbrcount; - my $base; - my $base_checkdata; - my $base_sumfnccount; - my $base_sumbrcount; - my $base_count; - my $sumcount; - my $sumfnccount; - my $sumbrcount; - my $found; - my $hit; - my $fn_found; - my $fn_hit; - my $br_found; - my $br_hit; - - foreach $filename (keys(%data_hash)) - { - # Get data set for data and baseline - $data = $data_hash{$filename}; - $base = $base_hash{$filename}; - - # Skip data entries for which no base entry exists - if (!defined($base)) - { - next; - } - - # Get set entries for data and baseline - ($data_testdata, undef, $data_funcdata, $data_checkdata, - $data_testfncdata, undef, $data_testbrdata) = - get_info_entry($data); - (undef, $base_count, undef, $base_checkdata, undef, - $base_sumfnccount, undef, $base_sumbrcount) = - get_info_entry($base); - - # Check for compatible checksums - merge_checksums($data_checkdata, $base_checkdata, $filename); - - # sumcount has to be calculated anew - $sumcount = {}; - $sumfnccount = {}; - $sumbrcount = {}; - - # For each test case, subtract test specific counts - foreach $testname (keys(%{$data_testdata})) - { - # Get counts of both data and baseline - $data_count = $data_testdata->{$testname}; - $data_testfnccount = $data_testfncdata->{$testname}; - $data_testbrcount = $data_testbrdata->{$testname}; - - ($data_count, undef, $hit) = - subtract_counts($data_count, $base_count); - ($data_testfnccount) = - subtract_fnccounts($data_testfnccount, - $base_sumfnccount); - ($data_testbrcount) = - combine_brcount($data_testbrcount, - $base_sumbrcount, $BR_SUB); - - - # Check whether this test case did hit any line at all - if ($hit > 0) - { - # Write back resulting hash - $data_testdata->{$testname} = $data_count; - $data_testfncdata->{$testname} = - $data_testfnccount; - $data_testbrdata->{$testname} = - $data_testbrcount; - } - else - { - # Delete test case which did not impact this - # file - delete($data_testdata->{$testname}); - delete($data_testfncdata->{$testname}); - delete($data_testbrdata->{$testname}); - } - - # Add counts to sum of counts - ($sumcount, $found, $hit) = - add_counts($sumcount, $data_count); - ($sumfnccount, $fn_found, $fn_hit) = - add_fnccount($sumfnccount, $data_testfnccount); - ($sumbrcount, $br_found, $br_hit) = - combine_brcount($sumbrcount, $data_testbrcount, - $BR_ADD); - } - - # Write back resulting entry - set_info_entry($data, $data_testdata, $sumcount, $data_funcdata, - $data_checkdata, $data_testfncdata, $sumfnccount, - $data_testbrdata, $sumbrcount, $found, $hit, - $fn_found, $fn_hit, $br_found, $br_hit); - - $data_hash{$filename} = $data; - } - - return (\%data_hash); -} - - -# -# remove_unused_descriptions() -# -# Removes all test descriptions from the global hash %test_description which -# are not present in %info_data. -# - -sub remove_unused_descriptions() -{ - my $filename; # The current filename - my %test_list; # Hash containing found test names - my $test_data; # Reference to hash test_name -> count_data - my $before; # Initial number of descriptions - my $after; # Remaining number of descriptions - - $before = scalar(keys(%test_description)); - - foreach $filename (keys(%info_data)) - { - ($test_data) = get_info_entry($info_data{$filename}); - foreach (keys(%{$test_data})) - { - $test_list{$_} = ""; - } - } - - # Remove descriptions for tests which are not in our list - foreach (keys(%test_description)) - { - if (!defined($test_list{$_})) - { - delete($test_description{$_}); - } - } - - $after = scalar(keys(%test_description)); - if ($after < $before) - { - info("Removed ".($before - $after). - " unused descriptions, $after remaining.\n"); - } -} - - -# -# apply_prefix(filename, PREFIXES) -# -# If FILENAME begins with PREFIX from PREFIXES, remove PREFIX from FILENAME -# and return resulting string, otherwise return FILENAME. -# - -sub apply_prefix($@) -{ - my $filename = shift; - my @dir_prefix = @_; - - if (@dir_prefix) - { - foreach my $prefix (@dir_prefix) - { - if ($prefix ne "" && $filename =~ /^\Q$prefix\E\/(.*)$/) - { - return substr($filename, length($prefix) + 1); - } - } - } - - return $filename; -} - - -# -# system_no_output(mode, parameters) -# -# Call an external program using PARAMETERS while suppressing depending on -# the value of MODE: -# -# MODE & 1: suppress STDOUT -# MODE & 2: suppress STDERR -# -# Return 0 on success, non-zero otherwise. -# - -sub system_no_output($@) -{ - my $mode = shift; - my $result; - local *OLD_STDERR; - local *OLD_STDOUT; - - # Save old stdout and stderr handles - ($mode & 1) && open(OLD_STDOUT, ">>&", "STDOUT"); - ($mode & 2) && open(OLD_STDERR, ">>&", "STDERR"); - - # Redirect to /dev/null - ($mode & 1) && open(STDOUT, ">", "/dev/null"); - ($mode & 2) && open(STDERR, ">", "/dev/null"); - - system(@_); - $result = $?; - - # Close redirected handles - ($mode & 1) && close(STDOUT); - ($mode & 2) && close(STDERR); - - # Restore old handles - ($mode & 1) && open(STDOUT, ">>&", "OLD_STDOUT"); - ($mode & 2) && open(STDERR, ">>&", "OLD_STDERR"); - - return $result; -} - - -# -# read_config(filename) -# -# Read configuration file FILENAME and return a reference to a hash containing -# all valid key=value pairs found. -# - -sub read_config($) -{ - my $filename = $_[0]; - my %result; - my $key; - my $value; - local *HANDLE; - - if (!open(HANDLE, "<", $filename)) - { - warn("WARNING: cannot read configuration file $filename\n"); - return undef; - } - while () - { - chomp; - # Skip comments - s/#.*//; - # Remove leading blanks - s/^\s+//; - # Remove trailing blanks - s/\s+$//; - next unless length; - ($key, $value) = split(/\s*=\s*/, $_, 2); - if (defined($key) && defined($value)) - { - $result{$key} = $value; - } - else - { - warn("WARNING: malformed statement in line $. ". - "of configuration file $filename\n"); - } - } - close(HANDLE); - return \%result; -} - - -# -# apply_config(REF) -# -# REF is a reference to a hash containing the following mapping: -# -# key_string => var_ref -# -# where KEY_STRING is a keyword and VAR_REF is a reference to an associated -# variable. If the global configuration hashes CONFIG or OPT_RC contain a value -# for keyword KEY_STRING, VAR_REF will be assigned the value for that keyword. -# - -sub apply_config($) -{ - my $ref = $_[0]; - - foreach (keys(%{$ref})) - { - if (defined($opt_rc{$_})) { - ${$ref->{$_}} = $opt_rc{$_}; - } elsif (defined($config->{$_})) { - ${$ref->{$_}} = $config->{$_}; - } - } -} - - -# -# get_html_prolog(FILENAME) -# -# If FILENAME is defined, return contents of file. Otherwise return default -# HTML prolog. Die on error. -# - -sub get_html_prolog($) -{ - my $filename = $_[0]; - my $result = ""; - - if (defined($filename)) - { - local *HANDLE; - - open(HANDLE, "<", $filename) - or die("ERROR: cannot open html prolog $filename!\n"); - while () - { - $result .= $_; - } - close(HANDLE); - } - else - { - $result = < - - - - - - \@pagetitle\@ - - - - - -END_OF_HTML - ; - } - - return $result; -} - - -# -# get_html_epilog(FILENAME) -# -# If FILENAME is defined, return contents of file. Otherwise return default -# HTML epilog. Die on error. -# -sub get_html_epilog($) -{ - my $filename = $_[0]; - my $result = ""; - - if (defined($filename)) - { - local *HANDLE; - - open(HANDLE, "<", $filename) - or die("ERROR: cannot open html epilog $filename!\n"); - while () - { - $result .= $_; - } - close(HANDLE); - } - else - { - $result = < - -END_OF_HTML - ; - } - - return $result; - -} - -sub warn_handler($) -{ - my ($msg) = @_; - - warn("$tool_name: $msg"); -} - -sub die_handler($) -{ - my ($msg) = @_; - - die("$tool_name: $msg"); -} - -# -# parse_ignore_errors(@ignore_errors) -# -# Parse user input about which errors to ignore. -# - -sub parse_ignore_errors(@) -{ - my (@ignore_errors) = @_; - my @items; - my $item; - - return if (!@ignore_errors); - - foreach $item (@ignore_errors) { - $item =~ s/\s//g; - if ($item =~ /,/) { - # Split and add comma-separated parameters - push(@items, split(/,/, $item)); - } else { - # Add single parameter - push(@items, $item); - } - } - foreach $item (@items) { - my $item_id = $ERROR_ID{lc($item)}; - - if (!defined($item_id)) { - die("ERROR: unknown argument for --ignore-errors: ". - "$item\n"); - } - $ignore[$item_id] = 1; - } -} - -# -# parse_dir_prefix(@dir_prefix) -# -# Parse user input about the prefix list -# - -sub parse_dir_prefix(@) -{ - my (@opt_dir_prefix) = @_; - my $item; - - return if (!@opt_dir_prefix); - - foreach $item (@opt_dir_prefix) { - if ($item =~ /,/) { - # Split and add comma-separated parameters - push(@dir_prefix, split(/,/, $item)); - } else { - # Add single parameter - push(@dir_prefix, $item); - } - } -} - -# -# rate(hit, found[, suffix, precision, width]) -# -# Return the coverage rate [0..100] for HIT and FOUND values. 0 is only -# returned when HIT is 0. 100 is only returned when HIT equals FOUND. -# PRECISION specifies the precision of the result. SUFFIX defines a -# string that is appended to the result if FOUND is non-zero. Spaces -# are added to the start of the resulting string until it is at least WIDTH -# characters wide. -# - -sub rate($$;$$$) -{ - my ($hit, $found, $suffix, $precision, $width) = @_; - my $rate; - - # Assign defaults if necessary - $precision = $default_precision if (!defined($precision)); - $suffix = "" if (!defined($suffix)); - $width = 0 if (!defined($width)); - - return sprintf("%*s", $width, "-") if (!defined($found) || $found == 0); - $rate = sprintf("%.*f", $precision, $hit * 100 / $found); - - # Adjust rates if necessary - if ($rate == 0 && $hit > 0) { - $rate = sprintf("%.*f", $precision, 1 / 10 ** $precision); - } elsif ($rate == 100 && $hit != $found) { - $rate = sprintf("%.*f", $precision, 100 - 1 / 10 ** $precision); - } - - return sprintf("%*s", $width, $rate.$suffix); -} diff --git a/worker/deps/lcov/bin/geninfo b/worker/deps/lcov/bin/geninfo deleted file mode 100755 index 4e7a293146..0000000000 --- a/worker/deps/lcov/bin/geninfo +++ /dev/null @@ -1,4593 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright (c) International Business Machines Corp., 2002,2012 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# -# geninfo -# -# This script generates .info files from data files as created by code -# instrumented with gcc's built-in profiling mechanism. Call it with -# --help and refer to the geninfo man page to get information on usage -# and available options. -# -# -# Authors: -# 2002-08-23 created by Peter Oberparleiter -# IBM Lab Boeblingen -# based on code by Manoj Iyer and -# Megan Bock -# IBM Austin -# 2002-09-05 / Peter Oberparleiter: implemented option that allows file list -# 2003-04-16 / Peter Oberparleiter: modified read_gcov so that it can also -# parse the new gcov format which is to be introduced in gcc 3.3 -# 2003-04-30 / Peter Oberparleiter: made info write to STDERR, not STDOUT -# 2003-07-03 / Peter Oberparleiter: added line checksum support, added -# --no-checksum -# 2003-09-18 / Nigel Hinds: capture branch coverage data from GCOV -# 2003-12-11 / Laurent Deniel: added --follow option -# workaround gcov (<= 3.2.x) bug with empty .da files -# 2004-01-03 / Laurent Deniel: Ignore empty .bb files -# 2004-02-16 / Andreas Krebbel: Added support for .gcno/.gcda files and -# gcov versioning -# 2004-08-09 / Peter Oberparleiter: added configuration file support -# 2008-07-14 / Tom Zoerner: added --function-coverage command line option -# 2008-08-13 / Peter Oberparleiter: modified function coverage -# implementation (now enabled per default) -# - -use strict; -use warnings; -use File::Basename; -use File::Spec::Functions qw /abs2rel catdir file_name_is_absolute splitdir - splitpath catpath/; -use File::Temp qw(tempfile tempdir); -use File::Copy qw(copy); -use Getopt::Long; -use Digest::MD5 qw(md5_base64); -use Cwd qw/abs_path/; -use PerlIO::gzip; -use JSON qw(decode_json); - -if( $^O eq "msys" ) -{ - require File::Spec::Win32; -} - -# Constants -our $tool_dir = abs_path(dirname($0)); -our $lcov_version = 'LCOV version '.`$tool_dir/get_version.sh --full`; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; -our $gcov_tool = "gcov"; -our $tool_name = basename($0); - -our $GCOV_VERSION_8_0_0 = 0x80000; -our $GCOV_VERSION_4_7_0 = 0x40700; -our $GCOV_VERSION_3_4_0 = 0x30400; -our $GCOV_VERSION_3_3_0 = 0x30300; -our $GCNO_FUNCTION_TAG = 0x01000000; -our $GCNO_LINES_TAG = 0x01450000; -our $GCNO_FILE_MAGIC = 0x67636e6f; -our $BBG_FILE_MAGIC = 0x67626267; - -# Error classes which users may specify to ignore during processing -our $ERROR_GCOV = 0; -our $ERROR_SOURCE = 1; -our $ERROR_GRAPH = 2; -our %ERROR_ID = ( - "gcov" => $ERROR_GCOV, - "source" => $ERROR_SOURCE, - "graph" => $ERROR_GRAPH, -); - -our $EXCL_START = "LCOV_EXCL_START"; -our $EXCL_STOP = "LCOV_EXCL_STOP"; - -# Marker to exclude branch coverage but keep function and line coveage -our $EXCL_BR_START = "LCOV_EXCL_BR_START"; -our $EXCL_BR_STOP = "LCOV_EXCL_BR_STOP"; - -# Compatibility mode values -our $COMPAT_VALUE_OFF = 0; -our $COMPAT_VALUE_ON = 1; -our $COMPAT_VALUE_AUTO = 2; - -# Compatibility mode value names -our %COMPAT_NAME_TO_VALUE = ( - "off" => $COMPAT_VALUE_OFF, - "on" => $COMPAT_VALUE_ON, - "auto" => $COMPAT_VALUE_AUTO, -); - -# Compatiblity modes -our $COMPAT_MODE_LIBTOOL = 1 << 0; -our $COMPAT_MODE_HAMMER = 1 << 1; -our $COMPAT_MODE_SPLIT_CRC = 1 << 2; - -# Compatibility mode names -our %COMPAT_NAME_TO_MODE = ( - "libtool" => $COMPAT_MODE_LIBTOOL, - "hammer" => $COMPAT_MODE_HAMMER, - "split_crc" => $COMPAT_MODE_SPLIT_CRC, - "android_4_4_0" => $COMPAT_MODE_SPLIT_CRC, -); - -# Map modes to names -our %COMPAT_MODE_TO_NAME = ( - $COMPAT_MODE_LIBTOOL => "libtool", - $COMPAT_MODE_HAMMER => "hammer", - $COMPAT_MODE_SPLIT_CRC => "split_crc", -); - -# Compatibility mode default values -our %COMPAT_MODE_DEFAULTS = ( - $COMPAT_MODE_LIBTOOL => $COMPAT_VALUE_ON, - $COMPAT_MODE_HAMMER => $COMPAT_VALUE_AUTO, - $COMPAT_MODE_SPLIT_CRC => $COMPAT_VALUE_AUTO, -); - -# Compatibility mode auto-detection routines -sub compat_hammer_autodetect(); -our %COMPAT_MODE_AUTO = ( - $COMPAT_MODE_HAMMER => \&compat_hammer_autodetect, - $COMPAT_MODE_SPLIT_CRC => 1, # will be done later -); - -our $BR_LINE = 0; -our $BR_BLOCK = 1; -our $BR_BRANCH = 2; -our $BR_TAKEN = 3; -our $BR_VEC_ENTRIES = 4; -our $BR_VEC_WIDTH = 32; -our $BR_VEC_MAX = vec(pack('b*', 1 x $BR_VEC_WIDTH), 0, $BR_VEC_WIDTH); - -our $UNNAMED_BLOCK = -1; - -# Prototypes -sub print_usage(*); -sub transform_pattern($); -sub gen_info($); -sub process_dafile($$); -sub match_filename($@); -sub solve_ambiguous_match($$$); -sub split_filename($); -sub solve_relative_path($$); -sub read_gcov_header($); -sub read_gcov_file($); -sub info(@); -sub process_intermediate($$$); -sub map_llvm_version($); -sub version_to_str($); -sub get_gcov_version(); -sub system_no_output($@); -sub read_config($); -sub apply_config($); -sub apply_exclusion_data($$); -sub process_graphfile($$); -sub filter_fn_name($); -sub warn_handler($); -sub die_handler($); -sub graph_error($$); -sub graph_expect($); -sub graph_read(*$;$$); -sub graph_skip(*$;$); -sub uniq(@); -sub sort_uniq(@); -sub sort_uniq_lex(@); -sub graph_cleanup($); -sub graph_find_base($); -sub graph_from_bb($$$$); -sub graph_add_order($$$); -sub read_bb_word(*;$); -sub read_bb_value(*;$); -sub read_bb_string(*$); -sub read_bb($); -sub read_bbg_word(*;$); -sub read_bbg_value(*;$); -sub read_bbg_string(*); -sub read_bbg_lines_record(*$$$$$); -sub read_bbg($); -sub read_gcno_word(*;$$); -sub read_gcno_value(*$;$$); -sub read_gcno_string(*$); -sub read_gcno_lines_record(*$$$$$$); -sub determine_gcno_split_crc($$$$); -sub read_gcno_function_record(*$$$$$); -sub read_gcno($); -sub get_gcov_capabilities(); -sub get_overall_line($$$$); -sub print_overall_rate($$$$$$$$$); -sub br_gvec_len($); -sub br_gvec_get($$); -sub debug($); -sub int_handler(); -sub parse_ignore_errors(@); -sub is_external($); -sub compat_name($); -sub parse_compat_modes($); -sub is_compat($); -sub is_compat_auto($); - - -# Global variables -our $gcov_version; -our $gcov_version_string; -our $graph_file_extension; -our $data_file_extension; -our @data_directory; -our $test_name = ""; -our $quiet; -our $help; -our $output_filename; -our $base_directory; -our $version; -our $follow; -our $checksum; -our $no_checksum; -our $opt_compat_libtool; -our $opt_no_compat_libtool; -our $rc_adjust_src_path;# Regexp specifying parts to remove from source path -our $adjust_src_pattern; -our $adjust_src_replace; -our $adjust_testname; -our $config; # Configuration file contents -our @ignore_errors; # List of errors to ignore (parameter) -our @ignore; # List of errors to ignore (array) -our $initial; -our @include_patterns; # List of source file patterns to include -our @exclude_patterns; # List of source file patterns to exclude -our %excluded_files; # Files excluded due to include/exclude options -our $no_recursion = 0; -our $maxdepth; -our $no_markers = 0; -our $opt_derive_func_data = 0; -our $opt_external = 1; -our $opt_no_external; -our $debug = 0; -our $gcov_caps; -our @gcov_options; -our @internal_dirs; -our $opt_config_file; -our $opt_gcov_all_blocks = 1; -our $opt_compat; -our %opt_rc; -our %compat_value; -our $gcno_split_crc; -our $func_coverage = 1; -our $br_coverage = 0; -our $rc_auto_base = 1; -our $rc_intermediate = "auto"; -our $intermediate; -our $excl_line = "LCOV_EXCL_LINE"; -our $excl_br_line = "LCOV_EXCL_BR_LINE"; - -our $cwd = `pwd`; -chomp($cwd); - - -# -# Code entry point -# - -# Register handler routine to be called when interrupted -$SIG{"INT"} = \&int_handler; -$SIG{__WARN__} = \&warn_handler; -$SIG{__DIE__} = \&die_handler; - -# Set LC_ALL so that gcov output will be in a unified format -$ENV{"LC_ALL"} = "C"; - -# Check command line for a configuration file name -Getopt::Long::Configure("pass_through", "no_auto_abbrev"); -GetOptions("config-file=s" => \$opt_config_file, - "rc=s%" => \%opt_rc); -Getopt::Long::Configure("default"); - -{ - # Remove spaces around rc options - my %new_opt_rc; - - while (my ($key, $value) = each(%opt_rc)) { - $key =~ s/^\s+|\s+$//g; - $value =~ s/^\s+|\s+$//g; - - $new_opt_rc{$key} = $value; - } - %opt_rc = %new_opt_rc; -} - -# Read configuration file if available -if (defined($opt_config_file)) { - $config = read_config($opt_config_file); -} elsif (defined($ENV{"HOME"}) && (-r $ENV{"HOME"}."/.lcovrc")) -{ - $config = read_config($ENV{"HOME"}."/.lcovrc"); -} -elsif (-r "/etc/lcovrc") -{ - $config = read_config("/etc/lcovrc"); -} elsif (-r "/usr/local/etc/lcovrc") -{ - $config = read_config("/usr/local/etc/lcovrc"); -} - -if ($config || %opt_rc) -{ - # Copy configuration file and --rc values to variables - apply_config({ - "geninfo_gcov_tool" => \$gcov_tool, - "geninfo_adjust_testname" => \$adjust_testname, - "geninfo_checksum" => \$checksum, - "geninfo_no_checksum" => \$no_checksum, # deprecated - "geninfo_compat_libtool" => \$opt_compat_libtool, - "geninfo_external" => \$opt_external, - "geninfo_gcov_all_blocks" => \$opt_gcov_all_blocks, - "geninfo_compat" => \$opt_compat, - "geninfo_adjust_src_path" => \$rc_adjust_src_path, - "geninfo_auto_base" => \$rc_auto_base, - "geninfo_intermediate" => \$rc_intermediate, - "lcov_function_coverage" => \$func_coverage, - "lcov_branch_coverage" => \$br_coverage, - "lcov_excl_line" => \$excl_line, - "lcov_excl_br_line" => \$excl_br_line, - }); - - # Merge options - if (defined($no_checksum)) - { - $checksum = ($no_checksum ? 0 : 1); - $no_checksum = undef; - } - - # Check regexp - if (defined($rc_adjust_src_path)) { - my ($pattern, $replace) = split(/\s*=>\s*/, - $rc_adjust_src_path); - local $SIG{__DIE__}; - eval '$adjust_src_pattern = qr>'.$pattern.'>;'; - if (!defined($adjust_src_pattern)) { - my $msg = $@; - - chomp($msg); - $msg =~ s/at \(eval.*$//; - warn("WARNING: invalid pattern in ". - "geninfo_adjust_src_path: $msg\n"); - } elsif (!defined($replace)) { - # If no replacement is specified, simply remove pattern - $adjust_src_replace = ""; - } else { - $adjust_src_replace = $replace; - } - } - for my $regexp (($excl_line, $excl_br_line)) { - eval 'qr/'.$regexp.'/'; - my $error = $@; - chomp($error); - $error =~ s/at \(eval.*$//; - die("ERROR: invalid exclude pattern: $error") if $error; - } -} - -# Parse command line options -if (!GetOptions("test-name|t=s" => \$test_name, - "output-filename|o=s" => \$output_filename, - "checksum" => \$checksum, - "no-checksum" => \$no_checksum, - "base-directory|b=s" => \$base_directory, - "version|v" =>\$version, - "quiet|q" => \$quiet, - "help|h|?" => \$help, - "follow|f" => \$follow, - "compat-libtool" => \$opt_compat_libtool, - "no-compat-libtool" => \$opt_no_compat_libtool, - "gcov-tool=s" => \$gcov_tool, - "ignore-errors=s" => \@ignore_errors, - "initial|i" => \$initial, - "include=s" => \@include_patterns, - "exclude=s" => \@exclude_patterns, - "no-recursion" => \$no_recursion, - "no-markers" => \$no_markers, - "derive-func-data" => \$opt_derive_func_data, - "debug" => \$debug, - "external|e" => \$opt_external, - "no-external" => \$opt_no_external, - "compat=s" => \$opt_compat, - "config-file=s" => \$opt_config_file, - "rc=s%" => \%opt_rc, - )) -{ - print(STDERR "Use $tool_name --help to get usage information\n"); - exit(1); -} -else -{ - # Merge options - if (defined($no_checksum)) - { - $checksum = ($no_checksum ? 0 : 1); - $no_checksum = undef; - } - - if (defined($opt_no_compat_libtool)) - { - $opt_compat_libtool = ($opt_no_compat_libtool ? 0 : 1); - $opt_no_compat_libtool = undef; - } - - if (defined($opt_no_external)) { - $opt_external = 0; - $opt_no_external = undef; - } - - if(@include_patterns) { - # Need perlreg expressions instead of shell pattern - @include_patterns = map({ transform_pattern($_); } @include_patterns); - } - - if(@exclude_patterns) { - # Need perlreg expressions instead of shell pattern - @exclude_patterns = map({ transform_pattern($_); } @exclude_patterns); - } -} - -@data_directory = @ARGV; - -debug("$lcov_version\n"); - -# Check for help option -if ($help) -{ - print_usage(*STDOUT); - exit(0); -} - -# Check for version option -if ($version) -{ - print("$tool_name: $lcov_version\n"); - exit(0); -} - -# Check gcov tool -if (system_no_output(3, $gcov_tool, "--help") == -1) -{ - die("ERROR: need tool $gcov_tool!\n"); -} - -($gcov_version, $gcov_version_string) = get_gcov_version(); -$gcov_caps = get_gcov_capabilities(); - -# Determine intermediate mode -if ($rc_intermediate eq "0") { - $intermediate = 0; -} elsif ($rc_intermediate eq "1") { - $intermediate = 1; -} elsif (lc($rc_intermediate) eq "auto") { - # Use intermediate format if supported by gcov - $intermediate = ($gcov_caps->{'intermediate-format'} || - $gcov_caps->{'json-format'}) ? 1 : 0; -} else { - die("ERROR: invalid value for geninfo_intermediate: ". - "'$rc_intermediate'\n"); -} - -if ($intermediate) { - info("Using intermediate gcov format\n"); - if ($opt_derive_func_data) { - warn("WARNING: --derive-func-data is not compatible with ". - "intermediate format - ignoring\n"); - $opt_derive_func_data = 0; - } -} - -# Determine gcov options -push(@gcov_options, "-b") if ($gcov_caps->{'branch-probabilities'} && - ($br_coverage || $func_coverage)); -push(@gcov_options, "-c") if ($gcov_caps->{'branch-counts'} && - $br_coverage); -push(@gcov_options, "-a") if ($gcov_caps->{'all-blocks'} && - $opt_gcov_all_blocks && $br_coverage && - !$intermediate); -if ($gcov_caps->{'hash-filenames'}) -{ - push(@gcov_options, "-x"); -} else { - push(@gcov_options, "-p") if ($gcov_caps->{'preserve-paths'}); -} - -# Determine compatibility modes -parse_compat_modes($opt_compat); - -# Determine which errors the user wants us to ignore -parse_ignore_errors(@ignore_errors); - -# Make sure test names only contain valid characters -if ($test_name =~ s/\W/_/g) -{ - warn("WARNING: invalid characters removed from testname!\n"); -} - -# Adjust test name to include uname output if requested -if ($adjust_testname) -{ - $test_name .= "__".`uname -a`; - $test_name =~ s/\W/_/g; -} - -# Make sure base_directory contains an absolute path specification -if ($base_directory) -{ - $base_directory = solve_relative_path($cwd, $base_directory); -} - -# Check for follow option -if ($follow) -{ - $follow = "-follow" -} -else -{ - $follow = ""; -} - -# Determine checksum mode -if (defined($checksum)) -{ - # Normalize to boolean - $checksum = ($checksum ? 1 : 0); -} -else -{ - # Default is off - $checksum = 0; -} - -# Determine max depth for recursion -if ($no_recursion) -{ - $maxdepth = "-maxdepth 1"; -} -else -{ - $maxdepth = ""; -} - -# Check for directory name -if (!@data_directory) -{ - die("No directory specified\n". - "Use $tool_name --help to get usage information\n"); -} -else -{ - foreach (@data_directory) - { - stat($_); - if (!-r _) - { - die("ERROR: cannot read $_!\n"); - } - } -} - -if ($gcov_version < $GCOV_VERSION_3_4_0) -{ - if (is_compat($COMPAT_MODE_HAMMER)) - { - $data_file_extension = ".da"; - $graph_file_extension = ".bbg"; - } - else - { - $data_file_extension = ".da"; - $graph_file_extension = ".bb"; - } -} -else -{ - $data_file_extension = ".gcda"; - $graph_file_extension = ".gcno"; -} - -# Check output filename -if (defined($output_filename) && ($output_filename ne "-")) -{ - # Initially create output filename, data is appended - # for each data file processed - local *DUMMY_HANDLE; - open(DUMMY_HANDLE, ">", $output_filename) - or die("ERROR: cannot create $output_filename!\n"); - close(DUMMY_HANDLE); - - # Make $output_filename an absolute path because we're going - # to change directories while processing files - if (!($output_filename =~ /^\/(.*)$/)) - { - $output_filename = $cwd."/".$output_filename; - } -} - -# Build list of directories to identify external files -foreach my $entry(@data_directory, $base_directory) { - next if (!defined($entry)); - push(@internal_dirs, solve_relative_path($cwd, $entry)); -} - -# Do something -foreach my $entry (@data_directory) { - gen_info($entry); -} - -if ($initial && $br_coverage && !$intermediate) { - warn("Note: --initial does not generate branch coverage ". - "data\n"); -} -info("Finished .info-file creation\n"); - -exit(0); - - - -# -# print_usage(handle) -# -# Print usage information. -# - -sub print_usage(*) -{ - local *HANDLE = $_[0]; - - print(HANDLE < (.) and * => (.*) - - $pattern =~ s/\*/\(\.\*\)/g; - $pattern =~ s/\?/\(\.\)/g; - - return $pattern; -} - - -# -# get_common_prefix(min_dir, filenames) -# -# Return the longest path prefix shared by all filenames. MIN_DIR specifies -# the minimum number of directories that a filename may have after removing -# the prefix. -# - -sub get_common_prefix($@) -{ - my ($min_dir, @files) = @_; - my $file; - my @prefix; - my $i; - - foreach $file (@files) { - my ($v, $d, $f) = splitpath($file); - my @comp = splitdir($d); - - if (!@prefix) { - @prefix = @comp; - next; - } - for ($i = 0; $i < scalar(@comp) && $i < scalar(@prefix); $i++) { - if ($comp[$i] ne $prefix[$i] || - ((scalar(@comp) - ($i + 1)) <= $min_dir)) { - delete(@prefix[$i..scalar(@prefix)]); - last; - } - } - } - - return catdir(@prefix); -} - -# -# gen_info(directory) -# -# Traverse DIRECTORY and create a .info file for each data file found. -# The .info file contains TEST_NAME in the following format: -# -# TN: -# -# For each source file name referenced in the data file, there is a section -# containing source code and coverage data: -# -# SF: -# FN:, for each function -# DA:, for each instrumented line -# LH: greater than 0 -# LF: -# -# Sections are separated by: -# -# end_of_record -# -# In addition to the main source code file there are sections for each -# #included file containing executable code. Note that the absolute path -# of a source file is generated by interpreting the contents of the respective -# graph file. Relative filenames are prefixed with the directory in which the -# graph file is found. Note also that symbolic links to the graph file will be -# resolved so that the actual file path is used instead of the path to a link. -# This approach is necessary for the mechanism to work with the /proc/gcov -# files. -# -# Die on error. -# - -sub gen_info($) -{ - my $directory = $_[0]; - my @file_list; - my $file; - my $prefix; - my $type; - my $ext; - my $tempdir; - - if ($initial) { - $type = "graph"; - $ext = $graph_file_extension; - } else { - $type = "data"; - $ext = $data_file_extension; - } - - if (-d $directory) - { - info("Scanning $directory for $ext files ...\n"); - - @file_list = `find "$directory" $maxdepth $follow -name \\*$ext -type f -o -name \\*$ext -type l 2>/dev/null`; - chomp(@file_list); - if (!@file_list) { - warn("WARNING: no $ext files found in $directory - ". - "skipping!\n"); - return; - } - $prefix = get_common_prefix(1, @file_list); - info("Found %d %s files in %s\n", $#file_list+1, $type, - $directory); - } - else - { - @file_list = ($directory); - $prefix = ""; - } - - $tempdir = tempdir(CLEANUP => 1); - - # Process all files in list - foreach $file (@file_list) { - # Process file - if ($intermediate) { - process_intermediate($file, $prefix, $tempdir); - } elsif ($initial) { - process_graphfile($file, $prefix); - } else { - process_dafile($file, $prefix); - } - } - - unlink($tempdir); - - # Report whether files were excluded. - if (%excluded_files) { - info("Excluded data for %d files due to include/exclude options\n", - scalar keys %excluded_files); - } -} - - -# -# derive_data(contentdata, funcdata, bbdata) -# -# Calculate function coverage data by combining line coverage data and the -# list of lines belonging to a function. -# -# contentdata: [ instr1, count1, source1, instr2, count2, source2, ... ] -# instr: Instrumentation flag for line n -# count: Execution count for line n -# source: Source code for line n -# -# funcdata: [ count1, func1, count2, func2, ... ] -# count: Execution count for function number n -# func: Function name for function number n -# -# bbdata: function_name -> [ line1, line2, ... ] -# line: Line number belonging to the corresponding function -# - -sub derive_data($$$) -{ - my ($contentdata, $funcdata, $bbdata) = @_; - my @gcov_content = @{$contentdata}; - my @gcov_functions = @{$funcdata}; - my %fn_count; - my %ln_fn; - my $line; - my $maxline; - my %fn_name; - my $fn; - my $count; - - if (!defined($bbdata)) { - return @gcov_functions; - } - - # First add existing function data - while (@gcov_functions) { - $count = shift(@gcov_functions); - $fn = shift(@gcov_functions); - - $fn_count{$fn} = $count; - } - - # Convert line coverage data to function data - foreach $fn (keys(%{$bbdata})) { - my $line_data = $bbdata->{$fn}; - my $line; - my $fninstr = 0; - - if ($fn eq "") { - next; - } - # Find the lowest line count for this function - $count = 0; - foreach $line (@$line_data) { - my $linstr = $gcov_content[ ( $line - 1 ) * 3 + 0 ]; - my $lcount = $gcov_content[ ( $line - 1 ) * 3 + 1 ]; - - next if (!$linstr); - $fninstr = 1; - if (($lcount > 0) && - (($count == 0) || ($lcount < $count))) { - $count = $lcount; - } - } - next if (!$fninstr); - $fn_count{$fn} = $count; - } - - - # Check if we got data for all functions - foreach $fn (keys(%fn_name)) { - if ($fn eq "") { - next; - } - if (defined($fn_count{$fn})) { - next; - } - warn("WARNING: no derived data found for function $fn\n"); - } - - # Convert hash to list in @gcov_functions format - foreach $fn (sort(keys(%fn_count))) { - push(@gcov_functions, $fn_count{$fn}, $fn); - } - - return @gcov_functions; -} - -# -# get_filenames(directory, pattern) -# -# Return a list of filenames found in directory which match the specified -# pattern. -# -# Die on error. -# - -sub get_filenames($$) -{ - my ($dirname, $pattern) = @_; - my @result; - my $directory; - local *DIR; - - opendir(DIR, $dirname) or - die("ERROR: cannot read directory $dirname\n"); - while ($directory = readdir(DIR)) { - push(@result, $directory) if ($directory =~ /$pattern/); - } - closedir(DIR); - - return @result; -} - -# -# process_dafile(da_filename, dir) -# -# Create a .info file for a single data file. -# -# Die on error. -# - -sub process_dafile($$) -{ - my ($file, $dir) = @_; - my $da_filename; # Name of data file to process - my $da_dir; # Directory of data file - my $source_dir; # Directory of source file - my $da_basename; # data filename without ".da/.gcda" extension - my $bb_filename; # Name of respective graph file - my $bb_basename; # Basename of the original graph file - my $graph; # Contents of graph file - my $instr; # Contents of graph file part 2 - my $gcov_error; # Error code of gcov tool - my $object_dir; # Directory containing all object files - my $source_filename; # Name of a source code file - my $gcov_file; # Name of a .gcov file - my @gcov_content; # Content of a .gcov file - my $gcov_branches; # Branch content of a .gcov file - my @gcov_functions; # Function calls of a .gcov file - my @gcov_list; # List of generated .gcov files - my $line_number; # Line number count - my $lines_hit; # Number of instrumented lines hit - my $lines_found; # Number of instrumented lines found - my $funcs_hit; # Number of instrumented functions hit - my $funcs_found; # Number of instrumented functions found - my $br_hit; - my $br_found; - my $source; # gcov source header information - my $object; # gcov object header information - my @matches; # List of absolute paths matching filename - my $base_dir; # Base directory for current file - my @tmp_links; # Temporary links to be cleaned up - my @result; - my $index; - my $da_renamed; # If data file is to be renamed - local *INFO_HANDLE; - - info("Processing %s\n", abs2rel($file, $dir)); - # Get path to data file in absolute and normalized form (begins with /, - # contains no more ../ or ./) - $da_filename = solve_relative_path($cwd, $file); - - # Get directory and basename of data file - ($da_dir, $da_basename) = split_filename($da_filename); - - $source_dir = $da_dir; - if (is_compat($COMPAT_MODE_LIBTOOL)) { - # Avoid files from .libs dirs - $source_dir =~ s/\.libs$//; - } - - if (-z $da_filename) - { - $da_renamed = 1; - } - else - { - $da_renamed = 0; - } - - # Construct base_dir for current file - if ($base_directory) - { - $base_dir = $base_directory; - } - else - { - $base_dir = $source_dir; - } - - # Check for writable $base_dir (gcov will try to write files there) - stat($base_dir); - if (!-w _) - { - die("ERROR: cannot write to directory $base_dir!\n"); - } - - # Construct name of graph file - $bb_basename = $da_basename.$graph_file_extension; - $bb_filename = "$da_dir/$bb_basename"; - - # Find out the real location of graph file in case we're just looking at - # a link - while (readlink($bb_filename)) - { - my $last_dir = dirname($bb_filename); - - $bb_filename = readlink($bb_filename); - $bb_filename = solve_relative_path($last_dir, $bb_filename); - } - - # Ignore empty graph file (e.g. source file with no statement) - if (-z $bb_filename) - { - warn("WARNING: empty $bb_filename (skipped)\n"); - return; - } - - # Read contents of graph file into hash. We need it later to find out - # the absolute path to each .gcov file created as well as for - # information about functions and their source code positions. - if ($gcov_version < $GCOV_VERSION_3_4_0) - { - if (is_compat($COMPAT_MODE_HAMMER)) - { - ($instr, $graph) = read_bbg($bb_filename); - } - else - { - ($instr, $graph) = read_bb($bb_filename); - } - } - else - { - ($instr, $graph) = read_gcno($bb_filename); - } - - # Try to find base directory automatically if requested by user - if ($rc_auto_base) { - $base_dir = find_base_from_source($base_dir, - [ keys(%{$instr}), keys(%{$graph}) ]); - } - - adjust_source_filenames($instr, $base_dir); - adjust_source_filenames($graph, $base_dir); - - # Set $object_dir to real location of object files. This may differ - # from $da_dir if the graph file is just a link to the "real" object - # file location. - $object_dir = dirname($bb_filename); - - # Is the data file in a different directory? (this happens e.g. with - # the gcov-kernel patch) - if ($object_dir ne $da_dir) - { - # Need to create link to data file in $object_dir - system("ln", "-s", $da_filename, - "$object_dir/$da_basename$data_file_extension") - and die ("ERROR: cannot create link $object_dir/". - "$da_basename$data_file_extension!\n"); - push(@tmp_links, - "$object_dir/$da_basename$data_file_extension"); - # Need to create link to graph file if basename of link - # and file are different (CONFIG_MODVERSION compat) - if ((basename($bb_filename) ne $bb_basename) && - (! -e "$object_dir/$bb_basename")) { - symlink($bb_filename, "$object_dir/$bb_basename") or - warn("WARNING: cannot create link ". - "$object_dir/$bb_basename\n"); - push(@tmp_links, "$object_dir/$bb_basename"); - } - } - - # Change to directory containing data files and apply GCOV - debug("chdir($base_dir)\n"); - chdir($base_dir); - - if ($da_renamed) - { - # Need to rename empty data file to workaround - # gcov <= 3.2.x bug (Abort) - system_no_output(3, "mv", "$da_filename", "$da_filename.ori") - and die ("ERROR: cannot rename $da_filename\n"); - } - - # Execute gcov command and suppress standard output - $gcov_error = system_no_output(1, $gcov_tool, $da_filename, - "-o", $object_dir, @gcov_options); - - if ($da_renamed) - { - system_no_output(3, "mv", "$da_filename.ori", "$da_filename") - and die ("ERROR: cannot rename $da_filename.ori"); - } - - # Clean up temporary links - foreach (@tmp_links) { - unlink($_); - } - - if ($gcov_error) - { - if ($ignore[$ERROR_GCOV]) - { - warn("WARNING: GCOV failed for $da_filename!\n"); - return; - } - die("ERROR: GCOV failed for $da_filename!\n"); - } - - # Collect data from resulting .gcov files and create .info file - @gcov_list = get_filenames('.', '\.gcov$'); - - # Check for files - if (!@gcov_list) - { - warn("WARNING: gcov did not create any files for ". - "$da_filename!\n"); - } - - # Check whether we're writing to a single file - if ($output_filename) - { - if ($output_filename eq "-") - { - *INFO_HANDLE = *STDOUT; - } - else - { - # Append to output file - open(INFO_HANDLE, ">>", $output_filename) - or die("ERROR: cannot write to ". - "$output_filename!\n"); - } - } - else - { - # Open .info file for output - open(INFO_HANDLE, ">", "$da_filename.info") - or die("ERROR: cannot create $da_filename.info!\n"); - } - - # Write test name - printf(INFO_HANDLE "TN:%s\n", $test_name); - - # Traverse the list of generated .gcov files and combine them into a - # single .info file - foreach $gcov_file (sort(@gcov_list)) - { - my $i; - my $num; - - # Skip gcov file for gcc built-in code - next if ($gcov_file eq ".gcov"); - - ($source, $object) = read_gcov_header($gcov_file); - - if (!defined($source)) { - # Derive source file name from gcov file name if - # header format could not be parsed - $source = $gcov_file; - $source =~ s/\.gcov$//; - } - - $source = solve_relative_path($base_dir, $source); - - if (defined($adjust_src_pattern)) { - # Apply transformation as specified by user - $source =~ s/$adjust_src_pattern/$adjust_src_replace/g; - } - - # gcov will happily create output even if there's no source code - # available - this interferes with checksum creation so we need - # to pull the emergency brake here. - if (! -r $source && $checksum) - { - if ($ignore[$ERROR_SOURCE]) - { - warn("WARNING: could not read source file ". - "$source\n"); - next; - } - die("ERROR: could not read source file $source\n"); - } - - @matches = match_filename($source, keys(%{$instr})); - - # Skip files that are not mentioned in the graph file - if (!@matches) - { - warn("WARNING: cannot find an entry for ".$gcov_file. - " in $graph_file_extension file, skipping ". - "file!\n"); - unlink($gcov_file); - next; - } - - # Read in contents of gcov file - @result = read_gcov_file($gcov_file); - if (!defined($result[0])) { - warn("WARNING: skipping unreadable file ". - $gcov_file."\n"); - unlink($gcov_file); - next; - } - @gcov_content = @{$result[0]}; - $gcov_branches = $result[1]; - @gcov_functions = @{$result[2]}; - - # Skip empty files - if (!@gcov_content) - { - warn("WARNING: skipping empty file ".$gcov_file."\n"); - unlink($gcov_file); - next; - } - - if (scalar(@matches) == 1) - { - # Just one match - $source_filename = $matches[0]; - } - else - { - # Try to solve the ambiguity - $source_filename = solve_ambiguous_match($gcov_file, - \@matches, \@gcov_content); - } - - if (@include_patterns) - { - my $keep = 0; - - foreach my $pattern (@include_patterns) - { - $keep ||= ($source_filename =~ (/^$pattern$/)); - } - - if (!$keep) - { - $excluded_files{$source_filename} = (); - unlink($gcov_file); - next; - } - } - - if (@exclude_patterns) - { - my $exclude = 0; - - foreach my $pattern (@exclude_patterns) - { - $exclude ||= ($source_filename =~ (/^$pattern$/)); - } - - if ($exclude) - { - $excluded_files{$source_filename} = (); - unlink($gcov_file); - next; - } - } - - # Skip external files if requested - if (!$opt_external) { - if (is_external($source_filename)) { - info(" ignoring data for external file ". - "$source_filename\n"); - unlink($gcov_file); - next; - } - } - - # Write absolute path of source file - printf(INFO_HANDLE "SF:%s\n", $source_filename); - - # If requested, derive function coverage data from - # line coverage data of the first line of a function - if ($opt_derive_func_data) { - @gcov_functions = - derive_data(\@gcov_content, \@gcov_functions, - $graph->{$source_filename}); - } - - # Write function-related information - if (defined($graph->{$source_filename})) - { - my $fn_data = $graph->{$source_filename}; - my $fn; - - foreach $fn (sort - {$fn_data->{$a}->[0] <=> $fn_data->{$b}->[0]} - keys(%{$fn_data})) { - my $ln_data = $fn_data->{$fn}; - my $line = $ln_data->[0]; - - # Skip empty function - if ($fn eq "") { - next; - } - # Remove excluded functions - if (!$no_markers) { - my $gfn; - my $found = 0; - - foreach $gfn (@gcov_functions) { - if ($gfn eq $fn) { - $found = 1; - last; - } - } - if (!$found) { - next; - } - } - - # Normalize function name - $fn = filter_fn_name($fn); - - print(INFO_HANDLE "FN:$line,$fn\n"); - } - } - - #-- - #-- FNDA: , - #-- FNF: overall count of functions - #-- FNH: overall count of functions with non-zero call count - #-- - $funcs_found = 0; - $funcs_hit = 0; - while (@gcov_functions) - { - my $count = shift(@gcov_functions); - my $fn = shift(@gcov_functions); - - $fn = filter_fn_name($fn); - printf(INFO_HANDLE "FNDA:$count,$fn\n"); - $funcs_found++; - $funcs_hit++ if ($count > 0); - } - if ($funcs_found > 0) { - printf(INFO_HANDLE "FNF:%s\n", $funcs_found); - printf(INFO_HANDLE "FNH:%s\n", $funcs_hit); - } - - # Write coverage information for each instrumented branch: - # - # BRDA:,,, - # - # where 'taken' is the number of times the branch was taken - # or '-' if the block to which the branch belongs was never - # executed - $br_found = 0; - $br_hit = 0; - $num = br_gvec_len($gcov_branches); - for ($i = 0; $i < $num; $i++) { - my ($line, $block, $branch, $taken) = - br_gvec_get($gcov_branches, $i); - - $block = $BR_VEC_MAX if ($block < 0); - print(INFO_HANDLE "BRDA:$line,$block,$branch,$taken\n"); - $br_found++; - $br_hit++ if ($taken ne '-' && $taken > 0); - } - if ($br_found > 0) { - printf(INFO_HANDLE "BRF:%s\n", $br_found); - printf(INFO_HANDLE "BRH:%s\n", $br_hit); - } - - # Reset line counters - $line_number = 0; - $lines_found = 0; - $lines_hit = 0; - - # Write coverage information for each instrumented line - # Note: @gcov_content contains a list of (flag, count, source) - # tuple for each source code line - while (@gcov_content) - { - $line_number++; - - # Check for instrumented line - if ($gcov_content[0]) - { - $lines_found++; - printf(INFO_HANDLE "DA:".$line_number.",". - $gcov_content[1].($checksum ? - ",". md5_base64($gcov_content[2]) : ""). - "\n"); - - # Increase $lines_hit in case of an execution - # count>0 - if ($gcov_content[1] > 0) { $lines_hit++; } - } - - # Remove already processed data from array - splice(@gcov_content,0,3); - } - - # Write line statistics and section separator - printf(INFO_HANDLE "LF:%s\n", $lines_found); - printf(INFO_HANDLE "LH:%s\n", $lines_hit); - print(INFO_HANDLE "end_of_record\n"); - - # Remove .gcov file after processing - unlink($gcov_file); - } - - if (!($output_filename && ($output_filename eq "-"))) - { - close(INFO_HANDLE); - } - - # Change back to initial directory - chdir($cwd); -} - - -# -# solve_relative_path(path, dir) -# -# Solve relative path components of DIR which, if not absolute, resides in PATH. -# - -sub solve_relative_path($$) -{ - my $path = $_[0]; - my $dir = $_[1]; - my $volume; - my $directories; - my $filename; - my @dirs; # holds path elements - my $result; - - # Convert from Windows path to msys path - if( $^O eq "msys" ) - { - # search for a windows drive letter at the beginning - ($volume, $directories, $filename) = File::Spec::Win32->splitpath( $dir ); - if( $volume ne '' ) - { - my $uppercase_volume; - # transform c/d\../e/f\g to Windows style c\d\..\e\f\g - $dir = File::Spec::Win32->canonpath( $dir ); - # use Win32 module to retrieve path components - # $uppercase_volume is not used any further - ( $uppercase_volume, $directories, $filename ) = File::Spec::Win32->splitpath( $dir ); - @dirs = File::Spec::Win32->splitdir( $directories ); - - # prepend volume, since in msys C: is always mounted to /c - $volume =~ s|^([a-zA-Z]+):|/\L$1\E|; - unshift( @dirs, $volume ); - - # transform to Unix style '/' path - $directories = File::Spec->catdir( @dirs ); - $dir = File::Spec->catpath( '', $directories, $filename ); - } else { - # eliminate '\' path separators - $dir = File::Spec->canonpath( $dir ); - } - } - - $result = $dir; - # Prepend path if not absolute - if ($dir =~ /^[^\/]/) - { - $result = "$path/$result"; - } - - # Remove // - $result =~ s/\/\//\//g; - - # Remove . - while ($result =~ s/\/\.\//\//g) - { - } - $result =~ s/\/\.$/\//g; - - # Remove trailing / - $result =~ s/\/$//g; - - # Solve .. - while ($result =~ s/\/[^\/]+\/\.\.\//\//) - { - } - - # Remove preceding .. - $result =~ s/^\/\.\.\//\//g; - - return $result; -} - - -# -# match_filename(gcov_filename, list) -# -# Return a list of those entries of LIST which match the relative filename -# GCOV_FILENAME. -# - -sub match_filename($@) -{ - my ($filename, @list) = @_; - my ($vol, $dir, $file) = splitpath($filename); - my @comp = splitdir($dir); - my $comps = scalar(@comp); - my $entry; - my @result; - -entry: - foreach $entry (@list) { - my ($evol, $edir, $efile) = splitpath($entry); - my @ecomp; - my $ecomps; - my $i; - - # Filename component must match - if ($efile ne $file) { - next; - } - # Check directory components last to first for match - @ecomp = splitdir($edir); - $ecomps = scalar(@ecomp); - if ($ecomps < $comps) { - next; - } - for ($i = 0; $i < $comps; $i++) { - if ($comp[$comps - $i - 1] ne - $ecomp[$ecomps - $i - 1]) { - next entry; - } - } - push(@result, $entry), - } - - return @result; -} - -# -# solve_ambiguous_match(rel_filename, matches_ref, gcov_content_ref) -# -# Try to solve ambiguous matches of mapping (gcov file) -> (source code) file -# by comparing source code provided in the GCOV file with that of the files -# in MATCHES. REL_FILENAME identifies the relative filename of the gcov -# file. -# -# Return the one real match or die if there is none. -# - -sub solve_ambiguous_match($$$) -{ - my $rel_name = $_[0]; - my $matches = $_[1]; - my $content = $_[2]; - my $filename; - my $index; - my $no_match; - local *SOURCE; - - # Check the list of matches - foreach $filename (@$matches) - { - - # Compare file contents - open(SOURCE, "<", $filename) - or die("ERROR: cannot read $filename!\n"); - - $no_match = 0; - for ($index = 2; ; $index += 3) - { - chomp; - - # Also remove CR from line-end - s/\015$//; - - if ($_ ne @$content[$index]) - { - $no_match = 1; - last; - } - } - - close(SOURCE); - - if (!$no_match) - { - info("Solved source file ambiguity for $rel_name\n"); - return $filename; - } - } - - die("ERROR: could not match gcov data for $rel_name!\n"); -} - - -# -# split_filename(filename) -# -# Return (path, filename, extension) for a given FILENAME. -# - -sub split_filename($) -{ - my @path_components = split('/', $_[0]); - my @file_components = split('\.', pop(@path_components)); - my $extension = pop(@file_components); - - return (join("/",@path_components), join(".",@file_components), - $extension); -} - - -# -# read_gcov_header(gcov_filename) -# -# Parse file GCOV_FILENAME and return a list containing the following -# information: -# -# (source, object) -# -# where: -# -# source: complete relative path of the source code file (gcc >= 3.3 only) -# object: name of associated graph file -# -# Die on error. -# - -sub read_gcov_header($) -{ - my $source; - my $object; - local *INPUT; - - if (!open(INPUT, "<", $_[0])) - { - if ($ignore_errors[$ERROR_GCOV]) - { - warn("WARNING: cannot read $_[0]!\n"); - return (undef,undef); - } - die("ERROR: cannot read $_[0]!\n"); - } - - while () - { - chomp($_); - - # Also remove CR from line-end - s/\015$//; - - if (/^\s+-:\s+0:Source:(.*)$/) - { - # Source: header entry - $source = $1; - } - elsif (/^\s+-:\s+0:Object:(.*)$/) - { - # Object: header entry - $object = $1; - } - else - { - last; - } - } - - close(INPUT); - - return ($source, $object); -} - - -# -# br_gvec_len(vector) -# -# Return the number of entries in the branch coverage vector. -# - -sub br_gvec_len($) -{ - my ($vec) = @_; - - return 0 if (!defined($vec)); - return (length($vec) * 8 / $BR_VEC_WIDTH) / $BR_VEC_ENTRIES; -} - - -# -# br_gvec_get(vector, number) -# -# Return an entry from the branch coverage vector. -# - -sub br_gvec_get($$) -{ - my ($vec, $num) = @_; - my $line; - my $block; - my $branch; - my $taken; - my $offset = $num * $BR_VEC_ENTRIES; - - # Retrieve data from vector - $line = vec($vec, $offset + $BR_LINE, $BR_VEC_WIDTH); - $block = vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH); - $block = -1 if ($block == $BR_VEC_MAX); - $branch = vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH); - $taken = vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH); - - # Decode taken value from an integer - if ($taken == 0) { - $taken = "-"; - } else { - $taken--; - } - - return ($line, $block, $branch, $taken); -} - - -# -# br_gvec_push(vector, line, block, branch, taken) -# -# Add an entry to the branch coverage vector. -# - -sub br_gvec_push($$$$$) -{ - my ($vec, $line, $block, $branch, $taken) = @_; - my $offset; - - $vec = "" if (!defined($vec)); - $offset = br_gvec_len($vec) * $BR_VEC_ENTRIES; - $block = $BR_VEC_MAX if $block < 0; - - # Encode taken value into an integer - if ($taken eq "-") { - $taken = 0; - } else { - $taken++; - } - - # Add to vector - vec($vec, $offset + $BR_LINE, $BR_VEC_WIDTH) = $line; - vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH) = $block; - vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH) = $branch; - vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH) = $taken; - - return $vec; -} - - -# -# read_gcov_file(gcov_filename) -# -# Parse file GCOV_FILENAME (.gcov file format) and return the list: -# (reference to gcov_content, reference to gcov_branch, reference to gcov_func) -# -# gcov_content is a list of 3 elements -# (flag, count, source) for each source code line: -# -# $result[($line_number-1)*3+0] = instrumentation flag for line $line_number -# $result[($line_number-1)*3+1] = execution count for line $line_number -# $result[($line_number-1)*3+2] = source code text for line $line_number -# -# gcov_branch is a vector of 4 4-byte long elements for each branch: -# line number, block number, branch number, count + 1 or 0 -# -# gcov_func is a list of 2 elements -# (number of calls, function name) for each function -# -# Die on error. -# - -sub read_gcov_file($) -{ - my $filename = $_[0]; - my @result = (); - my $branches = ""; - my @functions = (); - my $number; - my $exclude_flag = 0; - my $exclude_line = 0; - my $exclude_br_flag = 0; - my $exclude_branch = 0; - my $last_block = $UNNAMED_BLOCK; - my $last_line = 0; - local *INPUT; - - if (!open(INPUT, "<", $filename)) { - if ($ignore_errors[$ERROR_GCOV]) - { - warn("WARNING: cannot read $filename!\n"); - return (undef, undef, undef); - } - die("ERROR: cannot read $filename!\n"); - } - - if ($gcov_version < $GCOV_VERSION_3_3_0) - { - # Expect gcov format as used in gcc < 3.3 - while () - { - chomp($_); - - # Also remove CR from line-end - s/\015$//; - - if (/^branch\s+(\d+)\s+taken\s+=\s+(\d+)/) { - next if (!$br_coverage); - next if ($exclude_line); - next if ($exclude_branch); - $branches = br_gvec_push($branches, $last_line, - $last_block, $1, $2); - } elsif (/^branch\s+(\d+)\s+never\s+executed/) { - next if (!$br_coverage); - next if ($exclude_line); - next if ($exclude_branch); - $branches = br_gvec_push($branches, $last_line, - $last_block, $1, '-'); - } - elsif (/^call/ || /^function/) - { - # Function call return data - } - else - { - $last_line++; - # Check for exclusion markers - if (!$no_markers) { - if (/$EXCL_STOP/) { - $exclude_flag = 0; - } elsif (/$EXCL_START/) { - $exclude_flag = 1; - } - if (/$excl_line/ || $exclude_flag) { - $exclude_line = 1; - } else { - $exclude_line = 0; - } - } - # Check for exclusion markers (branch exclude) - if (!$no_markers) { - if (/$EXCL_BR_STOP/) { - $exclude_br_flag = 0; - } elsif (/$EXCL_BR_START/) { - $exclude_br_flag = 1; - } - if (/$excl_br_line/ || $exclude_br_flag) { - $exclude_branch = 1; - } else { - $exclude_branch = 0; - } - } - # Source code execution data - if (/^\t\t(.*)$/) - { - # Uninstrumented line - push(@result, 0); - push(@result, 0); - push(@result, $1); - next; - } - $number = (split(" ",substr($_, 0, 16)))[0]; - - # Check for zero count which is indicated - # by ###### - if ($number eq "######") { $number = 0; } - - if ($exclude_line) { - # Register uninstrumented line instead - push(@result, 0); - push(@result, 0); - } else { - push(@result, 1); - push(@result, $number); - } - push(@result, substr($_, 16)); - } - } - } - else - { - # Expect gcov format as used in gcc >= 3.3 - while () - { - chomp($_); - - # Also remove CR from line-end - s/\015$//; - - if (/^\s*(\d+|\$+|\%+):\s*(\d+)-block\s+(\d+)\s*$/) { - # Block information - used to group related - # branches - $last_line = $2; - $last_block = $3; - } elsif (/^branch\s+(\d+)\s+taken\s+(\d+)/) { - next if (!$br_coverage); - next if ($exclude_line); - next if ($exclude_branch); - $branches = br_gvec_push($branches, $last_line, - $last_block, $1, $2); - } elsif (/^branch\s+(\d+)\s+never\s+executed/) { - next if (!$br_coverage); - next if ($exclude_line); - next if ($exclude_branch); - $branches = br_gvec_push($branches, $last_line, - $last_block, $1, '-'); - } - elsif (/^function\s+(.+)\s+called\s+(\d+)\s+/) - { - next if (!$func_coverage); - if ($exclude_line) { - next; - } - push(@functions, $2, $1); - } - elsif (/^call/) - { - # Function call return data - } - elsif (/^\s*([^:]+):\s*([^:]+):(.*)$/) - { - my ($count, $line, $code) = ($1, $2, $3); - - # Skip instance-specific counts - next if ($line <= (scalar(@result) / 3)); - - $last_line = $line; - $last_block = $UNNAMED_BLOCK; - # Check for exclusion markers - if (!$no_markers) { - if (/$EXCL_STOP/) { - $exclude_flag = 0; - } elsif (/$EXCL_START/) { - $exclude_flag = 1; - } - if (/$excl_line/ || $exclude_flag) { - $exclude_line = 1; - } else { - $exclude_line = 0; - } - } - # Check for exclusion markers (branch exclude) - if (!$no_markers) { - if (/$EXCL_BR_STOP/) { - $exclude_br_flag = 0; - } elsif (/$EXCL_BR_START/) { - $exclude_br_flag = 1; - } - if (/$excl_br_line/ || $exclude_br_flag) { - $exclude_branch = 1; - } else { - $exclude_branch = 0; - } - } - - # Strip unexecuted basic block marker - $count =~ s/\*$//; - - # :: - if ($line eq "0") - { - # Extra data - } - elsif ($count eq "-") - { - # Uninstrumented line - push(@result, 0); - push(@result, 0); - push(@result, $code); - } - else - { - if ($exclude_line) { - push(@result, 0); - push(@result, 0); - } else { - # Check for zero count - if ($count =~ /^[#=]/) { - $count = 0; - } - push(@result, 1); - push(@result, $count); - } - push(@result, $code); - } - } - } - } - - close(INPUT); - if ($exclude_flag || $exclude_br_flag) { - warn("WARNING: unterminated exclusion section in $filename\n"); - } - return(\@result, $branches, \@functions); -} - - -# -# read_intermediate_text(gcov_filename, data) -# -# Read gcov intermediate text format in GCOV_FILENAME and add the resulting -# data to DATA in the following format: -# -# data: source_filename -> file_data -# file_data: concatenated lines of intermediate text data -# - -sub read_intermediate_text($$) -{ - my ($gcov_filename, $data) = @_; - my $fd; - my $filename; - - open($fd, "<", $gcov_filename) or - die("ERROR: Could not read $gcov_filename: $!\n"); - while (my $line = <$fd>) { - if ($line =~ /^file:(.*)$/) { - $filename = $1; - chomp($filename); - } elsif (defined($filename)) { - $data->{$filename} .= $line; - } - } - close($fd); -} - - -# -# read_intermediate_json(gcov_filename, data, basedir_ref) -# -# Read gcov intermediate JSON format in GCOV_FILENAME and add the resulting -# data to DATA in the following format: -# -# data: source_filename -> file_data -# file_data: GCOV JSON data for file -# -# Also store the value for current_working_directory to BASEDIR_REF. -# - -sub read_intermediate_json($$$) -{ - my ($gcov_filename, $data, $basedir_ref) = @_; - my $fd; - my $text; - my $json; - - open($fd, "<:gzip", $gcov_filename) or - die("ERROR: Could not read $gcov_filename: $!\n"); - local $/; - $text = <$fd>; - close($fd); - - $json = decode_json($text); - if (!defined($json) || !exists($json->{"files"}) || - ref($json->{"files"} ne "ARRAY")) { - die("ERROR: Unrecognized JSON output format in ". - "$gcov_filename\n"); - } - - $$basedir_ref = $json->{"current_working_directory"}; - - for my $file (@{$json->{"files"}}) { - my $filename = $file->{"file"}; - - $data->{$filename} = $file; - } -} - - -# -# intermediate_text_to_info(fd, data, srcdata) -# -# Write DATA in info format to file descriptor FD. -# -# data: filename -> file_data: -# file_data: concatenated lines of intermediate text data -# -# srcdata: filename -> [ excl, brexcl, checksums ] -# excl: lineno -> 1 for all lines for which to exclude all data -# brexcl: lineno -> 1 for all lines for which to exclude branch data -# checksums: lineno -> source code checksum -# -# Note: To simplify processing, gcov data is not combined here, that is counts -# that appear multiple times for the same lines/branches are not added. -# This is done by lcov/genhtml when reading the data files. -# - -sub intermediate_text_to_info($$$) -{ - my ($fd, $data, $srcdata) = @_; - my $branch_num = 0; - my $c; - - return if (!%{$data}); - - print($fd "TN:$test_name\n"); - for my $filename (keys(%{$data})) { - my ($excl, $brexcl, $checksums); - - if (defined($srcdata->{$filename})) { - ($excl, $brexcl, $checksums) = @{$srcdata->{$filename}}; - } - - print($fd "SF:$filename\n"); - for my $line (split(/\n/, $data->{$filename})) { - if ($line =~ /^lcount:(\d+),(\d+),?/) { - # lcount:, - # lcount:,, - if ($checksum && exists($checksums->{$1})) { - $c = ",".$checksums->{$1}; - } else { - $c = ""; - } - print($fd "DA:$1,$2$c\n") if (!$excl->{$1}); - - # Intermediate text format does not provide - # branch numbers, and the same branch may appear - # multiple times on the same line (e.g. in - # template instances). Synthesize a branch - # number based on the assumptions: - # a) the order of branches is fixed across - # instances - # b) an instance starts with an lcount line - $branch_num = 0; - } elsif ($line =~ /^function:(\d+),(\d+),([^,]+)$/) { - next if (!$func_coverage || $excl->{$1}); - - # function:,, - print($fd "FN:$1,$3\n"); - print($fd "FNDA:$2,$3\n"); - } elsif ($line =~ /^function:(\d+),\d+,(\d+),([^,]+)$/) { - next if (!$func_coverage || $excl->{$1}); - - # function:,,, - # - print($fd "FN:$1,$3\n"); - print($fd "FNDA:$2,$3\n"); - } elsif ($line =~ /^branch:(\d+),(taken|nottaken|notexec)/) { - next if (!$br_coverage || $excl->{$1} || - $brexcl->{$1}); - - # branch:,taken|nottaken|notexec - if ($2 eq "taken") { - $c = 1; - } elsif ($2 eq "nottaken") { - $c = 0; - } else { - $c = "-"; - } - print($fd "BRDA:$1,0,$branch_num,$c\n"); - $branch_num++; - } - } - print($fd "end_of_record\n"); - } -} - - -# -# intermediate_json_to_info(fd, data, srcdata) -# -# Write DATA in info format to file descriptor FD. -# -# data: filename -> file_data: -# file_data: GCOV JSON data for file -# -# srcdata: filename -> [ excl, brexcl, checksums ] -# excl: lineno -> 1 for all lines for which to exclude all data -# brexcl: lineno -> 1 for all lines for which to exclude branch data -# checksums: lineno -> source code checksum -# -# Note: To simplify processing, gcov data is not combined here, that is counts -# that appear multiple times for the same lines/branches are not added. -# This is done by lcov/genhtml when reading the data files. -# - -sub intermediate_json_to_info($$$) -{ - my ($fd, $data, $srcdata) = @_; - my $branch_num = 0; - - return if (!%{$data}); - - print($fd "TN:$test_name\n"); - for my $filename (keys(%{$data})) { - my ($excl, $brexcl, $checksums); - my $file_data = $data->{$filename}; - - if (defined($srcdata->{$filename})) { - ($excl, $brexcl, $checksums) = @{$srcdata->{$filename}}; - } - - print($fd "SF:$filename\n"); - - # Function data - if ($func_coverage) { - for my $d (@{$file_data->{"functions"}}) { - my $line = $d->{"start_line"}; - my $count = $d->{"execution_count"}; - my $name = $d->{"name"}; - - next if (!defined($line) || !defined($count) || - !defined($name) || $excl->{$line}); - - print($fd "FN:$line,$name\n"); - print($fd "FNDA:$count,$name\n"); - } - } - - # Line data - for my $d (@{$file_data->{"lines"}}) { - my $line = $d->{"line_number"}; - my $count = $d->{"count"}; - my $c; - my $branches = $d->{"branches"}; - my $unexec = $d->{"unexecuted_block"}; - - next if (!defined($line) || !defined($count) || - $excl->{$line}); - - if (defined($unexec) && $unexec && $count == 0) { - $unexec = 1; - } else { - $unexec = 0; - } - - if ($checksum && exists($checksums->{$line})) { - $c = ",".$checksums->{$line}; - } else { - $c = ""; - } - print($fd "DA:$line,$count$c\n"); - - $branch_num = 0; - # Branch data - if ($br_coverage && !$brexcl->{$line}) { - for my $b (@$branches) { - my $brcount = $b->{"count"}; - - if (!defined($brcount) || $unexec) { - $brcount = "-"; - } - print($fd "BRDA:$line,0,$branch_num,". - "$brcount\n"); - - $branch_num++; - } - } - - } - - print($fd "end_of_record\n"); - } -} - - -sub get_output_fd($$) -{ - my ($outfile, $file) = @_; - my $fd; - - if (!defined($outfile)) { - open($fd, ">", "$file.info") or - die("ERROR: Cannot create file $file.info: $!\n"); - } elsif ($outfile eq "-") { - open($fd, ">&STDOUT") or - die("ERROR: Cannot duplicate stdout: $!\n"); - } else { - open($fd, ">>", $outfile) or - die("ERROR: Cannot write to file $outfile: $!\n"); - } - - return $fd; -} - - -# -# print_gcov_warnings(stderr_file, is_graph, map) -# -# Print GCOV warnings in file STDERR_FILE to STDERR. If IS_GRAPH is non-zero, -# suppress warnings about missing as these are expected. Replace keys found -# in MAP with their values. -# - -sub print_gcov_warnings($$$) -{ - my ($stderr_file, $is_graph, $map) = @_; - my $fd; - - if (!open($fd, "<", $stderr_file)) { - warn("WARNING: Could not open GCOV stderr file ". - "$stderr_file: $!\n"); - return; - } - while (my $line = <$fd>) { - next if ($is_graph && $line =~ /cannot open data file/); - - for my $key (keys(%{$map})) { - $line =~ s/\Q$key\E/$map->{$key}/g; - } - - print(STDERR $line); - } - close($fd); -} - - -# -# process_intermediate(file, dir, tempdir) -# -# Create output for a single file (either a data file or a graph file) using -# gcov's intermediate option. -# - -sub process_intermediate($$$) -{ - my ($file, $dir, $tempdir) = @_; - my ($fdir, $fbase, $fext); - my $data_file; - my $errmsg; - my %data; - my $fd; - my $base; - my $srcdata; - my $is_graph = 0; - my ($out, $err, $rc); - my $json_basedir; - my $json_format; - - info("Processing %s\n", abs2rel($file, $dir)); - - $file = solve_relative_path($cwd, $file); - ($fdir, $fbase, $fext) = split_filename($file); - - $is_graph = 1 if (".$fext" eq $graph_file_extension); - - if ($is_graph) { - # Process graph file - copy to temp directory to prevent - # accidental processing of associated data file - $data_file = "$tempdir/$fbase$graph_file_extension"; - if (!copy($file, $data_file)) { - $errmsg = "ERROR: Could not copy file $file"; - goto err; - } - } else { - # Process data file in place - $data_file = $file; - } - - # Change directory - if (!chdir($tempdir)) { - $errmsg = "Could not change to directory $tempdir: $!"; - goto err; - } - - # Run gcov on data file - ($out, $err, $rc) = system_no_output(1 + 2 + 4, $gcov_tool, - $data_file, @gcov_options, "-i"); - defined($out) && unlink($out); - if (defined($err)) { - print_gcov_warnings($err, $is_graph, { - $data_file => $file, - }); - unlink($err); - } - if ($rc) { - $errmsg = "GCOV failed for $file"; - goto err; - } - - if ($is_graph) { - # Remove graph file copy - unlink($data_file); - } - - # Parse resulting file(s) - for my $gcov_filename (glob("*.gcov")) { - read_intermediate_text($gcov_filename, \%data); - unlink($gcov_filename); - } - - for my $gcov_filename (glob("*.gcov.json.gz")) { - read_intermediate_json($gcov_filename, \%data, \$json_basedir); - unlink($gcov_filename); - $json_format = 1; - } - - if (!%data) { - warn("WARNING: GCOV did not produce any data for $file\n"); - return; - } - - # Determine base directory - if (defined($base_directory)) { - $base = $base_directory; - } elsif (defined($json_basedir)) { - $base = $json_basedir; - } else { - $base = $fdir; - - if (is_compat($COMPAT_MODE_LIBTOOL)) { - # Avoid files from .libs dirs - $base =~ s/\.libs$//; - } - - # Try to find base directory automatically if requested by user - if ($rc_auto_base) { - $base = find_base_from_source($base, [ keys(%data) ]); - } - } - - # Apply base file name to relative source files - adjust_source_filenames(\%data, $base); - - # Remove excluded source files - filter_source_files(\%data); - - # Get data on exclusion markers and checksums if requested - if (!$no_markers || $checksum) { - $srcdata = get_all_source_data(keys(%data)); - } - - # Generate output - $fd = get_output_fd($output_filename, $file); - if ($json_format) { - intermediate_json_to_info($fd, \%data, $srcdata); - } else { - intermediate_text_to_info($fd, \%data, $srcdata); - } - close($fd); - - chdir($cwd); - - return; - -err: - if ($ignore[$ERROR_GCOV]) { - warn("WARNING: $errmsg!\n"); - } else { - die("ERROR: $errmsg!\n") - } -} - - -# Map LLVM versions to the version of GCC gcov which they emulate. - -sub map_llvm_version($) -{ - my ($ver) = @_; - - return 0x040200 if ($ver >= 0x030400); - - warn("WARNING: This version of LLVM's gcov is unknown. ". - "Assuming it emulates GCC gcov version 4.2.\n"); - - return 0x040200; -} - - -# Return a readable version of encoded gcov version. - -sub version_to_str($) -{ - my ($ver) = @_; - my ($a, $b, $c); - - $a = $ver >> 16 & 0xff; - $b = $ver >> 8 & 0xff; - $c = $ver & 0xff; - - return "$a.$b.$c"; -} - - -# -# Get the GCOV tool version. Return an integer number which represents the -# GCOV version. Version numbers can be compared using standard integer -# operations. -# - -sub get_gcov_version() -{ - local *HANDLE; - my $version_string; - my $result; - my ($a, $b, $c) = (4, 2, 0); # Fallback version - - # Examples for gcov version output: - # - # gcov (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3) - # - # gcov (crosstool-NG 1.18.0) 4.7.2 - # - # LLVM (http://llvm.org/): - # LLVM version 3.4svn - # - # Apple LLVM version 8.0.0 (clang-800.0.38) - # Optimized build. - # Default target: x86_64-apple-darwin16.0.0 - # Host CPU: haswell - - open(GCOV_PIPE, "-|", "$gcov_tool --version") - or die("ERROR: cannot retrieve gcov version!\n"); - local $/; - $version_string = ; - close(GCOV_PIPE); - - # Remove all bracketed information - $version_string =~ s/\([^\)]*\)//g; - - if ($version_string =~ /(\d+)\.(\d+)(\.(\d+))?/) { - ($a, $b, $c) = ($1, $2, $4); - $c = 0 if (!defined($c)); - } else { - warn("WARNING: cannot determine gcov version - ". - "assuming $a.$b.$c\n"); - } - $result = $a << 16 | $b << 8 | $c; - - if ($version_string =~ /LLVM/) { - $result = map_llvm_version($result); - info("Found LLVM gcov version $a.$b.$c, which emulates gcov ". - "version ".version_to_str($result)."\n"); - } else { - info("Found gcov version: ".version_to_str($result)."\n"); - } - - return ($result, $version_string); -} - - -# -# info(printf_parameter) -# -# Use printf to write PRINTF_PARAMETER to stdout only when the $quiet flag -# is not set. -# - -sub info(@) -{ - if (!$quiet) - { - # Print info string - if (defined($output_filename) && ($output_filename eq "-")) - { - # Don't interfere with the .info output to STDOUT - printf(STDERR @_); - } - else - { - printf(@_); - } - } -} - - -# -# int_handler() -# -# Called when the script was interrupted by an INT signal (e.g. CTRl-C) -# - -sub int_handler() -{ - if ($cwd) { chdir($cwd); } - info("Aborted.\n"); - exit(1); -} - - -# -# system_no_output(mode, parameters) -# -# Call an external program using PARAMETERS while suppressing depending on -# the value of MODE: -# -# MODE & 1: suppress STDOUT -# MODE & 2: suppress STDERR -# MODE & 4: redirect to temporary files instead of suppressing -# -# Return (stdout, stderr, rc): -# stdout: path to tempfile containing stdout or undef -# stderr: path to tempfile containing stderr or undef -# 0 on success, non-zero otherwise -# - -sub system_no_output($@) -{ - my $mode = shift; - my $result; - local *OLD_STDERR; - local *OLD_STDOUT; - my $stdout_file; - my $stderr_file; - my $fd; - - # Save old stdout and stderr handles - ($mode & 1) && open(OLD_STDOUT, ">>&", "STDOUT"); - ($mode & 2) && open(OLD_STDERR, ">>&", "STDERR"); - - if ($mode & 4) { - # Redirect to temporary files - if ($mode & 1) { - ($fd, $stdout_file) = tempfile(UNLINK => 1); - open(STDOUT, ">", $stdout_file) || warn("$!\n"); - close($fd); - } - if ($mode & 2) { - ($fd, $stderr_file) = tempfile(UNLINK => 1); - open(STDERR, ">", $stderr_file) || warn("$!\n"); - close($fd); - } - } else { - # Redirect to /dev/null - ($mode & 1) && open(STDOUT, ">", "/dev/null"); - ($mode & 2) && open(STDERR, ">", "/dev/null"); - } - - debug("system(".join(' ', @_).")\n"); - system(@_); - $result = $?; - - # Close redirected handles - ($mode & 1) && close(STDOUT); - ($mode & 2) && close(STDERR); - - # Restore old handles - ($mode & 1) && open(STDOUT, ">>&", "OLD_STDOUT"); - ($mode & 2) && open(STDERR, ">>&", "OLD_STDERR"); - - # Remove empty output files - if (defined($stdout_file) && -z $stdout_file) { - unlink($stdout_file); - $stdout_file = undef; - } - if (defined($stderr_file) && -z $stderr_file) { - unlink($stderr_file); - $stderr_file = undef; - } - - return ($stdout_file, $stderr_file, $result); -} - - -# -# read_config(filename) -# -# Read configuration file FILENAME and return a reference to a hash containing -# all valid key=value pairs found. -# - -sub read_config($) -{ - my $filename = $_[0]; - my %result; - my $key; - my $value; - local *HANDLE; - - if (!open(HANDLE, "<", $filename)) - { - warn("WARNING: cannot read configuration file $filename\n"); - return undef; - } - while () - { - chomp; - # Skip comments - s/#.*//; - # Remove leading blanks - s/^\s+//; - # Remove trailing blanks - s/\s+$//; - next unless length; - ($key, $value) = split(/\s*=\s*/, $_, 2); - if (defined($key) && defined($value)) - { - $result{$key} = $value; - } - else - { - warn("WARNING: malformed statement in line $. ". - "of configuration file $filename\n"); - } - } - close(HANDLE); - return \%result; -} - - -# -# apply_config(REF) -# -# REF is a reference to a hash containing the following mapping: -# -# key_string => var_ref -# -# where KEY_STRING is a keyword and VAR_REF is a reference to an associated -# variable. If the global configuration hashes CONFIG or OPT_RC contain a value -# for keyword KEY_STRING, VAR_REF will be assigned the value for that keyword. -# - -sub apply_config($) -{ - my $ref = $_[0]; - - foreach (keys(%{$ref})) - { - if (defined($opt_rc{$_})) { - ${$ref->{$_}} = $opt_rc{$_}; - } elsif (defined($config->{$_})) { - ${$ref->{$_}} = $config->{$_}; - } - } -} - - -# -# get_source_data(filename) -# -# Scan specified source code file for exclusion markers and checksums. Return -# ( excl, brexcl, checksums ) where -# excl: lineno -> 1 for all lines for which to exclude all data -# brexcl: lineno -> 1 for all lines for which to exclude branch data -# checksums: lineno -> source code checksum -# - -sub get_source_data($) -{ - my ($filename) = @_; - my %list; - my $flag = 0; - my %brdata; - my $brflag = 0; - my %checksums; - local *HANDLE; - - if (!open(HANDLE, "<", $filename)) { - warn("WARNING: could not open $filename\n"); - return; - } - while () { - if (/$EXCL_STOP/) { - $flag = 0; - } elsif (/$EXCL_START/) { - $flag = 1; - } - if (/$excl_line/ || $flag) { - $list{$.} = 1; - } - if (/$EXCL_BR_STOP/) { - $brflag = 0; - } elsif (/$EXCL_BR_START/) { - $brflag = 1; - } - if (/$excl_br_line/ || $brflag) { - $brdata{$.} = 1; - } - if ($checksum) { - chomp(); - $checksums{$.} = md5_base64($_); - } - } - close(HANDLE); - - if ($flag || $brflag) { - warn("WARNING: unterminated exclusion section in $filename\n"); - } - - return (\%list, \%brdata, \%checksums); -} - - -# -# get_all_source_data(filenames) -# -# Scan specified source code files for exclusion markers and return -# filename -> [ excl, brexcl, checksums ] -# excl: lineno -> 1 for all lines for which to exclude all data -# brexcl: lineno -> 1 for all lines for which to exclude branch data -# checksums: lineno -> source code checksum -# - -sub get_all_source_data(@) -{ - my @filenames = @_; - my %data; - my $failed = 0; - - for my $filename (@filenames) { - my @d; - next if (exists($data{$filename})); - - @d = get_source_data($filename); - if (@d) { - $data{$filename} = [ @d ]; - } else { - $failed = 1; - } - } - - if ($failed) { - warn("WARNING: some exclusion markers may be ignored\n"); - } - - return \%data; -} - - -# -# apply_exclusion_data(instr, graph) -# -# Remove lines from instr and graph data structures which are marked -# for exclusion in the source code file. -# -# Return adjusted (instr, graph). -# -# graph : file name -> function data -# function data : function name -> line data -# line data : [ line1, line2, ... ] -# -# instr : filename -> line data -# line data : [ line1, line2, ... ] -# - -sub apply_exclusion_data($$) -{ - my ($instr, $graph) = @_; - my $filename; - my $excl_data; - - ($excl_data) = get_all_source_data(keys(%{$graph}), keys(%{$instr})); - - # Skip if no markers were found - return ($instr, $graph) if (!%$excl_data); - - # Apply exclusion marker data to graph - foreach $filename (keys(%$excl_data)) { - my $function_data = $graph->{$filename}; - my $excl = $excl_data->{$filename}->[0]; - my $function; - - next if (!defined($function_data)); - - foreach $function (keys(%{$function_data})) { - my $line_data = $function_data->{$function}; - my $line; - my @new_data; - - # To be consistent with exclusion parser in non-initial - # case we need to remove a function if the first line - # was excluded - if ($excl->{$line_data->[0]}) { - delete($function_data->{$function}); - next; - } - # Copy only lines which are not excluded - foreach $line (@{$line_data}) { - push(@new_data, $line) if (!$excl->{$line}); - } - - # Store modified list - if (scalar(@new_data) > 0) { - $function_data->{$function} = \@new_data; - } else { - # All of this function was excluded - delete($function_data->{$function}); - } - } - - # Check if all functions of this file were excluded - if (keys(%{$function_data}) == 0) { - delete($graph->{$filename}); - } - } - - # Apply exclusion marker data to instr - foreach $filename (keys(%$excl_data)) { - my $line_data = $instr->{$filename}; - my $excl = $excl_data->{$filename}->[0]; - my $line; - my @new_data; - - next if (!defined($line_data)); - - # Copy only lines which are not excluded - foreach $line (@{$line_data}) { - push(@new_data, $line) if (!$excl->{$line}); - } - - # Store modified list - $instr->{$filename} = \@new_data; - } - - return ($instr, $graph); -} - - -sub process_graphfile($$) -{ - my ($file, $dir) = @_; - my $graph_filename = $file; - my $graph_dir; - my $graph_basename; - my $source_dir; - my $base_dir; - my $graph; - my $instr; - my $filename; - local *INFO_HANDLE; - - info("Processing %s\n", abs2rel($file, $dir)); - - # Get path to data file in absolute and normalized form (begins with /, - # contains no more ../ or ./) - $graph_filename = solve_relative_path($cwd, $graph_filename); - - # Get directory and basename of data file - ($graph_dir, $graph_basename) = split_filename($graph_filename); - - $source_dir = $graph_dir; - if (is_compat($COMPAT_MODE_LIBTOOL)) { - # Avoid files from .libs dirs - $source_dir =~ s/\.libs$//; - } - - # Construct base_dir for current file - if ($base_directory) - { - $base_dir = $base_directory; - } - else - { - $base_dir = $source_dir; - } - - # Ignore empty graph file (e.g. source file with no statement) - if (-z $graph_filename) - { - warn("WARNING: empty $graph_filename (skipped)\n"); - return; - } - - if ($gcov_version < $GCOV_VERSION_3_4_0) - { - if (is_compat($COMPAT_MODE_HAMMER)) - { - ($instr, $graph) = read_bbg($graph_filename); - } - else - { - ($instr, $graph) = read_bb($graph_filename); - } - } - else - { - ($instr, $graph) = read_gcno($graph_filename); - } - - # Try to find base directory automatically if requested by user - if ($rc_auto_base) { - $base_dir = find_base_from_source($base_dir, - [ keys(%{$instr}), keys(%{$graph}) ]); - } - - adjust_source_filenames($instr, $base_dir); - adjust_source_filenames($graph, $base_dir); - - if (!$no_markers) { - # Apply exclusion marker data to graph file data - ($instr, $graph) = apply_exclusion_data($instr, $graph); - } - - # Check whether we're writing to a single file - if ($output_filename) - { - if ($output_filename eq "-") - { - *INFO_HANDLE = *STDOUT; - } - else - { - # Append to output file - open(INFO_HANDLE, ">>", $output_filename) - or die("ERROR: cannot write to ". - "$output_filename!\n"); - } - } - else - { - # Open .info file for output - open(INFO_HANDLE, ">", "$graph_filename.info") - or die("ERROR: cannot create $graph_filename.info!\n"); - } - - # Write test name - printf(INFO_HANDLE "TN:%s\n", $test_name); - foreach $filename (sort(keys(%{$instr}))) - { - my $funcdata = $graph->{$filename}; - my $line; - my $linedata; - - # Skip external files if requested - if (!$opt_external) { - if (is_external($filename)) { - info(" ignoring data for external file ". - "$filename\n"); - next; - } - } - - print(INFO_HANDLE "SF:$filename\n"); - - if (defined($funcdata) && $func_coverage) { - my @functions = sort {$funcdata->{$a}->[0] <=> - $funcdata->{$b}->[0]} - keys(%{$funcdata}); - my $func; - - # Gather list of instrumented lines and functions - foreach $func (@functions) { - $linedata = $funcdata->{$func}; - - # Print function name and starting line - print(INFO_HANDLE "FN:".$linedata->[0]. - ",".filter_fn_name($func)."\n"); - } - # Print zero function coverage data - foreach $func (@functions) { - print(INFO_HANDLE "FNDA:0,". - filter_fn_name($func)."\n"); - } - # Print function summary - print(INFO_HANDLE "FNF:".scalar(@functions)."\n"); - print(INFO_HANDLE "FNH:0\n"); - } - # Print zero line coverage data - foreach $line (@{$instr->{$filename}}) { - print(INFO_HANDLE "DA:$line,0\n"); - } - # Print line summary - print(INFO_HANDLE "LF:".scalar(@{$instr->{$filename}})."\n"); - print(INFO_HANDLE "LH:0\n"); - - print(INFO_HANDLE "end_of_record\n"); - } - if (!($output_filename && ($output_filename eq "-"))) - { - close(INFO_HANDLE); - } -} - -sub filter_fn_name($) -{ - my ($fn) = @_; - - # Remove characters used internally as function name delimiters - $fn =~ s/[,=]/_/g; - - return $fn; -} - -sub warn_handler($) -{ - my ($msg) = @_; - - warn("$tool_name: $msg"); -} - -sub die_handler($) -{ - my ($msg) = @_; - - die("$tool_name: $msg"); -} - - -# -# graph_error(filename, message) -# -# Print message about error in graph file. If ignore_graph_error is set, return. -# Otherwise abort. -# - -sub graph_error($$) -{ - my ($filename, $msg) = @_; - - if ($ignore[$ERROR_GRAPH]) { - warn("WARNING: $filename: $msg - skipping\n"); - return; - } - die("ERROR: $filename: $msg\n"); -} - -# -# graph_expect(description) -# -# If debug is set to a non-zero value, print the specified description of what -# is expected to be read next from the graph file. -# - -sub graph_expect($) -{ - my ($msg) = @_; - - if (!$debug || !defined($msg)) { - return; - } - - print(STDERR "DEBUG: expecting $msg\n"); -} - -# -# graph_read(handle, bytes[, description, peek]) -# -# Read and return the specified number of bytes from handle. Return undef -# if the number of bytes could not be read. If PEEK is non-zero, reset -# file position after read. -# - -sub graph_read(*$;$$) -{ - my ($handle, $length, $desc, $peek) = @_; - my $data; - my $result; - my $pos; - - graph_expect($desc); - if ($peek) { - $pos = tell($handle); - if ($pos == -1) { - warn("Could not get current file position: $!\n"); - return undef; - } - } - $result = read($handle, $data, $length); - if ($debug) { - my $op = $peek ? "peek" : "read"; - my $ascii = ""; - my $hex = ""; - my $i; - - print(STDERR "DEBUG: $op($length)=$result: "); - for ($i = 0; $i < length($data); $i++) { - my $c = substr($data, $i, 1);; - my $n = ord($c); - - $hex .= sprintf("%02x ", $n); - if ($n >= 32 && $n <= 127) { - $ascii .= $c; - } else { - $ascii .= "."; - } - } - print(STDERR "$hex |$ascii|"); - print(STDERR "\n"); - } - if ($peek) { - if (!seek($handle, $pos, 0)) { - warn("Could not set file position: $!\n"); - return undef; - } - } - if ($result != $length) { - return undef; - } - return $data; -} - -# -# graph_skip(handle, bytes[, description]) -# -# Read and discard the specified number of bytes from handle. Return non-zero -# if bytes could be read, zero otherwise. -# - -sub graph_skip(*$;$) -{ - my ($handle, $length, $desc) = @_; - - if (defined(graph_read($handle, $length, $desc))) { - return 1; - } - return 0; -} - -# -# uniq(list) -# -# Return list without duplicate entries. -# - -sub uniq(@) -{ - my (@list) = @_; - my @new_list; - my %known; - - foreach my $item (@list) { - next if ($known{$item}); - $known{$item} = 1; - push(@new_list, $item); - } - - return @new_list; -} - -# -# sort_uniq(list) -# -# Return list in numerically ascending order and without duplicate entries. -# - -sub sort_uniq(@) -{ - my (@list) = @_; - my %hash; - - foreach (@list) { - $hash{$_} = 1; - } - return sort { $a <=> $b } keys(%hash); -} - -# -# sort_uniq_lex(list) -# -# Return list in lexically ascending order and without duplicate entries. -# - -sub sort_uniq_lex(@) -{ - my (@list) = @_; - my %hash; - - foreach (@list) { - $hash{$_} = 1; - } - return sort keys(%hash); -} - -# -# parent_dir(dir) -# -# Return parent directory for DIR. DIR must not contain relative path -# components. -# - -sub parent_dir($) -{ - my ($dir) = @_; - my ($v, $d, $f) = splitpath($dir, 1); - my @dirs = splitdir($d); - - pop(@dirs); - - return catpath($v, catdir(@dirs), $f); -} - -# -# find_base_from_source(base_dir, source_files) -# -# Try to determine the base directory of the object file built from -# SOURCE_FILES. The base directory is the base for all relative filenames in -# the gcov data. It is defined by the current working directory at time -# of compiling the source file. -# -# This function implements a heuristic which relies on the following -# assumptions: -# - all files used for compilation are still present at their location -# - the base directory is either BASE_DIR or one of its parent directories -# - files by the same name are not present in multiple parent directories -# - -sub find_base_from_source($$) -{ - my ($base_dir, $source_files) = @_; - my $old_base; - my $best_miss; - my $best_base; - my %rel_files; - - # Determine list of relative paths - foreach my $filename (@$source_files) { - next if (file_name_is_absolute($filename)); - - $rel_files{$filename} = 1; - } - - # Early exit if there are no relative paths - return $base_dir if (!%rel_files); - - do { - my $miss = 0; - - foreach my $filename (keys(%rel_files)) { - if (!-e solve_relative_path($base_dir, $filename)) { - $miss++; - } - } - - debug("base_dir=$base_dir miss=$miss\n"); - - # Exit if we find an exact match with no misses - return $base_dir if ($miss == 0); - - # No exact match, aim for the one with the least source file - # misses - if (!defined($best_base) || $miss < $best_miss) { - $best_base = $base_dir; - $best_miss = $miss; - } - - # Repeat until there's no more parent directory - $old_base = $base_dir; - $base_dir = parent_dir($base_dir); - } while ($old_base ne $base_dir); - - return $best_base; -} - -# -# adjust_source_filenames(hash, base_dir) -# -# Transform all keys of HASH to absolute form and apply requested -# transformations. -# - -sub adjust_source_filenames($$$) -{ - my ($hash, $base_dir) = @_; - - foreach my $filename (keys(%{$hash})) { - my $old_filename = $filename; - - # Convert to absolute canonical form - $filename = solve_relative_path($base_dir, $filename); - - # Apply adjustment - if (defined($adjust_src_pattern)) { - $filename =~ s/$adjust_src_pattern/$adjust_src_replace/g; - } - - if ($filename ne $old_filename) { - $hash->{$filename} = delete($hash->{$old_filename}); - } - } -} - - -# -# filter_source_files(hash) -# -# Remove unwanted source file data from HASH. -# - -sub filter_source_files($) -{ - my ($hash) = @_; - - foreach my $filename (keys(%{$hash})) { - # Skip external files if requested - goto del if (!$opt_external && is_external($filename)); - - # Apply include patterns - if (@include_patterns) { - my $keep; - - foreach my $pattern (@include_patterns) { - if ($filename =~ (/^$pattern$/)) { - $keep = 1; - last; - } - } - goto del if (!$keep); - } - - # Apply exclude patterns - foreach my $pattern (@exclude_patterns) { - goto del if ($filename =~ (/^$pattern$/)); - } - next; - -del: - # Remove file data - delete($hash->{$filename}); - $excluded_files{$filename} = 1; - } -} - -# -# graph_cleanup(graph) -# -# Remove entries for functions with no lines. Remove duplicate line numbers. -# Sort list of line numbers numerically ascending. -# - -sub graph_cleanup($) -{ - my ($graph) = @_; - my $filename; - - foreach $filename (keys(%{$graph})) { - my $per_file = $graph->{$filename}; - my $function; - - foreach $function (keys(%{$per_file})) { - my $lines = $per_file->{$function}; - - if (scalar(@$lines) == 0) { - # Remove empty function - delete($per_file->{$function}); - next; - } - # Normalize list - $per_file->{$function} = [ uniq(@$lines) ]; - } - if (scalar(keys(%{$per_file})) == 0) { - # Remove empty file - delete($graph->{$filename}); - } - } -} - -# -# graph_find_base(bb) -# -# Try to identify the filename which is the base source file for the -# specified bb data. -# - -sub graph_find_base($) -{ - my ($bb) = @_; - my %file_count; - my $basefile; - my $file; - my $func; - my $filedata; - my $count; - my $num; - - # Identify base name for this bb data. - foreach $func (keys(%{$bb})) { - $filedata = $bb->{$func}; - - foreach $file (keys(%{$filedata})) { - $count = $file_count{$file}; - - # Count file occurrence - $file_count{$file} = defined($count) ? $count + 1 : 1; - } - } - $count = 0; - $num = 0; - foreach $file (keys(%file_count)) { - if ($file_count{$file} > $count) { - # The file that contains code for the most functions - # is likely the base file - $count = $file_count{$file}; - $num = 1; - $basefile = $file; - } elsif ($file_count{$file} == $count) { - # If more than one file could be the basefile, we - # don't have a basefile - $basefile = undef; - } - } - - return $basefile; -} - -# -# graph_from_bb(bb, fileorder, bb_filename, fileorder_first) -# -# Convert data from bb to the graph format and list of instrumented lines. -# -# If FILEORDER_FIRST is set, use fileorder data to determine a functions -# base source file. -# -# Returns (instr, graph). -# -# bb : function name -> file data -# : undef -> file order -# file data : filename -> line data -# line data : [ line1, line2, ... ] -# -# file order : function name -> [ filename1, filename2, ... ] -# -# graph : file name -> function data -# function data : function name -> line data -# line data : [ line1, line2, ... ] -# -# instr : filename -> line data -# line data : [ line1, line2, ... ] -# - -sub graph_from_bb($$$$) -{ - my ($bb, $fileorder, $bb_filename, $fileorder_first) = @_; - my $graph = {}; - my $instr = {}; - my $basefile; - my $file; - my $func; - my $filedata; - my $linedata; - my $order; - - $basefile = graph_find_base($bb); - # Create graph structure - foreach $func (keys(%{$bb})) { - $filedata = $bb->{$func}; - $order = $fileorder->{$func}; - - # Account for lines in functions - if (defined($basefile) && defined($filedata->{$basefile}) && - !$fileorder_first) { - # If the basefile contributes to this function, - # account this function to the basefile. - $graph->{$basefile}->{$func} = $filedata->{$basefile}; - } else { - # If the basefile does not contribute to this function, - # account this function to the first file contributing - # lines. - $graph->{$order->[0]}->{$func} = - $filedata->{$order->[0]}; - } - - foreach $file (keys(%{$filedata})) { - # Account for instrumented lines - $linedata = $filedata->{$file}; - push(@{$instr->{$file}}, @$linedata); - } - } - # Clean up array of instrumented lines - foreach $file (keys(%{$instr})) { - $instr->{$file} = [ sort_uniq(@{$instr->{$file}}) ]; - } - - return ($instr, $graph); -} - -# -# graph_add_order(fileorder, function, filename) -# -# Add an entry for filename to the fileorder data set for function. -# - -sub graph_add_order($$$) -{ - my ($fileorder, $function, $filename) = @_; - my $item; - my $list; - - $list = $fileorder->{$function}; - foreach $item (@$list) { - if ($item eq $filename) { - return; - } - } - push(@$list, $filename); - $fileorder->{$function} = $list; -} - -# -# read_bb_word(handle[, description]) -# -# Read and return a word in .bb format from handle. -# - -sub read_bb_word(*;$) -{ - my ($handle, $desc) = @_; - - return graph_read($handle, 4, $desc); -} - -# -# read_bb_value(handle[, description]) -# -# Read a word in .bb format from handle and return the word and its integer -# value. -# - -sub read_bb_value(*;$) -{ - my ($handle, $desc) = @_; - my $word; - - $word = read_bb_word($handle, $desc); - return undef if (!defined($word)); - - return ($word, unpack("V", $word)); -} - -# -# read_bb_string(handle, delimiter) -# -# Read and return a string in .bb format from handle up to the specified -# delimiter value. -# - -sub read_bb_string(*$) -{ - my ($handle, $delimiter) = @_; - my $word; - my $value; - my $string = ""; - - graph_expect("string"); - do { - ($word, $value) = read_bb_value($handle, "string or delimiter"); - return undef if (!defined($value)); - if ($value != $delimiter) { - $string .= $word; - } - } while ($value != $delimiter); - $string =~ s/\0//g; - - return $string; -} - -# -# read_bb(filename) -# -# Read the contents of the specified .bb file and return (instr, graph), where: -# -# instr : filename -> line data -# line data : [ line1, line2, ... ] -# -# graph : filename -> file_data -# file_data : function name -> line_data -# line_data : [ line1, line2, ... ] -# -# See the gcov info pages of gcc 2.95 for a description of the .bb file format. -# - -sub read_bb($) -{ - my ($bb_filename) = @_; - my $minus_one = 0x80000001; - my $minus_two = 0x80000002; - my $value; - my $filename; - my $function; - my $bb = {}; - my $fileorder = {}; - my $instr; - my $graph; - local *HANDLE; - - open(HANDLE, "<", $bb_filename) or goto open_error; - binmode(HANDLE); - while (!eof(HANDLE)) { - $value = read_bb_value(*HANDLE, "data word"); - goto incomplete if (!defined($value)); - if ($value == $minus_one) { - # Source file name - graph_expect("filename"); - $filename = read_bb_string(*HANDLE, $minus_one); - goto incomplete if (!defined($filename)); - } elsif ($value == $minus_two) { - # Function name - graph_expect("function name"); - $function = read_bb_string(*HANDLE, $minus_two); - goto incomplete if (!defined($function)); - } elsif ($value > 0) { - # Line number - if (!defined($filename) || !defined($function)) { - warn("WARNING: unassigned line number ". - "$value\n"); - next; - } - push(@{$bb->{$function}->{$filename}}, $value); - graph_add_order($fileorder, $function, $filename); - } - } - close(HANDLE); - - ($instr, $graph) = graph_from_bb($bb, $fileorder, $bb_filename, 0); - graph_cleanup($graph); - - return ($instr, $graph); - -open_error: - graph_error($bb_filename, "could not open file"); - return undef; -incomplete: - graph_error($bb_filename, "reached unexpected end of file"); - return undef; -} - -# -# read_bbg_word(handle[, description]) -# -# Read and return a word in .bbg format. -# - -sub read_bbg_word(*;$) -{ - my ($handle, $desc) = @_; - - return graph_read($handle, 4, $desc); -} - -# -# read_bbg_value(handle[, description]) -# -# Read a word in .bbg format from handle and return its integer value. -# - -sub read_bbg_value(*;$) -{ - my ($handle, $desc) = @_; - my $word; - - $word = read_bbg_word($handle, $desc); - return undef if (!defined($word)); - - return unpack("N", $word); -} - -# -# read_bbg_string(handle) -# -# Read and return a string in .bbg format. -# - -sub read_bbg_string(*) -{ - my ($handle, $desc) = @_; - my $length; - my $string; - - graph_expect("string"); - # Read string length - $length = read_bbg_value($handle, "string length"); - return undef if (!defined($length)); - if ($length == 0) { - return ""; - } - # Read string - $string = graph_read($handle, $length, "string"); - return undef if (!defined($string)); - # Skip padding - graph_skip($handle, 4 - $length % 4, "string padding") or return undef; - - return $string; -} - -# -# read_bbg_lines_record(handle, bbg_filename, bb, fileorder, filename, -# function) -# -# Read a bbg format lines record from handle and add the relevant data to -# bb and fileorder. Return filename on success, undef on error. -# - -sub read_bbg_lines_record(*$$$$$) -{ - my ($handle, $bbg_filename, $bb, $fileorder, $filename, $function) = @_; - my $string; - my $lineno; - - graph_expect("lines record"); - # Skip basic block index - graph_skip($handle, 4, "basic block index") or return undef; - while (1) { - # Read line number - $lineno = read_bbg_value($handle, "line number"); - return undef if (!defined($lineno)); - if ($lineno == 0) { - # Got a marker for a new filename - graph_expect("filename"); - $string = read_bbg_string($handle); - return undef if (!defined($string)); - # Check for end of record - if ($string eq "") { - return $filename; - } - $filename = $string; - if (!exists($bb->{$function}->{$filename})) { - $bb->{$function}->{$filename} = []; - } - next; - } - # Got an actual line number - if (!defined($filename)) { - warn("WARNING: unassigned line number in ". - "$bbg_filename\n"); - next; - } - push(@{$bb->{$function}->{$filename}}, $lineno); - graph_add_order($fileorder, $function, $filename); - } -} - -# -# read_bbg(filename) -# -# Read the contents of the specified .bbg file and return the following mapping: -# graph: filename -> file_data -# file_data: function name -> line_data -# line_data: [ line1, line2, ... ] -# -# See the gcov-io.h file in the SLES 9 gcc 3.3.3 source code for a description -# of the .bbg format. -# - -sub read_bbg($) -{ - my ($bbg_filename) = @_; - my $file_magic = 0x67626267; - my $tag_function = 0x01000000; - my $tag_lines = 0x01450000; - my $word; - my $tag; - my $length; - my $function; - my $filename; - my $bb = {}; - my $fileorder = {}; - my $instr; - my $graph; - local *HANDLE; - - open(HANDLE, "<", $bbg_filename) or goto open_error; - binmode(HANDLE); - # Read magic - $word = read_bbg_value(*HANDLE, "file magic"); - goto incomplete if (!defined($word)); - # Check magic - if ($word != $file_magic) { - goto magic_error; - } - # Skip version - graph_skip(*HANDLE, 4, "version") or goto incomplete; - while (!eof(HANDLE)) { - # Read record tag - $tag = read_bbg_value(*HANDLE, "record tag"); - goto incomplete if (!defined($tag)); - # Read record length - $length = read_bbg_value(*HANDLE, "record length"); - goto incomplete if (!defined($tag)); - if ($tag == $tag_function) { - graph_expect("function record"); - # Read function name - graph_expect("function name"); - $function = read_bbg_string(*HANDLE); - goto incomplete if (!defined($function)); - $filename = undef; - # Skip function checksum - graph_skip(*HANDLE, 4, "function checksum") - or goto incomplete; - } elsif ($tag == $tag_lines) { - # Read lines record - $filename = read_bbg_lines_record(HANDLE, $bbg_filename, - $bb, $fileorder, $filename, - $function); - goto incomplete if (!defined($filename)); - } else { - # Skip record contents - graph_skip(*HANDLE, $length, "unhandled record") - or goto incomplete; - } - } - close(HANDLE); - ($instr, $graph) = graph_from_bb($bb, $fileorder, $bbg_filename, 0); - - graph_cleanup($graph); - - return ($instr, $graph); - -open_error: - graph_error($bbg_filename, "could not open file"); - return undef; -incomplete: - graph_error($bbg_filename, "reached unexpected end of file"); - return undef; -magic_error: - graph_error($bbg_filename, "found unrecognized bbg file magic"); - return undef; -} - -# -# read_gcno_word(handle[, description, peek]) -# -# Read and return a word in .gcno format. -# - -sub read_gcno_word(*;$$) -{ - my ($handle, $desc, $peek) = @_; - - return graph_read($handle, 4, $desc, $peek); -} - -# -# read_gcno_value(handle, big_endian[, description, peek]) -# -# Read a word in .gcno format from handle and return its integer value -# according to the specified endianness. If PEEK is non-zero, reset file -# position after read. -# - -sub read_gcno_value(*$;$$) -{ - my ($handle, $big_endian, $desc, $peek) = @_; - my $word; - my $pos; - - $word = read_gcno_word($handle, $desc, $peek); - return undef if (!defined($word)); - if ($big_endian) { - return unpack("N", $word); - } else { - return unpack("V", $word); - } -} - -# -# read_gcno_string(handle, big_endian) -# -# Read and return a string in .gcno format. -# - -sub read_gcno_string(*$) -{ - my ($handle, $big_endian) = @_; - my $length; - my $string; - - graph_expect("string"); - # Read string length - $length = read_gcno_value($handle, $big_endian, "string length"); - return undef if (!defined($length)); - if ($length == 0) { - return ""; - } - $length *= 4; - # Read string - $string = graph_read($handle, $length, "string and padding"); - return undef if (!defined($string)); - $string =~ s/\0//g; - - return $string; -} - -# -# read_gcno_lines_record(handle, gcno_filename, bb, fileorder, filename, -# function, big_endian) -# -# Read a gcno format lines record from handle and add the relevant data to -# bb and fileorder. Return filename on success, undef on error. -# - -sub read_gcno_lines_record(*$$$$$$) -{ - my ($handle, $gcno_filename, $bb, $fileorder, $filename, $function, - $big_endian) = @_; - my $string; - my $lineno; - - graph_expect("lines record"); - # Skip basic block index - graph_skip($handle, 4, "basic block index") or return undef; - while (1) { - # Read line number - $lineno = read_gcno_value($handle, $big_endian, "line number"); - return undef if (!defined($lineno)); - if ($lineno == 0) { - # Got a marker for a new filename - graph_expect("filename"); - $string = read_gcno_string($handle, $big_endian); - return undef if (!defined($string)); - # Check for end of record - if ($string eq "") { - return $filename; - } - $filename = $string; - if (!exists($bb->{$function}->{$filename})) { - $bb->{$function}->{$filename} = []; - } - next; - } - # Got an actual line number - if (!defined($filename)) { - warn("WARNING: unassigned line number in ". - "$gcno_filename\n"); - next; - } - # Add to list - push(@{$bb->{$function}->{$filename}}, $lineno); - graph_add_order($fileorder, $function, $filename); - } -} - -# -# determine_gcno_split_crc(handle, big_endian, rec_length, version) -# -# Determine if HANDLE refers to a .gcno file with a split checksum function -# record format. Return non-zero in case of split checksum format, zero -# otherwise, undef in case of read error. -# - -sub determine_gcno_split_crc($$$$) -{ - my ($handle, $big_endian, $rec_length, $version) = @_; - my $strlen; - my $overlong_string; - - return 1 if ($version >= $GCOV_VERSION_4_7_0); - return 1 if (is_compat($COMPAT_MODE_SPLIT_CRC)); - - # Heuristic: - # Decide format based on contents of next word in record: - # - pre-gcc 4.7 - # This is the function name length / 4 which should be - # less than the remaining record length - # - gcc 4.7 - # This is a checksum, likely with high-order bits set, - # resulting in a large number - $strlen = read_gcno_value($handle, $big_endian, undef, 1); - return undef if (!defined($strlen)); - $overlong_string = 1 if ($strlen * 4 >= $rec_length - 12); - - if ($overlong_string) { - if (is_compat_auto($COMPAT_MODE_SPLIT_CRC)) { - info("Auto-detected compatibility mode for split ". - "checksum .gcno file format\n"); - - return 1; - } else { - # Sanity check - warn("Found overlong string in function record: ". - "try '--compat split_crc'\n"); - } - } - - return 0; -} - -# -# read_gcno_function_record(handle, graph, big_endian, rec_length, version) -# -# Read a gcno format function record from handle and add the relevant data -# to graph. Return (filename, function, artificial) on success, undef on error. -# - -sub read_gcno_function_record(*$$$$$) -{ - my ($handle, $bb, $fileorder, $big_endian, $rec_length, $version) = @_; - my $filename; - my $function; - my $lineno; - my $lines; - my $artificial; - - graph_expect("function record"); - # Skip ident and checksum - graph_skip($handle, 8, "function ident and checksum") or return undef; - # Determine if this is a function record with split checksums - if (!defined($gcno_split_crc)) { - $gcno_split_crc = determine_gcno_split_crc($handle, $big_endian, - $rec_length, - $version); - return undef if (!defined($gcno_split_crc)); - } - # Skip cfg checksum word in case of split checksums - graph_skip($handle, 4, "function cfg checksum") if ($gcno_split_crc); - # Read function name - graph_expect("function name"); - $function = read_gcno_string($handle, $big_endian); - return undef if (!defined($function)); - if ($version >= $GCOV_VERSION_8_0_0) { - $artificial = read_gcno_value($handle, $big_endian, - "compiler-generated entity flag"); - return undef if (!defined($artificial)); - } - # Read filename - graph_expect("filename"); - $filename = read_gcno_string($handle, $big_endian); - return undef if (!defined($filename)); - # Read first line number - $lineno = read_gcno_value($handle, $big_endian, "initial line number"); - return undef if (!defined($lineno)); - # Skip column and ending line number - if ($version >= $GCOV_VERSION_8_0_0) { - graph_skip($handle, 4, "column number") or return undef; - graph_skip($handle, 4, "ending line number") or return undef; - } - # Add to list - push(@{$bb->{$function}->{$filename}}, $lineno); - graph_add_order($fileorder, $function, $filename); - - return ($filename, $function, $artificial); -} - -# -# map_gcno_version -# -# Map version number as found in .gcno files to the format used in geninfo. -# - -sub map_gcno_version($) -{ - my ($version) = @_; - my ($a, $b, $c); - my ($major, $minor); - - $a = $version >> 24; - $b = $version >> 16 & 0xff; - $c = $version >> 8 & 0xff; - - if ($a < ord('A')) { - $major = $a - ord('0'); - $minor = ($b - ord('0')) * 10 + $c - ord('0'); - } else { - $major = ($a - ord('A')) * 10 + $b - ord('0'); - $minor = $c - ord('0'); - } - - return $major << 16 | $minor << 8; -} - -sub remove_fn_from_hash($$) -{ - my ($hash, $fns) = @_; - - foreach my $fn (@$fns) { - delete($hash->{$fn}); - } -} - -# -# read_gcno(filename) -# -# Read the contents of the specified .gcno file and return the following -# mapping: -# graph: filename -> file_data -# file_data: function name -> line_data -# line_data: [ line1, line2, ... ] -# -# See the gcov-io.h file in the gcc 3.3 source code for a description of -# the .gcno format. -# - -sub read_gcno($) -{ - my ($gcno_filename) = @_; - my $file_magic = 0x67636e6f; - my $tag_function = 0x01000000; - my $tag_lines = 0x01450000; - my $big_endian; - my $word; - my $tag; - my $length; - my $filename; - my $function; - my $bb = {}; - my $fileorder = {}; - my $instr; - my $graph; - my $filelength; - my $version; - my $artificial; - my @artificial_fns; - local *HANDLE; - - open(HANDLE, "<", $gcno_filename) or goto open_error; - $filelength = (stat(HANDLE))[7]; - binmode(HANDLE); - # Read magic - $word = read_gcno_word(*HANDLE, "file magic"); - goto incomplete if (!defined($word)); - # Determine file endianness - if (unpack("N", $word) == $file_magic) { - $big_endian = 1; - } elsif (unpack("V", $word) == $file_magic) { - $big_endian = 0; - } else { - goto magic_error; - } - # Read version - $version = read_gcno_value(*HANDLE, $big_endian, "compiler version"); - $version = map_gcno_version($version); - debug(sprintf("found version 0x%08x\n", $version)); - # Skip stamp - graph_skip(*HANDLE, 4, "file timestamp") or goto incomplete; - if ($version >= $GCOV_VERSION_8_0_0) { - graph_skip(*HANDLE, 4, "support unexecuted blocks flag") - or goto incomplete; - } - while (!eof(HANDLE)) { - my $next_pos; - my $curr_pos; - - # Read record tag - $tag = read_gcno_value(*HANDLE, $big_endian, "record tag"); - goto incomplete if (!defined($tag)); - # Read record length - $length = read_gcno_value(*HANDLE, $big_endian, - "record length"); - goto incomplete if (!defined($length)); - # Convert length to bytes - $length *= 4; - # Calculate start of next record - $next_pos = tell(HANDLE); - goto tell_error if ($next_pos == -1); - $next_pos += $length; - # Catch garbage at the end of a gcno file - if ($next_pos > $filelength) { - debug("Overlong record: file_length=$filelength ". - "rec_length=$length\n"); - warn("WARNING: $gcno_filename: Overlong record at end ". - "of file!\n"); - last; - } - # Process record - if ($tag == $tag_function) { - ($filename, $function, $artificial) = - read_gcno_function_record( - *HANDLE, $bb, $fileorder, $big_endian, - $length, $version); - goto incomplete if (!defined($function)); - push(@artificial_fns, $function) if ($artificial); - } elsif ($tag == $tag_lines) { - # Read lines record - $filename = read_gcno_lines_record(*HANDLE, - $gcno_filename, $bb, $fileorder, - $filename, $function, $big_endian); - goto incomplete if (!defined($filename)); - } else { - # Skip record contents - graph_skip(*HANDLE, $length, "unhandled record") - or goto incomplete; - } - # Ensure that we are at the start of the next record - $curr_pos = tell(HANDLE); - goto tell_error if ($curr_pos == -1); - next if ($curr_pos == $next_pos); - goto record_error if ($curr_pos > $next_pos); - graph_skip(*HANDLE, $next_pos - $curr_pos, - "unhandled record content") - or goto incomplete; - } - close(HANDLE); - - # Remove artificial functions from result data - remove_fn_from_hash($bb, \@artificial_fns); - remove_fn_from_hash($fileorder, \@artificial_fns); - - ($instr, $graph) = graph_from_bb($bb, $fileorder, $gcno_filename, 1); - graph_cleanup($graph); - - return ($instr, $graph); - -open_error: - graph_error($gcno_filename, "could not open file"); - return undef; -incomplete: - graph_error($gcno_filename, "reached unexpected end of file"); - return undef; -magic_error: - graph_error($gcno_filename, "found unrecognized gcno file magic"); - return undef; -tell_error: - graph_error($gcno_filename, "could not determine file position"); - return undef; -record_error: - graph_error($gcno_filename, "found unrecognized record format"); - return undef; -} - -sub debug($) -{ - my ($msg) = @_; - - return if (!$debug); - print(STDERR "DEBUG: $msg"); -} - -# -# get_gcov_capabilities -# -# Determine the list of available gcov options. -# - -sub get_gcov_capabilities() -{ - my $help = `$gcov_tool --help`; - my %capabilities; - my %short_option_translations = ( - 'a' => 'all-blocks', - 'b' => 'branch-probabilities', - 'c' => 'branch-counts', - 'f' => 'function-summaries', - 'h' => 'help', - 'i' => 'intermediate-format', - 'l' => 'long-file-names', - 'n' => 'no-output', - 'o' => 'object-directory', - 'p' => 'preserve-paths', - 'u' => 'unconditional-branches', - 'v' => 'version', - 'x' => 'hash-filenames', - ); - - foreach (split(/\n/, $help)) { - my $capability; - if (/--(\S+)/) { - $capability = $1; - } else { - # If the line provides a short option, translate it. - next if (!/^\s*-(\S)\s/); - $capability = $short_option_translations{$1}; - next if not defined($capability); - } - next if ($capability eq 'help'); - next if ($capability eq 'version'); - next if ($capability eq 'object-directory'); - - $capabilities{$capability} = 1; - debug("gcov has capability '$capability'\n"); - } - - return \%capabilities; -} - -# -# parse_ignore_errors(@ignore_errors) -# -# Parse user input about which errors to ignore. -# - -sub parse_ignore_errors(@) -{ - my (@ignore_errors) = @_; - my @items; - my $item; - - return if (!@ignore_errors); - - foreach $item (@ignore_errors) { - $item =~ s/\s//g; - if ($item =~ /,/) { - # Split and add comma-separated parameters - push(@items, split(/,/, $item)); - } else { - # Add single parameter - push(@items, $item); - } - } - foreach $item (@items) { - my $item_id = $ERROR_ID{lc($item)}; - - if (!defined($item_id)) { - die("ERROR: unknown argument for --ignore-errors: ". - "$item\n"); - } - $ignore[$item_id] = 1; - } -} - -# -# is_external(filename) -# -# Determine if a file is located outside of the specified data directories. -# - -sub is_external($) -{ - my ($filename) = @_; - my $dir; - - foreach $dir (@internal_dirs) { - return 0 if ($filename =~ /^\Q$dir\/\E/); - } - return 1; -} - -# -# compat_name(mode) -# -# Return the name of compatibility mode MODE. -# - -sub compat_name($) -{ - my ($mode) = @_; - my $name = $COMPAT_MODE_TO_NAME{$mode}; - - return $name if (defined($name)); - - return ""; -} - -# -# parse_compat_modes(opt) -# -# Determine compatibility mode settings. -# - -sub parse_compat_modes($) -{ - my ($opt) = @_; - my @opt_list; - my %specified; - - # Initialize with defaults - %compat_value = %COMPAT_MODE_DEFAULTS; - - # Add old style specifications - if (defined($opt_compat_libtool)) { - $compat_value{$COMPAT_MODE_LIBTOOL} = - $opt_compat_libtool ? $COMPAT_VALUE_ON - : $COMPAT_VALUE_OFF; - } - - # Parse settings - if (defined($opt)) { - @opt_list = split(/\s*,\s*/, $opt); - } - foreach my $directive (@opt_list) { - my ($mode, $value); - - # Either - # mode=off|on|auto or - # mode (implies on) - if ($directive !~ /^(\w+)=(\w+)$/ && - $directive !~ /^(\w+)$/) { - die("ERROR: Unknown compatibility mode specification: ". - "$directive!\n"); - } - # Determine mode - $mode = $COMPAT_NAME_TO_MODE{lc($1)}; - if (!defined($mode)) { - die("ERROR: Unknown compatibility mode '$1'!\n"); - } - $specified{$mode} = 1; - # Determine value - if (defined($2)) { - $value = $COMPAT_NAME_TO_VALUE{lc($2)}; - if (!defined($value)) { - die("ERROR: Unknown compatibility mode ". - "value '$2'!\n"); - } - } else { - $value = $COMPAT_VALUE_ON; - } - $compat_value{$mode} = $value; - } - # Perform auto-detection - foreach my $mode (sort(keys(%compat_value))) { - my $value = $compat_value{$mode}; - my $is_autodetect = ""; - my $name = compat_name($mode); - - if ($value == $COMPAT_VALUE_AUTO) { - my $autodetect = $COMPAT_MODE_AUTO{$mode}; - - if (!defined($autodetect)) { - die("ERROR: No auto-detection for ". - "mode '$name' available!\n"); - } - - if (ref($autodetect) eq "CODE") { - $value = &$autodetect(); - $compat_value{$mode} = $value; - $is_autodetect = " (auto-detected)"; - } - } - - if ($specified{$mode}) { - if ($value == $COMPAT_VALUE_ON) { - info("Enabling compatibility mode ". - "'$name'$is_autodetect\n"); - } elsif ($value == $COMPAT_VALUE_OFF) { - info("Disabling compatibility mode ". - "'$name'$is_autodetect\n"); - } else { - info("Using delayed auto-detection for ". - "compatibility mode ". - "'$name'\n"); - } - } - } -} - -sub compat_hammer_autodetect() -{ - if ($gcov_version_string =~ /suse/i && $gcov_version == 0x30303 || - $gcov_version_string =~ /mandrake/i && $gcov_version == 0x30302) - { - info("Auto-detected compatibility mode for GCC 3.3 (hammer)\n"); - return $COMPAT_VALUE_ON; - } - return $COMPAT_VALUE_OFF; -} - -# -# is_compat(mode) -# -# Return non-zero if compatibility mode MODE is enabled. -# - -sub is_compat($) -{ - my ($mode) = @_; - - return 1 if ($compat_value{$mode} == $COMPAT_VALUE_ON); - return 0; -} - -# -# is_compat_auto(mode) -# -# Return non-zero if compatibility mode MODE is set to auto-detect. -# - -sub is_compat_auto($) -{ - my ($mode) = @_; - - return 1 if ($compat_value{$mode} == $COMPAT_VALUE_AUTO); - return 0; -} diff --git a/worker/deps/lcov/bin/genpng b/worker/deps/lcov/bin/genpng deleted file mode 100755 index e1d431a348..0000000000 --- a/worker/deps/lcov/bin/genpng +++ /dev/null @@ -1,389 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright (c) International Business Machines Corp., 2002 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# -# genpng -# -# This script creates an overview PNG image of a source code file by -# representing each source code character by a single pixel. -# -# Note that the Perl module GD.pm is required for this script to work. -# It may be obtained from http://www.cpan.org -# -# History: -# 2002-08-26: created by Peter Oberparleiter -# - -use strict; -use warnings; -use File::Basename; -use Getopt::Long; -use Cwd qw/abs_path/; - - -# Constants -our $tool_dir = abs_path(dirname($0)); -our $lcov_version = 'LCOV version '.`$tool_dir/get_version.sh --full`; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; -our $tool_name = basename($0); - - -# Prototypes -sub gen_png($$$@); -sub check_and_load_module($); -sub genpng_print_usage(*); -sub genpng_process_file($$$$); -sub genpng_warn_handler($); -sub genpng_die_handler($); - - -# -# Code entry point -# - -# Check whether required module GD.pm is installed -if (check_and_load_module("GD")) -{ - # Note: cannot use die() to print this message because inserting this - # code into another script via do() would not fail as required! - print(STDERR < \$tab_size, - "width=i" => \$width, - "output-filename=s" => \$out_filename, - "help" => \$help, - "version" => \$version)) - { - print(STDERR "Use $tool_name --help to get usage ". - "information\n"); - exit(1); - } - - $filename = $ARGV[0]; - - # Check for help flag - if ($help) - { - genpng_print_usage(*STDOUT); - exit(0); - } - - # Check for version flag - if ($version) - { - print("$tool_name: $lcov_version\n"); - exit(0); - } - - # Check options - if (!$filename) - { - die("No filename specified\n"); - } - - # Check for output filename - if (!$out_filename) - { - $out_filename = "$filename.png"; - } - - genpng_process_file($filename, $out_filename, $width, $tab_size); - exit(0); -} - - -# -# genpng_print_usage(handle) -# -# Write out command line usage information to given filehandle. -# - -sub genpng_print_usage(*) -{ - local *HANDLE = $_[0]; - - print(HANDLE <) - { - if (/^\t\t(.*)$/) - { - # Uninstrumented line - push(@source, ":$1"); - } - elsif (/^ ###### (.*)$/) - { - # Line with zero execution count - push(@source, "0:$1"); - } - elsif (/^( *)(\d*) (.*)$/) - { - # Line with positive execution count - push(@source, "$2:$3"); - } - } - } - else - { - # Plain text file - while () { push(@source, ":$_"); } - } - close(HANDLE); - - gen_png($out_filename, $width, $tab_size, @source); -} - - -# -# gen_png(filename, width, tab_size, source) -# -# Write an overview PNG file to FILENAME. Source code is defined by SOURCE -# which is a list of lines : per source code line. -# The output image will be made up of one pixel per character of source, -# coloring will be done according to execution counts. WIDTH defines the -# image width. TAB_SIZE specifies the number of spaces to use as replacement -# string for tabulator signs in source code text. -# -# Die on error. -# - -sub gen_png($$$@) -{ - my $filename = shift(@_); # Filename for PNG file - my $overview_width = shift(@_); # Imagewidth for image - my $tab_size = shift(@_); # Replacement string for tab signs - my @source = @_; # Source code as passed via argument 2 - my $height; # Height as define by source size - my $overview; # Source code overview image data - my $col_plain_back; # Color for overview background - my $col_plain_text; # Color for uninstrumented text - my $col_cov_back; # Color for background of covered lines - my $col_cov_text; # Color for text of covered lines - my $col_nocov_back; # Color for background of lines which - # were not covered (count == 0) - my $col_nocov_text; # Color for test of lines which were not - # covered (count == 0) - my $col_hi_back; # Color for background of highlighted lines - my $col_hi_text; # Color for text of highlighted lines - my $line; # Current line during iteration - my $row = 0; # Current row number during iteration - my $column; # Current column number during iteration - my $color_text; # Current text color during iteration - my $color_back; # Current background color during iteration - my $last_count; # Count of last processed line - my $count; # Count of current line - my $source; # Source code of current line - my $replacement; # Replacement string for tabulator chars - local *PNG_HANDLE; # Handle for output PNG file - - # Handle empty source files - if (!@source) { - @source = ( "" ); - } - $height = scalar(@source); - # Create image - $overview = new GD::Image($overview_width, $height) - or die("ERROR: cannot allocate overview image!\n"); - - # Define colors - $col_plain_back = $overview->colorAllocate(0xff, 0xff, 0xff); - $col_plain_text = $overview->colorAllocate(0xaa, 0xaa, 0xaa); - $col_cov_back = $overview->colorAllocate(0xaa, 0xa7, 0xef); - $col_cov_text = $overview->colorAllocate(0x5d, 0x5d, 0xea); - $col_nocov_back = $overview->colorAllocate(0xff, 0x00, 0x00); - $col_nocov_text = $overview->colorAllocate(0xaa, 0x00, 0x00); - $col_hi_back = $overview->colorAllocate(0x00, 0xff, 0x00); - $col_hi_text = $overview->colorAllocate(0x00, 0xaa, 0x00); - - # Visualize each line - foreach $line (@source) - { - # Replace tabs with spaces to keep consistent with source - # code view - while ($line =~ /^([^\t]*)(\t)/) - { - $replacement = " "x($tab_size - ((length($1) - 1) % - $tab_size)); - $line =~ s/^([^\t]*)(\t)/$1$replacement/; - } - - # Skip lines which do not follow the : - # specification, otherwise $1 = count, $2 = source code - if (!($line =~ /(\*?)(\d*):(.*)$/)) { next; } - $count = $2; - $source = $3; - - # Decide which color pair to use - - # If this line was not instrumented but the one before was, - # take the color of that line to widen color areas in - # resulting image - if (($count eq "") && defined($last_count) && - ($last_count ne "")) - { - $count = $last_count; - } - - if ($count eq "") - { - # Line was not instrumented - $color_text = $col_plain_text; - $color_back = $col_plain_back; - } - elsif ($count == 0) - { - # Line was instrumented but not executed - $color_text = $col_nocov_text; - $color_back = $col_nocov_back; - } - elsif ($1 eq "*") - { - # Line was highlighted - $color_text = $col_hi_text; - $color_back = $col_hi_back; - } - else - { - # Line was instrumented and executed - $color_text = $col_cov_text; - $color_back = $col_cov_back; - } - - # Write one pixel for each source character - $column = 0; - foreach (split("", $source)) - { - # Check for width - if ($column >= $overview_width) { last; } - - if ($_ eq " ") - { - # Space - $overview->setPixel($column++, $row, - $color_back); - } - else - { - # Text - $overview->setPixel($column++, $row, - $color_text); - } - } - - # Fill rest of line - while ($column < $overview_width) - { - $overview->setPixel($column++, $row, $color_back); - } - - $last_count = $2; - - $row++; - } - - # Write PNG file - open (PNG_HANDLE, ">", $filename) - or die("ERROR: cannot write png file $filename!\n"); - binmode(*PNG_HANDLE); - print(PNG_HANDLE $overview->png()); - close(PNG_HANDLE); -} - -sub genpng_warn_handler($) -{ - my ($msg) = @_; - - warn("$tool_name: $msg"); -} - -sub genpng_die_handler($) -{ - my ($msg) = @_; - - die("$tool_name: $msg"); -} diff --git a/worker/deps/lcov/bin/get_changes.sh b/worker/deps/lcov/bin/get_changes.sh deleted file mode 100755 index ec373b4f4f..0000000000 --- a/worker/deps/lcov/bin/get_changes.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -# -# Usage: get_changes.sh -# -# Print lcov change log information as provided by Git - -TOOLDIR=$(cd $(dirname $0) >/dev/null ; pwd) - -cd $TOOLDIR - -if ! git --no-pager log --no-merges --decorate=short --color=never 2>/dev/null ; then - cat "$TOOLDIR/../CHANGES" 2>/dev/null -fi diff --git a/worker/deps/lcov/bin/get_version.sh b/worker/deps/lcov/bin/get_version.sh deleted file mode 100755 index ac5a363146..0000000000 --- a/worker/deps/lcov/bin/get_version.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -# -# Usage: get_version.sh --version|--release|--full -# -# Print lcov version or release information as provided by Git, .version -# or a fallback. - -TOOLDIR=$(cd $(dirname $0) >/dev/null ; pwd) -GITVER=$(cd $TOOLDIR ; git describe --tags 2>/dev/null) - -if [ -z "$GITVER" ] ; then - # Get version information from file - if [ -e "$TOOLDIR/../.version" ] ; then - source "$TOOLDIR/../.version" - fi -else - # Get version information from git - FULL=${GITVER:1} - VERSION=${GITVER%%-*} - VERSION=${VERSION:1} - if [ "${GITVER#*-}" != "$GITVER" ] ; then - RELEASE=${GITVER#*-} - RELEASE=${RELEASE/-/.} - fi -fi - -# Fallback -[ -z "$VERSION" ] && VERSION="1.0" -[ -z "$RELEASE" ] && RELEASE="1" -[ -z "$FULL" ] && FULL="$VERSION" - -[ "$1" == "--version" ] && echo -n "$VERSION" -[ "$1" == "--release" ] && echo -n "$RELEASE" -[ "$1" == "--full" ] && echo -n "$FULL" diff --git a/worker/deps/lcov/bin/install.sh b/worker/deps/lcov/bin/install.sh deleted file mode 100755 index 2cdef45b6c..0000000000 --- a/worker/deps/lcov/bin/install.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env bash -# -# install.sh [--uninstall] sourcefile targetfile [install options] -# - - -# Check for uninstall option -if test "x$1" == "x--uninstall" ; then - UNINSTALL=true - SOURCE=$2 - TARGET=$3 - shift 3 -else - UNINSTALL=false - SOURCE=$1 - TARGET=$2 - shift 2 -fi - -# Check usage -if test -z "$SOURCE" || test -z "$TARGET" ; then - echo Usage: install.sh [--uninstall] source target [install options] >&2 - exit 1 -fi - - -# -# do_install(SOURCE_FILE, TARGET_FILE) -# - -do_install() -{ - local SOURCE=$1 - local TARGET=$2 - local PARAMS=$3 - - install -d $(dirname $TARGET) - install -p $PARAMS $SOURCE $TARGET - if [ -n "$LCOV_PERL_PATH" ] ; then - # Replace Perl interpreter specification - sed -e "1 s%^#\!.*perl.*$%#\!$LCOV_PERL_PATH%" -i $TARGET - fi -} - - -# -# do_uninstall(SOURCE_FILE, TARGET_FILE) -# - -do_uninstall() -{ - local SOURCE=$1 - local TARGET=$2 - - # Does target exist? - if test -r $TARGET ; then - # Is target of the same version as this package? - if diff -I '^our \$lcov_version' -I '^\.TH ' -I '^#!' $SOURCE $TARGET >/dev/null; then - rm -f $TARGET - else - echo WARNING: Skipping uninstall for $TARGET - versions differ! >&2 - fi - else - echo WARNING: Skipping uninstall for $TARGET - not installed! >&2 - fi -} - - -# Call sub routine -if $UNINSTALL ; then - do_uninstall $SOURCE $TARGET -else - do_install $SOURCE $TARGET "$*" -fi - -exit 0 diff --git a/worker/deps/lcov/bin/lcov b/worker/deps/lcov/bin/lcov deleted file mode 100755 index e30d991abb..0000000000 --- a/worker/deps/lcov/bin/lcov +++ /dev/null @@ -1,4329 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright (c) International Business Machines Corp., 2002,2012 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# -# lcov -# -# This is a wrapper script which provides a single interface for accessing -# LCOV coverage data. -# -# -# History: -# 2002-08-29 created by Peter Oberparleiter -# IBM Lab Boeblingen -# 2002-09-05 / Peter Oberparleiter: implemented --kernel-directory + -# multiple directories -# 2002-10-16 / Peter Oberparleiter: implemented --add-tracefile option -# 2002-10-17 / Peter Oberparleiter: implemented --extract option -# 2002-11-04 / Peter Oberparleiter: implemented --list option -# 2003-03-07 / Paul Larson: Changed to make it work with the latest gcov -# kernel patch. This will break it with older gcov-kernel -# patches unless you change the value of $gcovmod in this script -# 2003-04-07 / Peter Oberparleiter: fixed bug which resulted in an error -# when trying to combine .info files containing data without -# a test name -# 2003-04-10 / Peter Oberparleiter: extended Paul's change so that LCOV -# works both with the new and the old gcov-kernel patch -# 2003-04-10 / Peter Oberparleiter: added $gcov_dir constant in anticipation -# of a possible move of the gcov kernel directory to another -# file system in a future version of the gcov-kernel patch -# 2003-04-15 / Paul Larson: make info write to STDERR, not STDOUT -# 2003-04-15 / Paul Larson: added --remove option -# 2003-04-30 / Peter Oberparleiter: renamed --reset to --zerocounters -# to remove naming ambiguity with --remove -# 2003-04-30 / Peter Oberparleiter: adjusted help text to include --remove -# 2003-06-27 / Peter Oberparleiter: implemented --diff -# 2003-07-03 / Peter Oberparleiter: added line checksum support, added -# --no-checksum -# 2003-12-11 / Laurent Deniel: added --follow option -# 2004-03-29 / Peter Oberparleiter: modified --diff option to better cope with -# ambiguous patch file entries, modified --capture option to use -# modprobe before insmod (needed for 2.6) -# 2004-03-30 / Peter Oberparleiter: added --path option -# 2004-08-09 / Peter Oberparleiter: added configuration file support -# 2008-08-13 / Peter Oberparleiter: added function coverage support -# - -use strict; -use warnings; -use File::Basename; -use File::Path; -use File::Find; -use File::Temp qw /tempdir/; -use File::Spec::Functions qw /abs2rel canonpath catdir catfile catpath - file_name_is_absolute rootdir splitdir splitpath/; -use Getopt::Long; -use Cwd qw /abs_path getcwd/; - - -# Global constants -our $tool_dir = abs_path(dirname($0)); -our $lcov_version = 'LCOV version '.`$tool_dir/get_version.sh --full`; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; -our $tool_name = basename($0); - -# Directory containing gcov kernel files -our $gcov_dir; - -# Where to create temporary directories -our $tmp_dir; - -# Internal constants -our $GKV_PROC = 0; # gcov-kernel data in /proc via external patch -our $GKV_SYS = 1; # gcov-kernel data in /sys via vanilla 2.6.31+ -our @GKV_NAME = ( "external", "upstream" ); -our $pkg_gkv_file = ".gcov_kernel_version"; -our $pkg_build_file = ".build_directory"; - -# Branch data combination types -our $BR_SUB = 0; -our $BR_ADD = 1; - -# Prototypes -sub print_usage(*); -sub check_options(); -sub userspace_reset(); -sub userspace_capture(); -sub kernel_reset(); -sub kernel_capture(); -sub kernel_capture_initial(); -sub package_capture(); -sub add_traces(); -sub read_info_file($); -sub get_info_entry($); -sub set_info_entry($$$$$$$$$;$$$$$$); -sub add_counts($$); -sub merge_checksums($$$); -sub combine_info_entries($$$); -sub combine_info_files($$); -sub write_info_file(*$); -sub extract(); -sub remove(); -sub list(); -sub get_common_filename($$); -sub read_diff($); -sub diff(); -sub system_no_output($@); -sub read_config($); -sub apply_config($); -sub info(@); -sub create_temp_dir(); -sub transform_pattern($); -sub warn_handler($); -sub die_handler($); -sub abort_handler($); -sub temp_cleanup(); -sub setup_gkv(); -sub get_overall_line($$$$); -sub print_overall_rate($$$$$$$$$); -sub lcov_geninfo(@); -sub create_package($$$;$); -sub get_func_found_and_hit($); -sub summary(); -sub rate($$;$$$); - -# Global variables & initialization -our @directory; # Specifies where to get coverage data from -our @kernel_directory; # If set, captures only from specified kernel subdirs -our @add_tracefile; # If set, reads in and combines all files in list -our $list; # If set, list contents of tracefile -our $extract; # If set, extracts parts of tracefile -our $remove; # If set, removes parts of tracefile -our $diff; # If set, modifies tracefile according to diff -our $reset; # If set, reset all coverage data to zero -our $capture; # If set, capture data -our $output_filename; # Name for file to write coverage data to -our $test_name = ""; # Test case name -our $quiet = ""; # If set, suppress information messages -our $help; # Help option flag -our $version; # Version option flag -our $convert_filenames; # If set, convert filenames when applying diff -our $strip; # If set, strip leading directories when applying diff -our $temp_dir_name; # Name of temporary directory -our $cwd = `pwd`; # Current working directory -our $data_stdout; # If set, indicates that data is written to stdout -our $follow; # If set, indicates that find shall follow links -our $diff_path = ""; # Path removed from tracefile when applying diff -our $base_directory; # Base directory (cwd of gcc during compilation) -our $checksum; # If set, calculate a checksum for each line -our $no_checksum; # If set, don't calculate a checksum for each line -our $compat_libtool; # If set, indicates that libtool mode is to be enabled -our $no_compat_libtool; # If set, indicates that libtool mode is to be disabled -our $gcov_tool; -our @opt_ignore_errors; -our $initial; -our @include_patterns; # List of source file patterns to include -our @exclude_patterns; # List of source file patterns to exclude -our $no_recursion = 0; -our $to_package; -our $from_package; -our $maxdepth; -our $no_markers; -our $config; # Configuration file contents -chomp($cwd); -our @temp_dirs; -our $gcov_gkv; # gcov kernel support version found on machine -our $opt_derive_func_data; -our $opt_debug; -our $opt_list_full_path; -our $opt_no_list_full_path; -our $opt_list_width = 80; -our $opt_list_truncate_max = 20; -our $opt_external; -our $opt_no_external; -our $opt_config_file; -our %opt_rc; -our @opt_summary; -our $opt_compat; -our $ln_overall_found; -our $ln_overall_hit; -our $fn_overall_found; -our $fn_overall_hit; -our $br_overall_found; -our $br_overall_hit; -our $func_coverage = 1; -our $br_coverage = 0; - - -# -# Code entry point -# - -$SIG{__WARN__} = \&warn_handler; -$SIG{__DIE__} = \&die_handler; -$SIG{'INT'} = \&abort_handler; -$SIG{'QUIT'} = \&abort_handler; - -# Check command line for a configuration file name -Getopt::Long::Configure("pass_through", "no_auto_abbrev"); -GetOptions("config-file=s" => \$opt_config_file, - "rc=s%" => \%opt_rc); -Getopt::Long::Configure("default"); - -{ - # Remove spaces around rc options - my %new_opt_rc; - - while (my ($key, $value) = each(%opt_rc)) { - $key =~ s/^\s+|\s+$//g; - $value =~ s/^\s+|\s+$//g; - - $new_opt_rc{$key} = $value; - } - %opt_rc = %new_opt_rc; -} - -# Read configuration file if available -if (defined($opt_config_file)) { - $config = read_config($opt_config_file); -} elsif (defined($ENV{"HOME"}) && (-r $ENV{"HOME"}."/.lcovrc")) -{ - $config = read_config($ENV{"HOME"}."/.lcovrc"); -} -elsif (-r "/etc/lcovrc") -{ - $config = read_config("/etc/lcovrc"); -} elsif (-r "/usr/local/etc/lcovrc") -{ - $config = read_config("/usr/local/etc/lcovrc"); -} - -if ($config || %opt_rc) -{ - # Copy configuration file and --rc values to variables - apply_config({ - "lcov_gcov_dir" => \$gcov_dir, - "lcov_tmp_dir" => \$tmp_dir, - "lcov_list_full_path" => \$opt_list_full_path, - "lcov_list_width" => \$opt_list_width, - "lcov_list_truncate_max"=> \$opt_list_truncate_max, - "lcov_branch_coverage" => \$br_coverage, - "lcov_function_coverage"=> \$func_coverage, - }); -} - -# Parse command line options -if (!GetOptions("directory|d|di=s" => \@directory, - "add-tracefile|a=s" => \@add_tracefile, - "list|l=s" => \$list, - "kernel-directory|k=s" => \@kernel_directory, - "extract|e=s" => \$extract, - "remove|r=s" => \$remove, - "diff=s" => \$diff, - "convert-filenames" => \$convert_filenames, - "strip=i" => \$strip, - "capture|c" => \$capture, - "output-file|o=s" => \$output_filename, - "test-name|t=s" => \$test_name, - "zerocounters|z" => \$reset, - "quiet|q" => \$quiet, - "help|h|?" => \$help, - "version|v" => \$version, - "follow|f" => \$follow, - "path=s" => \$diff_path, - "base-directory|b=s" => \$base_directory, - "checksum" => \$checksum, - "no-checksum" => \$no_checksum, - "compat-libtool" => \$compat_libtool, - "no-compat-libtool" => \$no_compat_libtool, - "gcov-tool=s" => \$gcov_tool, - "ignore-errors=s" => \@opt_ignore_errors, - "initial|i" => \$initial, - "include=s" => \@include_patterns, - "exclude=s" => \@exclude_patterns, - "no-recursion" => \$no_recursion, - "to-package=s" => \$to_package, - "from-package=s" => \$from_package, - "no-markers" => \$no_markers, - "derive-func-data" => \$opt_derive_func_data, - "debug" => \$opt_debug, - "list-full-path" => \$opt_list_full_path, - "no-list-full-path" => \$opt_no_list_full_path, - "external" => \$opt_external, - "no-external" => \$opt_no_external, - "summary=s" => \@opt_summary, - "compat=s" => \$opt_compat, - "config-file=s" => \$opt_config_file, - "rc=s%" => \%opt_rc, - )) -{ - print(STDERR "Use $tool_name --help to get usage information\n"); - exit(1); -} -else -{ - # Merge options - if (defined($no_checksum)) - { - $checksum = ($no_checksum ? 0 : 1); - $no_checksum = undef; - } - - if (defined($no_compat_libtool)) - { - $compat_libtool = ($no_compat_libtool ? 0 : 1); - $no_compat_libtool = undef; - } - - if (defined($opt_no_list_full_path)) - { - $opt_list_full_path = ($opt_no_list_full_path ? 0 : 1); - $opt_no_list_full_path = undef; - } - - if (defined($opt_no_external)) { - $opt_external = 0; - $opt_no_external = undef; - } -} - -# Check for help option -if ($help) -{ - print_usage(*STDOUT); - exit(0); -} - -# Check for version option -if ($version) -{ - print("$tool_name: $lcov_version\n"); - exit(0); -} - -# Check list width option -if ($opt_list_width <= 40) { - die("ERROR: lcov_list_width parameter out of range (needs to be ". - "larger than 40)\n"); -} - -# Normalize --path text -$diff_path =~ s/\/$//; - -if ($follow) -{ - $follow = "-follow"; -} -else -{ - $follow = ""; -} - -if ($no_recursion) -{ - $maxdepth = "-maxdepth 1"; -} -else -{ - $maxdepth = ""; -} - -# Check for valid options -check_options(); - -# Only --extract, --remove and --diff allow unnamed parameters -if (@ARGV && !($extract || $remove || $diff || @opt_summary)) -{ - die("Extra parameter found: '".join(" ", @ARGV)."'\n". - "Use $tool_name --help to get usage information\n"); -} - -# Check for output filename -$data_stdout = !($output_filename && ($output_filename ne "-")); - -if ($capture) -{ - if ($data_stdout) - { - # Option that tells geninfo to write to stdout - $output_filename = "-"; - } -} - -# Determine kernel directory for gcov data -if (!$from_package && !@directory && ($capture || $reset)) { - ($gcov_gkv, $gcov_dir) = setup_gkv(); -} - -# Check for requested functionality -if ($reset) -{ - $data_stdout = 0; - # Differentiate between user space and kernel reset - if (@directory) - { - userspace_reset(); - } - else - { - kernel_reset(); - } -} -elsif ($capture) -{ - # Capture source can be user space, kernel or package - if ($from_package) { - package_capture(); - } elsif (@directory) { - userspace_capture(); - } else { - if ($initial) { - if (defined($to_package)) { - die("ERROR: --initial cannot be used together ". - "with --to-package\n"); - } - kernel_capture_initial(); - } else { - kernel_capture(); - } - } -} -elsif (@add_tracefile) -{ - ($ln_overall_found, $ln_overall_hit, - $fn_overall_found, $fn_overall_hit, - $br_overall_found, $br_overall_hit) = add_traces(); -} -elsif ($remove) -{ - ($ln_overall_found, $ln_overall_hit, - $fn_overall_found, $fn_overall_hit, - $br_overall_found, $br_overall_hit) = remove(); -} -elsif ($extract) -{ - ($ln_overall_found, $ln_overall_hit, - $fn_overall_found, $fn_overall_hit, - $br_overall_found, $br_overall_hit) = extract(); -} -elsif ($list) -{ - $data_stdout = 0; - list(); -} -elsif ($diff) -{ - if (scalar(@ARGV) != 1) - { - die("ERROR: option --diff requires one additional argument!\n". - "Use $tool_name --help to get usage information\n"); - } - ($ln_overall_found, $ln_overall_hit, - $fn_overall_found, $fn_overall_hit, - $br_overall_found, $br_overall_hit) = diff(); -} -elsif (@opt_summary) -{ - $data_stdout = 0; - ($ln_overall_found, $ln_overall_hit, - $fn_overall_found, $fn_overall_hit, - $br_overall_found, $br_overall_hit) = summary(); -} - -temp_cleanup(); - -if (defined($ln_overall_found)) { - print_overall_rate(1, $ln_overall_found, $ln_overall_hit, - 1, $fn_overall_found, $fn_overall_hit, - 1, $br_overall_found, $br_overall_hit); -} else { - info("Done.\n") if (!$list && !$capture); -} -exit(0); - -# -# print_usage(handle) -# -# Print usage information. -# - -sub print_usage(*) -{ - local *HANDLE = $_[0]; - - print(HANDLE < 1) - { - die("ERROR: only one of -z, -c, -a, -e, -r, -l, ". - "--diff or --summary allowed!\n". - "Use $tool_name --help to get usage information\n"); - } -} - - -# -# userspace_reset() -# -# Reset coverage data found in DIRECTORY by deleting all contained .da files. -# -# Die on error. -# - -sub userspace_reset() -{ - my $current_dir; - my @file_list; - - foreach $current_dir (@directory) - { - info("Deleting all .da files in $current_dir". - ($no_recursion?"\n":" and subdirectories\n")); - @file_list = `find "$current_dir" $maxdepth $follow -name \\*\\.da -type f -o -name \\*\\.gcda -type f 2>/dev/null`; - chomp(@file_list); - foreach (@file_list) - { - unlink($_) or die("ERROR: cannot remove file $_!\n"); - } - } -} - - -# -# userspace_capture() -# -# Capture coverage data found in DIRECTORY and write it to a package (if -# TO_PACKAGE specified) or to OUTPUT_FILENAME or STDOUT. -# -# Die on error. -# - -sub userspace_capture() -{ - my $dir; - my $build; - - if (!defined($to_package)) { - lcov_geninfo(@directory); - return; - } - if (scalar(@directory) != 1) { - die("ERROR: -d may be specified only once with --to-package\n"); - } - $dir = $directory[0]; - if (defined($base_directory)) { - $build = $base_directory; - } else { - $build = $dir; - } - create_package($to_package, $dir, $build); -} - - -# -# kernel_reset() -# -# Reset kernel coverage. -# -# Die on error. -# - -sub kernel_reset() -{ - local *HANDLE; - my $reset_file; - - info("Resetting kernel execution counters\n"); - if (-e "$gcov_dir/vmlinux") { - $reset_file = "$gcov_dir/vmlinux"; - } elsif (-e "$gcov_dir/reset") { - $reset_file = "$gcov_dir/reset"; - } else { - die("ERROR: no reset control found in $gcov_dir\n"); - } - open(HANDLE, ">", $reset_file) or - die("ERROR: cannot write to $reset_file!\n"); - print(HANDLE "0"); - close(HANDLE); -} - - -# -# lcov_copy_single(from, to) -# -# Copy single regular file FROM to TO without checking its size. This is -# required to work with special files generated by the kernel -# seq_file-interface. -# -# -sub lcov_copy_single($$) -{ - my ($from, $to) = @_; - my $content; - local $/; - local *HANDLE; - - open(HANDLE, "<", $from) or die("ERROR: cannot read $from: $!\n"); - $content = ; - close(HANDLE); - open(HANDLE, ">", $to) or die("ERROR: cannot write $from: $!\n"); - if (defined($content)) { - print(HANDLE $content); - } - close(HANDLE); -} - -# -# lcov_find(dir, function, data[, extension, ...)]) -# -# Search DIR for files and directories whose name matches PATTERN and run -# FUNCTION for each match. If not pattern is specified, match all names. -# -# FUNCTION has the following prototype: -# function(dir, relative_name, data) -# -# Where: -# dir: the base directory for this search -# relative_name: the name relative to the base directory of this entry -# data: the DATA variable passed to lcov_find -# -sub lcov_find($$$;@) -{ - my ($dir, $fn, $data, @pattern) = @_; - my $result; - my $_fn = sub { - my $filename = $File::Find::name; - - if (defined($result)) { - return; - } - $filename = abs2rel($filename, $dir); - foreach (@pattern) { - if ($filename =~ /$_/) { - goto ok; - } - } - return; - ok: - $result = &$fn($dir, $filename, $data); - }; - if (scalar(@pattern) == 0) { - @pattern = ".*"; - } - find( { wanted => $_fn, no_chdir => 1 }, $dir); - - return $result; -} - -# -# lcov_copy_fn(from, rel, to) -# -# Copy directories, files and links from/rel to to/rel. -# - -sub lcov_copy_fn($$$) -{ - my ($from, $rel, $to) = @_; - my $absfrom = canonpath(catfile($from, $rel)); - my $absto = canonpath(catfile($to, $rel)); - - if (-d) { - if (! -d $absto) { - mkpath($absto) or - die("ERROR: cannot create directory $absto\n"); - chmod(0700, $absto); - } - } elsif (-l) { - # Copy symbolic link - my $link = readlink($absfrom); - - if (!defined($link)) { - die("ERROR: cannot read link $absfrom: $!\n"); - } - symlink($link, $absto) or - die("ERROR: cannot create link $absto: $!\n"); - } else { - lcov_copy_single($absfrom, $absto); - chmod(0600, $absto); - } - return undef; -} - -# -# lcov_copy(from, to, subdirs) -# -# Copy all specified SUBDIRS and files from directory FROM to directory TO. For -# regular files, copy file contents without checking its size. This is required -# to work with seq_file-generated files. -# - -sub lcov_copy($$;@) -{ - my ($from, $to, @subdirs) = @_; - my @pattern; - - foreach (@subdirs) { - push(@pattern, "^$_"); - } - lcov_find($from, \&lcov_copy_fn, $to, @pattern); -} - -# -# lcov_geninfo(directory) -# -# Call geninfo for the specified directory and with the parameters specified -# at the command line. -# - -sub lcov_geninfo(@) -{ - my (@dir) = @_; - my @param; - - # Capture data - info("Capturing coverage data from ".join(" ", @dir)."\n"); - @param = ("$tool_dir/geninfo", @dir); - if ($output_filename) - { - @param = (@param, "--output-filename", $output_filename); - } - if ($test_name) - { - @param = (@param, "--test-name", $test_name); - } - if ($follow) - { - @param = (@param, "--follow"); - } - if ($quiet) - { - @param = (@param, "--quiet"); - } - if (defined($checksum)) - { - if ($checksum) - { - @param = (@param, "--checksum"); - } - else - { - @param = (@param, "--no-checksum"); - } - } - if ($base_directory) - { - @param = (@param, "--base-directory", $base_directory); - } - if ($no_compat_libtool) - { - @param = (@param, "--no-compat-libtool"); - } - elsif ($compat_libtool) - { - @param = (@param, "--compat-libtool"); - } - if ($gcov_tool) - { - @param = (@param, "--gcov-tool", $gcov_tool); - } - foreach (@opt_ignore_errors) { - @param = (@param, "--ignore-errors", $_); - } - if ($no_recursion) { - @param = (@param, "--no-recursion"); - } - if ($initial) - { - @param = (@param, "--initial"); - } - if ($no_markers) - { - @param = (@param, "--no-markers"); - } - if ($opt_derive_func_data) - { - @param = (@param, "--derive-func-data"); - } - if ($opt_debug) - { - @param = (@param, "--debug"); - } - if (defined($opt_external) && $opt_external) - { - @param = (@param, "--external"); - } - if (defined($opt_external) && !$opt_external) - { - @param = (@param, "--no-external"); - } - if (defined($opt_compat)) { - @param = (@param, "--compat", $opt_compat); - } - if (%opt_rc) { - foreach my $key (keys(%opt_rc)) { - @param = (@param, "--rc", "$key=".$opt_rc{$key}); - } - } - if (defined($opt_config_file)) { - @param = (@param, "--config-file", $opt_config_file); - } - foreach (@include_patterns) { - @param = (@param, "--include", $_); - } - foreach (@exclude_patterns) { - @param = (@param, "--exclude", $_); - } - - system(@param) and exit($? >> 8); -} - -# -# read_file(filename) -# -# Return the contents of the file defined by filename. -# - -sub read_file($) -{ - my ($filename) = @_; - my $content; - local $\; - local *HANDLE; - - open(HANDLE, "<", $filename) || return undef; - $content = ; - close(HANDLE); - - return $content; -} - -# -# get_package(package_file) -# -# Unpack unprocessed coverage data files from package_file to a temporary -# directory and return directory name, build directory and gcov kernel version -# as found in package. -# - -sub get_package($) -{ - my ($file) = @_; - my $dir = create_temp_dir(); - my $gkv; - my $build; - my $cwd = getcwd(); - my $count; - local *HANDLE; - - info("Reading package $file:\n"); - $file = abs_path($file); - chdir($dir); - open(HANDLE, "-|", "tar xvfz '$file' 2>/dev/null") - or die("ERROR: could not process package $file\n"); - $count = 0; - while () { - if (/\.da$/ || /\.gcda$/) { - $count++; - } - } - close(HANDLE); - if ($count == 0) { - die("ERROR: no data file found in package $file\n"); - } - info(" data directory .......: $dir\n"); - $build = read_file("$dir/$pkg_build_file"); - if (defined($build)) { - info(" build directory ......: $build\n"); - } - $gkv = read_file("$dir/$pkg_gkv_file"); - if (defined($gkv)) { - $gkv = int($gkv); - if ($gkv != $GKV_PROC && $gkv != $GKV_SYS) { - die("ERROR: unsupported gcov kernel version found ". - "($gkv)\n"); - } - info(" content type .........: kernel data\n"); - info(" gcov kernel version ..: %s\n", $GKV_NAME[$gkv]); - } else { - info(" content type .........: application data\n"); - } - info(" data files ...........: $count\n"); - chdir($cwd); - - return ($dir, $build, $gkv); -} - -# -# write_file(filename, $content) -# -# Create a file named filename and write the specified content to it. -# - -sub write_file($$) -{ - my ($filename, $content) = @_; - local *HANDLE; - - open(HANDLE, ">", $filename) || return 0; - print(HANDLE $content); - close(HANDLE) || return 0; - - return 1; -} - -# count_package_data(filename) -# -# Count the number of coverage data files in the specified package file. -# - -sub count_package_data($) -{ - my ($filename) = @_; - local *HANDLE; - my $count = 0; - - open(HANDLE, "-|", "tar tfz '$filename'") or return undef; - while () { - if (/\.da$/ || /\.gcda$/) { - $count++; - } - } - close(HANDLE); - return $count; -} - -# -# create_package(package_file, source_directory, build_directory[, -# kernel_gcov_version]) -# -# Store unprocessed coverage data files from source_directory to package_file. -# - -sub create_package($$$;$) -{ - my ($file, $dir, $build, $gkv) = @_; - my $cwd = getcwd(); - - # Check for availability of tar tool first - system("tar --help > /dev/null") - and die("ERROR: tar command not available\n"); - - # Print information about the package - info("Creating package $file:\n"); - info(" data directory .......: $dir\n"); - - # Handle build directory - if (defined($build)) { - info(" build directory ......: $build\n"); - write_file("$dir/$pkg_build_file", $build) - or die("ERROR: could not write to ". - "$dir/$pkg_build_file\n"); - } - - # Handle gcov kernel version data - if (defined($gkv)) { - info(" content type .........: kernel data\n"); - info(" gcov kernel version ..: %s\n", $GKV_NAME[$gkv]); - write_file("$dir/$pkg_gkv_file", $gkv) - or die("ERROR: could not write to ". - "$dir/$pkg_gkv_file\n"); - } else { - info(" content type .........: application data\n"); - } - - # Create package - $file = abs_path($file); - chdir($dir); - system("tar cfz $file .") - and die("ERROR: could not create package $file\n"); - chdir($cwd); - - # Remove temporary files - unlink("$dir/$pkg_build_file"); - unlink("$dir/$pkg_gkv_file"); - - # Show number of data files - if (!$quiet) { - my $count = count_package_data($file); - - if (defined($count)) { - info(" data files ...........: $count\n"); - } - } -} - -sub find_link_fn($$$) -{ - my ($from, $rel, $filename) = @_; - my $absfile = catfile($from, $rel, $filename); - - if (-l $absfile) { - return $absfile; - } - return undef; -} - -# -# get_base(dir) -# -# Return (BASE, OBJ), where -# - BASE: is the path to the kernel base directory relative to dir -# - OBJ: is the absolute path to the kernel build directory -# - -sub get_base($) -{ - my ($dir) = @_; - my $marker = "kernel/gcov/base.gcno"; - my $markerfile; - my $sys; - my $obj; - my $link; - - $markerfile = lcov_find($dir, \&find_link_fn, $marker); - if (!defined($markerfile)) { - return (undef, undef); - } - - # sys base is parent of parent of markerfile. - $sys = abs2rel(dirname(dirname(dirname($markerfile))), $dir); - - # obj base is parent of parent of markerfile link target. - $link = readlink($markerfile); - if (!defined($link)) { - die("ERROR: could not read $markerfile\n"); - } - $obj = dirname(dirname(dirname($link))); - - return ($sys, $obj); -} - -# -# apply_base_dir(data_dir, base_dir, build_dir, @directories) -# -# Make entries in @directories relative to data_dir. -# - -sub apply_base_dir($$$@) -{ - my ($data, $base, $build, @dirs) = @_; - my $dir; - my @result; - - foreach $dir (@dirs) { - # Is directory path relative to data directory? - if (-d catdir($data, $dir)) { - push(@result, $dir); - next; - } - # Relative to the auto-detected base-directory? - if (defined($base)) { - if (-d catdir($data, $base, $dir)) { - push(@result, catdir($base, $dir)); - next; - } - } - # Relative to the specified base-directory? - if (defined($base_directory)) { - if (file_name_is_absolute($base_directory)) { - $base = abs2rel($base_directory, rootdir()); - } else { - $base = $base_directory; - } - if (-d catdir($data, $base, $dir)) { - push(@result, catdir($base, $dir)); - next; - } - } - # Relative to the build directory? - if (defined($build)) { - if (file_name_is_absolute($build)) { - $base = abs2rel($build, rootdir()); - } else { - $base = $build; - } - if (-d catdir($data, $base, $dir)) { - push(@result, catdir($base, $dir)); - next; - } - } - die("ERROR: subdirectory $dir not found\n". - "Please use -b to specify the correct directory\n"); - } - return @result; -} - -# -# copy_gcov_dir(dir, [@subdirectories]) -# -# Create a temporary directory and copy all or, if specified, only some -# subdirectories from dir to that directory. Return the name of the temporary -# directory. -# - -sub copy_gcov_dir($;@) -{ - my ($data, @dirs) = @_; - my $tempdir = create_temp_dir(); - - info("Copying data to temporary directory $tempdir\n"); - lcov_copy($data, $tempdir, @dirs); - - return $tempdir; -} - -# -# kernel_capture_initial -# -# Capture initial kernel coverage data, i.e. create a coverage data file from -# static graph files which contains zero coverage data for all instrumented -# lines. -# - -sub kernel_capture_initial() -{ - my $build; - my $source; - my @params; - - if (defined($base_directory)) { - $build = $base_directory; - $source = "specified"; - } else { - (undef, $build) = get_base($gcov_dir); - if (!defined($build)) { - die("ERROR: could not auto-detect build directory.\n". - "Please use -b to specify the build directory\n"); - } - $source = "auto-detected"; - } - info("Using $build as kernel build directory ($source)\n"); - # Build directory needs to be passed to geninfo - $base_directory = $build; - if (@kernel_directory) { - foreach my $dir (@kernel_directory) { - push(@params, "$build/$dir"); - } - } else { - push(@params, $build); - } - lcov_geninfo(@params); -} - -# -# kernel_capture_from_dir(directory, gcov_kernel_version, build) -# -# Perform the actual kernel coverage capturing from the specified directory -# assuming that the data was copied from the specified gcov kernel version. -# - -sub kernel_capture_from_dir($$$) -{ - my ($dir, $gkv, $build) = @_; - - # Create package or coverage file - if (defined($to_package)) { - create_package($to_package, $dir, $build, $gkv); - } else { - # Build directory needs to be passed to geninfo - $base_directory = $build; - lcov_geninfo($dir); - } -} - -# -# adjust_kernel_dir(dir, build) -# -# Adjust directories specified with -k so that they point to the directory -# relative to DIR. Return the build directory if specified or the auto- -# detected build-directory. -# - -sub adjust_kernel_dir($$) -{ - my ($dir, $build) = @_; - my ($sys_base, $build_auto) = get_base($dir); - - if (!defined($build)) { - $build = $build_auto; - } - if (!defined($build)) { - die("ERROR: could not auto-detect build directory.\n". - "Please use -b to specify the build directory\n"); - } - # Make @kernel_directory relative to sysfs base - if (@kernel_directory) { - @kernel_directory = apply_base_dir($dir, $sys_base, $build, - @kernel_directory); - } - return $build; -} - -sub kernel_capture() -{ - my $data_dir; - my $build = $base_directory; - - if ($gcov_gkv == $GKV_SYS) { - $build = adjust_kernel_dir($gcov_dir, $build); - } - $data_dir = copy_gcov_dir($gcov_dir, @kernel_directory); - kernel_capture_from_dir($data_dir, $gcov_gkv, $build); -} - -# -# link_data_cb(datadir, rel, graphdir) -# -# Create symbolic link in GRAPDIR/REL pointing to DATADIR/REL. -# - -sub link_data_cb($$$) -{ - my ($datadir, $rel, $graphdir) = @_; - my $absfrom = catfile($datadir, $rel); - my $absto = catfile($graphdir, $rel); - my $base; - my $dir; - - if (-e $absto) { - die("ERROR: could not create symlink at $absto: ". - "File already exists!\n"); - } - if (-l $absto) { - # Broken link - possibly from an interrupted earlier run - unlink($absto); - } - - # Check for graph file - $base = $absto; - $base =~ s/\.(gcda|da)$//; - if (! -e $base.".gcno" && ! -e $base.".bbg" && ! -e $base.".bb") { - die("ERROR: No graph file found for $absfrom in ". - dirname($base)."!\n"); - } - - symlink($absfrom, $absto) or - die("ERROR: could not create symlink at $absto: $!\n"); -} - -# -# unlink_data_cb(datadir, rel, graphdir) -# -# Remove symbolic link from GRAPHDIR/REL to DATADIR/REL. -# - -sub unlink_data_cb($$$) -{ - my ($datadir, $rel, $graphdir) = @_; - my $absfrom = catfile($datadir, $rel); - my $absto = catfile($graphdir, $rel); - my $target; - - return if (!-l $absto); - $target = readlink($absto); - return if (!defined($target) || $target ne $absfrom); - - unlink($absto) or - warn("WARNING: could not remove symlink $absto: $!\n"); -} - -# -# link_data(datadir, graphdir, create) -# -# If CREATE is non-zero, create symbolic links in GRAPHDIR for data files -# found in DATADIR. Otherwise remove link in GRAPHDIR. -# - -sub link_data($$$) -{ - my ($datadir, $graphdir, $create) = @_; - - $datadir = abs_path($datadir); - $graphdir = abs_path($graphdir); - if ($create) { - lcov_find($datadir, \&link_data_cb, $graphdir, '\.gcda$', - '\.da$'); - } else { - lcov_find($datadir, \&unlink_data_cb, $graphdir, '\.gcda$', - '\.da$'); - } -} - -# -# find_graph_cb(datadir, rel, count_ref) -# -# Count number of files found. -# - -sub find_graph_cb($$$) -{ - my ($dir, $rel, $count_ref) = @_; - - ($$count_ref)++; -} - -# -# find_graph(dir) -# -# Search DIR for a graph file. Return non-zero if one was found, zero otherwise. -# - -sub find_graph($) -{ - my ($dir) = @_; - my $count = 0; - - lcov_find($dir, \&find_graph_cb, \$count, '\.gcno$', '\.bb$', '\.bbg$'); - - return $count > 0 ? 1 : 0; -} - -# -# package_capture() -# -# Capture coverage data from a package of unprocessed coverage data files -# as generated by lcov --to-package. -# - -sub package_capture() -{ - my $dir; - my $build; - my $gkv; - - ($dir, $build, $gkv) = get_package($from_package); - - # Check for build directory - if (defined($base_directory)) { - if (defined($build)) { - info("Using build directory specified by -b.\n"); - } - $build = $base_directory; - } - - # Do the actual capture - if (defined($gkv)) { - if ($gkv == $GKV_SYS) { - $build = adjust_kernel_dir($dir, $build); - } - if (@kernel_directory) { - $dir = copy_gcov_dir($dir, @kernel_directory); - } - kernel_capture_from_dir($dir, $gkv, $build); - } else { - # Build directory needs to be passed to geninfo - $base_directory = $build; - if (find_graph($dir)) { - # Package contains graph files - collect from there - lcov_geninfo($dir); - } else { - # No graph files found, link data files next to - # graph files - link_data($dir, $base_directory, 1); - lcov_geninfo($base_directory); - link_data($dir, $base_directory, 0); - } - } -} - - -# -# info(printf_parameter) -# -# Use printf to write PRINTF_PARAMETER to stdout only when the $quiet flag -# is not set. -# - -sub info(@) -{ - if (!$quiet) - { - # Print info string - if (!$data_stdout) - { - printf(@_) - } - else - { - # Don't interfere with the .info output to STDOUT - printf(STDERR @_); - } - } -} - - -# -# create_temp_dir() -# -# Create a temporary directory and return its path. -# -# Die on error. -# - -sub create_temp_dir() -{ - my $dir; - - if (defined($tmp_dir)) { - $dir = tempdir(DIR => $tmp_dir, CLEANUP => 1); - } else { - $dir = tempdir(CLEANUP => 1); - } - if (!defined($dir)) { - die("ERROR: cannot create temporary directory\n"); - } - push(@temp_dirs, $dir); - - return $dir; -} - -sub compress_brcount($) -{ - my ($brcount) = @_; - my $db; - - $db = brcount_to_db($brcount); - return db_to_brcount($db, $brcount); -} - -sub get_br_found_and_hit($) -{ - my ($brcount) = @_; - my $db; - - $db = brcount_to_db($brcount); - - return brcount_db_get_found_and_hit($db); -} - - -# -# read_info_file(info_filename) -# -# Read in the contents of the .info file specified by INFO_FILENAME. Data will -# be returned as a reference to a hash containing the following mappings: -# -# %result: for each filename found in file -> \%data -# -# %data: "test" -> \%testdata -# "sum" -> \%sumcount -# "func" -> \%funcdata -# "found" -> $lines_found (number of instrumented lines found in file) -# "hit" -> $lines_hit (number of executed lines in file) -# "f_found" -> $fn_found (number of instrumented functions found in file) -# "f_hit" -> $fn_hit (number of executed functions in file) -# "b_found" -> $br_found (number of instrumented branches found in file) -# "b_hit" -> $br_hit (number of executed branches in file) -# "check" -> \%checkdata -# "testfnc" -> \%testfncdata -# "sumfnc" -> \%sumfnccount -# "testbr" -> \%testbrdata -# "sumbr" -> \%sumbrcount -# -# %testdata : name of test affecting this file -> \%testcount -# %testfncdata: name of test affecting this file -> \%testfnccount -# %testbrdata: name of test affecting this file -> \%testbrcount -# -# %testcount : line number -> execution count for a single test -# %testfnccount: function name -> execution count for a single test -# %testbrcount : line number -> branch coverage data for a single test -# %sumcount : line number -> execution count for all tests -# %sumfnccount : function name -> execution count for all tests -# %sumbrcount : line number -> branch coverage data for all tests -# %funcdata : function name -> line number -# %checkdata : line number -> checksum of source code line -# $brdata : text "block,branch,taken:..." -# -# Note that .info file sections referring to the same file and test name -# will automatically be combined by adding all execution counts. -# -# Note that if INFO_FILENAME ends with ".gz", it is assumed that the file -# is compressed using GZIP. If available, GUNZIP will be used to decompress -# this file. -# -# Die on error. -# - -sub read_info_file($) -{ - my $tracefile = $_[0]; # Name of tracefile - my %result; # Resulting hash: file -> data - my $data; # Data handle for current entry - my $testdata; # " " - my $testcount; # " " - my $sumcount; # " " - my $funcdata; # " " - my $checkdata; # " " - my $testfncdata; - my $testfnccount; - my $sumfnccount; - my $testbrdata; - my $testbrcount; - my $sumbrcount; - my $line; # Current line read from .info file - my $testname; # Current test name - my $filename; # Current filename - my $hitcount; # Count for lines hit - my $count; # Execution count of current line - my $negative; # If set, warn about negative counts - my $changed_testname; # If set, warn about changed testname - my $line_checksum; # Checksum of current line - local *INFO_HANDLE; # Filehandle for .info file - - info("Reading tracefile $tracefile\n"); - - # Check if file exists and is readable - stat($_[0]); - if (!(-r _)) - { - die("ERROR: cannot read file $_[0]!\n"); - } - - # Check if this is really a plain file - if (!(-f _)) - { - die("ERROR: not a plain file: $_[0]!\n"); - } - - # Check for .gz extension - if ($_[0] =~ /\.gz$/) - { - # Check for availability of GZIP tool - system_no_output(1, "gunzip" ,"-h") - and die("ERROR: gunzip command not available!\n"); - - # Check integrity of compressed file - system_no_output(1, "gunzip", "-t", $_[0]) - and die("ERROR: integrity check failed for ". - "compressed file $_[0]!\n"); - - # Open compressed file - open(INFO_HANDLE, "-|", "gunzip -c '$_[0]'") - or die("ERROR: cannot start gunzip to decompress ". - "file $_[0]!\n"); - } - else - { - # Open decompressed file - open(INFO_HANDLE, "<", $_[0]) - or die("ERROR: cannot read file $_[0]!\n"); - } - - $testname = ""; - while () - { - chomp($_); - $line = $_; - - # Switch statement - foreach ($line) - { - /^TN:([^,]*)(,diff)?/ && do - { - # Test name information found - $testname = defined($1) ? $1 : ""; - if ($testname =~ s/\W/_/g) - { - $changed_testname = 1; - } - $testname .= $2 if (defined($2)); - last; - }; - - /^[SK]F:(.*)/ && do - { - # Filename information found - # Retrieve data for new entry - $filename = $1; - - $data = $result{$filename}; - ($testdata, $sumcount, $funcdata, $checkdata, - $testfncdata, $sumfnccount, $testbrdata, - $sumbrcount) = - get_info_entry($data); - - if (defined($testname)) - { - $testcount = $testdata->{$testname}; - $testfnccount = $testfncdata->{$testname}; - $testbrcount = $testbrdata->{$testname}; - } - else - { - $testcount = {}; - $testfnccount = {}; - $testbrcount = {}; - } - last; - }; - - /^DA:(\d+),(-?\d+)(,[^,\s]+)?/ && do - { - # Fix negative counts - $count = $2 < 0 ? 0 : $2; - if ($2 < 0) - { - $negative = 1; - } - # Execution count found, add to structure - # Add summary counts - $sumcount->{$1} += $count; - - # Add test-specific counts - if (defined($testname)) - { - $testcount->{$1} += $count; - } - - # Store line checksum if available - if (defined($3)) - { - $line_checksum = substr($3, 1); - - # Does it match a previous definition - if (defined($checkdata->{$1}) && - ($checkdata->{$1} ne - $line_checksum)) - { - die("ERROR: checksum mismatch ". - "at $filename:$1\n"); - } - - $checkdata->{$1} = $line_checksum; - } - last; - }; - - /^FN:(\d+),([^,]+)/ && do - { - last if (!$func_coverage); - - # Function data found, add to structure - $funcdata->{$2} = $1; - - # Also initialize function call data - if (!defined($sumfnccount->{$2})) { - $sumfnccount->{$2} = 0; - } - if (defined($testname)) - { - if (!defined($testfnccount->{$2})) { - $testfnccount->{$2} = 0; - } - } - last; - }; - - /^FNDA:(\d+),([^,]+)/ && do - { - last if (!$func_coverage); - - # Function call count found, add to structure - # Add summary counts - $sumfnccount->{$2} += $1; - - # Add test-specific counts - if (defined($testname)) - { - $testfnccount->{$2} += $1; - } - last; - }; - - /^BRDA:(\d+),(\d+),(\d+),(\d+|-)/ && do { - # Branch coverage data found - my ($line, $block, $branch, $taken) = - ($1, $2, $3, $4); - - last if (!$br_coverage); - $sumbrcount->{$line} .= - "$block,$branch,$taken:"; - - # Add test-specific counts - if (defined($testname)) { - $testbrcount->{$line} .= - "$block,$branch,$taken:"; - } - last; - }; - - /^end_of_record/ && do - { - # Found end of section marker - if ($filename) - { - # Store current section data - if (defined($testname)) - { - $testdata->{$testname} = - $testcount; - $testfncdata->{$testname} = - $testfnccount; - $testbrdata->{$testname} = - $testbrcount; - } - - set_info_entry($data, $testdata, - $sumcount, $funcdata, - $checkdata, $testfncdata, - $sumfnccount, - $testbrdata, - $sumbrcount); - $result{$filename} = $data; - last; - } - }; - - # default - last; - } - } - close(INFO_HANDLE); - - # Calculate hit and found values for lines and functions of each file - foreach $filename (keys(%result)) - { - $data = $result{$filename}; - - ($testdata, $sumcount, undef, undef, $testfncdata, - $sumfnccount, $testbrdata, $sumbrcount) = - get_info_entry($data); - - # Filter out empty files - if (scalar(keys(%{$sumcount})) == 0) - { - delete($result{$filename}); - next; - } - # Filter out empty test cases - foreach $testname (keys(%{$testdata})) - { - if (!defined($testdata->{$testname}) || - scalar(keys(%{$testdata->{$testname}})) == 0) - { - delete($testdata->{$testname}); - delete($testfncdata->{$testname}); - } - } - - $data->{"found"} = scalar(keys(%{$sumcount})); - $hitcount = 0; - - foreach (keys(%{$sumcount})) - { - if ($sumcount->{$_} > 0) { $hitcount++; } - } - - $data->{"hit"} = $hitcount; - - # Get found/hit values for function call data - $data->{"f_found"} = scalar(keys(%{$sumfnccount})); - $hitcount = 0; - - foreach (keys(%{$sumfnccount})) { - if ($sumfnccount->{$_} > 0) { - $hitcount++; - } - } - $data->{"f_hit"} = $hitcount; - - # Combine branch data for the same branches - (undef, $data->{"b_found"}, $data->{"b_hit"}) = - compress_brcount($sumbrcount); - foreach $testname (keys(%{$testbrdata})) { - compress_brcount($testbrdata->{$testname}); - } - } - - if (scalar(keys(%result)) == 0) - { - die("ERROR: no valid records found in tracefile $tracefile\n"); - } - if ($negative) - { - warn("WARNING: negative counts found in tracefile ". - "$tracefile\n"); - } - if ($changed_testname) - { - warn("WARNING: invalid characters removed from testname in ". - "tracefile $tracefile\n"); - } - - return(\%result); -} - - -# -# get_info_entry(hash_ref) -# -# Retrieve data from an entry of the structure generated by read_info_file(). -# Return a list of references to hashes: -# (test data hash ref, sum count hash ref, funcdata hash ref, checkdata hash -# ref, testfncdata hash ref, sumfnccount hash ref, testbrdata hash ref, -# sumbrcount hash ref, lines found, lines hit, functions found, -# functions hit, branches found, branches hit) -# - -sub get_info_entry($) -{ - my $testdata_ref = $_[0]->{"test"}; - my $sumcount_ref = $_[0]->{"sum"}; - my $funcdata_ref = $_[0]->{"func"}; - my $checkdata_ref = $_[0]->{"check"}; - my $testfncdata = $_[0]->{"testfnc"}; - my $sumfnccount = $_[0]->{"sumfnc"}; - my $testbrdata = $_[0]->{"testbr"}; - my $sumbrcount = $_[0]->{"sumbr"}; - my $lines_found = $_[0]->{"found"}; - my $lines_hit = $_[0]->{"hit"}; - my $f_found = $_[0]->{"f_found"}; - my $f_hit = $_[0]->{"f_hit"}; - my $br_found = $_[0]->{"b_found"}; - my $br_hit = $_[0]->{"b_hit"}; - - return ($testdata_ref, $sumcount_ref, $funcdata_ref, $checkdata_ref, - $testfncdata, $sumfnccount, $testbrdata, $sumbrcount, - $lines_found, $lines_hit, $f_found, $f_hit, - $br_found, $br_hit); -} - - -# -# set_info_entry(hash_ref, testdata_ref, sumcount_ref, funcdata_ref, -# checkdata_ref, testfncdata_ref, sumfcncount_ref, -# testbrdata_ref, sumbrcount_ref[,lines_found, -# lines_hit, f_found, f_hit, $b_found, $b_hit]) -# -# Update the hash referenced by HASH_REF with the provided data references. -# - -sub set_info_entry($$$$$$$$$;$$$$$$) -{ - my $data_ref = $_[0]; - - $data_ref->{"test"} = $_[1]; - $data_ref->{"sum"} = $_[2]; - $data_ref->{"func"} = $_[3]; - $data_ref->{"check"} = $_[4]; - $data_ref->{"testfnc"} = $_[5]; - $data_ref->{"sumfnc"} = $_[6]; - $data_ref->{"testbr"} = $_[7]; - $data_ref->{"sumbr"} = $_[8]; - - if (defined($_[9])) { $data_ref->{"found"} = $_[9]; } - if (defined($_[10])) { $data_ref->{"hit"} = $_[10]; } - if (defined($_[11])) { $data_ref->{"f_found"} = $_[11]; } - if (defined($_[12])) { $data_ref->{"f_hit"} = $_[12]; } - if (defined($_[13])) { $data_ref->{"b_found"} = $_[13]; } - if (defined($_[14])) { $data_ref->{"b_hit"} = $_[14]; } -} - - -# -# add_counts(data1_ref, data2_ref) -# -# DATA1_REF and DATA2_REF are references to hashes containing a mapping -# -# line number -> execution count -# -# Return a list (RESULT_REF, LINES_FOUND, LINES_HIT) where RESULT_REF -# is a reference to a hash containing the combined mapping in which -# execution counts are added. -# - -sub add_counts($$) -{ - my $data1_ref = $_[0]; # Hash 1 - my $data2_ref = $_[1]; # Hash 2 - my %result; # Resulting hash - my $line; # Current line iteration scalar - my $data1_count; # Count of line in hash1 - my $data2_count; # Count of line in hash2 - my $found = 0; # Total number of lines found - my $hit = 0; # Number of lines with a count > 0 - - foreach $line (keys(%$data1_ref)) - { - $data1_count = $data1_ref->{$line}; - $data2_count = $data2_ref->{$line}; - - # Add counts if present in both hashes - if (defined($data2_count)) { $data1_count += $data2_count; } - - # Store sum in %result - $result{$line} = $data1_count; - - $found++; - if ($data1_count > 0) { $hit++; } - } - - # Add lines unique to data2_ref - foreach $line (keys(%$data2_ref)) - { - # Skip lines already in data1_ref - if (defined($data1_ref->{$line})) { next; } - - # Copy count from data2_ref - $result{$line} = $data2_ref->{$line}; - - $found++; - if ($result{$line} > 0) { $hit++; } - } - - return (\%result, $found, $hit); -} - - -# -# merge_checksums(ref1, ref2, filename) -# -# REF1 and REF2 are references to hashes containing a mapping -# -# line number -> checksum -# -# Merge checksum lists defined in REF1 and REF2 and return reference to -# resulting hash. Die if a checksum for a line is defined in both hashes -# but does not match. -# - -sub merge_checksums($$$) -{ - my $ref1 = $_[0]; - my $ref2 = $_[1]; - my $filename = $_[2]; - my %result; - my $line; - - foreach $line (keys(%{$ref1})) - { - if (defined($ref2->{$line}) && - ($ref1->{$line} ne $ref2->{$line})) - { - die("ERROR: checksum mismatch at $filename:$line\n"); - } - $result{$line} = $ref1->{$line}; - } - - foreach $line (keys(%{$ref2})) - { - $result{$line} = $ref2->{$line}; - } - - return \%result; -} - - -# -# merge_func_data(funcdata1, funcdata2, filename) -# - -sub merge_func_data($$$) -{ - my ($funcdata1, $funcdata2, $filename) = @_; - my %result; - my $func; - - if (defined($funcdata1)) { - %result = %{$funcdata1}; - } - - foreach $func (keys(%{$funcdata2})) { - my $line1 = $result{$func}; - my $line2 = $funcdata2->{$func}; - - if (defined($line1) && ($line1 != $line2)) { - warn("WARNING: function data mismatch at ". - "$filename:$line2\n"); - next; - } - $result{$func} = $line2; - } - - return \%result; -} - - -# -# add_fnccount(fnccount1, fnccount2) -# -# Add function call count data. Return list (fnccount_added, f_found, f_hit) -# - -sub add_fnccount($$) -{ - my ($fnccount1, $fnccount2) = @_; - my %result; - my $f_found; - my $f_hit; - my $function; - - if (defined($fnccount1)) { - %result = %{$fnccount1}; - } - foreach $function (keys(%{$fnccount2})) { - $result{$function} += $fnccount2->{$function}; - } - $f_found = scalar(keys(%result)); - $f_hit = 0; - foreach $function (keys(%result)) { - if ($result{$function} > 0) { - $f_hit++; - } - } - - return (\%result, $f_found, $f_hit); -} - -# -# add_testfncdata(testfncdata1, testfncdata2) -# -# Add function call count data for several tests. Return reference to -# added_testfncdata. -# - -sub add_testfncdata($$) -{ - my ($testfncdata1, $testfncdata2) = @_; - my %result; - my $testname; - - foreach $testname (keys(%{$testfncdata1})) { - if (defined($testfncdata2->{$testname})) { - my $fnccount; - - # Function call count data for this testname exists - # in both data sets: merge - ($fnccount) = add_fnccount( - $testfncdata1->{$testname}, - $testfncdata2->{$testname}); - $result{$testname} = $fnccount; - next; - } - # Function call count data for this testname is unique to - # data set 1: copy - $result{$testname} = $testfncdata1->{$testname}; - } - - # Add count data for testnames unique to data set 2 - foreach $testname (keys(%{$testfncdata2})) { - if (!defined($result{$testname})) { - $result{$testname} = $testfncdata2->{$testname}; - } - } - return \%result; -} - - -# -# brcount_to_db(brcount) -# -# Convert brcount data to the following format: -# -# db: line number -> block hash -# block hash: block number -> branch hash -# branch hash: branch number -> taken value -# - -sub brcount_to_db($) -{ - my ($brcount) = @_; - my $line; - my $db = {}; - - # Add branches to database - foreach $line (keys(%{$brcount})) { - my $brdata = $brcount->{$line}; - - foreach my $entry (split(/:/, $brdata)) { - my ($block, $branch, $taken) = split(/,/, $entry); - my $old = $db->{$line}->{$block}->{$branch}; - - if (!defined($old) || $old eq "-") { - $old = $taken; - } elsif ($taken ne "-") { - $old += $taken; - } - - $db->{$line}->{$block}->{$branch} = $old; - } - } - - return $db; -} - - -# -# db_to_brcount(db[, brcount]) -# -# Convert branch coverage data back to brcount format. If brcount is specified, -# the converted data is directly inserted in brcount. -# - -sub db_to_brcount($;$) -{ - my ($db, $brcount) = @_; - my $line; - my $br_found = 0; - my $br_hit = 0; - - # Convert database back to brcount format - foreach $line (sort({$a <=> $b} keys(%{$db}))) { - my $ldata = $db->{$line}; - my $brdata; - my $block; - - foreach $block (sort({$a <=> $b} keys(%{$ldata}))) { - my $bdata = $ldata->{$block}; - my $branch; - - foreach $branch (sort({$a <=> $b} keys(%{$bdata}))) { - my $taken = $bdata->{$branch}; - - $br_found++; - $br_hit++ if ($taken ne "-" && $taken > 0); - $brdata .= "$block,$branch,$taken:"; - } - } - $brcount->{$line} = $brdata; - } - - return ($brcount, $br_found, $br_hit); -} - - -# -# brcount_db_combine(db1, db2, op) -# -# db1 := db1 op db2, where -# db1, db2: brcount data as returned by brcount_to_db -# op: one of $BR_ADD and BR_SUB -# -sub brcount_db_combine($$$) -{ - my ($db1, $db2, $op) = @_; - - foreach my $line (keys(%{$db2})) { - my $ldata = $db2->{$line}; - - foreach my $block (keys(%{$ldata})) { - my $bdata = $ldata->{$block}; - - foreach my $branch (keys(%{$bdata})) { - my $taken = $bdata->{$branch}; - my $new = $db1->{$line}->{$block}->{$branch}; - - if (!defined($new) || $new eq "-") { - $new = $taken; - } elsif ($taken ne "-") { - if ($op == $BR_ADD) { - $new += $taken; - } elsif ($op == $BR_SUB) { - $new -= $taken; - $new = 0 if ($new < 0); - } - } - - $db1->{$line}->{$block}->{$branch} = $new; - } - } - } -} - - -# -# brcount_db_get_found_and_hit(db) -# -# Return (br_found, br_hit) for db. -# - -sub brcount_db_get_found_and_hit($) -{ - my ($db) = @_; - my ($br_found , $br_hit) = (0, 0); - - foreach my $line (keys(%{$db})) { - my $ldata = $db->{$line}; - - foreach my $block (keys(%{$ldata})) { - my $bdata = $ldata->{$block}; - - foreach my $branch (keys(%{$bdata})) { - my $taken = $bdata->{$branch}; - - $br_found++; - $br_hit++ if ($taken ne "-" && $taken > 0); - } - } - } - - return ($br_found, $br_hit); -} - - -# combine_brcount(brcount1, brcount2, type, inplace) -# -# If add is BR_ADD, add branch coverage data and return list brcount_added. -# If add is BR_SUB, subtract the taken values of brcount2 from brcount1 and -# return brcount_sub. If inplace is set, the result is inserted into brcount1. -# - -sub combine_brcount($$$;$) -{ - my ($brcount1, $brcount2, $type, $inplace) = @_; - my ($db1, $db2); - - $db1 = brcount_to_db($brcount1); - $db2 = brcount_to_db($brcount2); - brcount_db_combine($db1, $db2, $type); - - return db_to_brcount($db1, $inplace ? $brcount1 : undef); -} - - -# -# add_testbrdata(testbrdata1, testbrdata2) -# -# Add branch coverage data for several tests. Return reference to -# added_testbrdata. -# - -sub add_testbrdata($$) -{ - my ($testbrdata1, $testbrdata2) = @_; - my %result; - my $testname; - - foreach $testname (keys(%{$testbrdata1})) { - if (defined($testbrdata2->{$testname})) { - my $brcount; - - # Branch coverage data for this testname exists - # in both data sets: add - ($brcount) = combine_brcount( - $testbrdata1->{$testname}, - $testbrdata2->{$testname}, $BR_ADD); - $result{$testname} = $brcount; - next; - } - # Branch coverage data for this testname is unique to - # data set 1: copy - $result{$testname} = $testbrdata1->{$testname}; - } - - # Add count data for testnames unique to data set 2 - foreach $testname (keys(%{$testbrdata2})) { - if (!defined($result{$testname})) { - $result{$testname} = $testbrdata2->{$testname}; - } - } - return \%result; -} - - -# -# combine_info_entries(entry_ref1, entry_ref2, filename) -# -# Combine .info data entry hashes referenced by ENTRY_REF1 and ENTRY_REF2. -# Return reference to resulting hash. -# - -sub combine_info_entries($$$) -{ - my $entry1 = $_[0]; # Reference to hash containing first entry - my $testdata1; - my $sumcount1; - my $funcdata1; - my $checkdata1; - my $testfncdata1; - my $sumfnccount1; - my $testbrdata1; - my $sumbrcount1; - - my $entry2 = $_[1]; # Reference to hash containing second entry - my $testdata2; - my $sumcount2; - my $funcdata2; - my $checkdata2; - my $testfncdata2; - my $sumfnccount2; - my $testbrdata2; - my $sumbrcount2; - - my %result; # Hash containing combined entry - my %result_testdata; - my $result_sumcount = {}; - my $result_funcdata; - my $result_testfncdata; - my $result_sumfnccount; - my $result_testbrdata; - my $result_sumbrcount; - my $lines_found; - my $lines_hit; - my $f_found; - my $f_hit; - my $br_found; - my $br_hit; - - my $testname; - my $filename = $_[2]; - - # Retrieve data - ($testdata1, $sumcount1, $funcdata1, $checkdata1, $testfncdata1, - $sumfnccount1, $testbrdata1, $sumbrcount1) = get_info_entry($entry1); - ($testdata2, $sumcount2, $funcdata2, $checkdata2, $testfncdata2, - $sumfnccount2, $testbrdata2, $sumbrcount2) = get_info_entry($entry2); - - # Merge checksums - $checkdata1 = merge_checksums($checkdata1, $checkdata2, $filename); - - # Combine funcdata - $result_funcdata = merge_func_data($funcdata1, $funcdata2, $filename); - - # Combine function call count data - $result_testfncdata = add_testfncdata($testfncdata1, $testfncdata2); - ($result_sumfnccount, $f_found, $f_hit) = - add_fnccount($sumfnccount1, $sumfnccount2); - - # Combine branch coverage data - $result_testbrdata = add_testbrdata($testbrdata1, $testbrdata2); - ($result_sumbrcount, $br_found, $br_hit) = - combine_brcount($sumbrcount1, $sumbrcount2, $BR_ADD); - - # Combine testdata - foreach $testname (keys(%{$testdata1})) - { - if (defined($testdata2->{$testname})) - { - # testname is present in both entries, requires - # combination - ($result_testdata{$testname}) = - add_counts($testdata1->{$testname}, - $testdata2->{$testname}); - } - else - { - # testname only present in entry1, add to result - $result_testdata{$testname} = $testdata1->{$testname}; - } - - # update sum count hash - ($result_sumcount, $lines_found, $lines_hit) = - add_counts($result_sumcount, - $result_testdata{$testname}); - } - - foreach $testname (keys(%{$testdata2})) - { - # Skip testnames already covered by previous iteration - if (defined($testdata1->{$testname})) { next; } - - # testname only present in entry2, add to result hash - $result_testdata{$testname} = $testdata2->{$testname}; - - # update sum count hash - ($result_sumcount, $lines_found, $lines_hit) = - add_counts($result_sumcount, - $result_testdata{$testname}); - } - - # Calculate resulting sumcount - - # Store result - set_info_entry(\%result, \%result_testdata, $result_sumcount, - $result_funcdata, $checkdata1, $result_testfncdata, - $result_sumfnccount, $result_testbrdata, - $result_sumbrcount, $lines_found, $lines_hit, - $f_found, $f_hit, $br_found, $br_hit); - - return(\%result); -} - - -# -# combine_info_files(info_ref1, info_ref2) -# -# Combine .info data in hashes referenced by INFO_REF1 and INFO_REF2. Return -# reference to resulting hash. -# - -sub combine_info_files($$) -{ - my %hash1 = %{$_[0]}; - my %hash2 = %{$_[1]}; - my $filename; - - foreach $filename (keys(%hash2)) - { - if ($hash1{$filename}) - { - # Entry already exists in hash1, combine them - $hash1{$filename} = - combine_info_entries($hash1{$filename}, - $hash2{$filename}, - $filename); - } - else - { - # Entry is unique in both hashes, simply add to - # resulting hash - $hash1{$filename} = $hash2{$filename}; - } - } - - return(\%hash1); -} - - -# -# add_traces() -# - -sub add_traces() -{ - my $total_trace; - my $current_trace; - my $tracefile; - my @result; - local *INFO_HANDLE; - - info("Combining tracefiles.\n"); - - foreach $tracefile (@add_tracefile) - { - $current_trace = read_info_file($tracefile); - if ($total_trace) - { - $total_trace = combine_info_files($total_trace, - $current_trace); - } - else - { - $total_trace = $current_trace; - } - } - - # Write combined data - if (!$data_stdout) - { - info("Writing data to $output_filename\n"); - open(INFO_HANDLE, ">", $output_filename) - or die("ERROR: cannot write to $output_filename!\n"); - @result = write_info_file(*INFO_HANDLE, $total_trace); - close(*INFO_HANDLE); - } - else - { - @result = write_info_file(*STDOUT, $total_trace); - } - - return @result; -} - - -# -# write_info_file(filehandle, data) -# - -sub write_info_file(*$) -{ - local *INFO_HANDLE = $_[0]; - my %data = %{$_[1]}; - my $source_file; - my $entry; - my $testdata; - my $sumcount; - my $funcdata; - my $checkdata; - my $testfncdata; - my $sumfnccount; - my $testbrdata; - my $sumbrcount; - my $testname; - my $line; - my $func; - my $testcount; - my $testfnccount; - my $testbrcount; - my $found; - my $hit; - my $f_found; - my $f_hit; - my $br_found; - my $br_hit; - my $ln_total_found = 0; - my $ln_total_hit = 0; - my $fn_total_found = 0; - my $fn_total_hit = 0; - my $br_total_found = 0; - my $br_total_hit = 0; - - foreach $source_file (sort(keys(%data))) - { - $entry = $data{$source_file}; - ($testdata, $sumcount, $funcdata, $checkdata, $testfncdata, - $sumfnccount, $testbrdata, $sumbrcount, $found, $hit, - $f_found, $f_hit, $br_found, $br_hit) = - get_info_entry($entry); - - # Add to totals - $ln_total_found += $found; - $ln_total_hit += $hit; - $fn_total_found += $f_found; - $fn_total_hit += $f_hit; - $br_total_found += $br_found; - $br_total_hit += $br_hit; - - foreach $testname (sort(keys(%{$testdata}))) - { - $testcount = $testdata->{$testname}; - $testfnccount = $testfncdata->{$testname}; - $testbrcount = $testbrdata->{$testname}; - $found = 0; - $hit = 0; - - print(INFO_HANDLE "TN:$testname\n"); - print(INFO_HANDLE "SF:$source_file\n"); - - # Write function related data - foreach $func ( - sort({$funcdata->{$a} <=> $funcdata->{$b}} - keys(%{$funcdata}))) - { - print(INFO_HANDLE "FN:".$funcdata->{$func}. - ",$func\n"); - } - foreach $func (keys(%{$testfnccount})) { - print(INFO_HANDLE "FNDA:". - $testfnccount->{$func}. - ",$func\n"); - } - ($f_found, $f_hit) = - get_func_found_and_hit($testfnccount); - print(INFO_HANDLE "FNF:$f_found\n"); - print(INFO_HANDLE "FNH:$f_hit\n"); - - # Write branch related data - $br_found = 0; - $br_hit = 0; - foreach $line (sort({$a <=> $b} - keys(%{$testbrcount}))) { - my $brdata = $testbrcount->{$line}; - - foreach my $brentry (split(/:/, $brdata)) { - my ($block, $branch, $taken) = - split(/,/, $brentry); - - print(INFO_HANDLE "BRDA:$line,$block,". - "$branch,$taken\n"); - $br_found++; - $br_hit++ if ($taken ne '-' && - $taken > 0); - } - } - if ($br_found > 0) { - print(INFO_HANDLE "BRF:$br_found\n"); - print(INFO_HANDLE "BRH:$br_hit\n"); - } - - # Write line related data - foreach $line (sort({$a <=> $b} keys(%{$testcount}))) - { - print(INFO_HANDLE "DA:$line,". - $testcount->{$line}. - (defined($checkdata->{$line}) && - $checksum ? - ",".$checkdata->{$line} : "")."\n"); - $found++; - if ($testcount->{$line} > 0) - { - $hit++; - } - - } - print(INFO_HANDLE "LF:$found\n"); - print(INFO_HANDLE "LH:$hit\n"); - print(INFO_HANDLE "end_of_record\n"); - } - } - - return ($ln_total_found, $ln_total_hit, $fn_total_found, $fn_total_hit, - $br_total_found, $br_total_hit); -} - - -# -# transform_pattern(pattern) -# -# Transform shell wildcard expression to equivalent Perl regular expression. -# Return transformed pattern. -# - -sub transform_pattern($) -{ - my $pattern = $_[0]; - - # Escape special chars - - $pattern =~ s/\\/\\\\/g; - $pattern =~ s/\//\\\//g; - $pattern =~ s/\^/\\\^/g; - $pattern =~ s/\$/\\\$/g; - $pattern =~ s/\(/\\\(/g; - $pattern =~ s/\)/\\\)/g; - $pattern =~ s/\[/\\\[/g; - $pattern =~ s/\]/\\\]/g; - $pattern =~ s/\{/\\\{/g; - $pattern =~ s/\}/\\\}/g; - $pattern =~ s/\./\\\./g; - $pattern =~ s/\,/\\\,/g; - $pattern =~ s/\|/\\\|/g; - $pattern =~ s/\+/\\\+/g; - $pattern =~ s/\!/\\\!/g; - - # Transform ? => (.) and * => (.*) - - $pattern =~ s/\*/\(\.\*\)/g; - $pattern =~ s/\?/\(\.\)/g; - - return $pattern; -} - - -# -# extract() -# - -sub extract() -{ - my $data = read_info_file($extract); - my $filename; - my $keep; - my $pattern; - my @pattern_list; - my $extracted = 0; - my @result; - local *INFO_HANDLE; - - # Need perlreg expressions instead of shell pattern - @pattern_list = map({ transform_pattern($_); } @ARGV); - - # Filter out files which do not match any pattern - foreach $filename (sort(keys(%{$data}))) - { - $keep = 0; - - foreach $pattern (@pattern_list) - { - $keep ||= ($filename =~ (/^$pattern$/)); - } - - - if (!$keep) - { - delete($data->{$filename}); - } - else - { - info("Extracting $filename\n"), - $extracted++; - } - } - - # Write extracted data - if (!$data_stdout) - { - info("Extracted $extracted files\n"); - info("Writing data to $output_filename\n"); - open(INFO_HANDLE, ">", $output_filename) - or die("ERROR: cannot write to $output_filename!\n"); - @result = write_info_file(*INFO_HANDLE, $data); - close(*INFO_HANDLE); - } - else - { - @result = write_info_file(*STDOUT, $data); - } - - return @result; -} - - -# -# remove() -# - -sub remove() -{ - my $data = read_info_file($remove); - my $filename; - my $match_found; - my $pattern; - my @pattern_list; - my $removed = 0; - my @result; - local *INFO_HANDLE; - - # Need perlreg expressions instead of shell pattern - @pattern_list = map({ transform_pattern($_); } @ARGV); - - # Filter out files that match the pattern - foreach $filename (sort(keys(%{$data}))) - { - $match_found = 0; - - foreach $pattern (@pattern_list) - { - $match_found ||= ($filename =~ (/^$pattern$/)); - } - - - if ($match_found) - { - delete($data->{$filename}); - info("Removing $filename\n"), - $removed++; - } - } - - # Write data - if (!$data_stdout) - { - info("Deleted $removed files\n"); - info("Writing data to $output_filename\n"); - open(INFO_HANDLE, ">", $output_filename) - or die("ERROR: cannot write to $output_filename!\n"); - @result = write_info_file(*INFO_HANDLE, $data); - close(*INFO_HANDLE); - } - else - { - @result = write_info_file(*STDOUT, $data); - } - - return @result; -} - - -# get_prefix(max_width, max_percentage_too_long, path_list) -# -# Return a path prefix that satisfies the following requirements: -# - is shared by more paths in path_list than any other prefix -# - the percentage of paths which would exceed the given max_width length -# after applying the prefix does not exceed max_percentage_too_long -# -# If multiple prefixes satisfy all requirements, the longest prefix is -# returned. Return an empty string if no prefix could be found. - -sub get_prefix($$@) -{ - my ($max_width, $max_long, @path_list) = @_; - my $path; - my $ENTRY_NUM = 0; - my $ENTRY_LONG = 1; - my %prefix; - - # Build prefix hash - foreach $path (@path_list) { - my ($v, $d, $f) = splitpath($path); - my @dirs = splitdir($d); - my $p_len = length($path); - my $i; - - # Remove trailing '/' - pop(@dirs) if ($dirs[scalar(@dirs) - 1] eq ''); - for ($i = 0; $i < scalar(@dirs); $i++) { - my $subpath = catpath($v, catdir(@dirs[0..$i]), ''); - my $entry = $prefix{$subpath}; - - $entry = [ 0, 0 ] if (!defined($entry)); - $entry->[$ENTRY_NUM]++; - if (($p_len - length($subpath) - 1) > $max_width) { - $entry->[$ENTRY_LONG]++; - } - $prefix{$subpath} = $entry; - } - } - # Find suitable prefix (sort descending by two keys: 1. number of - # entries covered by a prefix, 2. length of prefix) - foreach $path (sort {($prefix{$a}->[$ENTRY_NUM] == - $prefix{$b}->[$ENTRY_NUM]) ? - length($b) <=> length($a) : - $prefix{$b}->[$ENTRY_NUM] <=> - $prefix{$a}->[$ENTRY_NUM]} - keys(%prefix)) { - my ($num, $long) = @{$prefix{$path}}; - - # Check for additional requirement: number of filenames - # that would be too long may not exceed a certain percentage - if ($long <= $num * $max_long / 100) { - return $path; - } - } - - return ""; -} - - -# -# shorten_filename(filename, width) -# -# Truncate filename if it is longer than width characters. -# - -sub shorten_filename($$) -{ - my ($filename, $width) = @_; - my $l = length($filename); - my $s; - my $e; - - return $filename if ($l <= $width); - $e = int(($width - 3) / 2); - $s = $width - 3 - $e; - - return substr($filename, 0, $s).'...'.substr($filename, $l - $e); -} - - -sub shorten_number($$) -{ - my ($number, $width) = @_; - my $result = sprintf("%*d", $width, $number); - - return $result if (length($result) <= $width); - $number = $number / 1000; - return $result if (length($result) <= $width); - $result = sprintf("%*dk", $width - 1, $number); - return $result if (length($result) <= $width); - $number = $number / 1000; - $result = sprintf("%*dM", $width - 1, $number); - return $result if (length($result) <= $width); - return '#'; -} - -sub shorten_rate($$$) -{ - my ($hit, $found, $width) = @_; - my $result = rate($hit, $found, "%", 1, $width); - - return $result if (length($result) <= $width); - $result = rate($hit, $found, "%", 0, $width); - return $result if (length($result) <= $width); - return "#"; -} - -# -# list() -# - -sub list() -{ - my $data = read_info_file($list); - my $filename; - my $found; - my $hit; - my $entry; - my $fn_found; - my $fn_hit; - my $br_found; - my $br_hit; - my $total_found = 0; - my $total_hit = 0; - my $fn_total_found = 0; - my $fn_total_hit = 0; - my $br_total_found = 0; - my $br_total_hit = 0; - my $prefix; - my $strlen = length("Filename"); - my $format; - my $heading1; - my $heading2; - my @footer; - my $barlen; - my $rate; - my $fnrate; - my $brrate; - my $lastpath; - my $F_LN_NUM = 0; - my $F_LN_RATE = 1; - my $F_FN_NUM = 2; - my $F_FN_RATE = 3; - my $F_BR_NUM = 4; - my $F_BR_RATE = 5; - my @fwidth_narrow = (5, 5, 3, 5, 4, 5); - my @fwidth_wide = (6, 5, 5, 5, 6, 5); - my @fwidth = @fwidth_wide; - my $w; - my $max_width = $opt_list_width; - my $max_long = $opt_list_truncate_max; - my $fwidth_narrow_length; - my $fwidth_wide_length; - my $got_prefix = 0; - my $root_prefix = 0; - - # Calculate total width of narrow fields - $fwidth_narrow_length = 0; - foreach $w (@fwidth_narrow) { - $fwidth_narrow_length += $w + 1; - } - # Calculate total width of wide fields - $fwidth_wide_length = 0; - foreach $w (@fwidth_wide) { - $fwidth_wide_length += $w + 1; - } - # Get common file path prefix - $prefix = get_prefix($max_width - $fwidth_narrow_length, $max_long, - keys(%{$data})); - $root_prefix = 1 if ($prefix eq rootdir()); - $got_prefix = 1 if (length($prefix) > 0); - $prefix =~ s/\/$//; - # Get longest filename length - foreach $filename (keys(%{$data})) { - if (!$opt_list_full_path) { - if (!$got_prefix || !$root_prefix && - !($filename =~ s/^\Q$prefix\/\E//)) { - my ($v, $d, $f) = splitpath($filename); - - $filename = $f; - } - } - # Determine maximum length of entries - if (length($filename) > $strlen) { - $strlen = length($filename) - } - } - if (!$opt_list_full_path) { - my $blanks; - - $w = $fwidth_wide_length; - # Check if all columns fit into max_width characters - if ($strlen + $fwidth_wide_length > $max_width) { - # Use narrow fields - @fwidth = @fwidth_narrow; - $w = $fwidth_narrow_length; - if (($strlen + $fwidth_narrow_length) > $max_width) { - # Truncate filenames at max width - $strlen = $max_width - $fwidth_narrow_length; - } - } - # Add some blanks between filename and fields if possible - $blanks = int($strlen * 0.5); - $blanks = 4 if ($blanks < 4); - $blanks = 8 if ($blanks > 8); - if (($strlen + $w + $blanks) < $max_width) { - $strlen += $blanks; - } else { - $strlen = $max_width - $w; - } - } - # Filename - $w = $strlen; - $format = "%-${w}s|"; - $heading1 = sprintf("%*s|", $w, ""); - $heading2 = sprintf("%-*s|", $w, "Filename"); - $barlen = $w + 1; - # Line coverage rate - $w = $fwidth[$F_LN_RATE]; - $format .= "%${w}s "; - $heading1 .= sprintf("%-*s |", $w + $fwidth[$F_LN_NUM], - "Lines"); - $heading2 .= sprintf("%-*s ", $w, "Rate"); - $barlen += $w + 1; - # Number of lines - $w = $fwidth[$F_LN_NUM]; - $format .= "%${w}s|"; - $heading2 .= sprintf("%*s|", $w, "Num"); - $barlen += $w + 1; - # Function coverage rate - $w = $fwidth[$F_FN_RATE]; - $format .= "%${w}s "; - $heading1 .= sprintf("%-*s|", $w + $fwidth[$F_FN_NUM] + 1, - "Functions"); - $heading2 .= sprintf("%-*s ", $w, "Rate"); - $barlen += $w + 1; - # Number of functions - $w = $fwidth[$F_FN_NUM]; - $format .= "%${w}s|"; - $heading2 .= sprintf("%*s|", $w, "Num"); - $barlen += $w + 1; - # Branch coverage rate - $w = $fwidth[$F_BR_RATE]; - $format .= "%${w}s "; - $heading1 .= sprintf("%-*s", $w + $fwidth[$F_BR_NUM] + 1, - "Branches"); - $heading2 .= sprintf("%-*s ", $w, "Rate"); - $barlen += $w + 1; - # Number of branches - $w = $fwidth[$F_BR_NUM]; - $format .= "%${w}s"; - $heading2 .= sprintf("%*s", $w, "Num"); - $barlen += $w; - # Line end - $format .= "\n"; - $heading1 .= "\n"; - $heading2 .= "\n"; - - # Print heading - print($heading1); - print($heading2); - print(("="x$barlen)."\n"); - - # Print per file information - foreach $filename (sort(keys(%{$data}))) - { - my @file_data; - my $print_filename = $filename; - - $entry = $data->{$filename}; - if (!$opt_list_full_path) { - my $p; - - $print_filename = $filename; - if (!$got_prefix || !$root_prefix && - !($print_filename =~ s/^\Q$prefix\/\E//)) { - my ($v, $d, $f) = splitpath($filename); - - $p = catpath($v, $d, ""); - $p =~ s/\/$//; - $print_filename = $f; - } else { - $p = $prefix; - } - - if (!defined($lastpath) || $lastpath ne $p) { - print("\n") if (defined($lastpath)); - $lastpath = $p; - print("[$lastpath/]\n") if (!$root_prefix); - } - $print_filename = shorten_filename($print_filename, - $strlen); - } - - (undef, undef, undef, undef, undef, undef, undef, undef, - $found, $hit, $fn_found, $fn_hit, $br_found, $br_hit) = - get_info_entry($entry); - - # Assume zero count if there is no function data for this file - if (!defined($fn_found) || !defined($fn_hit)) { - $fn_found = 0; - $fn_hit = 0; - } - # Assume zero count if there is no branch data for this file - if (!defined($br_found) || !defined($br_hit)) { - $br_found = 0; - $br_hit = 0; - } - - # Add line coverage totals - $total_found += $found; - $total_hit += $hit; - # Add function coverage totals - $fn_total_found += $fn_found; - $fn_total_hit += $fn_hit; - # Add branch coverage totals - $br_total_found += $br_found; - $br_total_hit += $br_hit; - - # Determine line coverage rate for this file - $rate = shorten_rate($hit, $found, $fwidth[$F_LN_RATE]); - # Determine function coverage rate for this file - $fnrate = shorten_rate($fn_hit, $fn_found, $fwidth[$F_FN_RATE]); - # Determine branch coverage rate for this file - $brrate = shorten_rate($br_hit, $br_found, $fwidth[$F_BR_RATE]); - - # Assemble line parameters - push(@file_data, $print_filename); - push(@file_data, $rate); - push(@file_data, shorten_number($found, $fwidth[$F_LN_NUM])); - push(@file_data, $fnrate); - push(@file_data, shorten_number($fn_found, $fwidth[$F_FN_NUM])); - push(@file_data, $brrate); - push(@file_data, shorten_number($br_found, $fwidth[$F_BR_NUM])); - - # Print assembled line - printf($format, @file_data); - } - - # Determine total line coverage rate - $rate = shorten_rate($total_hit, $total_found, $fwidth[$F_LN_RATE]); - # Determine total function coverage rate - $fnrate = shorten_rate($fn_total_hit, $fn_total_found, - $fwidth[$F_FN_RATE]); - # Determine total branch coverage rate - $brrate = shorten_rate($br_total_hit, $br_total_found, - $fwidth[$F_BR_RATE]); - - # Print separator - print(("="x$barlen)."\n"); - - # Assemble line parameters - push(@footer, sprintf("%*s", $strlen, "Total:")); - push(@footer, $rate); - push(@footer, shorten_number($total_found, $fwidth[$F_LN_NUM])); - push(@footer, $fnrate); - push(@footer, shorten_number($fn_total_found, $fwidth[$F_FN_NUM])); - push(@footer, $brrate); - push(@footer, shorten_number($br_total_found, $fwidth[$F_BR_NUM])); - - # Print assembled line - printf($format, @footer); -} - - -# -# get_common_filename(filename1, filename2) -# -# Check for filename components which are common to FILENAME1 and FILENAME2. -# Upon success, return -# -# (common, path1, path2) -# -# or 'undef' in case there are no such parts. -# - -sub get_common_filename($$) -{ - my @list1 = split("/", $_[0]); - my @list2 = split("/", $_[1]); - my @result; - - # Work in reverse order, i.e. beginning with the filename itself - while (@list1 && @list2 && ($list1[$#list1] eq $list2[$#list2])) - { - unshift(@result, pop(@list1)); - pop(@list2); - } - - # Did we find any similarities? - if (scalar(@result) > 0) - { - return (join("/", @result), join("/", @list1), - join("/", @list2)); - } - else - { - return undef; - } -} - - -# -# strip_directories($path, $depth) -# -# Remove DEPTH leading directory levels from PATH. -# - -sub strip_directories($$) -{ - my $filename = $_[0]; - my $depth = $_[1]; - my $i; - - if (!defined($depth) || ($depth < 1)) - { - return $filename; - } - for ($i = 0; $i < $depth; $i++) - { - $filename =~ s/^[^\/]*\/+(.*)$/$1/; - } - return $filename; -} - - -# -# read_diff(filename) -# -# Read diff output from FILENAME to memory. The diff file has to follow the -# format generated by 'diff -u'. Returns a list of hash references: -# -# (mapping, path mapping) -# -# mapping: filename -> reference to line hash -# line hash: line number in new file -> corresponding line number in old file -# -# path mapping: filename -> old filename -# -# Die in case of error. -# - -sub read_diff($) -{ - my $diff_file = $_[0]; # Name of diff file - my %diff; # Resulting mapping filename -> line hash - my %paths; # Resulting mapping old path -> new path - my $mapping; # Reference to current line hash - my $line; # Contents of current line - my $num_old; # Current line number in old file - my $num_new; # Current line number in new file - my $file_old; # Name of old file in diff section - my $file_new; # Name of new file in diff section - my $filename; # Name of common filename of diff section - my $in_block = 0; # Non-zero while we are inside a diff block - local *HANDLE; # File handle for reading the diff file - - info("Reading diff $diff_file\n"); - - # Check if file exists and is readable - stat($diff_file); - if (!(-r _)) - { - die("ERROR: cannot read file $diff_file!\n"); - } - - # Check if this is really a plain file - if (!(-f _)) - { - die("ERROR: not a plain file: $diff_file!\n"); - } - - # Check for .gz extension - if ($diff_file =~ /\.gz$/) - { - # Check for availability of GZIP tool - system_no_output(1, "gunzip", "-h") - and die("ERROR: gunzip command not available!\n"); - - # Check integrity of compressed file - system_no_output(1, "gunzip", "-t", $diff_file) - and die("ERROR: integrity check failed for ". - "compressed file $diff_file!\n"); - - # Open compressed file - open(HANDLE, "-|", "gunzip -c '$diff_file'") - or die("ERROR: cannot start gunzip to decompress ". - "file $_[0]!\n"); - } - else - { - # Open decompressed file - open(HANDLE, "<", $diff_file) - or die("ERROR: cannot read file $_[0]!\n"); - } - - # Parse diff file line by line - while () - { - chomp($_); - $line = $_; - - foreach ($line) - { - # Filename of old file: - # --- - /^--- (\S+)/ && do - { - $file_old = strip_directories($1, $strip); - last; - }; - # Filename of new file: - # +++ - /^\+\+\+ (\S+)/ && do - { - # Add last file to resulting hash - if ($filename) - { - my %new_hash; - $diff{$filename} = $mapping; - $mapping = \%new_hash; - } - $file_new = strip_directories($1, $strip); - $filename = $file_old; - $paths{$filename} = $file_new; - $num_old = 1; - $num_new = 1; - last; - }; - # Start of diff block: - # @@ -old_start,old_num, +new_start,new_num @@ - /^\@\@\s+-(\d+),(\d+)\s+\+(\d+),(\d+)\s+\@\@$/ && do - { - $in_block = 1; - while ($num_old < $1) - { - $mapping->{$num_new} = $num_old; - $num_old++; - $num_new++; - } - last; - }; - # Unchanged line - # - /^ / && do - { - if ($in_block == 0) - { - last; - } - $mapping->{$num_new} = $num_old; - $num_old++; - $num_new++; - last; - }; - # Line as seen in old file - # - /^-/ && do - { - if ($in_block == 0) - { - last; - } - $num_old++; - last; - }; - # Line as seen in new file - # - /^\+/ && do - { - if ($in_block == 0) - { - last; - } - $num_new++; - last; - }; - # Empty line - /^$/ && do - { - if ($in_block == 0) - { - last; - } - $mapping->{$num_new} = $num_old; - $num_old++; - $num_new++; - last; - }; - } - } - - close(HANDLE); - - # Add final diff file section to resulting hash - if ($filename) - { - $diff{$filename} = $mapping; - } - - if (!%diff) - { - die("ERROR: no valid diff data found in $diff_file!\n". - "Make sure to use 'diff -u' when generating the diff ". - "file.\n"); - } - return (\%diff, \%paths); -} - - -# -# apply_diff($count_data, $line_hash) -# -# Transform count data using a mapping of lines: -# -# $count_data: reference to hash: line number -> data -# $line_hash: reference to hash: line number new -> line number old -# -# Return a reference to transformed count data. -# - -sub apply_diff($$) -{ - my $count_data = $_[0]; # Reference to data hash: line -> hash - my $line_hash = $_[1]; # Reference to line hash: new line -> old line - my %result; # Resulting hash - my $last_new = 0; # Last new line number found in line hash - my $last_old = 0; # Last old line number found in line hash - - # Iterate all new line numbers found in the diff - foreach (sort({$a <=> $b} keys(%{$line_hash}))) - { - $last_new = $_; - $last_old = $line_hash->{$last_new}; - - # Is there data associated with the corresponding old line? - if (defined($count_data->{$line_hash->{$_}})) - { - # Copy data to new hash with a new line number - $result{$_} = $count_data->{$line_hash->{$_}}; - } - } - # Transform all other lines which come after the last diff entry - foreach (sort({$a <=> $b} keys(%{$count_data}))) - { - if ($_ <= $last_old) - { - # Skip lines which were covered by line hash - next; - } - # Copy data to new hash with an offset - $result{$_ + ($last_new - $last_old)} = $count_data->{$_}; - } - - return \%result; -} - - -# -# apply_diff_to_brcount(brcount, linedata) -# -# Adjust line numbers of branch coverage data according to linedata. -# - -sub apply_diff_to_brcount($$) -{ - my ($brcount, $linedata) = @_; - my $db; - - # Convert brcount to db format - $db = brcount_to_db($brcount); - # Apply diff to db format - $db = apply_diff($db, $linedata); - # Convert db format back to brcount format - ($brcount) = db_to_brcount($db); - - return $brcount; -} - - -# -# get_hash_max(hash_ref) -# -# Return the highest integer key from hash. -# - -sub get_hash_max($) -{ - my ($hash) = @_; - my $max; - - foreach (keys(%{$hash})) { - if (!defined($max)) { - $max = $_; - } elsif ($hash->{$_} > $max) { - $max = $_; - } - } - return $max; -} - -sub get_hash_reverse($) -{ - my ($hash) = @_; - my %result; - - foreach (keys(%{$hash})) { - $result{$hash->{$_}} = $_; - } - - return \%result; -} - -# -# apply_diff_to_funcdata(funcdata, line_hash) -# - -sub apply_diff_to_funcdata($$) -{ - my ($funcdata, $linedata) = @_; - my $last_new = get_hash_max($linedata); - my $last_old = $linedata->{$last_new}; - my $func; - my %result; - my $line_diff = get_hash_reverse($linedata); - - foreach $func (keys(%{$funcdata})) { - my $line = $funcdata->{$func}; - - if (defined($line_diff->{$line})) { - $result{$func} = $line_diff->{$line}; - } elsif ($line > $last_old) { - $result{$func} = $line + $last_new - $last_old; - } - } - - return \%result; -} - - -# -# get_line_hash($filename, $diff_data, $path_data) -# -# Find line hash in DIFF_DATA which matches FILENAME. On success, return list -# line hash. or undef in case of no match. Die if more than one line hashes in -# DIFF_DATA match. -# - -sub get_line_hash($$$) -{ - my $filename = $_[0]; - my $diff_data = $_[1]; - my $path_data = $_[2]; - my $conversion; - my $old_path; - my $new_path; - my $diff_name; - my $common; - my $old_depth; - my $new_depth; - - # Remove trailing slash from diff path - $diff_path =~ s/\/$//; - foreach (keys(%{$diff_data})) - { - my $sep = ""; - - $sep = '/' if (!/^\//); - - # Try to match diff filename with filename - if ($filename =~ /^\Q$diff_path$sep$_\E$/) - { - if ($diff_name) - { - # Two files match, choose the more specific one - # (the one with more path components) - $old_depth = ($diff_name =~ tr/\///); - $new_depth = (tr/\///); - if ($old_depth == $new_depth) - { - die("ERROR: diff file contains ". - "ambiguous entries for ". - "$filename\n"); - } - elsif ($new_depth > $old_depth) - { - $diff_name = $_; - } - } - else - { - $diff_name = $_; - } - }; - } - if ($diff_name) - { - # Get converted path - if ($filename =~ /^(.*)$diff_name$/) - { - ($common, $old_path, $new_path) = - get_common_filename($filename, - $1.$path_data->{$diff_name}); - } - return ($diff_data->{$diff_name}, $old_path, $new_path); - } - else - { - return undef; - } -} - - -# -# convert_paths(trace_data, path_conversion_data) -# -# Rename all paths in TRACE_DATA which show up in PATH_CONVERSION_DATA. -# - -sub convert_paths($$) -{ - my $trace_data = $_[0]; - my $path_conversion_data = $_[1]; - my $filename; - my $new_path; - - if (scalar(keys(%{$path_conversion_data})) == 0) - { - info("No path conversion data available.\n"); - return; - } - - # Expand path conversion list - foreach $filename (keys(%{$path_conversion_data})) - { - $new_path = $path_conversion_data->{$filename}; - while (($filename =~ s/^(.*)\/[^\/]+$/$1/) && - ($new_path =~ s/^(.*)\/[^\/]+$/$1/) && - ($filename ne $new_path)) - { - $path_conversion_data->{$filename} = $new_path; - } - } - - # Adjust paths - FILENAME: foreach $filename (keys(%{$trace_data})) - { - # Find a path in our conversion table that matches, starting - # with the longest path - foreach (sort({length($b) <=> length($a)} - keys(%{$path_conversion_data}))) - { - # Is this path a prefix of our filename? - if (!($filename =~ /^$_(.*)$/)) - { - next; - } - $new_path = $path_conversion_data->{$_}.$1; - - # Make sure not to overwrite an existing entry under - # that path name - if ($trace_data->{$new_path}) - { - # Need to combine entries - $trace_data->{$new_path} = - combine_info_entries( - $trace_data->{$filename}, - $trace_data->{$new_path}, - $filename); - } - else - { - # Simply rename entry - $trace_data->{$new_path} = - $trace_data->{$filename}; - } - delete($trace_data->{$filename}); - next FILENAME; - } - info("No conversion available for filename $filename\n"); - } -} - -# -# sub adjust_fncdata(funcdata, testfncdata, sumfnccount) -# -# Remove function call count data from testfncdata and sumfnccount which -# is no longer present in funcdata. -# - -sub adjust_fncdata($$$) -{ - my ($funcdata, $testfncdata, $sumfnccount) = @_; - my $testname; - my $func; - my $f_found; - my $f_hit; - - # Remove count data in testfncdata for functions which are no longer - # in funcdata - foreach $testname (keys(%{$testfncdata})) { - my $fnccount = $testfncdata->{$testname}; - - foreach $func (keys(%{$fnccount})) { - if (!defined($funcdata->{$func})) { - delete($fnccount->{$func}); - } - } - } - # Remove count data in sumfnccount for functions which are no longer - # in funcdata - foreach $func (keys(%{$sumfnccount})) { - if (!defined($funcdata->{$func})) { - delete($sumfnccount->{$func}); - } - } -} - -# -# get_func_found_and_hit(sumfnccount) -# -# Return (f_found, f_hit) for sumfnccount -# - -sub get_func_found_and_hit($) -{ - my ($sumfnccount) = @_; - my $function; - my $f_found; - my $f_hit; - - $f_found = scalar(keys(%{$sumfnccount})); - $f_hit = 0; - foreach $function (keys(%{$sumfnccount})) { - if ($sumfnccount->{$function} > 0) { - $f_hit++; - } - } - return ($f_found, $f_hit); -} - -# -# diff() -# - -sub diff() -{ - my $trace_data = read_info_file($diff); - my $diff_data; - my $path_data; - my $old_path; - my $new_path; - my %path_conversion_data; - my $filename; - my $line_hash; - my $new_name; - my $entry; - my $testdata; - my $testname; - my $sumcount; - my $funcdata; - my $checkdata; - my $testfncdata; - my $sumfnccount; - my $testbrdata; - my $sumbrcount; - my $found; - my $hit; - my $f_found; - my $f_hit; - my $br_found; - my $br_hit; - my $converted = 0; - my $unchanged = 0; - my @result; - local *INFO_HANDLE; - - ($diff_data, $path_data) = read_diff($ARGV[0]); - - foreach $filename (sort(keys(%{$trace_data}))) - { - # Find a diff section corresponding to this file - ($line_hash, $old_path, $new_path) = - get_line_hash($filename, $diff_data, $path_data); - if (!$line_hash) - { - # There's no diff section for this file - $unchanged++; - next; - } - $converted++; - if ($old_path && $new_path && ($old_path ne $new_path)) - { - $path_conversion_data{$old_path} = $new_path; - } - # Check for deleted files - if (scalar(keys(%{$line_hash})) == 0) - { - info("Removing $filename\n"); - delete($trace_data->{$filename}); - next; - } - info("Converting $filename\n"); - $entry = $trace_data->{$filename}; - ($testdata, $sumcount, $funcdata, $checkdata, $testfncdata, - $sumfnccount, $testbrdata, $sumbrcount) = - get_info_entry($entry); - # Convert test data - foreach $testname (keys(%{$testdata})) - { - # Adjust line numbers of line coverage data - $testdata->{$testname} = - apply_diff($testdata->{$testname}, $line_hash); - # Adjust line numbers of branch coverage data - $testbrdata->{$testname} = - apply_diff_to_brcount($testbrdata->{$testname}, - $line_hash); - # Remove empty sets of test data - if (scalar(keys(%{$testdata->{$testname}})) == 0) - { - delete($testdata->{$testname}); - delete($testfncdata->{$testname}); - delete($testbrdata->{$testname}); - } - } - # Rename test data to indicate conversion - foreach $testname (keys(%{$testdata})) - { - # Skip testnames which already contain an extension - if ($testname =~ /,[^,]+$/) - { - next; - } - # Check for name conflict - if (defined($testdata->{$testname.",diff"})) - { - # Add counts - ($testdata->{$testname}) = add_counts( - $testdata->{$testname}, - $testdata->{$testname.",diff"}); - delete($testdata->{$testname.",diff"}); - # Add function call counts - ($testfncdata->{$testname}) = add_fnccount( - $testfncdata->{$testname}, - $testfncdata->{$testname.",diff"}); - delete($testfncdata->{$testname.",diff"}); - # Add branch counts - combine_brcount( - $testbrdata->{$testname}, - $testbrdata->{$testname.",diff"}, - $BR_ADD, 1); - delete($testbrdata->{$testname.",diff"}); - } - # Move test data to new testname - $testdata->{$testname.",diff"} = $testdata->{$testname}; - delete($testdata->{$testname}); - # Move function call count data to new testname - $testfncdata->{$testname.",diff"} = - $testfncdata->{$testname}; - delete($testfncdata->{$testname}); - # Move branch count data to new testname - $testbrdata->{$testname.",diff"} = - $testbrdata->{$testname}; - delete($testbrdata->{$testname}); - } - # Convert summary of test data - $sumcount = apply_diff($sumcount, $line_hash); - # Convert function data - $funcdata = apply_diff_to_funcdata($funcdata, $line_hash); - # Convert branch coverage data - $sumbrcount = apply_diff_to_brcount($sumbrcount, $line_hash); - # Update found/hit numbers - # Convert checksum data - $checkdata = apply_diff($checkdata, $line_hash); - # Convert function call count data - adjust_fncdata($funcdata, $testfncdata, $sumfnccount); - ($f_found, $f_hit) = get_func_found_and_hit($sumfnccount); - ($br_found, $br_hit) = get_br_found_and_hit($sumbrcount); - # Update found/hit numbers - $found = 0; - $hit = 0; - foreach (keys(%{$sumcount})) - { - $found++; - if ($sumcount->{$_} > 0) - { - $hit++; - } - } - if ($found > 0) - { - # Store converted entry - set_info_entry($entry, $testdata, $sumcount, $funcdata, - $checkdata, $testfncdata, $sumfnccount, - $testbrdata, $sumbrcount, $found, $hit, - $f_found, $f_hit, $br_found, $br_hit); - } - else - { - # Remove empty data set - delete($trace_data->{$filename}); - } - } - - # Convert filenames as well if requested - if ($convert_filenames) - { - convert_paths($trace_data, \%path_conversion_data); - } - - info("$converted entr".($converted != 1 ? "ies" : "y")." converted, ". - "$unchanged entr".($unchanged != 1 ? "ies" : "y")." left ". - "unchanged.\n"); - - # Write data - if (!$data_stdout) - { - info("Writing data to $output_filename\n"); - open(INFO_HANDLE, ">", $output_filename) - or die("ERROR: cannot write to $output_filename!\n"); - @result = write_info_file(*INFO_HANDLE, $trace_data); - close(*INFO_HANDLE); - } - else - { - @result = write_info_file(*STDOUT, $trace_data); - } - - return @result; -} - -# -# summary() -# - -sub summary() -{ - my $filename; - my $current; - my $total; - my $ln_total_found; - my $ln_total_hit; - my $fn_total_found; - my $fn_total_hit; - my $br_total_found; - my $br_total_hit; - - # Read and combine trace files - foreach $filename (@opt_summary) { - $current = read_info_file($filename); - if (!defined($total)) { - $total = $current; - } else { - $total = combine_info_files($total, $current); - } - } - # Calculate coverage data - foreach $filename (keys(%{$total})) - { - my $entry = $total->{$filename}; - my $ln_found; - my $ln_hit; - my $fn_found; - my $fn_hit; - my $br_found; - my $br_hit; - - (undef, undef, undef, undef, undef, undef, undef, undef, - $ln_found, $ln_hit, $fn_found, $fn_hit, $br_found, - $br_hit) = get_info_entry($entry); - - # Add to totals - $ln_total_found += $ln_found; - $ln_total_hit += $ln_hit; - $fn_total_found += $fn_found; - $fn_total_hit += $fn_hit; - $br_total_found += $br_found; - $br_total_hit += $br_hit; - } - - - return ($ln_total_found, $ln_total_hit, $fn_total_found, $fn_total_hit, - $br_total_found, $br_total_hit); -} - -# -# system_no_output(mode, parameters) -# -# Call an external program using PARAMETERS while suppressing depending on -# the value of MODE: -# -# MODE & 1: suppress STDOUT -# MODE & 2: suppress STDERR -# -# Return 0 on success, non-zero otherwise. -# - -sub system_no_output($@) -{ - my $mode = shift; - my $result; - local *OLD_STDERR; - local *OLD_STDOUT; - - # Save old stdout and stderr handles - ($mode & 1) && open(OLD_STDOUT, ">>&", "STDOUT"); - ($mode & 2) && open(OLD_STDERR, ">>&", "STDERR"); - - # Redirect to /dev/null - ($mode & 1) && open(STDOUT, ">", "/dev/null"); - ($mode & 2) && open(STDERR, ">", "/dev/null"); - - system(@_); - $result = $?; - - # Close redirected handles - ($mode & 1) && close(STDOUT); - ($mode & 2) && close(STDERR); - - # Restore old handles - ($mode & 1) && open(STDOUT, ">>&", "OLD_STDOUT"); - ($mode & 2) && open(STDERR, ">>&", "OLD_STDERR"); - - return $result; -} - - -# -# read_config(filename) -# -# Read configuration file FILENAME and return a reference to a hash containing -# all valid key=value pairs found. -# - -sub read_config($) -{ - my $filename = $_[0]; - my %result; - my $key; - my $value; - local *HANDLE; - - if (!open(HANDLE, "<", $filename)) - { - warn("WARNING: cannot read configuration file $filename\n"); - return undef; - } - while () - { - chomp; - # Skip comments - s/#.*//; - # Remove leading blanks - s/^\s+//; - # Remove trailing blanks - s/\s+$//; - next unless length; - ($key, $value) = split(/\s*=\s*/, $_, 2); - if (defined($key) && defined($value)) - { - $result{$key} = $value; - } - else - { - warn("WARNING: malformed statement in line $. ". - "of configuration file $filename\n"); - } - } - close(HANDLE); - return \%result; -} - - -# -# apply_config(REF) -# -# REF is a reference to a hash containing the following mapping: -# -# key_string => var_ref -# -# where KEY_STRING is a keyword and VAR_REF is a reference to an associated -# variable. If the global configuration hashes CONFIG or OPT_RC contain a value -# for keyword KEY_STRING, VAR_REF will be assigned the value for that keyword. -# - -sub apply_config($) -{ - my $ref = $_[0]; - - foreach (keys(%{$ref})) - { - if (defined($opt_rc{$_})) { - ${$ref->{$_}} = $opt_rc{$_}; - } elsif (defined($config->{$_})) { - ${$ref->{$_}} = $config->{$_}; - } - } -} - -sub warn_handler($) -{ - my ($msg) = @_; - - warn("$tool_name: $msg"); -} - -sub die_handler($) -{ - my ($msg) = @_; - - temp_cleanup(); - die("$tool_name: $msg"); -} - -sub abort_handler($) -{ - temp_cleanup(); - exit(1); -} - -sub temp_cleanup() -{ - # Ensure temp directory is not in use by current process - chdir("/"); - - if (@temp_dirs) { - info("Removing temporary directories.\n"); - foreach (@temp_dirs) { - rmtree($_); - } - @temp_dirs = (); - } -} - -sub setup_gkv_sys() -{ - system_no_output(3, "mount", "-t", "debugfs", "nodev", - "/sys/kernel/debug"); -} - -sub setup_gkv_proc() -{ - if (system_no_output(3, "modprobe", "gcov_proc")) { - system_no_output(3, "modprobe", "gcov_prof"); - } -} - -sub check_gkv_sys($) -{ - my ($dir) = @_; - - if (-e "$dir/reset") { - return 1; - } - return 0; -} - -sub check_gkv_proc($) -{ - my ($dir) = @_; - - if (-e "$dir/vmlinux") { - return 1; - } - return 0; -} - -sub setup_gkv() -{ - my $dir; - my $sys_dir = "/sys/kernel/debug/gcov"; - my $proc_dir = "/proc/gcov"; - my @todo; - - if (!defined($gcov_dir)) { - info("Auto-detecting gcov kernel support.\n"); - @todo = ( "cs", "cp", "ss", "cs", "sp", "cp" ); - } elsif ($gcov_dir =~ /proc/) { - info("Checking gcov kernel support at $gcov_dir ". - "(user-specified).\n"); - @todo = ( "cp", "sp", "cp", "cs", "ss", "cs"); - } else { - info("Checking gcov kernel support at $gcov_dir ". - "(user-specified).\n"); - @todo = ( "cs", "ss", "cs", "cp", "sp", "cp", ); - } - foreach (@todo) { - if ($_ eq "cs") { - # Check /sys - $dir = defined($gcov_dir) ? $gcov_dir : $sys_dir; - if (check_gkv_sys($dir)) { - info("Found ".$GKV_NAME[$GKV_SYS]." gcov ". - "kernel support at $dir\n"); - return ($GKV_SYS, $dir); - } - } elsif ($_ eq "cp") { - # Check /proc - $dir = defined($gcov_dir) ? $gcov_dir : $proc_dir; - if (check_gkv_proc($dir)) { - info("Found ".$GKV_NAME[$GKV_PROC]." gcov ". - "kernel support at $dir\n"); - return ($GKV_PROC, $dir); - } - } elsif ($_ eq "ss") { - # Setup /sys - setup_gkv_sys(); - } elsif ($_ eq "sp") { - # Setup /proc - setup_gkv_proc(); - } - } - if (defined($gcov_dir)) { - die("ERROR: could not find gcov kernel data at $gcov_dir\n"); - } else { - die("ERROR: no gcov kernel data found\n"); - } -} - - -# -# get_overall_line(found, hit, name_singular, name_plural) -# -# Return a string containing overall information for the specified -# found/hit data. -# - -sub get_overall_line($$$$) -{ - my ($found, $hit, $name_sn, $name_pl) = @_; - my $name; - - return "no data found" if (!defined($found) || $found == 0); - $name = ($found == 1) ? $name_sn : $name_pl; - - return rate($hit, $found, "% ($hit of $found $name)"); -} - - -# -# print_overall_rate(ln_do, ln_found, ln_hit, fn_do, fn_found, fn_hit, br_do -# br_found, br_hit) -# -# Print overall coverage rates for the specified coverage types. -# - -sub print_overall_rate($$$$$$$$$) -{ - my ($ln_do, $ln_found, $ln_hit, $fn_do, $fn_found, $fn_hit, - $br_do, $br_found, $br_hit) = @_; - - info("Summary coverage rate:\n"); - info(" lines......: %s\n", - get_overall_line($ln_found, $ln_hit, "line", "lines")) - if ($ln_do); - info(" functions..: %s\n", - get_overall_line($fn_found, $fn_hit, "function", "functions")) - if ($fn_do); - info(" branches...: %s\n", - get_overall_line($br_found, $br_hit, "branch", "branches")) - if ($br_do); -} - - -# -# rate(hit, found[, suffix, precision, width]) -# -# Return the coverage rate [0..100] for HIT and FOUND values. 0 is only -# returned when HIT is 0. 100 is only returned when HIT equals FOUND. -# PRECISION specifies the precision of the result. SUFFIX defines a -# string that is appended to the result if FOUND is non-zero. Spaces -# are added to the start of the resulting string until it is at least WIDTH -# characters wide. -# - -sub rate($$;$$$) -{ - my ($hit, $found, $suffix, $precision, $width) = @_; - my $rate; - - # Assign defaults if necessary - $precision = 1 if (!defined($precision)); - $suffix = "" if (!defined($suffix)); - $width = 0 if (!defined($width)); - - return sprintf("%*s", $width, "-") if (!defined($found) || $found == 0); - $rate = sprintf("%.*f", $precision, $hit * 100 / $found); - - # Adjust rates if necessary - if ($rate == 0 && $hit > 0) { - $rate = sprintf("%.*f", $precision, 1 / 10 ** $precision); - } elsif ($rate == 100 && $hit != $found) { - $rate = sprintf("%.*f", $precision, 100 - 1 / 10 ** $precision); - } - - return sprintf("%*s", $width, $rate.$suffix); -} diff --git a/worker/deps/lcov/bin/updateversion.pl b/worker/deps/lcov/bin/updateversion.pl deleted file mode 100755 index 19db81ecd3..0000000000 --- a/worker/deps/lcov/bin/updateversion.pl +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/env perl - -use strict; -use warnings; - -use File::Basename; - -sub update_man_page($); -sub update_bin_tool($); -sub update_txt_file($); -sub update_spec_file($); -sub write_version_file($); -sub get_file_info($); - -our $directory = $ARGV[0]; -our $version = $ARGV[1]; -our $release = $ARGV[2]; -our $full = $ARGV[3]; - -our @man_pages = ("man/gendesc.1", "man/genhtml.1", "man/geninfo.1", - "man/genpng.1", "man/lcov.1", "man/lcovrc.5"); -our @bin_tools = ("bin/gendesc", "bin/genhtml", "bin/geninfo", - "bin/genpng", "bin/lcov"); -our @txt_files = ("README"); -our @spec_files = ("rpm/lcov.spec"); - -if (!defined($directory) || !defined($version) || !defined($release)) { - die("Usage: $0 DIRECTORY|FILE VERSION RELEASE FULL_VERSION\n"); -} - -# Determine mode of operation -if (-f $directory) { - my $file = $directory; - my $base = basename($file); - - if (grep(/^$base$/, map({ basename($_) } @man_pages))) { - print("Updating man page $file\n"); - update_man_page($file); - } elsif (grep(/^$base$/, map({ basename($_) } @bin_tools))) { - print("Updating bin tool $file\n"); - update_bin_tool($file); - } elsif (grep(/^$base$/, map({ basename($_) } @txt_files))) { - print("Updating text file $file\n"); - update_txt_file($file); - } elsif (grep(/^$base$/, map({ basename($_) } @spec_files))) { - print("Updating spec file $file\n"); - update_spec_file($file); - } elsif ($base eq ".version") { - print("Updating version file $file\n"); - write_version_file($file); - } else { - print("WARNING: Skipping unknown file $file\n"); - } - print("Done.\n"); - exit(0); -} - -foreach (@man_pages) { - print("Updating man page $_\n"); - update_man_page($directory."/".$_); -} -foreach (@bin_tools) { - print("Updating bin tool $_\n"); - update_bin_tool($directory."/".$_); -} -foreach (@txt_files) { - print("Updating text file $_\n"); - update_txt_file($directory."/".$_); -} -foreach (@spec_files) { - print("Updating spec file $_\n"); - update_spec_file($directory."/".$_); -} -print("Updating version file $directory/.version\n"); -write_version_file("$directory/.version"); -print("Done.\n"); - -sub get_file_info($) -{ - my ($filename) = @_; - my ($sec, $min, $hour, $year, $month, $day); - my @stat; - my $gittime; - - return (0, 0, 0) if (!-e $filename); - @stat = stat($filename); - ($sec, $min, $hour, $day, $month, $year) = gmtime($stat[9]); - $year += 1900; - $month += 1; - - return (sprintf("%04d-%02d-%02d", $year, $month, $day), - sprintf("%04d%02d%02d%02d%02d.%02d", $year, $month, $day, - $hour, $min, $sec), - sprintf("%o", $stat[2] & 07777)); -} - -sub update_man_page($) -{ - my ($filename) = @_; - my @date = get_file_info($filename); - my $date_string = $date[0]; - local *IN; - local *OUT; - - $date_string =~ s/-/\\-/g; - open(IN, "<$filename") || die ("Error: cannot open $filename\n"); - open(OUT, ">$filename.new") || - die("Error: cannot create $filename.new\n"); - while () { - s/\"LCOV\s+\d+\.\d+\"/\"LCOV $version\"/g; - s/\d\d\d\d\\\-\d\d\\\-\d\d/$date_string/g; - print(OUT $_); - } - close(OUT); - close(IN); - chmod(oct($date[2]), "$filename.new"); - system("mv", "-f", "$filename.new", "$filename"); - system("touch", "$filename", "-t", $date[1]); -} - -sub update_bin_tool($) -{ - my ($filename) = @_; - my @date = get_file_info($filename); - local *IN; - local *OUT; - - open(IN, "<$filename") || die ("Error: cannot open $filename\n"); - open(OUT, ">$filename.new") || - die("Error: cannot create $filename.new\n"); - while () { - s/^(our\s+\$lcov_version\s*=).*$/$1 "LCOV version $full";/g; - print(OUT $_); - } - close(OUT); - close(IN); - chmod(oct($date[2]), "$filename.new"); - system("mv", "-f", "$filename.new", "$filename"); - system("touch", "$filename", "-t", $date[1]); -} - -sub update_txt_file($) -{ - my ($filename) = @_; - my @date = get_file_info($filename); - local *IN; - local *OUT; - - open(IN, "<$filename") || die ("Error: cannot open $filename\n"); - open(OUT, ">$filename.new") || - die("Error: cannot create $filename.new\n"); - while () { - s/(Last\s+changes:\s+)\d\d\d\d-\d\d-\d\d/$1$date[0]/g; - print(OUT $_); - } - close(OUT); - close(IN); - chmod(oct($date[2]), "$filename.new"); - system("mv", "-f", "$filename.new", "$filename"); - system("touch", "$filename", "-t", $date[1]); -} - -sub update_spec_file($) -{ - my ($filename) = @_; - my @date = get_file_info($filename); - local *IN; - local *OUT; - - open(IN, "<$filename") || die ("Error: cannot open $filename\n"); - open(OUT, ">$filename.new") || - die("Error: cannot create $filename.new\n"); - while () { - s/^(Version:\s*)\d+\.\d+.*$/$1$version/; - s/^(Release:\s*).*$/$1$release/; - print(OUT $_); - } - close(OUT); - close(IN); - system("mv", "-f", "$filename.new", "$filename"); - system("touch", "$filename", "-t", $date[1]); -} - -sub write_version_file($) -{ - my ($filename) = @_; - my $fd; - - open($fd, ">", $filename) or die("Error: cannot write $filename: $!\n"); - print($fd "VERSION=$version\n"); - print($fd "RELEASE=$release\n"); - print($fd "FULL=$full\n"); - close($fd); -} diff --git a/worker/deps/lcov/example/Makefile b/worker/deps/lcov/example/Makefile deleted file mode 100644 index 2f698a1b32..0000000000 --- a/worker/deps/lcov/example/Makefile +++ /dev/null @@ -1,98 +0,0 @@ -# -# Makefile for the LCOV example program. -# -# Make targets: -# - example: compile the example program -# - output: run test cases on example program and create HTML output -# - clean: clean up directory -# - -CC := gcc -CFLAGS := -Wall -I. -fprofile-arcs -ftest-coverage - -LCOV := ../bin/lcov -GENHTML := ../bin/genhtml -GENDESC := ../bin/gendesc -GENPNG := ../bin/genpng - -# Depending on the presence of the GD.pm perl module, we can use the -# special option '--frames' for genhtml -USE_GENPNG := $(shell $(GENPNG) --help >/dev/null 2>/dev/null; echo $$?) - -ifeq ($(USE_GENPNG),0) - FRAMES := --frames -else - FRAMES := -endif - -.PHONY: clean output test_noargs test_2_to_2000 test_overflow - -all: output - -example: example.o iterate.o gauss.o - $(CC) example.o iterate.o gauss.o -o example -lgcov - -example.o: example.c iterate.h gauss.h - $(CC) $(CFLAGS) -c example.c -o example.o - -iterate.o: methods/iterate.c iterate.h - $(CC) $(CFLAGS) -c methods/iterate.c -o iterate.o - -gauss.o: methods/gauss.c gauss.h - $(CC) $(CFLAGS) -c methods/gauss.c -o gauss.o - -output: example descriptions test_noargs test_2_to_2000 test_overflow - @echo - @echo '*' - @echo '* Generating HTML output' - @echo '*' - @echo - $(GENHTML) trace_noargs.info trace_args.info trace_overflow.info \ - --output-directory output --title "Basic example" \ - --show-details --description-file descriptions $(FRAMES) \ - --legend - @echo - @echo '*' - @echo '* See '`pwd`/output/index.html - @echo '*' - @echo - -descriptions: descriptions.txt - $(GENDESC) descriptions.txt -o descriptions - -all_tests: example test_noargs test_2_to_2000 test_overflow - -test_noargs: - @echo - @echo '*' - @echo '* Test case 1: running ./example without parameters' - @echo '*' - @echo - $(LCOV) --zerocounters --directory . - ./example - $(LCOV) --capture --directory . --output-file trace_noargs.info --test-name test_noargs --no-external - -test_2_to_2000: - @echo - @echo '*' - @echo '* Test case 2: running ./example 2 2000' - @echo '*' - @echo - $(LCOV) --zerocounters --directory . - ./example 2 2000 - $(LCOV) --capture --directory . --output-file trace_args.info --test-name test_2_to_2000 --no-external - -test_overflow: - @echo - @echo '*' - @echo '* Test case 3: running ./example 0 100000 (causes an overflow)' - @echo '*' - @echo - $(LCOV) --zerocounters --directory . - ./example 0 100000 || true - $(LCOV) --capture --directory . --output-file trace_overflow.info --test-name "test_overflow" --no-external - -clean: - rm -rf *.o *.bb *.bbg *.da *.gcno *.gcda *.info output example \ - descriptions - diff --git a/worker/deps/lcov/example/README b/worker/deps/lcov/example/README deleted file mode 100644 index cf6cf2e4c6..0000000000 --- a/worker/deps/lcov/example/README +++ /dev/null @@ -1,6 +0,0 @@ - -To get an example of how the LCOV generated HTML output looks like, -type 'make output' and point a web browser to the resulting file - - output/index.html - diff --git a/worker/deps/lcov/example/descriptions.txt b/worker/deps/lcov/example/descriptions.txt deleted file mode 100644 index 47e6021310..0000000000 --- a/worker/deps/lcov/example/descriptions.txt +++ /dev/null @@ -1,10 +0,0 @@ -test_noargs - Example program is called without arguments so that default range - [0..9] is used. - -test_2_to_2000 - Example program is called with "2" and "2000" as arguments. - -test_overflow - Example program is called with "0" and "100000" as arguments. The - resulting sum is too large to be stored as an int variable. diff --git a/worker/deps/lcov/example/example.c b/worker/deps/lcov/example/example.c deleted file mode 100644 index f9049aa64b..0000000000 --- a/worker/deps/lcov/example/example.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * example.c - * - * Calculate the sum of a given range of integer numbers. The range is - * specified by providing two integer numbers as command line argument. - * If no arguments are specified, assume the predefined range [0..9]. - * Abort with an error message if the resulting number is too big to be - * stored as int variable. - * - * This program example is similar to the one found in the GCOV documentation. - * It is used to demonstrate the HTML output generated by LCOV. - * - * The program is split into 3 modules to better demonstrate the 'directory - * overview' function. There are also a lot of bloated comments inserted to - * artificially increase the source code size so that the 'source code - * overview' function makes at least a minimum of sense. - * - */ - -#include -#include -#include "iterate.h" -#include "gauss.h" - -static int start = 0; -static int end = 9; - - -int main (int argc, char* argv[]) -{ - int total1, total2; - - /* Accept a pair of numbers as command line arguments. */ - - if (argc == 3) - { - start = atoi(argv[1]); - end = atoi(argv[2]); - } - - - /* Use both methods to calculate the result. */ - - total1 = iterate_get_sum (start, end); - total2 = gauss_get_sum (start, end); - - - /* Make sure both results are the same. */ - - if (total1 != total2) - { - printf ("Failure (%d != %d)!\n", total1, total2); - } - else - { - printf ("Success, sum[%d..%d] = %d\n", start, end, total1); - } - - return 0; -} diff --git a/worker/deps/lcov/example/gauss.h b/worker/deps/lcov/example/gauss.h deleted file mode 100644 index 302a4a9803..0000000000 --- a/worker/deps/lcov/example/gauss.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef GAUSS_H -#define GAUSS_H GAUSS_h - -extern int gauss_get_sum (int min, int max); - -#endif /* GAUSS_H */ diff --git a/worker/deps/lcov/example/iterate.h b/worker/deps/lcov/example/iterate.h deleted file mode 100644 index 471327951c..0000000000 --- a/worker/deps/lcov/example/iterate.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef ITERATE_H -#define ITERATE_H ITERATE_H - -extern int iterate_get_sum (int min, int max); - -#endif /* ITERATE_H */ diff --git a/worker/deps/lcov/example/methods/gauss.c b/worker/deps/lcov/example/methods/gauss.c deleted file mode 100644 index 9da3ce5083..0000000000 --- a/worker/deps/lcov/example/methods/gauss.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * methods/gauss.c - * - * Calculate the sum of a given range of integer numbers. - * - * Somewhat of a more subtle way of calculation - and it even has a story - * behind it: - * - * Supposedly during math classes in elementary school, the teacher of - * young mathematician Gauss gave the class an assignment to calculate the - * sum of all natural numbers between 1 and 100, hoping that this task would - * keep the kids occupied for some time. The story goes that Gauss had the - * result ready after only a few minutes. What he had written on his black - * board was something like this: - * - * 1 + 100 = 101 - * 2 + 99 = 101 - * 3 + 98 = 101 - * . - * . - * 100 + 1 = 101 - * - * s = (1/2) * 100 * 101 = 5050 - * - * A more general form of this formula would be - * - * s = (1/2) * (max + min) * (max - min + 1) - * - * which is used in the piece of code below to implement the requested - * function in constant time, i.e. without dependencies on the size of the - * input parameters. - * - */ - -#include "gauss.h" - - -int gauss_get_sum (int min, int max) -{ - /* This algorithm doesn't work well with invalid range specifications - so we're intercepting them here. */ - if (max < min) - { - return 0; - } - - return (int) ((max + min) * (double) (max - min + 1) / 2); -} diff --git a/worker/deps/lcov/example/methods/iterate.c b/worker/deps/lcov/example/methods/iterate.c deleted file mode 100644 index 023d1801c9..0000000000 --- a/worker/deps/lcov/example/methods/iterate.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * methods/iterate.c - * - * Calculate the sum of a given range of integer numbers. - * - * This particular method of implementation works by way of brute force, - * i.e. it iterates over the entire range while adding the numbers to finally - * get the total sum. As a positive side effect, we're able to easily detect - * overflows, i.e. situations in which the sum would exceed the capacity - * of an integer variable. - * - */ - -#include -#include -#include "iterate.h" - - -int iterate_get_sum (int min, int max) -{ - int i, total; - - total = 0; - - /* This is where we loop over each number in the range, including - both the minimum and the maximum number. */ - - for (i = min; i <= max; i++) - { - /* We can detect an overflow by checking whether the new - sum would become negative. */ - - if (total + i < total) - { - printf ("Error: sum too large!\n"); - exit (1); - } - - /* Everything seems to fit into an int, so continue adding. */ - - total += i; - } - - return total; -} diff --git a/worker/deps/lcov/lcovrc b/worker/deps/lcov/lcovrc deleted file mode 100644 index bd4bc3b73a..0000000000 --- a/worker/deps/lcov/lcovrc +++ /dev/null @@ -1,172 +0,0 @@ -# -# /etc/lcovrc - system-wide defaults for LCOV -# -# To change settings for a single user, place a customized copy of this file -# at location ~/.lcovrc -# - -# Specify an external style sheet file (same as --css-file option of genhtml) -#genhtml_css_file = gcov.css - -# Specify coverage rate limits (in %) for classifying file entries -# HI: hi_limit <= rate <= 100 graph color: green -# MED: med_limit <= rate < hi_limit graph color: orange -# LO: 0 <= rate < med_limit graph color: red -genhtml_hi_limit = 90 -genhtml_med_limit = 75 - -# Width of line coverage field in source code view -genhtml_line_field_width = 12 - -# Width of branch coverage field in source code view -genhtml_branch_field_width = 16 - -# Width of overview image (used by --frames option of genhtml) -genhtml_overview_width = 80 - -# Resolution of overview navigation: this number specifies the maximum -# difference in lines between the position a user selected from the overview -# and the position the source code window is scrolled to (used by --frames -# option of genhtml) -genhtml_nav_resolution = 4 - -# Clicking a line in the overview image should show the source code view at -# a position a bit further up so that the requested line is not the first -# line in the window. This number specifies that offset in lines (used by -# --frames option of genhtml) -genhtml_nav_offset = 10 - -# Do not remove unused test descriptions if non-zero (same as -# --keep-descriptions option of genhtml) -genhtml_keep_descriptions = 0 - -# Do not remove prefix from directory names if non-zero (same as --no-prefix -# option of genhtml) -genhtml_no_prefix = 0 - -# Do not create source code view if non-zero (same as --no-source option of -# genhtml) -genhtml_no_source = 0 - -# Replace tabs with number of spaces in source view (same as --num-spaces -# option of genhtml) -genhtml_num_spaces = 8 - -# Highlight lines with converted-only data if non-zero (same as --highlight -# option of genhtml) -genhtml_highlight = 0 - -# Include color legend in HTML output if non-zero (same as --legend option of -# genhtml) -genhtml_legend = 0 - -# Use FILE as HTML prolog for generated pages (same as --html-prolog option of -# genhtml) -#genhtml_html_prolog = FILE - -# Use FILE as HTML epilog for generated pages (same as --html-epilog option of -# genhtml) -#genhtml_html_epilog = FILE - -# Use custom filename extension for pages (same as --html-extension option of -# genhtml) -#genhtml_html_extension = html - -# Compress all generated html files with gzip. -#genhtml_html_gzip = 1 - -# Include sorted overview pages (can be disabled by the --no-sort option of -# genhtml) -genhtml_sort = 1 - -# Include function coverage data display (can be disabled by the -# --no-func-coverage option of genhtml) -#genhtml_function_coverage = 1 - -# Include branch coverage data display (can be disabled by the -# --no-branch-coverage option of genhtml) -#genhtml_branch_coverage = 1 - -# Specify the character set of all generated HTML pages -genhtml_charset=UTF-8 - -# Allow HTML markup in test case description text if non-zero -genhtml_desc_html=0 - -# Specify the precision for coverage rates -#genhtml_precision=1 - -# Show missed counts instead of hit counts -#genhtml_missed=1 - -# Demangle C++ symbols -#genhtml_demangle_cpp=1 - -# Location of the gcov tool (same as --gcov-info option of geninfo) -#geninfo_gcov_tool = gcov - -# Adjust test names to include operating system information if non-zero -#geninfo_adjust_testname = 0 - -# Calculate checksum for each source code line if non-zero (same as --checksum -# option of geninfo if non-zero, same as --no-checksum if zero) -#geninfo_checksum = 1 - -# Specify whether to capture coverage data for external source files (can -# be overridden by the --external and --no-external options of geninfo/lcov) -#geninfo_external = 1 - -# Enable libtool compatibility mode if non-zero (same as --compat-libtool option -# of geninfo if non-zero, same as --no-compat-libtool if zero) -#geninfo_compat_libtool = 0 - -# Use gcov's --all-blocks option if non-zero -#geninfo_gcov_all_blocks = 1 - -# Specify compatiblity modes (same as --compat option of geninfo). -#geninfo_compat = libtool=on, hammer=auto, split_crc=auto - -# Adjust path to source files by removing or changing path components that -# match the specified pattern (Perl regular expression format) -#geninfo_adjust_src_path = /tmp/build => /usr/src - -# Specify if geninfo should try to automatically determine the base-directory -# when collecting coverage data. -geninfo_auto_base = 1 - -# Use gcov intermediate format? Valid values are 0, 1, auto -geninfo_intermediate = auto - -# Directory containing gcov kernel files -# lcov_gcov_dir = /proc/gcov - -# Location of the insmod tool -lcov_insmod_tool = /sbin/insmod - -# Location of the modprobe tool -lcov_modprobe_tool = /sbin/modprobe - -# Location of the rmmod tool -lcov_rmmod_tool = /sbin/rmmod - -# Location for temporary directories -lcov_tmp_dir = /tmp - -# Show full paths during list operation if non-zero (same as --list-full-path -# option of lcov) -lcov_list_full_path = 0 - -# Specify the maximum width for list output. This value is ignored when -# lcov_list_full_path is non-zero. -lcov_list_width = 80 - -# Specify the maximum percentage of file names which may be truncated when -# choosing a directory prefix in list output. This value is ignored when -# lcov_list_full_path is non-zero. -lcov_list_truncate_max = 20 - -# Specify if function coverage data should be collected and processed. -lcov_function_coverage = 1 - -# Specify if branch coverage data should be collected and processed. -lcov_branch_coverage = 0 diff --git a/worker/deps/lcov/man/gendesc.1 b/worker/deps/lcov/man/gendesc.1 deleted file mode 100644 index 806d1f5e45..0000000000 --- a/worker/deps/lcov/man/gendesc.1 +++ /dev/null @@ -1,78 +0,0 @@ -.TH gendesc 1 "LCOV 1.14" 2016\-12\-19 "User Manuals" -.SH NAME -gendesc \- Generate a test case description file -.SH SYNOPSIS -.B gendesc -.RB [ \-h | \-\-help ] -.RB [ \-v | \-\-version ] -.RS 8 -.br -.RB [ \-o | \-\-output\-filename -.IR filename ] -.br -.I inputfile -.SH DESCRIPTION -Convert plain text test case descriptions into a format as understood by -.BR genhtml . -.I inputfile -needs to observe the following format: - -For each test case: -.IP " \-" -one line containing the test case name beginning at the start of the line -.RE -.IP " \-" -one or more lines containing the test case description indented with at -least one whitespace character (tab or space) -.RE - -.B Example input file: - -test01 -.RS -An example test case description. -.br -Description continued -.RE - -test42 -.RS -Supposedly the answer to most of your questions -.RE - -Note: valid test names can consist of letters, decimal digits and the -underscore character ('_'). -.SH OPTIONS -.B \-h -.br -.B \-\-help -.RS -Print a short help text, then exit. -.RE - -.B \-v -.br -.B \-\-version -.RS -Print version number, then exit. -.RE - - -.BI "\-o " filename -.br -.BI "\-\-output\-filename " filename -.RS -Write description data to -.IR filename . - -By default, output is written to STDOUT. -.RE -.SH AUTHOR -Peter Oberparleiter - -.SH SEE ALSO -.BR lcov (1), -.BR genhtml (1), -.BR geninfo (1), -.BR genpng (1), -.BR gcov (1) diff --git a/worker/deps/lcov/man/genhtml.1 b/worker/deps/lcov/man/genhtml.1 deleted file mode 100644 index 6f13be302e..0000000000 --- a/worker/deps/lcov/man/genhtml.1 +++ /dev/null @@ -1,601 +0,0 @@ -.TH genhtml 1 "LCOV 1.14" 2018\-01\-30 "User Manuals" -.SH NAME -genhtml \- Generate HTML view from LCOV coverage data files -.SH SYNOPSIS -.B genhtml -.RB [ \-h | \-\-help ] -.RB [ \-v | \-\-version ] -.RS 8 -.br -.RB [ \-q | \-\-quiet ] -.RB [ \-s | \-\-show\-details ] -.RB [ \-f | \-\-frames ] -.br -.RB [ \-b | \-\-baseline\-file ] -.IR baseline\-file -.br -.RB [ \-o | \-\-output\-directory -.IR output\-directory ] -.br -.RB [ \-t | \-\-title -.IR title ] -.br -.RB [ \-d | \-\-description\-file -.IR description\-file ] -.br -.RB [ \-k | \-\-keep\-descriptions ] -.RB [ \-c | \-\-css\-file -.IR css\-file ] -.br -.RB [ \-p | \-\-prefix -.IR prefix ] -.RB [ \-\-no\-prefix ] -.br -.RB [ \-\-no\-source ] -.RB [ \-\-num\-spaces -.IR num ] -.RB [ \-\-highlight ] -.br -.RB [ \-\-legend ] -.RB [ \-\-html\-prolog -.IR prolog\-file ] -.br -.RB [ \-\-html\-epilog -.IR epilog\-file ] -.RB [ \-\-html\-extension -.IR extension ] -.br -.RB [ \-\-html\-gzip ] -.RB [ \-\-sort ] -.RB [ \-\-no\-sort ] -.br -.RB [ \-\-function\-coverage ] -.RB [ \-\-no\-function\-coverage ] -.br -.RB [ \-\-branch\-coverage ] -.RB [ \-\-no\-branch\-coverage ] -.br -.RB [ \-\-demangle\-cpp ] -.RB [ \-\-ignore\-errors -.IR errors ] -.br -.RB [ \-\-config\-file -.IR config\-file ] -.RB [ \-\-rc -.IR keyword = value ] -.br -.RB [ \-\-precision -.IR num ] -.RB [ \-\-missed ] -.br -.IR tracefile(s) -.RE -.SH DESCRIPTION -Create an HTML view of coverage data found in -.IR tracefile . -Note that -.I tracefile -may also be a list of filenames. - -HTML output files are created in the current working directory unless the -\-\-output\-directory option is used. If -.I tracefile -ends with ".gz", it is assumed to be GZIP\-compressed and the gunzip tool -will be used to decompress it transparently. - -Note that all source code files have to be present and readable at the -exact file system location they were compiled. - -Use option -.I \--css\-file -to modify layout and colors of the generated HTML output. Files are -marked in different colors depending on the associated coverage rate. By -default, the coverage limits for low, medium and high coverage are set to -0\-75%, 75\-90% and 90\-100% percent respectively. To change these -values, use configuration file options -.IR genhtml_hi_limit " and " genhtml_med_limit . - -Also note that when displaying percentages, 0% and 100% are only printed when -the values are exactly 0% and 100% respectively. Other values which would -conventionally be rounded to 0% or 100% are instead printed as nearest -non-boundary value. This behavior is in accordance with that of the -.BR gcov (1) -tool. - -.SH OPTIONS -.B \-h -.br -.B \-\-help -.RS -Print a short help text, then exit. - -.RE -.B \-v -.br -.B \-\-version -.RS -Print version number, then exit. - -.RE -.B \-q -.br -.B \-\-quiet -.RS -Do not print progress messages. - -Suppresses all informational progress output. When this switch is enabled, -only error or warning messages are printed. - -.RE -.B \-f -.br -.B \-\-frames -.RS -Use HTML frames for source code view. - -If enabled, a frameset is created for each source code file, providing -an overview of the source code as a "clickable" image. Note that this -option will slow down output creation noticeably because each source -code character has to be inspected once. Note also that the GD.pm Perl -module has to be installed for this option to work (it may be obtained -from http://www.cpan.org). - -.RE -.B \-s -.br -.B \-\-show\-details -.RS -Generate detailed directory view. - -When this option is enabled, -.B genhtml -generates two versions of each -file view. One containing the standard information plus a link to a -"detailed" version. The latter additionally contains information about -which test case covered how many lines of each source file. - -.RE -.BI "\-b " baseline\-file -.br -.BI "\-\-baseline\-file " baseline\-file -.RS -Use data in -.I baseline\-file -as coverage baseline. - -The tracefile specified by -.I baseline\-file -is read and all counts found in the original -.I tracefile -are decremented by the corresponding counts in -.I baseline\-file -before creating any output. - -Note that when a count for a particular line in -.I baseline\-file -is greater than the count in the -.IR tracefile , -the result is zero. - -.RE -.BI "\-o " output\-directory -.br -.BI "\-\-output\-directory " output\-directory -.RS -Create files in -.I output\-directory. - -Use this option to tell -.B genhtml -to write the resulting files to a directory other than -the current one. If -.I output\-directory -does not exist, it will be created. - -It is advisable to use this option since depending on the -project size, a lot of files and subdirectories may be created. - -.RE -.BI "\-t " title -.br -.BI "\-\-title " title -.RS -Display -.I title -in header of all pages. - -.I title -is written to the header portion of each generated HTML page to -identify the context in which a particular output -was created. By default this is the name of the tracefile. - -.RE -.BI "\-d " description\-file -.br -.BI "\-\-description\-file " description\-file -.RS -Read test case descriptions from -.IR description\-file . - -All test case descriptions found in -.I description\-file -and referenced in the input data file are read and written to an extra page -which is then incorporated into the HTML output. - -The file format of -.IR "description\-file " is: - -for each test case: -.RS -TN: -.br -TD: - -.RE - -Valid test case names can consist of letters, numbers and the underscore -character ('_'). -.RE -.B \-k -.br -.B \-\-keep\-descriptions -.RS -Do not remove unused test descriptions. - -Keep descriptions found in the description file even if the coverage data -indicates that the associated test case did not cover any lines of code. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_keep_descriptions . - -.RE -.BI "\-c " css\-file -.br -.BI "\-\-css\-file " css\-file -.RS -Use external style sheet file -.IR css\-file . - -Using this option, an extra .css file may be specified which will replace -the default one. This may be helpful if the default colors make your eyes want -to jump out of their sockets :) - -This option can also be configured permanently using the configuration file -option -.IR genhtml_css_file . - -.RE -.BI "\-p " prefix -.br -.BI "\-\-prefix " prefix -.RS -Remove -.I prefix -from all directory names. - -Because lists containing long filenames are difficult to read, there is a -mechanism implemented that will automatically try to shorten all directory -names on the overview page beginning with a common prefix. By default, -this is done using an algorithm that tries to find the prefix which, when -applied, will minimize the resulting sum of characters of all directory -names. - -Use this option to specify the prefix to be removed by yourself. - -.RE -.B \-\-no\-prefix -.RS -Do not remove prefix from directory names. - -This switch will completely disable the prefix mechanism described in the -previous section. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_no_prefix . - -.RE -.B \-\-no\-source -.RS -Do not create source code view. - -Use this switch if you don't want to get a source code view for each file. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_no_source . - -.RE -.BI "\-\-num\-spaces " spaces -.RS -Replace tabs in source view with -.I num -spaces. - -Default value is 8. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_num_spaces . - -.RE -.B \-\-highlight -.RS -Highlight lines with converted\-only coverage data. - -Use this option in conjunction with the \-\-diff option of -.B lcov -to highlight those lines which were only covered in data sets which were -converted from previous source code versions. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_highlight . - -.RE -.B \-\-legend -.RS -Include color legend in HTML output. - -Use this option to include a legend explaining the meaning of color coding -in the resulting HTML output. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_legend . - -.RE -.BI "\-\-html\-prolog " prolog\-file -.RS -Read customized HTML prolog from -.IR prolog\-file . - -Use this option to replace the default HTML prolog (the initial part of the -HTML source code leading up to and including the tag) with the contents -of -.IR prolog\-file . -Within the prolog text, the following words will be replaced when a page is generated: - -.B "@pagetitle@" -.br -The title of the page. - -.B "@basedir@" -.br -A relative path leading to the base directory (e.g. for locating css\-files). - -This option can also be configured permanently using the configuration file -option -.IR genhtml_html_prolog . - -.RE -.BI "\-\-html\-epilog " epilog\-file -.RS -Read customized HTML epilog from -.IR epilog\-file . - -Use this option to replace the default HTML epilog (the final part of the HTML -source including ) with the contents of -.IR epilog\-file . - -Within the epilog text, the following words will be replaced when a page is generated: - -.B "@basedir@" -.br -A relative path leading to the base directory (e.g. for locating css\-files). - -This option can also be configured permanently using the configuration file -option -.IR genhtml_html_epilog . - -.RE -.BI "\-\-html\-extension " extension -.RS -Use customized filename extension for generated HTML pages. - -This option is useful in situations where different filename extensions -are required to render the resulting pages correctly (e.g. php). Note that -a '.' will be inserted between the filename and the extension specified by -this option. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_html_extension . -.RE - -.B \-\-html\-gzip -.RS -Compress all generated html files with gzip and add a .htaccess file specifying -gzip\-encoding in the root output directory. - -Use this option if you want to save space on your webserver. Requires a -webserver with .htaccess support and a browser with support for gzip -compressed html. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_html_gzip . - -.RE -.B \-\-sort -.br -.B \-\-no\-sort -.RS -Specify whether to include sorted views of file and directory overviews. - -Use \-\-sort to include sorted views or \-\-no\-sort to not include them. -Sorted views are -.B enabled -by default. - -When sorted views are enabled, each overview page will contain links to -views of that page sorted by coverage rate. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_sort . - -.RE -.B \-\-function\-coverage -.br -.B \-\-no\-function\-coverage -.RS -Specify whether to display function coverage summaries in HTML output. - -Use \-\-function\-coverage to enable function coverage summaries or -\-\-no\-function\-coverage to disable it. Function coverage summaries are -.B enabled -by default - -When function coverage summaries are enabled, each overview page will contain -the number of functions found and hit per file or directory, together with -the resulting coverage rate. In addition, each source code view will contain -a link to a page which lists all functions found in that file plus the -respective call count for those functions. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_function_coverage . - -.RE -.B \-\-branch\-coverage -.br -.B \-\-no\-branch\-coverage -.RS -Specify whether to display branch coverage data in HTML output. - -Use \-\-branch\-coverage to enable branch coverage display or -\-\-no\-branch\-coverage to disable it. Branch coverage data display is -.B enabled -by default - -When branch coverage display is enabled, each overview page will contain -the number of branches found and hit per file or directory, together with -the resulting coverage rate. In addition, each source code view will contain -an extra column which lists all branches of a line with indications of -whether the branch was taken or not. Branches are shown in the following format: - - ' + ': Branch was taken at least once -.br - ' - ': Branch was not taken -.br - ' # ': The basic block containing the branch was never executed -.br - -Note that it might not always be possible to relate branches to the -corresponding source code statements: during compilation, GCC might shuffle -branches around or eliminate some of them to generate better code. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_branch_coverage . - -.RE -.B \-\-demangle\-cpp -.RS -Specify whether to demangle C++ function names. - -Use this option if you want to convert C++ internal function names to -human readable format for display on the HTML function overview page. -This option requires that the c++filt tool is installed (see -.BR c++filt (1)). - -.RE -.B \-\-ignore\-errors -.I errors -.br -.RS -Specify a list of errors after which to continue processing. - -Use this option to specify a list of one or more classes of errors after which -geninfo should continue processing instead of aborting. - -.I errors -can be a comma\-separated list of the following keywords: - -.B source: -the source code file for a data set could not be found. -.RE - -.B \-\-config\-file -.I config\-file -.br -.RS -Specify a configuration file to use. - -When this option is specified, neither the system\-wide configuration file -/etc/lcovrc, nor the per\-user configuration file ~/.lcovrc is read. - -This option may be useful when there is a need to run several -instances of -.B genhtml -with different configuration file options in parallel. -.RE - -.B \-\-rc -.IR keyword = value -.br -.RS -Override a configuration directive. - -Use this option to specify a -.IR keyword = value -statement which overrides the corresponding configuration statement in -the lcovrc configuration file. You can specify this option more than once -to override multiple configuration statements. -See -.BR lcovrc (5) -for a list of available keywords and their meaning. -.RE - -.BI "\-\-precision " num -.RS -Show coverage rates with -.I num -number of digits after the decimal-point. - -Default value is 1. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_precision . -.RE - -.B \-\-missed -.RS -Show counts of missed lines, functions, or branches - -Use this option to change overview pages to show the count of lines, functions, -or branches that were not hit. These counts are represented by negative numbers. - -When specified together with \-\-sort, file and directory views will be sorted -by missed counts. - -This option can also be configured permanently using the configuration file -option -.IR genhtml_missed . -.RE - -.SH FILES - -.I /etc/lcovrc -.RS -The system\-wide configuration file. -.RE - -.I ~/.lcovrc -.RS -The per\-user configuration file. -.RE - -.SH AUTHOR -Peter Oberparleiter - -.SH SEE ALSO -.BR lcov (1), -.BR lcovrc (5), -.BR geninfo (1), -.BR genpng (1), -.BR gendesc (1), -.BR gcov (1) diff --git a/worker/deps/lcov/man/geninfo.1 b/worker/deps/lcov/man/geninfo.1 deleted file mode 100644 index 1878575b3b..0000000000 --- a/worker/deps/lcov/man/geninfo.1 +++ /dev/null @@ -1,578 +0,0 @@ -.TH geninfo 1 "LCOV 1.14" 2017\-10\-10 "User Manuals" -.SH NAME -geninfo \- Generate tracefiles from .da files -.SH SYNOPSIS -.B geninfo -.RB [ \-h | \-\-help ] -.RB [ \-v | \-\-version ] -.RB [ \-q | \-\-quiet ] -.br -.RS 8 -.RB [ \-i | \-\-initial ] -.RB [ \-t | \-\-test\-name -.IR test\-name ] -.br -.RB [ \-o | \-\-output\-filename -.IR filename ] -.RB [ \-f | \-\-follow ] -.br -.RB [ \-b | \-\-base\-directory -.IR directory ] -.br -.RB [ \-\-checksum ] -.RB [ \-\-no\-checksum ] -.br -.RB [ \-\-compat\-libtool ] -.RB [ \-\-no\-compat\-libtool ] -.br -.RB [ \-\-gcov\-tool -.IR tool ] -.RB [ \-\-ignore\-errors -.IR errors ] -.br -.RB [ \-\-no\-recursion ] -.I directory -.RB [ \-\-external ] -.RB [ \-\-no\-external ] -.br -.RB [ \-\-config\-file -.IR config\-file ] -.RB [ \-\-no\-markers ] -.br -.RB [ \-\-derive\-func\-data ] -.RB [ \-\-compat -.IR mode =on|off|auto] -.br -.RB [ \-\-rc -.IR keyword = value ] -.br -.RB [ \-\-include -.IR pattern ] -.RB [ \-\-exclude -.IR pattern ] -.RE -.SH DESCRIPTION -.B geninfo -converts all GCOV coverage data files found in -.I directory -into tracefiles, which the -.B genhtml -tool can convert to HTML output. - -Unless the \-\-output\-filename option is specified, -.B geninfo -writes its -output to one file per .da file, the name of which is generated by simply -appending ".info" to the respective .da file name. - -Note that the current user needs write access to both -.I directory -as well as to the original source code location. This is necessary because -some temporary files have to be created there during the conversion process. - -Note also that -.B geninfo -is called from within -.BR lcov , -so that there is usually no need to call it directly. - -.B Exclusion markers - -To exclude specific lines of code from a tracefile, you can add exclusion -markers to the source code. Additionally you can exclude specific branches from -branch coverage without excluding the involved lines from line and function -coverage. Exclusion markers are keywords which can for example be added in the -form of a comment. -See -.BR lcovrc (5) -how to override some of them. - -The following markers are recognized by geninfo: - -LCOV_EXCL_LINE -.RS -Lines containing this marker will be excluded. -.br -.RE -LCOV_EXCL_START -.RS -Marks the beginning of an excluded section. The current line is part of this -section. -.br -.RE -LCOV_EXCL_STOP -.RS -Marks the end of an excluded section. The current line not part of this -section. -.RE -.br -LCOV_EXCL_BR_LINE -.RS -Lines containing this marker will be excluded from branch coverage. -.br -.RE -LCOV_EXCL_BR_START -.RS -Marks the beginning of a section which is excluded from branch coverage. The -current line is part of this section. -.br -.RE -LCOV_EXCL_BR_STOP -.RS -Marks the end of a section which is excluded from branch coverage. The current -line not part of this section. -.RE -.br - -.SH OPTIONS - -.B \-b -.I directory -.br -.B \-\-base\-directory -.I directory -.br -.RS -.RI "Use " directory -as base directory for relative paths. - -Use this option to specify the base directory of a build\-environment -when geninfo produces error messages like: - -.RS -ERROR: could not read source file /home/user/project/subdir1/subdir2/subdir1/subdir2/file.c -.RE - -In this example, use /home/user/project as base directory. - -This option is required when using geninfo on projects built with libtool or -similar build environments that work with a base directory, i.e. environments, -where the current working directory when invoking the compiler is not the same -directory in which the source code file is located. - -Note that this option will not work in environments where multiple base -directories are used. In that case use configuration file setting -.B geninfo_auto_base=1 -(see -.BR lcovrc (5)). -.RE - -.B \-\-checksum -.br -.B \-\-no\-checksum -.br -.RS -Specify whether to generate checksum data when writing tracefiles. - -Use \-\-checksum to enable checksum generation or \-\-no\-checksum to -disable it. Checksum generation is -.B disabled -by default. - -When checksum generation is enabled, a checksum will be generated for each -source code line and stored along with the coverage data. This checksum will -be used to prevent attempts to combine coverage data from different source -code versions. - -If you don't work with different source code versions, disable this option -to speed up coverage data processing and to reduce the size of tracefiles. -.RE - -.B \-\-compat -.IR mode = value [, mode = value ,...] -.br -.RS -Set compatibility mode. - -Use \-\-compat to specify that geninfo should enable one or more compatibility -modes when capturing coverage data. You can provide a comma-separated list -of mode=value pairs to specify the values for multiple modes. - -Valid -.I values -are: - -.B on -.RS -Enable compatibility mode. -.RE -.B off -.RS -Disable compatibility mode. -.RE -.B auto -.RS -Apply auto-detection to determine if compatibility mode is required. Note that -auto-detection is not available for all compatibility modes. -.RE - -If no value is specified, 'on' is assumed as default value. - -Valid -.I modes -are: - -.B libtool -.RS -Enable this mode if you are capturing coverage data for a project that -was built using the libtool mechanism. See also -\-\-compat\-libtool. - -The default value for this setting is 'on'. - -.RE -.B hammer -.RS -Enable this mode if you are capturing coverage data for a project that -was built using a version of GCC 3.3 that contains a modification -(hammer patch) of later GCC versions. You can identify a modified GCC 3.3 -by checking the build directory of your project for files ending in the -extension '.bbg'. Unmodified versions of GCC 3.3 name these files '.bb'. - -The default value for this setting is 'auto'. - -.RE -.B split_crc -.RS -Enable this mode if you are capturing coverage data for a project that -was built using a version of GCC 4.6 that contains a modification -(split function checksums) of later GCC versions. Typical error messages -when running geninfo on coverage data produced by such GCC versions are -\'out of memory' and 'reached unexpected end of file'. - -The default value for this setting is 'auto' -.RE - -.RE - -.B \-\-compat\-libtool -.br -.B \-\-no\-compat\-libtool -.br -.RS -Specify whether to enable libtool compatibility mode. - -Use \-\-compat\-libtool to enable libtool compatibility mode or \-\-no\-compat\-libtool -to disable it. The libtool compatibility mode is -.B enabled -by default. - -When libtool compatibility mode is enabled, geninfo will assume that the source -code relating to a .da file located in a directory named ".libs" can be -found in its parent directory. - -If you have directories named ".libs" in your build environment but don't use -libtool, disable this option to prevent problems when capturing coverage data. -.RE - -.B \-\-config\-file -.I config\-file -.br -.RS -Specify a configuration file to use. - -When this option is specified, neither the system\-wide configuration file -/etc/lcovrc, nor the per\-user configuration file ~/.lcovrc is read. - -This option may be useful when there is a need to run several -instances of -.B geninfo -with different configuration file options in parallel. -.RE - -.B \-\-derive\-func\-data -.br -.RS -Calculate function coverage data from line coverage data. - -Use this option to collect function coverage data, even if the version of the -gcov tool installed on the test system does not provide this data. lcov will -instead derive function coverage data from line coverage data and -information about which lines belong to a function. -.RE - -.B \-\-exclude -.I pattern -.br -.RS -Exclude source files matching -.IR pattern . - -Use this switch if you want to exclude coverage data for a particular set -of source files matching any of the given patterns. Multiple patterns can be -specified by using multiple -.B --exclude -command line switches. The -.I patterns -will be interpreted as shell wildcard patterns (note that they may need to be -escaped accordingly to prevent the shell from expanding them first). - -Can be combined with the -.B --include -command line switch. If a given file matches both the include pattern and the -exclude pattern, the exclude pattern will take precedence. -.RE - -.B \-\-external -.br -.B \-\-no\-external -.br -.RS -Specify whether to capture coverage data for external source files. - -External source files are files which are not located in one of the directories -specified by \-\-directory or \-\-base\-directory. Use \-\-external to include -external source files while capturing coverage data or \-\-no\-external to -ignore this data. - -Data for external source files is -.B included -by default. -.RE - -.B \-f -.br -.B \-\-follow -.RS -Follow links when searching .da files. -.RE - -.B \-\-gcov\-tool -.I tool -.br -.RS -Specify the location of the gcov tool. -.RE - -.B \-h -.br -.B \-\-help -.RS -Print a short help text, then exit. -.RE - -.B \-\-include -.I pattern -.br -.RS -Include source files matching -.IR pattern . - -Use this switch if you want to include coverage data for only a particular set -of source files matching any of the given patterns. Multiple patterns can be -specified by using multiple -.B --include -command line switches. The -.I patterns -will be interpreted as shell wildcard patterns (note that they may need to be -escaped accordingly to prevent the shell from expanding them first). -.RE - -.B \-\-ignore\-errors -.I errors -.br -.RS -Specify a list of errors after which to continue processing. - -Use this option to specify a list of one or more classes of errors after which -geninfo should continue processing instead of aborting. - -.I errors -can be a comma\-separated list of the following keywords: - -.B gcov: -the gcov tool returned with a non\-zero return code. - -.B source: -the source code file for a data set could not be found. -.RE - -.B \-i -.br -.B \-\-initial -.RS -Capture initial zero coverage data. - -Run geninfo with this option on the directories containing .bb, .bbg or .gcno -files before running any test case. The result is a "baseline" coverage data -file that contains zero coverage for every instrumented line and function. -Combine this data file (using lcov \-a) with coverage data files captured -after a test run to ensure that the percentage of total lines covered is -correct even when not all object code files were loaded during the test. - -Note: currently, the \-\-initial option does not generate branch coverage -information. -.RE - -.B \-\-no\-markers -.br -.RS -Use this option if you want to get coverage data without regard to exclusion -markers in the source code file. -.RE - -.B \-\-no\-recursion -.br -.RS -Use this option if you want to get coverage data for the specified directory -only without processing subdirectories. -.RE - -.BI "\-o " output\-filename -.br -.BI "\-\-output\-filename " output\-filename -.RS -Write all data to -.IR output\-filename . - -If you want to have all data written to a single file (for easier -handling), use this option to specify the respective filename. By default, -one tracefile will be created for each processed .da file. -.RE - -.B \-q -.br -.B \-\-quiet -.RS -Do not print progress messages. - -Suppresses all informational progress output. When this switch is enabled, -only error or warning messages are printed. -.RE - -.B \-\-rc -.IR keyword = value -.br -.RS -Override a configuration directive. - -Use this option to specify a -.IR keyword = value -statement which overrides the corresponding configuration statement in -the lcovrc configuration file. You can specify this option more than once -to override multiple configuration statements. -See -.BR lcovrc (5) -for a list of available keywords and their meaning. -.RE - -.BI "\-t " testname -.br -.BI "\-\-test\-name " testname -.RS -Use test case name -.I testname -for resulting data. Valid test case names can consist of letters, decimal -digits and the underscore character ('_'). - -This proves useful when data from several test cases is merged (i.e. by -simply concatenating the respective tracefiles) in which case a test -name can be used to differentiate between data from each test case. -.RE - -.B \-v -.br -.B \-\-version -.RS -Print version number, then exit. -.RE - - -.SH FILES - -.I /etc/lcovrc -.RS -The system\-wide configuration file. -.RE - -.I ~/.lcovrc -.RS -The per\-user configuration file. -.RE - -Following is a quick description of the tracefile format as used by -.BR genhtml ", " geninfo " and " lcov . - -A tracefile is made up of several human\-readable lines of text, -divided into sections. If available, a tracefile begins with the -.I testname -which is stored in the following format: - - TN: - -For each source file referenced in the .da file, there is a section containing -filename and coverage data: - - SF: - -Following is a list of line numbers for each function name found in the -source file: - - FN:, - -Next, there is a list of execution counts for each instrumented function: - - FNDA:, - -This list is followed by two lines containing the number of functions found -and hit: - - FNF: - FNH: - -Branch coverage information is stored which one line per branch: - - BRDA:,,, - -Block number and branch number are gcc internal IDs for the branch. Taken is -either '-' if the basic block containing the branch was never executed or -a number indicating how often that branch was taken. - -Branch coverage summaries are stored in two lines: - - BRF: - BRH: - -Then there is a list of execution counts for each instrumented line -(i.e. a line which resulted in executable code): - - DA:,[,] - -Note that there may be an optional checksum present for each instrumented -line. The current -.B geninfo -implementation uses an MD5 hash as checksumming algorithm. - -At the end of a section, there is a summary about how many lines -were found and how many were actually instrumented: - - LH: - LF: - -Each sections ends with: - - end_of_record - -In addition to the main source code file there are sections for all -#included files which also contain executable code. - -Note that the absolute path of a source file is generated by interpreting -the contents of the respective .bb file (see -.BR "gcov " (1) -for more information on this file type). Relative filenames are prefixed -with the directory in which the .bb file is found. - -Note also that symbolic links to the .bb file will be resolved so that the -actual file path is used instead of the path to a link. This approach is -necessary for the mechanism to work with the /proc/gcov files. - -.SH AUTHOR -Peter Oberparleiter - -.SH SEE ALSO -.BR lcov (1), -.BR lcovrc (5), -.BR genhtml (1), -.BR genpng (1), -.BR gendesc (1), -.BR gcov (1) diff --git a/worker/deps/lcov/man/genpng.1 b/worker/deps/lcov/man/genpng.1 deleted file mode 100644 index 376f2646aa..0000000000 --- a/worker/deps/lcov/man/genpng.1 +++ /dev/null @@ -1,101 +0,0 @@ -.TH genpng 1 "LCOV 1.14" 2016\-12\-19 "User Manuals" -.SH NAME -genpng \- Generate an overview image from a source file -.SH SYNOPSIS -.B genpng -.RB [ \-h | \-\-help ] -.RB [ \-v | \-\-version ] -.RS 7 -.br -.RB [ \-t | \-\-tab\-size -.IR tabsize ] -.RB [ \-w | \-\-width -.IR width ] -.br -.RB [ \-o | \-\-output\-filename -.IR output\-filename ] -.br -.IR source\-file -.SH DESCRIPTION -.B genpng -creates an overview image for a given source code file of either -plain text or .gcov file format. - -Note that the -.I GD.pm -Perl module has to be installed for this script to work -(it may be obtained from -.IR http://www.cpan.org ). - -Note also that -.B genpng -is called from within -.B genhtml -so that there is usually no need to call it directly. - -.SH OPTIONS -.B \-h -.br -.B \-\-help -.RS -Print a short help text, then exit. -.RE - -.B \-v -.br -.B \-\-version -.RS -Print version number, then exit. -.RE - -.BI "\-t " tab\-size -.br -.BI "\-\-tab\-size " tab\-size -.RS -Use -.I tab\-size -spaces in place of tab. - -All occurrences of tabulator signs in the source code file will be replaced -by the number of spaces defined by -.I tab\-size -(default is 4). -.RE - -.BI "\-w " width -.br -.BI "\-\-width " width -.RS -Set width of output image to -.I width -pixel. - -The resulting image will be exactly -.I width -pixel wide (default is 80). - -Note that source code lines which are longer than -.I width -will be truncated. -.RE - - -.BI "\-o " filename -.br -.BI "\-\-output\-filename " filename -.RS -Write image to -.IR filename . - -Specify a name for the resulting image file (default is -.IR source\-file .png). -.RE -.SH AUTHOR -Peter Oberparleiter - -.SH SEE ALSO -.BR lcov (1), -.BR genhtml (1), -.BR geninfo (1), -.BR gendesc (1), -.BR gcov (1) diff --git a/worker/deps/lcov/man/lcov.1 b/worker/deps/lcov/man/lcov.1 deleted file mode 100644 index 2bf91bbf83..0000000000 --- a/worker/deps/lcov/man/lcov.1 +++ /dev/null @@ -1,930 +0,0 @@ -.TH lcov 1 "LCOV 1.14" 2017\-10\-10 "User Manuals" -.SH NAME -lcov \- a graphical GCOV front\-end -.SH SYNOPSIS -.B lcov -.BR \-c | \-\-capture -.RS 5 -.br -.RB [ \-d | \-\-directory -.IR directory ] -.RB [ \-k | \-\-kernel\-directory -.IR directory ] -.br -.RB [ \-o | \-\-output\-file -.IR tracefile ] -.RB [ \-t | \-\-test\-name -.IR testname ] -.br -.RB [ \-b | \-\-base\-directory -.IR directory ] -.RB [ \-i | \-\-initial ] -.RB [ \-\-gcov\-tool -.IR tool ] -.br -.RB [ \-\-checksum ] -.RB [ \-\-no\-checksum ] -.RB [ \-\-no\-recursion ] -.RB [ \-f | \-\-follow ] -.br -.RB [ \-\-compat\-libtool ] -.RB [ \-\-no\-compat\-libtool ] -.RB [ \-\-ignore\-errors -.IR errors ] -.br -.RB [ \-\-to\-package -.IR package ] -.RB [ \-\-from\-package -.IR package ] -.RB [ \-q | \-\-quiet ] -.br -.RB [ \-\-no\-markers ] -.RB [ \-\-external ] -.RB [ \-\-no\-external ] -.br -.RB [ \-\-config\-file -.IR config\-file ] -.RB [ \-\-rc -.IR keyword = value ] -.br -.RB [ \-\-compat -.IR mode =on|off|auto] -.br -.RB [ \-\-include -.IR pattern ] -.RB [ \-\-exclude -.IR pattern ] -.br -.RE - -.B lcov -.BR \-z | \-\-zerocounters -.RS 5 -.br -.RB [ \-d | \-\-directory -.IR directory ] -.RB [ \-\-no\-recursion ] -.RB [ \-f | \-\-follow ] -.br -.RB [ \-q | \-\-quiet ] -.br -.RE - -.B lcov -.BR \-l | \-\-list -.I tracefile -.RS 5 -.br -.RB [ \-q | \-\-quiet ] -.RB [ \-\-list\-full\-path ] -.RB [ \-\-no\-list\-full\-path ] -.br -.RB [ \-\-config\-file -.IR config\-file ] -.RB [ \-\-rc -.IR keyword = value ] -.br -.RE - -.B lcov -.BR \-a | \-\-add\-tracefile -.I tracefile -.RS 5 -.br -.RB [ \-o | \-\-output\-file -.IR tracefile ] -.RB [ \-\-checksum ] -.RB [ \-\-no\-checksum ] -.br -.RB [ \-q | \-\-quiet ] -.RB [ \-\-config\-file -.IR config\-file ] -.RB [ \-\-rc -.IR keyword = value ] -.br -.RE - -.B lcov -.BR \-e | \-\-extract -.I tracefile pattern -.RS 5 -.br -.RB [ \-o | \-\-output\-file -.IR tracefile ] -.RB [ \-\-checksum ] -.RB [ \-\-no\-checksum ] -.br -.RB [ \-q | \-\-quiet ] -.RB [ \-\-config\-file -.IR config\-file ] -.RB [ \-\-rc -.IR keyword = value ] -.br -.RE - -.B lcov -.BR \-r | \-\-remove -.I tracefile pattern -.RS 5 -.br -.RB [ \-o | \-\-output\-file -.IR tracefile ] -.RB [ \-\-checksum ] -.RB [ \-\-no\-checksum ] -.br -.RB [ \-q | \-\-quiet ] -.RB [ \-\-config\-file -.IR config\-file ] -.RB [ \-\-rc -.IR keyword = value ] -.br -.RE - -.B lcov -.BR \-\-diff -.IR "tracefile diff" -.RS 5 -.br -.RB [ \-o | \-\-output\-file -.IR tracefile ] -.RB [ \-\-checksum ] -.RB [ \-\-no\-checksum ] -.br -.RB [ \-\-convert\-filenames ] -.RB [ \-\-strip -.IR depth ] -.RB [ \-\-path -.IR path ] -.RB [ \-q | \-\-quiet ] -.br -.RB [ \-\-config\-file -.IR config\-file ] -.RB [ \-\-rc -.IR keyword = value ] -.br -.RE - -.B lcov -.BR \-\-summary -.I tracefile -.RS 5 -.br -.RB [ \-q | \-\-quiet ] -.br -.RE - -.B lcov -.RB [ \-h | \-\-help ] -.RB [ \-v | \-\-version ] -.RS 5 -.br -.RE - -.SH DESCRIPTION -.B lcov -is a graphical front\-end for GCC's coverage testing tool gcov. It collects -line, function and branch coverage data for multiple source files and creates -HTML pages containing the source code annotated with coverage information. -It also adds overview pages for easy navigation within the file structure. - -Use -.B lcov -to collect coverage data and -.B genhtml -to create HTML pages. Coverage data can either be collected from the -currently running Linux kernel or from a user space application. To do this, -you have to complete the following preparation steps: - -For Linux kernel coverage: -.RS -Follow the setup instructions for the gcov\-kernel infrastructure: -.I http://ltp.sourceforge.net/coverage/gcov.php -.br - - -.RE -For user space application coverage: -.RS -Compile the application with GCC using the options -"\-fprofile\-arcs" and "\-ftest\-coverage". -.RE - -Please note that this man page refers to the output format of -.B lcov -as ".info file" or "tracefile" and that the output of GCOV -is called ".da file". - -Also note that when printing percentages, 0% and 100% are only printed when -the values are exactly 0% and 100% respectively. Other values which would -conventionally be rounded to 0% or 100% are instead printed as nearest -non-boundary value. This behavior is in accordance with that of the -.BR gcov (1) -tool. - -.SH OPTIONS - - -.B \-a -.I tracefile -.br -.B \-\-add\-tracefile -.I tracefile -.br -.RS -Add contents of -.IR tracefile . - -Specify several tracefiles using the \-a switch to combine the coverage data -contained in these files by adding up execution counts for matching test and -filename combinations. - -The result of the add operation will be written to stdout or the tracefile -specified with \-o. - -Only one of \-z, \-c, \-a, \-e, \-r, \-l, \-\-diff or \-\-summary may be -specified at a time. - -.RE - -.B \-b -.I directory -.br -.B \-\-base\-directory -.I directory -.br -.RS -.RI "Use " directory -as base directory for relative paths. - -Use this option to specify the base directory of a build\-environment -when lcov produces error messages like: - -.RS -ERROR: could not read source file /home/user/project/subdir1/subdir2/subdir1/subdir2/file.c -.RE - -In this example, use /home/user/project as base directory. - -This option is required when using lcov on projects built with libtool or -similar build environments that work with a base directory, i.e. environments, -where the current working directory when invoking the compiler is not the same -directory in which the source code file is located. - -Note that this option will not work in environments where multiple base -directories are used. In that case use configuration file setting -.B geninfo_auto_base=1 -(see -.BR lcovrc (5)). -.RE - -.B \-c -.br -.B \-\-capture -.br -.RS -Capture coverage data. - -By default captures the current kernel execution counts and writes the -resulting coverage data to the standard output. Use the \-\-directory -option to capture counts for a user space program. - -The result of the capture operation will be written to stdout or the tracefile -specified with \-o. - -Only one of \-z, \-c, \-a, \-e, \-r, \-l, \-\-diff or \-\-summary may be -specified at a time. -.RE - -.B \-\-checksum -.br -.B \-\-no\-checksum -.br -.RS -Specify whether to generate checksum data when writing tracefiles. - -Use \-\-checksum to enable checksum generation or \-\-no\-checksum to -disable it. Checksum generation is -.B disabled -by default. - -When checksum generation is enabled, a checksum will be generated for each -source code line and stored along with the coverage data. This checksum will -be used to prevent attempts to combine coverage data from different source -code versions. - -If you don't work with different source code versions, disable this option -to speed up coverage data processing and to reduce the size of tracefiles. -.RE - -.B \-\-compat -.IR mode = value [, mode = value ,...] -.br -.RS -Set compatibility mode. - -Use \-\-compat to specify that lcov should enable one or more compatibility -modes when capturing coverage data. You can provide a comma-separated list -of mode=value pairs to specify the values for multiple modes. - -Valid -.I values -are: - -.B on -.RS -Enable compatibility mode. -.RE -.B off -.RS -Disable compatibility mode. -.RE -.B auto -.RS -Apply auto-detection to determine if compatibility mode is required. Note that -auto-detection is not available for all compatibility modes. -.RE - -If no value is specified, 'on' is assumed as default value. - -Valid -.I modes -are: - -.B libtool -.RS -Enable this mode if you are capturing coverage data for a project that -was built using the libtool mechanism. See also -\-\-compat\-libtool. - -The default value for this setting is 'on'. - -.RE -.B hammer -.RS -Enable this mode if you are capturing coverage data for a project that -was built using a version of GCC 3.3 that contains a modification -(hammer patch) of later GCC versions. You can identify a modified GCC 3.3 -by checking the build directory of your project for files ending in the -extension '.bbg'. Unmodified versions of GCC 3.3 name these files '.bb'. - -The default value for this setting is 'auto'. - -.RE -.B split_crc -.RS -Enable this mode if you are capturing coverage data for a project that -was built using a version of GCC 4.6 that contains a modification -(split function checksums) of later GCC versions. Typical error messages -when running lcov on coverage data produced by such GCC versions are -\'out of memory' and 'reached unexpected end of file'. - -The default value for this setting is 'auto' -.RE - -.RE - -.B \-\-compat\-libtool -.br -.B \-\-no\-compat\-libtool -.br -.RS -Specify whether to enable libtool compatibility mode. - -Use \-\-compat\-libtool to enable libtool compatibility mode or \-\-no\-compat\-libtool -to disable it. The libtool compatibility mode is -.B enabled -by default. - -When libtool compatibility mode is enabled, lcov will assume that the source -code relating to a .da file located in a directory named ".libs" can be -found in its parent directory. - -If you have directories named ".libs" in your build environment but don't use -libtool, disable this option to prevent problems when capturing coverage data. -.RE - -.B \-\-config\-file -.I config\-file -.br -.RS -Specify a configuration file to use. - -When this option is specified, neither the system\-wide configuration file -/etc/lcovrc, nor the per\-user configuration file ~/.lcovrc is read. - -This option may be useful when there is a need to run several -instances of -.B lcov -with different configuration file options in parallel. -.RE - -.B \-\-convert\-filenames -.br -.RS -Convert filenames when applying diff. - -Use this option together with \-\-diff to rename the file names of processed -data sets according to the data provided by the diff. -.RE - -.B \-\-diff -.I tracefile -.I difffile -.br -.RS -Convert coverage data in -.I tracefile -using source code diff file -.IR difffile . - -Use this option if you want to merge coverage data from different source code -levels of a program, e.g. when you have data taken from an older version -and want to combine it with data from a more current version. -.B lcov -will try to map source code lines between those versions and adjust the coverage -data respectively. -.I difffile -needs to be in unified format, i.e. it has to be created using the "\-u" option -of the -.B diff -tool. - -Note that lines which are not present in the old version will not be counted -as instrumented, therefore tracefiles resulting from this operation should -not be interpreted individually but together with other tracefiles taken -from the newer version. Also keep in mind that converted coverage data should -only be used for overview purposes as the process itself introduces a loss -of accuracy. - -The result of the diff operation will be written to stdout or the tracefile -specified with \-o. - -Only one of \-z, \-c, \-a, \-e, \-r, \-l, \-\-diff or \-\-summary may be -specified at a time. -.RE - -.B \-d -.I directory -.br -.B \-\-directory -.I directory -.br -.RS -Use .da files in -.I directory -instead of kernel. - -If you want to work on coverage data for a user space program, use this -option to specify the location where the program was compiled (that's -where the counter files ending with .da will be stored). - -Note that you may specify this option more than once. -.RE - -.B \-\-exclude -.I pattern -.br -.RS -Exclude source files matching -.IR pattern . - -Use this switch if you want to exclude coverage data for a particular set -of source files matching any of the given patterns. Multiple patterns can be -specified by using multiple -.B --exclude -command line switches. The -.I patterns -will be interpreted as shell wildcard patterns (note that they may need to be -escaped accordingly to prevent the shell from expanding them first). - -Can be combined with the -.B --include -command line switch. If a given file matches both the include pattern and the -exclude pattern, the exclude pattern will take precedence. -.RE - -.B \-\-external -.br -.B \-\-no\-external -.br -.RS -Specify whether to capture coverage data for external source files. - -External source files are files which are not located in one of the directories -specified by \-\-directory or \-\-base\-directory. Use \-\-external to include -external source files while capturing coverage data or \-\-no\-external to -ignore this data. - -Data for external source files is -.B included -by default. -.RE - -.B \-e -.I tracefile -.I pattern -.br -.B \-\-extract -.I tracefile -.I pattern -.br -.RS -Extract data from -.IR tracefile . - -Use this switch if you want to extract coverage data for only a particular -set of files from a tracefile. Additional command line parameters will be -interpreted as shell wildcard patterns (note that they may need to be -escaped accordingly to prevent the shell from expanding them first). -Every file entry in -.I tracefile -which matches at least one of those patterns will be extracted. - -The result of the extract operation will be written to stdout or the tracefile -specified with \-o. - -Only one of \-z, \-c, \-a, \-e, \-r, \-l, \-\-diff or \-\-summary may be -specified at a time. -.RE - -.B \-f -.br -.B \-\-follow -.br -.RS -Follow links when searching for .da files. -.RE - -.B \-\-from\-package -.I package -.br -.RS -Use .da files in -.I package -instead of kernel or directory. - -Use this option if you have separate machines for build and test and -want to perform the .info file creation on the build machine. See -\-\-to\-package for more information. -.RE - -.B \-\-gcov\-tool -.I tool -.br -.RS -Specify the location of the gcov tool. -.RE - -.B \-h -.br -.B \-\-help -.br -.RS -Print a short help text, then exit. -.RE - -.B \-\-include -.I pattern -.br -.RS -Include source files matching -.IR pattern . - -Use this switch if you want to include coverage data for only a particular set -of source files matching any of the given patterns. Multiple patterns can be -specified by using multiple -.B --include -command line switches. The -.I patterns -will be interpreted as shell wildcard patterns (note that they may need to be -escaped accordingly to prevent the shell from expanding them first). -.RE - -.B \-\-ignore\-errors -.I errors -.br -.RS -Specify a list of errors after which to continue processing. - -Use this option to specify a list of one or more classes of errors after which -lcov should continue processing instead of aborting. - -.I errors -can be a comma\-separated list of the following keywords: - -.B gcov: -the gcov tool returned with a non\-zero return code. - -.B source: -the source code file for a data set could not be found. - -.B graph: -the graph file could not be found or is corrupted. -.RE - -.B \-i -.br -.B \-\-initial -.RS -Capture initial zero coverage data. - -Run lcov with \-c and this option on the directories containing .bb, .bbg -or .gcno files before running any test case. The result is a "baseline" -coverage data file that contains zero coverage for every instrumented line. -Combine this data file (using lcov \-a) with coverage data files captured -after a test run to ensure that the percentage of total lines covered is -correct even when not all source code files were loaded during the test. - -Recommended procedure when capturing data for a test case: - -1. create baseline coverage data file -.RS -# lcov \-c \-i \-d appdir \-o app_base.info -.br - -.RE -2. perform test -.RS -# appdir/test -.br - -.RE -3. create test coverage data file -.RS -# lcov \-c \-d appdir \-o app_test.info -.br - -.RE -4. combine baseline and test coverage data -.RS -# lcov \-a app_base.info \-a app_test.info \-o app_total.info -.br - -.RE -.RE - -.B \-k -.I subdirectory -.br -.B \-\-kernel\-directory -.I subdirectory -.br -.RS -Capture kernel coverage data only from -.IR subdirectory . - -Use this option if you don't want to get coverage data for all of the -kernel, but only for specific subdirectories. This option may be specified -more than once. - -Note that you may need to specify the full path to the kernel subdirectory -depending on the version of the kernel gcov support. -.RE - -.B \-l -.I tracefile -.br -.B \-\-list -.I tracefile -.br -.RS -List the contents of the -.IR tracefile . - -Only one of \-z, \-c, \-a, \-e, \-r, \-l, \-\-diff or \-\-summary may be -specified at a time. -.RE - -.B \-\-list\-full\-path -.br -.B \-\-no\-list\-full\-path -.br -.RS -Specify whether to show full paths during list operation. - -Use \-\-list\-full\-path to show full paths during list operation -or \-\-no\-list\-full\-path to show shortened paths. Paths are -.B shortened -by default. -.RE - -.B \-\-no\-markers -.br -.RS -Use this option if you want to get coverage data without regard to exclusion -markers in the source code file. See -.BR "geninfo " (1) -for details on exclusion markers. -.RE - -.B \-\-no\-recursion -.br -.RS -Use this option if you want to get coverage data for the specified directory -only without processing subdirectories. -.RE - -.B \-o -.I tracefile -.br -.B \-\-output\-file -.I tracefile -.br -.RS -Write data to -.I tracefile -instead of stdout. - -Specify "\-" as a filename to use the standard output. - -By convention, lcov\-generated coverage data files are called "tracefiles" and -should have the filename extension ".info". -.RE - -.B \-\-path -.I path -.br -.RS -Strip path from filenames when applying diff. - -Use this option together with \-\-diff to tell lcov to disregard the specified -initial path component when matching between tracefile and diff filenames. -.RE - -.B \-q -.br -.B \-\-quiet -.br -.RS -Do not print progress messages. - -This option is implied when no output filename is specified to prevent -progress messages to mess with coverage data which is also printed to -the standard output. -.RE - -.B \-\-rc -.IR keyword = value -.br -.RS -Override a configuration directive. - -Use this option to specify a -.IR keyword = value -statement which overrides the corresponding configuration statement in -the lcovrc configuration file. You can specify this option more than once -to override multiple configuration statements. -See -.BR lcovrc (5) -for a list of available keywords and their meaning. -.RE - -.B \-r -.I tracefile -.I pattern -.br -.B \-\-remove -.I tracefile -.I pattern -.br -.RS -Remove data from -.IR tracefile . - -Use this switch if you want to remove coverage data for a particular -set of files from a tracefile. Additional command line parameters will be -interpreted as shell wildcard patterns (note that they may need to be -escaped accordingly to prevent the shell from expanding them first). -Every file entry in -.I tracefile -which matches at least one of those patterns will be removed. - -The result of the remove operation will be written to stdout or the tracefile -specified with \-o. - -Only one of \-z, \-c, \-a, \-e, \-r, \-l, \-\-diff or \-\-summary may be -specified at a time. -.RE - -.B \-\-strip -.I depth -.br -.RS -Strip path components when applying diff. - -Use this option together with \-\-diff to tell lcov to disregard the specified -number of initial directories when matching tracefile and diff filenames. -.RE - -.B \-\-summary -.I tracefile -.br -.RS -Show summary coverage information for the specified tracefile. - -Note that you may specify this option more than once. - -Only one of \-z, \-c, \-a, \-e, \-r, \-l, \-\-diff or \-\-summary may be -specified at a time. -.RE - -.B \-t -.I testname -.br -.B \-\-test\-name -.I testname -.br -.RS -Specify test name to be stored in the tracefile. - -This name identifies a coverage data set when more than one data set is merged -into a combined tracefile (see option \-a). - -Valid test names can consist of letters, decimal digits and the underscore -character ("_"). -.RE - -.B \-\-to\-package -.I package -.br -.RS -Store .da files for later processing. - -Use this option if you have separate machines for build and test and -want to perform the .info file creation on the build machine. To do this, -follow these steps: - -On the test machine: -.RS -.br -\- run the test -.br -\- run lcov \-c [\-d directory] \-\-to-package -.I file -.br -\- copy -.I file -to the build machine -.RE -.br - -On the build machine: -.RS -.br -\- run lcov \-c \-\-from-package -.I file -[\-o and other options] -.RE -.br - -This works for both kernel and user space coverage data. Note that you might -have to specify the path to the build directory using \-b with -either \-\-to\-package or \-\-from-package. Note also that the package data -must be converted to a .info file before recompiling the program or it will -become invalid. -.RE - -.B \-v -.br -.B \-\-version -.br -.RS -Print version number, then exit. -.RE - -.B \-z -.br -.B \-\-zerocounters -.br -.RS -Reset all execution counts to zero. - -By default tries to reset kernel execution counts. Use the \-\-directory -option to reset all counters of a user space program. - -Only one of \-z, \-c, \-a, \-e, \-r, \-l, \-\-diff or \-\-summary may be -specified at a time. -.RE - -.SH FILES - -.I /etc/lcovrc -.RS -The system\-wide configuration file. -.RE - -.I ~/.lcovrc -.RS -The per\-user configuration file. -.RE - -.SH AUTHOR -Peter Oberparleiter - -.SH SEE ALSO -.BR lcovrc (5), -.BR genhtml (1), -.BR geninfo (1), -.BR genpng (1), -.BR gendesc (1), -.BR gcov (1) diff --git a/worker/deps/lcov/man/lcovrc.5 b/worker/deps/lcov/man/lcovrc.5 deleted file mode 100644 index 07d35ff3c5..0000000000 --- a/worker/deps/lcov/man/lcovrc.5 +++ /dev/null @@ -1,937 +0,0 @@ -.TH lcovrc 5 "LCOV 1.14" 2018\-01\-30 "User Manuals" - -.SH NAME -lcovrc \- lcov configuration file - -.SH DESCRIPTION -The -.I lcovrc -file contains configuration information for the -.B lcov -code coverage tool (see -.BR lcov (1)). -.br - -The system\-wide configuration file is located at -.IR /etc/lcovrc . -To change settings for a single user, place a customized copy of this file at -location -.IR ~/.lcovrc . -Where available, command\-line options override configuration file settings. - -Lines in a configuration file can either be: -.IP " *" -empty lines or lines consisting only of white space characters. These lines are -ignored. -.IP " *" -comment lines which start with a hash sign ('#'). These are treated like empty -lines and will be ignored. -.IP " *" -statements in the form -.RI ' key " = " value '. -A list of valid statements and their description can be found in -section 'OPTIONS' below. -.PP - -.B Example configuration: -.IP -# -.br -# Example LCOV configuration file -.br -# -.br - -# External style sheet file -.br -#genhtml_css_file = gcov.css -.br - -# Coverage rate limits -.br -genhtml_hi_limit = 90 -.br -genhtml_med_limit = 75 -.br - -# Width of line coverage field in source code view -.br -genhtml_line_field_width = 12 -.br - -# Width of branch coverage field in source code view -.br -genhtml_branch_field_width = 16 -.br - -# Width of overview image -.br -genhtml_overview_width = 80 -.br - -# Resolution of overview navigation -.br -genhtml_nav_resolution = 4 -.br - -# Offset for source code navigation -.br -genhtml_nav_offset = 10 -.br - -# Do not remove unused test descriptions if non\-zero -.br -genhtml_keep_descriptions = 0 -.br - -# Do not remove prefix from directory names if non\-zero -.br -genhtml_no_prefix = 0 -.br - -# Do not create source code view if non\-zero -.br -genhtml_no_source = 0 -.br - -# Specify size of tabs -.br -genhtml_num_spaces = 8 -.br - -# Highlight lines with converted\-only data if non\-zero -.br -genhtml_highlight = 0 -.br - -# Include color legend in HTML output if non\-zero -.br -genhtml_legend = 0 -.br - -# Include HTML file at start of HTML output -.br -#genhtml_html_prolog = prolog.html -.br - -# Include HTML file at end of HTML output -.br -#genhtml_html_epilog = epilog.html -.br - -# Use custom HTML file extension -.br -#genhtml_html_extension = html -.br - -# Compress all generated html files with gzip. -.br -#genhtml_html_gzip = 1 -.br - -# Include sorted overview pages -.br -genhtml_sort = 1 -.br - -# Include function coverage data display -.br -#genhtml_function_coverage = 1 -.br - -# Include branch coverage data display -.br -#genhtml_branch_coverage = 1 -.br - -# Specify the character set of all generated HTML pages -.br -genhtml_charset=UTF\-8 -.br - -# Allow HTML markup in test case description text if non\-zero -.br -genhtml_desc_html=0 -.br - -# Specify the precision for coverage rates -.br -#genhtml_precision=1 -.br - -# Show missed counts instead of hit counts -.br -#genhtml_missed=1 -.br - -# Demangle C++ symbols -.br -#genhtml_demangle_cpp=1 -.br - -# Location of the gcov tool -.br -#geninfo_gcov_tool = gcov -.br - -# Adjust test names if non\-zero -.br -#geninfo_adjust_testname = 0 -.br - -# Calculate a checksum for each line if non\-zero -.br -geninfo_checksum = 0 -.br - -# Enable libtool compatibility mode if non\-zero -.br -geninfo_compat_libtool = 0 -.br - -# Specify whether to capture coverage data for external source -.br -# files -.br -#geninfo_external = 1 -.br - -# Use gcov's --all-blocks option if non-zero -.br -#geninfo_gcov_all_blocks = 1 -.br - -# Specify compatiblity modes (same as \-\-compat option -.br -# of geninfo) -.br -#geninfo_compat = libtool=on, hammer=auto, split_crc=auto -.br - -# Adjust path to source files by removing or changing path -.br -# components that match the specified pattern (Perl regular -.br -# expression format) -.br -#geninfo_adjust_src_path = /tmp/build => /usr/src - -# Specify if geninfo should try to automatically determine -.br -# the base-directory when collecting coverage data. -.br -geninfo_auto_base = 1 -.br - -# Use gcov intermediate format? Valid values are 0, 1, auto -.br -geninfo_intermediate = auto -.br - -# Directory containing gcov kernel files -.br -lcov_gcov_dir = /proc/gcov -.br - -# Location for temporary directories -.br -lcov_tmp_dir = /tmp -.br - -# Show full paths during list operation if non\-zero -.br -lcov_list_full_path = 0 -.br - -# Specify the maximum width for list output. This value is -.br -# ignored when lcov_list_full_path is non\-zero. -.br -lcov_list_width = 80 -.br - -# Specify the maximum percentage of file names which may be -.br -# truncated when choosing a directory prefix in list output. -.br -# This value is ignored when lcov_list_full_path is non\-zero. -.br -lcov_list_truncate_max = 20 - -# Specify if function coverage data should be collected and -.br -# processed. -.br -lcov_function_coverage = 1 -.br - -# Specify if branch coverage data should be collected and -.br -# processed. -.br -lcov_branch_coverage = 0 -.br -.PP - -.SH OPTIONS - -.BR genhtml_css_file " =" -.I filename -.IP -Specify an external style sheet file. Use this option to modify the appearance of the HTML output as generated by -.BR genhtml . -During output generation, a copy of this file will be placed in the output -directory. -.br - -This option corresponds to the \-\-css\-file command line option of -.BR genhtml . -.br - -By default, a standard CSS file is generated. -.PP - -.BR genhtml_hi_limit " =" -.I hi_limit -.br -.BR genhtml_med_limit " =" -.I med_limit -.br -.IP -Specify coverage rate limits for classifying file entries. Use this option to -modify the coverage rates (in percent) for line, function and branch coverage at -which a result is classified as high, medium or low coverage. This -classification affects the color of the corresponding entries on the overview -pages of the HTML output: -.br - -High: hi_limit <= rate <= 100 default color: green -.br -Medium: med_limit <= rate < hi_limit default color: orange -.br -Low: 0 <= rate < med_limit default color: red -.br - -Defaults are 90 and 75 percent. -.PP - -.BR genhtml_line_field_width " =" -.I number_of_characters -.IP -Specify the width (in characters) of the source code view column containing -line coverage information. -.br - -Default is 12. -.PP - -.BR genhtml_branch_field_width " =" -.I number_of_characters -.IP -Specify the width (in characters) of the source code view column containing -branch coverage information. -.br - -Default is 16. -.PP - -.BR genhtml_overview_width " =" -.I pixel_size -.IP -Specify the width (in pixel) of the overview image created when generating HTML -output using the \-\-frames option of -.BR genhtml . -.br - -Default is 80. -.PP - -.BR genhtml_nav_resolution " =" -.I lines -.IP -Specify the resolution of overview navigation when generating HTML output using -the \-\-frames option of -.BR genhtml . -This number specifies the maximum difference in lines between the position a -user selected from the overview and the position the source code window is -scrolled to. -.br - -Default is 4. -.PP - - -.BR genhtml_nav_offset " =" -.I lines -.IP -Specify the overview navigation line offset as applied when generating HTML -output using the \-\-frames option of -.BR genhtml. -.br - -Clicking a line in the overview image should show the source code view at -a position a bit further up, so that the requested line is not the first -line in the window. This number specifies that offset. -.br - -Default is 10. -.PP - - -.BR genhtml_keep_descriptions " =" -.IR 0 | 1 -.IP -If non\-zero, keep unused test descriptions when generating HTML output using -.BR genhtml . -.br - -This option corresponds to the \-\-keep\-descriptions option of -.BR genhtml . -.br - -Default is 0. -.PP - -.BR genhtml_no_prefix " =" -.IR 0 | 1 -.IP -If non\-zero, do not try to find and remove a common prefix from directory names. -.br - -This option corresponds to the \-\-no\-prefix option of -.BR genhtml . -.br - -Default is 0. -.PP - -.BR genhtml_no_source " =" -.IR 0 | 1 -.IP -If non\-zero, do not create a source code view when generating HTML output using -.BR genhtml . -.br - -This option corresponds to the \-\-no\-source option of -.BR genhtml . -.br - -Default is 0. -.PP - -.BR genhtml_num_spaces " =" -.I num -.IP -Specify the number of spaces to use as replacement for tab characters in the -HTML source code view as generated by -.BR genhtml . -.br - -This option corresponds to the \-\-num\-spaces option of -.BR genthml . -.br - -Default is 8. - -.PP - -.BR genhtml_highlight " =" -.IR 0 | 1 -.IP -If non\-zero, highlight lines with converted\-only data in -HTML output as generated by -.BR genhtml . -.br - -This option corresponds to the \-\-highlight option of -.BR genhtml . -.br - -Default is 0. -.PP - -.BR genhtml_legend " =" -.IR 0 | 1 -.IP -If non\-zero, include a legend explaining the meaning of color coding in the HTML -output as generated by -.BR genhtml . -.br - -This option corresponds to the \-\-legend option of -.BR genhtml . -.br - -Default is 0. -.PP - -.BR genhtml_html_prolog " =" -.I filename -.IP -If set, include the contents of the specified file at the beginning of HTML -output. - -This option corresponds to the \-\-html\-prolog option of -.BR genhtml . -.br - -Default is to use no extra prolog. -.PP - -.BR genhtml_html_epilog " =" -.I filename -.IP -If set, include the contents of the specified file at the end of HTML output. - -This option corresponds to the \-\-html\-epilog option of -.BR genhtml . -.br - -Default is to use no extra epilog. -.PP - -.BR genhtml_html_extension " =" -.I extension -.IP -If set, use the specified string as filename extension for generated HTML files. - -This option corresponds to the \-\-html\-extension option of -.BR genhtml . -.br - -Default extension is "html". -.PP - -.BR genhtml_html_gzip " =" -.IR 0 | 1 -.IP -If set, compress all html files using gzip. - -This option corresponds to the \-\-html\-gzip option of -.BR genhtml . -.br - -Default extension is 0. -.PP - -.BR genhtml_sort " =" -.IR 0 | 1 -.IP -If non\-zero, create overview pages sorted by coverage rates when generating -HTML output using -.BR genhtml . -.br - -This option can be set to 0 by using the \-\-no\-sort option of -.BR genhtml . -.br - -Default is 1. -.PP - -.BR genhtml_function_coverage " =" -.IR 0 | 1 -.IP -If non\-zero, include function coverage data when generating HTML output using -.BR genhtml . -.br - -This option can be set to 0 by using the \-\-no\-function\-coverage option of -.BR genhtml . -.br - -Default is 1. -.PP - -.BR genhtml_branch_coverage " =" -.IR 0 | 1 -.IP -If non\-zero, include branch coverage data when generating HTML output using -.BR genhtml . -.br - -This option can be set to 0 by using the \-\-no\-branch\-coverage option of -.BR genhtml . -.br - -Default is 1. -.PP - -.BR genhtml_charset " =" -.I charset -.IP -Specify the character set of all generated HTML pages. -.br - -Use this option if the source code contains characters which are not -part of the default character set. Note that this option is ignored -when a custom HTML prolog is specified (see also -.BR genhtml_html_prolog ). -.br - -Default is UTF-8. -.PP - -.BR genhtml_demangle_cpp " =" -.IR 0 | 1 -.IP -If non-zero, demangle C++ function names in function overviews. - -Set this option to one if you want to convert C++ internal function -names to human readable format for display on the HTML function overview -page. This option requires that the c++filt tool is installed (see -.BR c++filt(1) -). -.br - -This option corresponds to the \-\-demangle\-cpp command line option of -.BR genhtml . -.br - -Default is 0. -.PP - -.BR genhtml_desc_html " =" -.IR 0 | 1 -.IP -If non-zero, test case descriptions may contain HTML markup. - -Set this option to one if you want to embed HTML markup (for example to -include links) in test case descriptions. When set to zero, HTML markup -characters will be escaped to show up as plain text on the test case -description page. -.br - -Default is 0. -.PP - -.BR genhtml_precision " =" -.IR 1 | 2 | 3 | 4 -.IP -Specify how many digits after the decimal-point should be used for -displaying coverage rates. -.br - -Default is 1. -.PP -.BR genhtml_missed " =" -.IR 0 | 1 -.IP -If non-zero, the count of missed lines, functions, or branches is shown -as negative numbers in overview pages. -.br - -Default is 0. -.PP - -. -.BR geninfo_gcov_tool " =" -.I path_to_gcov -.IP -Specify the location of the gcov tool (see -.BR gcov (1)) -which is used to generate coverage information from data files. -.br - -Default is 'gcov'. -.PP - -.BR geninfo_adjust_testname " =" -.IR 0 | 1 -.IP -If non\-zero, adjust test names to include operating system information -when capturing coverage data. -.br - -Default is 0. -.PP - -.BR geninfo_checksum " =" -.IR 0 | 1 -.IP -If non\-zero, generate source code checksums when capturing coverage data. -Checksums are useful to prevent merging coverage data from incompatible -source code versions but checksum generation increases the size of coverage -files and the time used to generate those files. -.br - -This option corresponds to the \-\-checksum and \-\-no\-checksum command line -option of -.BR geninfo . -.br - -Default is 0. -.PP - -.BR geninfo_compat_libtool " =" -.IR 0 | 1 -.IP -If non\-zero, enable libtool compatibility mode. When libtool compatibility -mode is enabled, lcov will assume that the source code relating to a .da file -located in a directory named ".libs" can be found in its parent directory. -.br - -This option corresponds to the \-\-compat\-libtool and \-\-no\-compat\-libtool -command line option of -.BR geninfo . -.br - -Default is 1. -.PP - -.BR geninfo_external " =" -.IR 0 | 1 -.IP -If non\-zero, capture coverage data for external source files. - -External source files are files which are not located in one of the directories -(including sub-directories) -specified by the \-\-directory or \-\-base\-directory options of -.BR lcov / geninfo . - -Default is 1. -.PP - -.BR geninfo_gcov_all_blocks " =" -.IR 0 | 1 -.IP -If non\-zero, call the gcov tool with option --all-blocks. - -Using --all-blocks will produce more detailed branch coverage information for -each line. Set this option to zero if you do not need detailed branch coverage -information to speed up the process of capturing code coverage or to work -around a bug in some versions of gcov which will cause it to endlessly loop -when analysing some files. - -Default is 1. -.PP - -.BR geninfo_compat " =" -.IR mode = value [, mode = value ,...] -.IP -Specify that geninfo should enable one or more compatibility modes -when capturing coverage data. - -This option corresponds to the \-\-compat command line option of -.BR geninfo . - -Default is 'libtool=on, hammer=auto, split_crc=auto'. -.PP - -.BR geninfo_adjust_src_path " =" -.IR pattern " => " replacement -.br -.BR geninfo_adjust_src_path " =" -.I pattern -.IP -Adjust source paths when capturing coverage data. - -Use this option in situations where geninfo cannot find the correct -path to source code files of a project. By providing a -.I pattern -in Perl regular expression format (see -.BR perlre (1)) -and an optional replacement string, you can instruct geninfo to -remove or change parts of the incorrect source path. - -.B Example: -.br - -1. When geninfo reports that it cannot find source file -.br - - /path/to/src/.libs/file.c -.br - -while the file is actually located in -.br - - /path/to/src/file.c -.br - -use the following parameter: -.br - - geninfo_adjust_src_path = /.libs - -This will remove all "/.libs" strings from the path. - -2. When geninfo reports that it cannot find source file -.br - - /tmp/build/file.c -.br - -while the file is actually located in -.br - - /usr/src/file.c -.br - -use the following parameter: -.br - - geninfo_adjust_src_path = /tmp/build => /usr/src -.br - -This will change all "/tmp/build" strings in the path to "/usr/src". -.PP - -.BR geninfo_auto_base " =" -.IR 0 | 1 -.IP -If non\-zero, apply a heuristic to determine the base directory when -collecting coverage data. -.br - -Use this option when using geninfo on projects built with libtool or -similar build environments that work with multiple base directories, -i.e. environments, where the current working directory when invoking the -compiler ist not the same directory in which the source code file is -located, and in addition, is different between files of the same project. -.br - -Default is 1. -.PP - -.BR geninfo_intermediate " =" -.IR 0 | 1 | auto -.IP -Specify whether to use gcov intermediate format -.br - -Use this option to control whether geninfo should use the gcov intermediate -format while collecting coverage data. The use of the gcov intermediate format -should increase processing speed. It also provides branch coverage data when -using the \-\-initial command line option. -.br - -Valid values are 0 for off, 1 for on, and "auto" to let geninfo automatically -use immediate format when supported by gcov. -.br - -Default is "auto". -.PP - -.BR lcov_gcov_dir " =" -.I path_to_kernel_coverage_data -.IP -Specify the path to the directory where kernel coverage data can be found -or leave undefined for auto-detection. -.br - -Default is auto-detection. -.PP - -.BR lcov_tmp_dir " =" -.I temp -.IP -Specify the location of a directory used for temporary files. -.br - -Default is '/tmp'. -.PP - -.BR lcov_list_full_path " =" -.IR 0 | 1 -.IP -If non-zero, print the full path to source code files during a list operation. -.br - -This option corresponds to the \-\-list\-full\-path option of -.BR lcov . -.br - -Default is 0. -.PP - -.BR lcov_list_max_width " =" -.IR width -.IP -Specify the maximum width for list output. This value is ignored when -lcov_list_full_path is non\-zero. -.br - -Default is 80. -.PP - -.BR lcov_list_truncate_max -.B " =" -.IR percentage -.IP -Specify the maximum percentage of file names which may be truncated when -choosing a directory prefix in list output. This value is ignored when -lcov_list_full_path is non\-zero. -.br - -Default is 20. -.PP - -.BR lcov_function_coverage " =" -.IR 0 | 1 -.IP -Specify whether lcov should handle function coverage data. -.br - -Setting this option to 0 can reduce memory and CPU time consumption -when lcov is collecting and processing coverage data, as well as -reduce the size of the resulting data files. Note that setting -.B genhtml_function_coverage -will override this option for HTML generation. -.br - -Default is 1. -.PP - -.BR lcov_branch_coverage " =" -.IR 0 | 1 -.IP -Specify whether lcov should handle branch coverage data. -.br - -Setting this option to 0 can reduce memory and CPU time consumption -when lcov is collecting and processing coverage data, as well as -reduce the size of the resulting data files. Note that setting -.B genhtml_branch_coverage -will override this option for HTML generation. -.br - -Default is 0. -.PP - -.BR lcov_excl_line " =" -.I expression -.IP -Specify the regular expression of lines to exclude. -.br - -Default is 'LCOV_EXCL_LINE'. -.PP - -.BR lcov_excl_br_line " =" -.I expression -.IP -Specify the regular expression of lines to exclude from branch coverage. -.br - -Default is 'LCOV_EXCL_BR_LINE'. -.PP - -.SH FILES - -.TP -.I /etc/lcovrc -The system\-wide -.B lcov -configuration file. - -.TP -.I ~/.lcovrc -The individual per\-user configuration file. -.PP - -.SH SEE ALSO -.BR lcov (1), -.BR genhtml (1), -.BR geninfo (1), -.BR gcov (1) diff --git a/worker/deps/lcov/rpm/lcov.spec b/worker/deps/lcov/rpm/lcov.spec deleted file mode 100644 index e96c8d47bd..0000000000 --- a/worker/deps/lcov/rpm/lcov.spec +++ /dev/null @@ -1,59 +0,0 @@ -Summary: A graphical GCOV front-end -Name: lcov -Version: 1.14 -Release: 1 -License: GPLv2+ -Group: Development/Tools -URL: http://ltp.sourceforge.net/coverage/lcov.php -Source0: http://downloads.sourceforge.net/ltp/%{name}-%{version}.tar.gz -BuildRoot: %{_tmppath}/%{name}-%{version}-root -BuildArch: noarch -Requires: perl >= 5.8.8 - -%description -LCOV is a graphical front-end for GCC's coverage testing tool gcov. It collects -gcov data for multiple source files and creates HTML pages containing the -source code annotated with coverage information. It also adds overview pages -for easy navigation within the file structure. - -%prep -%setup -q -n %{name}-%{version} - -%build -exit 0 - -%install -rm -rf $RPM_BUILD_ROOT -make install DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr CFG_DIR=/etc - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root) -/usr/bin/* -/usr/share/man/man*/* -%config /etc/* - -%changelog -* Mon Aug 22 2016 Peter Oberparleiter (Peter.Oberparleiter@de.ibm.com) -- updated "make install" call to work with PREFIX Makefile changes - -* Mon May 07 2012 Peter Oberparleiter (Peter.Oberparleiter@de.ibm.com) -- added dependency on perl 5.8.8 for >>& open mode support - -* Wed Aug 13 2008 Peter Oberparleiter (Peter.Oberparleiter@de.ibm.com) -- changed description + summary text - -* Mon Aug 20 2007 Peter Oberparleiter (Peter.Oberparleiter@de.ibm.com) -- fixed "Copyright" tag - -* Mon Jul 14 2003 Peter Oberparleiter (Peter.Oberparleiter@de.ibm.com) -- removed variables for version/release to support source rpm building -- added initial rm command in install section - -* Mon Apr 7 2003 Peter Oberparleiter (Peter.Oberparleiter@de.ibm.com) -- implemented variables for version/release - -* Fri Oct 18 2002 Peter Oberparleiter (Peter.Oberparleiter@de.ibm.com) -- created initial spec file diff --git a/worker/deps/lcov/test/Makefile b/worker/deps/lcov/test/Makefile deleted file mode 100644 index ecb96042aa..0000000000 --- a/worker/deps/lcov/test/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -include common.mak - -TESTDIRS := $(sort $(patsubst %/,%,$(dir $(wildcard */Makefile)))) - -help: info - -info: - echo "Available make targets:" - echo " test : perform self-tests" - echo " clean : remove all temporary files" - echo "" - echo "Available make variables:" - echo " SIZE : specify size of test data (small, medium, large)" - echo " V : specify level of verbosity (0, 1, 2)" - -test: - for TEST in $(TESTDIRS) ; do \ - make -C $$TEST test ; \ - done - -clean: - rm -rf *.info *.counts test.log src/ - for TEST in $(TESTDIRS) ; do \ - make -C $$TEST clean ; \ - done - -.PHONY: help info test clean diff --git a/worker/deps/lcov/test/bin/common b/worker/deps/lcov/test/bin/common deleted file mode 100644 index a8b527deda..0000000000 --- a/worker/deps/lcov/test/bin/common +++ /dev/null @@ -1,103 +0,0 @@ -function elapsed_to_ms() -{ - local ELAPSED=$1 - local IFS=:. - local MS - - set -- $ELAPSED - if [ $# -eq 3 ] ; then - let MS=${3#0}*10+${2#0}*1000+$1*60000 - else - let MS=${4#0}*10+${3#0}*1000+${2#0}*60000+$1*3600000 - fi - - echo $MS -} - -function t_timestamp() -{ - date +"%Y-%m-%d %H:%M:%S %z" -} - -function t_marker() -{ - echo - echo "======================================================================" -} - -function t_detail() -{ - local KEY=$1 - local VALUE=$2 - local DOTS=" ............" - - printf "%-.12s: %s\n" "$KEY$DOTS" "$VALUE" -} - -function t_announce() -{ - local TESTNAME="$1" - - printf "$BOLD%-.30s$RESET " "$TESTNAME .............................." - t_marker >> "$LOGFILE" - t_detail "DATE" "$(t_timestamp)" >> "$LOGFILE" - t_detail "TESTNAME" "$TESTNAME" >> "$LOGFILE" -} - -function t_result() -{ - local COLOR="$1" - local TEXT="$2" - - printf "[$COLOR$TEXT$RESET]" -} - -function t_pass() -{ - local TESTNAME="$1" - - t_result "$GREEN" "pass" - echo "pass $TESTNAME" >> "$COUNTFILE" -} - -function t_fail() -{ - local TESTNAME="$1" - - t_result "$RED" "fail" - echo "fail $TESTNAME" >> "$COUNTFILE" -} - -function t_kill() -{ - local TESTNAME="$1" - - t_result "$RED" "kill" - echo "fail $TESTNAME" >> "$COUNTFILE" -} - -function t_skip() -{ - local TESTNAME="$1" - - t_result "$BLUE" "skip" - echo "skip $TESTNAME" >> "$COUNTFILE" -} - -function t_indent() -{ - sed -e 's/^/ /' -} - -LOGFILE="$TOPDIR/test.log" -COUNTFILE="$TOPDIR/test.counts" -TIMEFILE="$TOPDIR/test.time" - -if [ -t 1 ] ; then - RED="\e[31m" - GREEN="\e[32m" - BLUE="\e[34m" - BOLD="\e[1m" - DEFAULT="\e[39m" - RESET="\e[0m" -fi diff --git a/worker/deps/lcov/test/bin/mkinfo b/worker/deps/lcov/test/bin/mkinfo deleted file mode 100755 index 5231aeac5d..0000000000 --- a/worker/deps/lcov/test/bin/mkinfo +++ /dev/null @@ -1,952 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright IBM Corp. 2017 -# -# Usage: mkinfo [-o ] [--seed ] -# [=...] -# -# Create a fake lcov code coverage data file and optionally the corresponding -# source tree. DATA_FILE contains all specifications for creating the data -# file. Directives can be overridden using KEY=VALUE specifications with KEY -# being in the form SECTION.KEY. SEED specifies the number used to initialize -# the pseudo random number generator. -# -# Example: -# mkinfo profiles/small -o src files.numfiles=12 -# - -use strict; -use warnings; - -use Getopt::Long; -use Cwd qw(abs_path getcwd); -use File::Path qw(make_path); -use File::Basename; -use Data::Dumper; - -my $MAX_TAKEN = 1000; -my $use_colors = -t STDIN; -my $BOLD = $use_colors ? "\033[1m" : ""; -my $RESET = $use_colors ? "\033[0m" : ""; - -sub usage() -{ - print(< [-o ] [--seed ] [=...] - -Create a fake lcov code coverage data file and optionally the corresponding -source tree. DATA_FILE contains all specifications for creating the data -file. Directives can be overridden using KEY=VALUE specifications with KEY -being in the form SECTION.KEY. SEED specifies the number used to initialize -the pseudo random number generator. - -Example: -$0 profiles/small -o src files.numfiles=12 -EOF -} - -sub read_config($) -{ - my ($filename) = @_; - my $fd; - my %config; - my $section; - - open($fd, "<", $filename) or die("Could not open $filename: $!\n"); - while (my $line = <$fd>) { - my ($key, $value); - - $line =~ s/(^\s*|\s*$)//g; - next if ($line eq "" || $line =~ /^#/); - if ($line =~ /^\[\s*(\S+)\s*]$/) { - $section = $1; - next; - } - if ($line !~ /^(\S+)\s*=\s*(.*)$/) { - die("$filename:$.: Unknown line format: $line\n"); - } - ($key, $value) = ($1, $2); - if (!defined($section)) { - die("$filename:$.: Directive outside of section\n"); - } - $config{$section}->{$1} = $2; - } - close($fd); - - return \%config; -} - -sub apply_config($$) -{ - my ($config, $directive) = @_; - - for my $dir (@$directive) { - if ($dir !~ /^([^\.]+)\.([^=]+)=(.*)$/) { - die("Unknown directive format: $dir\n"); - } - $config->{$1}->{$2} = $3; - } -} - -sub get_value($$;$) -{ - my ($config, $dir, $default) = @_; - my ($section, $key, $value); - - if ($dir !~ /^([^\.]+)\.([^=]+)$/) { - die("$0: Internal error: Unknown key format: $key\n"); - } - ($section, $key) = ($1, $2); - - $value = $config->{$section}->{$key}; - - if (!defined($value)) { - if (!defined($default)) { - die("$0: Missing config value for $dir\n"); - } - $value = $default; - } - - return $value; -} - -sub get_int($$;$$$) -{ - my ($config, $dir, $default, $min, $max) = @_; - my $value = get_value($config, $dir, $default); - - if ($value !~ /^\d+$/) { - die("$0: Config value $dir must be an integer: $value\n"); - } - $value = int($value); - if (defined($min) && $value < $min) { - die("$0: Config value $dir is too low (min $min): $value\n"); - } - if (defined($max) && $value > $max) { - die("$0: Config value $dir is too high (max $max): $value\n"); - } - - return int($value); -} - -sub get_list($$;$) -{ - my ($config, $dir, $default) = @_; - my $value = get_value($config, $dir, $default); - my @list = split(/\s+/, $value); - - return \@list; -} - -sub randlist($) -{ - my ($list) = @_; - - return "" if (!@$list); - return $list->[int(rand(scalar(@$list)))]; -} - -sub randbool() -{ - return int(rand(2)); -} - -# Reduce LIST to PERCENTAGE of its former size. -sub reduce_list_per($$) -{ - my ($list, $percentage) = @_; - my $remove; - - $remove = int((100 - $percentage) * scalar(@$list) / 100); - - for (my $i = 0; $i < $remove; $i++) { - splice(@$list, int(rand(scalar(@$list))), 1); - } -} - -# Reduce LIST to NUM items. -sub reduce_list_num($$) -{ - my ($list, $num) = @_; - my $remove; - - $remove = scalar(@$list) - $num; - - for (my $i = 0; $i < $remove; $i++) { - splice(@$list, int(rand(scalar(@$list))), 1); - } -} - -sub _gen_filename($$) -{ - my ($c, $root) = @_; - my $ltop = get_list($c, "files.top", ""); - my $lsub = get_list($c, "files.sub", ""); - my $lsubsub = get_list($c, "files.subsub", ""); - my $lprefix = get_list($c, "files.prefix"); - my $lsuffix = get_list($c, "files.suffix", ""); - my $lext = get_list($c, "files.ext"); - my ($top, $sub, $subsub, $prefix, $suffix, $ext) = - ("", "", "", "", "", ""); - my $filename = ""; - - $top = randlist($ltop) if (randbool()); - $sub = randlist($lsub) if (randbool()); - $subsub = randlist($lsubsub) if (randbool()); - $prefix = randlist($lprefix); - $suffix = randlist($lsuffix) if (randbool()); - $ext = randlist($lext); - - $filename = $root; - $filename .= "/".$top if ($top ne ""); - $filename .= "/".$sub if ($sub ne ""); - $filename .= "/".$subsub if ($subsub ne ""); - $filename .= "/".$prefix; - $filename .= "_".$suffix if ($suffix ne ""); - $filename .= $ext; - $filename =~ s#^//#/#; - - return $filename; -} - -sub gen_filename($$$) -{ - my ($c, $root, $filenames) = @_; - my $filename; - - do { - $filename = _gen_filename($c, $root); - } while ($filenames->{$filename}); - $filenames->{$filename} = 1; - - return $filename; -} - -sub gen_lines($$) -{ - my ($c, $length) = @_; - my @lines = 1 .. $length; - my $percent = get_int($c, "lines.instrumented", undef, 0, 100); - - reduce_list_per(\@lines, $percent); - - return \@lines; -} - -sub gen_fnname($$) -{ - my ($c, $hash) = @_; - my $lverb = get_list($c, "functions.verb"); - my $ladj = get_list($c, "functions.adj", ""); - my $lnoun = get_list($c, "functions.noun", ""); - my ($verb, $adj, $noun) = ("", "", ""); - my $fnname; - - $verb = randlist($lverb); - $adj = randlist($ladj) if (randbool()); - $noun = randlist($lnoun) if (randbool()); - - $fnname = $verb; - $fnname .= "_".$adj if ($adj ne ""); - $fnname .= "_".$noun if ($noun ne ""); - - if (exists($hash->{$fnname})) { - my $i = 2; - - while (exists($hash->{$fnname.$i})) { - $i++; - } - $fnname .= $i; - } - $hash->{$fnname} = 1; - - return $fnname; -} - -sub gen_functions($$) -{ - my ($c, $lines) = @_; - my @fnlines; - my @functions; - my %names; - my $percent = get_int($c, "functions.perinstrumented", undef, 0, 100); - - @fnlines = @$lines; - reduce_list_per(\@fnlines, $percent); - - foreach my $fnline (@fnlines) { - push(@functions, [ $fnline, gen_fnname($c, \%names) ]); - } - - return \@functions; -} - - -# Returns a value distribution object. This object can be used to randomly -# choose one element from a list of elements with a given relative distribution. -# -# dist: [ sumprob, probs] -# sumprob: Sum of all probabilities -# probs: [ prob1, prob2, ... ] -# prob: [ num, x ] -# num: Value -sub get_dist($$;$) -{ - my ($c, $dir, $default) = @_; - my $list = get_list($c, $dir, $default); - my $sumprob = 0; - my @probs; - - foreach my $spec (@$list) { - my ($n, $p); - - if ($spec =~ /^(\d+):(\d+)$/) { - ($n, $p) = ($1, $2); - } elsif ($spec =~ /^(\d+)$/) { - $n = $1; - $p = 1; - } else { - die("$0: Config value $dir must be a distribution ". - "list (a:p1 b:p2 ...)\n"); - } - $sumprob += $p; - push(@probs, [ $n, $sumprob ]); - } - - return [ $sumprob, \@probs ]; -} - -sub rand_dist($) -{ - my ($dist) = @_; - my ($sumprob, $probs) = @$dist; - my $r = int(rand($sumprob)); - - foreach my $prob (@$probs) { - my ($num, $x) = @$prob; - return $num if ($r < $x); - } - - die("Internal error: Incomplete distribution list\n"); -} - -sub gen_branches($$) -{ - my ($c, $lines) = @_; - my $percent = get_int($c, "branches.perinstrumented", undef, 0, 100); - my @allblocks = @{get_list($c, "branches.blocks", "0")}; - my $branchdist = get_dist($c, "branches.branchdist", "2"); - my @brlines; - my @branches; - - @brlines = @$lines; - reduce_list_per(\@brlines, $percent); - - foreach my $brline (@brlines) { - my @blocks = @allblocks; - my $numblocks = int(rand(scalar(@blocks))) + 1; - - reduce_list_num(\@blocks, $numblocks); - - foreach my $block (@blocks) { - my $numbranch = rand_dist($branchdist); - - for (my $branch = 0; $branch < $numbranch; $branch++) { - push(@branches, [ $brline, $block, $branch]); - } - } - } - - return \@branches; -} - -sub gen_filesrc($) -{ - my ($c) = @_; - my ($length, $lines, $functions, $branches); - my $do_ln = get_int($c, "lines.enabled"); - my $do_fn = get_int($c, "functions.enabled"); - my $do_br = get_int($c, "branches.enabled"); - - $length = 1 + int(rand(get_int($c, "lines.maxlines"))); - $lines = gen_lines($c, $length); - $functions = gen_functions($c, $lines) if ($do_fn); - $branches = gen_branches($c, $lines) if ($do_br); - - return [ $length, $lines, $functions, $branches ]; -} - -# Generate fake source tree. -# -# returns: [ files, numlns, numfns, numbrs ] -# files: filename -> filesrc -# filesrc: [ length, lines, functions, branches ] -# length: Total number of lines in file -# -# lines: [ line1, line2, ... ] -# -# functions: [ fn1, fn2, ... ] -# fn: [ fnline, fnname ] -# fnline: Starting line of function -# fnname: Function name -# -# branches: [ brdata1, brdata2, ...] -# brdata: [ brline, block, branch ] -# brline: Line number containing branches -# block: Block ID -# branch: Branch ID -# -sub gen_src($$) -{ - my ($c, $root) = @_; - my %files; - my $numfiles = get_int($c, "files.numfiles"); - my %filenames; - my ($numlns, $numfns, $numbrs) = (0, 0, 0); - - for (my $i = 0; $i < $numfiles; $i++) { - my $filename = gen_filename($c, $root, \%filenames); - my $filesrc = gen_filesrc($c); - - $files{$filename} = $filesrc; - $numlns += scalar(@{$filesrc->[1]}) if (defined($filesrc->[1])); - $numfns += scalar(@{$filesrc->[2]}) if (defined($filesrc->[2])); - $numbrs += scalar(@{$filesrc->[3]}) if (defined($filesrc->[3])); - } - - return [ \%files, $numlns, $numfns, $numbrs ]; -} - -sub write_src($) -{ - my ($src) = @_; - my ($files, $numlns, $numfns, $numbrs) = @$src; - - foreach my $filename (sort(keys(%{$files}))) { - my $filesrc = $files->{$filename}; - my $length = $filesrc->[0]; - my $dir = dirname($filename); - my $fd; - - if (!-d $dir) { - make_path($dir) or - die("Could not create directory $dir\n"); - } - - open($fd, ">", $filename) or - die("Could not create file $filename: $!\n"); - for (my $i = 0; $i < $length; $i++) { - print($fd "\n"); - } - close($fd); - } -} - -sub write_branches($$$$) -{ - my ($fd, $branches, $brhits, $iref) = @_; - my ($found, $hit) = (0, 0); - - # Line coverage data - foreach my $brdata (@$branches) { - my $brhit = $brhits->[$$iref++]; - my ($brline, $block, $branch) = @$brdata; - - $found++; - $hit++ if ($brhit ne "-" && $brhit > 0); - print($fd "BRDA:$brline,$block,$branch,$brhit\n"); - } - if ($found > 0) { - print($fd "BRF:$found\n"); - print($fd "BRH:$hit\n"); - } -} - -sub write_lines($$$$) -{ - my ($fd, $lines, $lnhist, $iref) = @_; - my ($found, $hit) = (0, 0); - - # Line coverage data - foreach my $line (@$lines) { - my $lnhit = $lnhist->[$$iref++]; - - $found++; - $hit++ if ($lnhit > 0); - print($fd "DA:$line,$lnhit\n"); - } - print($fd "LF:$found\n"); - print($fd "LH:$hit\n"); -} - -sub write_functions($$$$) -{ - my ($fd, $functions, $fnhits, $iref) = @_; - my ($found, $hit) = (0, 0); - - # Function coverage data - foreach my $fn (@$functions) { - my ($fnline, $fnname) = @$fn; - - print($fd "FN:$fnline,$fnname\n"); - } - foreach my $fn (@$functions) { - my ($fnline, $fnname) = @$fn; - my $fnhit = $fnhits->[$$iref++]; - - $found++; - $hit++ if ($fnhit > 0); - print($fd "FNDA:$fnhit,$fnname\n"); - } - print($fd "FNF:$found\n"); - print($fd "FNH:$hit\n"); -} - -sub write_filesrc($$$$$) -{ - my ($c, $fd, $filesrc, $hits, $iter) = @_; - my ($length, $lines, $functions, $branches) = @$filesrc; - my $do_ln = get_int($c, "lines.enabled"); - my $do_fn = get_int($c, "functions.enabled"); - my $do_br = get_int($c, "branches.enabled"); - - write_functions($fd, $functions, $hits->[1], \$iter->[1]) if ($do_fn); - write_branches($fd, $branches, $hits->[2], \$iter->[2]) if ($do_br); - write_lines($fd, $lines, $hits->[0], \$iter->[0]) if ($do_ln); -} - -sub write_info($$$$) -{ - my ($c, $filename, $src, $hits) = @_; - my $files = $src->[0]; - my $fd; - my %iters; - - foreach my $testname (keys(%{$hits})) { - $iters{$testname} = [ 0, 0, 0 ]; - } - - open($fd, ">", $filename) or die("Could not create $filename: $!\n"); - - foreach my $filename (sort(keys(%{$files}))) { - my $filesrc = $files->{$filename}; - - foreach my $testname (sort(keys(%{$hits}))) { - my $testhits = $hits->{$testname}; - my $iter = $iters{$testname}; - - print($fd "TN:$testname\n"); - print($fd "SF:$filename\n"); - - write_filesrc($c, $fd, $filesrc, $testhits, $iter); - - print($fd "end_of_record\n"); - } - } - - close($fd); -} - -sub get_hit_found($) -{ - my ($list) = @_; - my ($hit, $found) = (0, 0); - - foreach my $e (@$list) { - $hit++ if ($e ne "-" && $e > 0); - $found++; - } - return ($hit, $found); -} - -sub write_counts($$) -{ - my ($filename, $hits) = @_; - my $fd; - my (@tlnhits, @tfnhits, @tbrhits); - - foreach my $testname (keys(%{$hits})) { - my $testhits = $hits->{$testname}; - my ($lnhits, $fnhits, $brhits) = @$testhits; - - for (my $i = 0; $i < scalar(@$lnhits); $i++) { - $tlnhits[$i] += $lnhits->[$i]; - } - for (my $i = 0; $i < scalar(@$fnhits); $i++) { - $tfnhits[$i] += $fnhits->[$i]; - } - for (my $i = 0; $i < scalar(@$brhits); $i++) { - my $h = $brhits->[$i]; - - $h = 0 if ($h eq "-"); - $tbrhits[$i] += $h; - } - } - - open($fd, ">", $filename) or die("Could not create $filename: $!\n"); - print($fd join(" ", get_hit_found(\@tlnhits), get_hit_found(\@tfnhits), - get_hit_found(\@tbrhits))."\n"); - close($fd); -} - -# A branch hit value for a block that was not hit must be "-". A branch hit -# value for a block that was hit cannot be "-", but must be "0" if not hit. -sub sanitize_brhits($) -{ - my ($brhits) = @_; - my $block_hit = 0; - - foreach my $brhit_ref (@$brhits) { - if ($$brhit_ref ne "-" && $$brhit_ref > 0) { - $block_hit = 1; - last; - } - } - foreach my $brhit_ref (@$brhits) { - if (!$block_hit) { - $$brhit_ref = "-"; - } elsif ($$brhit_ref eq "-") { - $$brhit_ref = 0; - } - } -} - -# Ensure coverage rate interdependencies are met -sub sanitize_hits($$) -{ - my ($src, $hits) = @_; - my $files = $src->[0]; - - foreach my $hits (values(%{$hits})) { - my $brhits = $hits->[2]; - my $i = 0; - - foreach my $filename (sort(keys(%{$files}))) { - my $filesrc = $files->{$filename}; - my $branches = $filesrc->[3]; - my $lastblock; - my $lastline; - my @blist; - - foreach my $brdata (@$branches) { - my ($brline, $block, $branch) = @$brdata; - - if (!defined($lastblock) || - $block != $lastblock || - $brline != $lastline) { - sanitize_brhits(\@blist); - @blist = (); - $lastblock = $block; - $lastline = $brline; - } - push(@blist, \$brhits->[$i++]); - } - sanitize_brhits(\@blist); - } - } -} - -# Generate random coverage data -# -# returns: testname -> testhits -# testhits: [ lnhits, fnhits, brhits ] -# lnhits: [ ln1hit, ln2hit, ... ] -# lnhit: Number of times a line was hit by a specific test -# fnhits: [ fn1hit, fn2hit, ... ] -# fnhit: Number of times a function was hit by a specific test -# brhits: [ br1hit, br2hit, ... ] -# brhit: Number of times a branch was hit by a specific test -sub gen_hits($$) -{ - my ($c, $src) = @_; - my (@lnhits, @fnhits, @brhits); - my ($files, $numlns, $numfns, $numbrs) = @$src; - my $testnames = get_list($c, "tests.names", ""); - my %hits; - - $testnames = [ "" ] if (!@$testnames); - - foreach my $testname (@$testnames) { - my (@lnhits, @fnhits, @brhits); - - for (my $i = 0; $i < $numlns; $i++) { - push(@lnhits, 1 + int(rand($MAX_TAKEN))); - } - - for (my $i = 0; $i < $numfns; $i++) { - push(@fnhits, 1 + int(rand($MAX_TAKEN))); - } - - for (my $i = 0; $i < $numbrs; $i++) { - push(@brhits, 1 + int(rand($MAX_TAKEN))); - } - - $hits{$testname} = [ \@lnhits, \@fnhits, \@brhits ]; - } - - sanitize_hits($src, \%hits); - - return \%hits; -} - -# Return a hash containing RATE percent of indices [0..NUM-1]. -sub gen_filter($$) -{ - my ($num, $rate) = @_; - my @list = (0 .. ($num - 1)); - my %hash; - - reduce_list_per(\@list, $rate); - foreach my $i (@list) { - $hash{$i} = 1; - } - - return \%hash; -} - -# Zero all entries in LIST identified by the indices in FILTER. -sub zero_by_filter($$) -{ - my ($list, $filter) = @_; - - foreach my $i (keys(%{$filter})) { - $list->[$i] = 0; - } -} - -# Add a random number of indices between [0..NUM-1] to FILTER. -sub widen_filter($$) -{ - my ($filter, $num) = @_; - my @list; - - for (my $i = 0; $i < $num; $i++) { - push(@list, $i) if (!exists($filter->{$i})); - } - reduce_list_per(\@list, int(rand(101))); - - foreach my $i (@list) { - $filter->{$i} = 1; - } -} - -# Zero coverage data in HITS until the combined coverage rates reach the -# specified RATEs. -sub reduce_hits($$$$$) -{ - my ($src, $hits, $lnrate, $fnrate, $brrate) = @_; - my ($files, $numlns, $numfns, $numbrs) = @$src; - my ($lnfilter, $fnfilter, $brfilter); - - $lnfilter = gen_filter($numlns, 100 - $lnrate); - $fnfilter = gen_filter($numfns, 100 - $fnrate); - $brfilter = gen_filter($numbrs, 100 - $brrate); - - foreach my $testhits (values(%{$hits})) { - my ($lnhits, $fnhits, $brhits) = @$testhits; - - zero_by_filter($lnhits, $lnfilter); - zero_by_filter($fnhits, $fnfilter); - zero_by_filter($brhits, $brfilter); - - # Provide some variation between tests - widen_filter($lnfilter, $numlns); - widen_filter($fnfilter, $numfns); - widen_filter($brfilter, $numbrs); - } - - sanitize_hits($src, $hits); -} - -sub zero_list($) -{ - my ($list) = @_; - - foreach my $i (@$list) { - $i = 0; - } -} - -# Zero all coverage in HITS. -sub zero_hits($$) -{ - my ($src, $hits) = @_; - - foreach my $testhits (values(%{$hits})) { - my ($lnhits, $fnhits, $brhits) = @$testhits; - - zero_list($lnhits); - zero_list($fnhits); - zero_list($brhits); - } - - sanitize_hits($src, $hits); -} - -# Distribute items from LIST to A and B depending on whether the index for -# an item is found in FILTER. -sub split_by_filter($$$$) -{ - my ($list, $filter, $a, $b) = @_; - - for (my $i = 0; $i < scalar(@$list); $i++) { - if (exists($filter->{$i})) { - push(@$a, $list->[$i]); - push(@$b, 0); - } else { - push(@$a, 0); - push(@$b, $list->[$i]); - } - } -} - -sub split_hits($$$) -{ - my ($c, $src, $hits) = @_; - my ($files, $numlns, $numfns, $numbrs) = @$src; - my ($lnsplit, $fnsplit, $brsplit); - my (%a, %b); - - $lnsplit = gen_filter($numlns, int(rand(101))); - $fnsplit = gen_filter($numfns, int(rand(101))); - $brsplit = gen_filter($numbrs, int(rand(101))); - - foreach my $testname (keys(%{$hits})) { - my $testhits = $hits->{$testname}; - my ($lnhits, $fnhits, $brhits) = @$testhits; - my (@lnhitsa, @fnhitsa, @brhitsa); - my (@lnhitsb, @fnhitsb, @brhitsb); - - split_by_filter($lnhits, $lnsplit, \@lnhitsa, \@lnhitsb); - split_by_filter($fnhits, $fnsplit, \@fnhitsa, \@fnhitsb); - split_by_filter($brhits, $brsplit, \@brhitsa, \@brhitsb); - - $a{$testname} = [ \@lnhitsa, \@fnhitsa, \@brhitsa ]; - $b{$testname} = [ \@lnhitsb, \@fnhitsb, \@brhitsb ]; - } - - sanitize_hits($src, \%a); - sanitize_hits($src, \%b); - - return (\%a, \%b); -} - -sub plural($$$) -{ - my ($num, $sing, $plur) = @_; - - return $num <= 1 ? $sing : $plur; -} - -sub print_intro($) -{ - my ($c) = @_; - my $numtests = scalar(@{get_list($c, "tests.names")}); - my $numfiles = get_int($c, "files.numfiles"); - - $numtests = 1 if ($numtests < 1); - - print($BOLD."Creating coverage files ($numtests ". - plural($numtests, "test", "tests").", $numfiles ". - plural($numfiles, "source file", "source files").")\n".$RESET); -} - -sub main() -{ - my $opt_help; - my $opt_output; - my $opt_configfile; - my $opt_seed = 0; - my $c; - my $src; - my $hits; - my $root; - my $enum; - my ($a, $b); - - # Parse options - if (!GetOptions("output|o=s" => \$opt_output, - "seed=s" => \$opt_seed, - "help|h" => \$opt_help, - )) { - print(STDERR "Use $0 --help to get usage information\n"); - exit(2); - } - - if ($opt_help) { - usage(); - exit(0); - } - - $opt_configfile = shift(@ARGV); - if (!defined($opt_configfile)) { - print(STDERR "Please specify a config file\n"); - exit(2); - } - - if (defined($opt_output)) { - if (! -d $opt_output) { - mkdir($opt_output) or - die("$0: Could not create directory ". - "$opt_output: $!\n"); - } - $root = abs_path($opt_output) - } else { - $root = "/"; - } - - srand($opt_seed); - - # Get config - $c = read_config($opt_configfile); - apply_config($c, \@ARGV) if (@ARGV); - - print_intro($c); - # Show lines on STDOUT without newline - $| = 1; - - # Create source tree - print(" Source tree ......... "); - $src = gen_src($c, $root); - # Write out source code if requested - write_src($src) if (defined($opt_output)); - print("done ("); - print($src->[1]." lines, "); - print($src->[2]." functions, "); - print($src->[3]." branches)\n"); - - # Write out full-coverage data files - print(" Full coverage ....... "); - $hits = gen_hits($c, $src); - write_info($c, "full.info", $src, $hits); - write_counts("full.counts", $hits); - print("done\n"); - - # Write out data files with target coverage rates - print(" Target coverage ..... "); - reduce_hits($src, $hits, get_int($c, "lines.covered"), - get_int($c, "functions.covered"), - get_int($c, "branches.covered")); - write_info($c, "target.info", $src, $hits); - write_counts("target.counts", $hits); - print("done\n"); - - # Write out partial data files - print(" Partial coverage .... "); - ($a, $b) = split_hits($c, $src, $hits); - write_info($c, "part1.info", $src, $a); - write_counts("part1.counts", $a); - write_info($c, "part2.info", $src, $b); - write_counts("part2.counts", $b); - print("done\n"); - - # Write out zero-coverage data files - print(" Zero coverage ....... "); - zero_hits($src, $hits); - write_info($c, "zero.info", $src, $hits); - write_counts("zero.counts", $hits); - print("done\n"); -} - -main(); -exit(0); diff --git a/worker/deps/lcov/test/bin/norminfo b/worker/deps/lcov/test/bin/norminfo deleted file mode 100755 index 9fe0ef2f00..0000000000 --- a/worker/deps/lcov/test/bin/norminfo +++ /dev/null @@ -1,243 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright IBM Corp. 2017 -# -# Usage: norminfo [] -# -# Normalize coverage data file (ensure stable order), perform some sanity -# checks, and apply optional multiplier to execution counts. -# - -use strict; -use warnings; - -sub ferr($$$) -{ - my ($pos, $filename, $msg) = @_; - - if (defined($pos)) { - $pos .= ":"; - } else { - $pos = ""; - } - - die("$0:$filename:$pos $msg"); -} - -sub print_sorted($$$) -{ - my ($fd, $info, $multi) = @_; - my (%fn, %fns, %fnda, %brda, %da); - my ($fnf, $fnh, $brf, $brh, $lf, $lh); - - while (my $line = <$fd>) { - $line =~ s/(^\s*|\s*$)//g; - - if ($line =~ /^end_of_record$/) { - last; - } elsif ($line =~ /^FN:(\d+),(.*)$/) { - my ($lineno, $fnname) = ($1, $2); - - if (exists($fn{$lineno})) { - ferr($., $info, "Duplicate FN: entry\n"); - } - $fn{$lineno} = $fnname; - if (exists($fns{$fnname})) { - ferr($., $info, "Duplicate function name\n"); - } - $fns{$fnname} = $lineno; - } elsif ($line =~ /^FNDA:(\d+),(.*)$/) { - my ($count, $fnname) = ($1, $2); - - if (exists($fnda{$fnname})) { - ferr($., $info, "Duplicate FNDA: entry\n"); - } - $fnda{$fnname} = int($count * $multi); - } elsif ($line =~ /^FNF:(\d+)$/) { - if (defined($fnf)) { - ferr($., $info, "Duplicate FNF: entry\n"); - } - $fnf = $1; - } elsif ($line =~ /^FNH:(\d+)$/) { - if (defined($fnh)) { - ferr($., $info, "Duplicate FNH: entry\n"); - } - $fnh = $1; - } elsif ($line =~ /^BRDA:(\d+),(\d+),(\d+),(\d+|-)$/) { - my ($lineno, $block, $branch, $count) = ($1, $2, $3, $4); - - if (exists($brda{$lineno}->{$block}->{$branch})) { - ferr($., $info, "Duplicate BRDA: entry\n"); - } - $count = int($count * $multi) if ($count ne "-"); - $brda{$lineno}->{$block}->{$branch} = $count; - - } elsif ($line =~ /^BRF:(\d+)$/) { - if (defined($brf)) { - ferr($., $info, "Duplicate BRF: entry\n"); - } - $brf = $1; - } elsif ($line =~ /^BRH:(\d+)$/) { - if (defined($brh)) { - ferr($., $info, "Duplicate BRH: entry\n"); - } - $brh = $1; - } elsif ($line =~ /^DA:(\d+),(\d+)$/) { - my ($lineno, $count) = ($1, $2); - - if (exists($da{$lineno})) { - ferr($., $info, "Duplicate FNDA: entry\n"); - } - $da{$lineno} = int($count * $multi); - } elsif ($line =~ /^LF:(\d+)$/) { - if (defined($lf)) { - ferr($., $info, "Duplicate LF: entry\n"); - } - $lf = $1; - } elsif ($line =~ /^LH:(\d+)$/) { - if (defined($lh)) { - ferr($., $info, "Duplicate LH: entry\n"); - } - $lh = $1; - } else { - ferr($., $info, "Unknown line: $line\n"); - } - } - - # FN:, - foreach my $lineno (sort({ $a <=> $b } keys(%fn))) { - my $fnname = $fn{$lineno}; - print("FN:$lineno,$fnname\n"); - } - - # FNDA:, - foreach my $fnname (keys(%fnda)) { - if (!exists($fns{$fnname})) { - ferr(undef, $info, "FNDA entry without FN: $fnname\n"); - } - } - foreach my $fnname (sort({ $fns{$a} <=> $fns{$b} } keys(%fnda))) { - my $count = $fnda{$fnname}; - print("FNDA:$count,$fnname\n"); - } - # FNF: - print("FNF:$fnf\n") if (defined($fnf)); - # FNH: - if (defined($fnh)) { - $fnh = 0 if ($multi == 0); - print("FNH:$fnh\n"); - } - # BRDA:,,, - foreach my $lineno (sort({ $a <=> $b } keys(%brda))) { - my $blocks = $brda{$lineno}; - - foreach my $block (sort({ $a <=> $b } keys(%{$blocks}))) { - my $branches = $blocks->{$block}; - - foreach my $branch (sort({ $a <=> $b } - keys(%{$branches}))) { - my $count = $branches->{$branch}; - - $count = "-" if ($multi == 0); - print("BRDA:$lineno,$block,$branch,$count\n"); - } - } - - } - # BRF: - print("BRF:$brf\n") if (defined($brf)); - # BRH: - if (defined($brh)) { - $brh = 0 if ($multi == 0); - print("BRH:$brh\n"); - } - # DA:, - foreach my $lineno (sort({ $a <=> $b } keys(%da))) { - my $count = $da{$lineno}; - - print("DA:$lineno,$count\n"); - } - # LF: - print("LF:$lf\n") if (defined($lf)); - # LH: - if (defined($lh)) { - $lh = 0 if ($multi == 0); - print("LH:$lh\n"); - } -} - -sub main() -{ - my $infofile = $ARGV[0]; - my $multi = $ARGV[1]; - # info: testname -> files - # files: infofile -> data - # data: [ starting offset, starting line ] - my %info; - my $fd; - my $tn = ""; - my %allfiles; - - $multi = 1 if (!defined($multi)); - if (!defined($infofile)) { - $infofile = "standard input"; - warn("$0: Reading data from standard input\n"); - open($fd, "<&STDIN") or - die("$0: Could not duplicated stdin: $!\n"); - } else { - open($fd, "<", $infofile) or - die("$0: Could not open $infofile: $!\n"); - } - - # Register starting positions of data sets - while (my $line = <$fd>) { - if ($line =~ /^TN:(.*)$/) { - $tn = $1; - } elsif ($line =~ /^SF:(.*)$/) { - my $sf = $1; - my $pos = tell($fd); - - die("$0: Could not get file position: $!\n") - if ($pos == -1); - if (exists($info{$tn}->{$sf})) { - ferr($., $infofile, - "Duplicate entry for $tn:$sf\n"); - } - $info{$tn}->{$sf} = [ $pos, $. ]; - $allfiles{$sf} = 1; - } - } - - # Print data sets in normalized order - foreach my $filename (sort(keys(%allfiles))) { - foreach my $testname (sort(keys(%info))) { - my $pos = $info{$testname}->{$filename}; - my ($cpos, $lpos) = @$pos; - - next if (!defined($pos)); - - if (seek($fd, $cpos, 0) != 1) { - die("$0: Could not seek in $infofile: $!\n"); - } - printf("TN:$testname\n"); - printf("SF:$filename\n"); - - $. = $lpos; - print_sorted($fd, $infofile, $multi); - - printf("end_of_record\n"); - - } - } - foreach my $testname (sort(keys(%info))) { - my $files = $info{$testname}; - - foreach my $filename (sort(keys(%{$files}))) { - } - } - - close($fd); -} - -main(); -exit(0); diff --git a/worker/deps/lcov/test/bin/test_run b/worker/deps/lcov/test/bin/test_run deleted file mode 100755 index 23e69d0f4e..0000000000 --- a/worker/deps/lcov/test/bin/test_run +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright IBM Corp. 2017 -# -# Usage: test_run -# -# Announce a test case, run it, and record the resulting output in the -# test log file. Must be run after testsuite_init. -# - -TOPDIR=$(realpath $(dirname $0)/..) && source "$TOPDIR/bin/common" -EXCERPTLEN=10 -TESTNAME="$1" -shift - -TIME=$(which time 2>/dev/null) -if [ ! -z "$TIME" ] ; then - TIME="$TIME -v -o $TIMEFILE" - if ! $TIME true 2>/dev/null ; then - TIME="" - fi -fi - -t_announce "$TESTNAME" - -let POS=$(stat -c %s "$LOGFILE")+1 - -t_detail "COMMAND" "\"$*\"" >>"$LOGFILE" -t_detail "OUTPUT" "" >>"$LOGFILE" - -# Run command -$TIME bash -c "$*" 2>&1 | t_indent >>"$LOGFILE" -RC=$? - -# Evaluate output of time command -ELAPSED= -RESIDENT= -SIGNAL= -if [ ! -z "$TIME" ] ; then - while read LINE ; do - case "$LINE" in - "Command terminated by signal"*) SIGNAL=${LINE##* } ;; - "Elapsed"*) ELAPSED=$(elapsed_to_ms ${LINE##* }) ;; - "Maximum resident"*) RESIDENT=${LINE##* } ;; - "Exit status"*) RC=${LINE##* } ;; - esac - done < "$TIMEFILE" - rm -f "$TIMEFILE" -fi - -t_detail "EXITCODE" "$RC" >>"$LOGFILE" - -# Show result -if [ $RC -eq 0 -a -z "$SIGNAL" ] ; then - RESULT="pass" - t_pass "$TESTNAME" -else - if [ -z "$SIGNAL" ] ; then - RESULT="fail" - t_fail "$TESTNAME" - else - RESULT="kill" - t_kill "$TESTNAME" - fi -fi - -if [ ! -z "$SIGNAL" ] ; then - t_detail "SIGNAL" "$SIGNAL" >>"$LOGFILE" -fi - -if [ ! -z "$ELAPSED" ] ; then - echo -n " (time $(($ELAPSED/1000)).$(($ELAPSED%1000/100))s, " - echo "elapsed $TESTNAME $ELAPSED" >> "$COUNTFILE" -fi - -if [ ! -z "$RESIDENT" ] ; then - echo -n "mem $(($RESIDENT/1024)).$((($RESIDENT%1024)/100))MB)" - echo "resident $TESTNAME $RESIDENT" >> "$COUNTFILE" -fi - -echo - -# Show log excerpt on failure or if requested -if [ $RC -ne 0 -o "$V" == "1" ] ; then - LEN=$(tail -c "+$POS" "$LOGFILE" | wc -l) - if [ "$LEN" -gt "$EXCERPTLEN" -a "$V" != "1" ] ; then - tail -c "+$POS" "$LOGFILE" | head -n $EXCERPTLEN | t_indent - let LEN=$LEN-$EXCERPTLEN - echo " ..." - echo " Skipping $LEN more lines (see $LOGFILE)" - else - tail -c "+$POS" "$LOGFILE" | t_indent - fi -fi - -# Log more details -[ ! -z "$ELAPSED" ] && t_detail "TIME" "${ELAPSED}ms" >>"$LOGFILE" -[ ! -z "$RESIDENT" ] && t_detail "MEM" "${RESIDENT}kB" >>"$LOGFILE" -t_detail "RESULT" "$RESULT" >> "$LOGFILE" diff --git a/worker/deps/lcov/test/bin/test_skip b/worker/deps/lcov/test/bin/test_skip deleted file mode 100755 index 202606f4f9..0000000000 --- a/worker/deps/lcov/test/bin/test_skip +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright IBM Corp. 2017 -# -# Usage: test_skip -# -# Announce and record that a single test case was skipped, including an -# optional reason text. Must be run after testsuite_init. -# - -TOPDIR=$(realpath $(dirname $0)/..) && source "$TOPDIR/bin/common" -TESTNAME="$1" -REASON="${*:2}" ; [ -z "$REASON" ] && REASON="" - -t_announce "$TESTNAME" -t_skip "$TESTNAME" -echo -t_detail "REASON" "$REASON" >>"$LOGFILE" -t_detail "REASON" "$REASON" | t_indent diff --git a/worker/deps/lcov/test/bin/testsuite_exit b/worker/deps/lcov/test/bin/testsuite_exit deleted file mode 100755 index 6720df99f2..0000000000 --- a/worker/deps/lcov/test/bin/testsuite_exit +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright IBM Corp. 2017 -# -# Usage: testsuite_exit -# -# Announce end of test suite and show aggregate results. -# - -TOPDIR=$(realpath $(dirname $0)/..) && source "$TOPDIR/bin/common" - -echo "end_time $(date +%s.%N)" >>"$COUNTFILE" - -SUCCESS=0 -FAILED=0 -SKIPPED=0 -TOTAL_TIME=0 -TOTAL_MEM=0 -HAVE_EXT=0 - -# Get results -while read LINE ; do - set -- $LINE - case "$1" in - start_time) START_TIME=$2 ;; - end_time) END_TIME=$2 ;; - pass) let SUCCESS=$SUCCESS+1 ;; - fail) let FAILED=$FAILED+1 ;; - skip) let SKIPPED=$SKIPPED+1 ;; - elapsed) let TOTAL_TIME=$TOTAL_TIME+$3 ; HAVE_EXT=1 ;; - resident) let TOTAL_MEM=$TOTAL_MEM+$3 ; HAVE_EXT=1 ;; - esac -done < "$COUNTFILE" - -exec 3>&1 -exec >>"$LOGFILE" 2>&1 - -t_marker -t_detail "DATE" "$(t_timestamp)" - -let TOTAL=$SUCCESS+$SKIPPED+$FAILED -t_detail "EXECUTED" "$TOTAL" -t_detail "PASSED" "$SUCCESS" -t_detail "FAILED" "$FAILED" -t_detail "SKIPPED" "$SKIPPED" -[ $HAVE_EXT -eq 1 ] && t_detail "TIME" "${TOTAL_TIME}ms" -[ $HAVE_EXT -eq 1 ] && t_detail "MEM" "${TOTAL_MEM}kB" - -TOTAL_TIME=$(($TOTAL_TIME/1000)).$(($TOTAL_TIME%1000/100)) -TOTAL_MEM=$(($TOTAL_MEM/1024)).$((($TOTAL_MEM%1024)/100)) -TOTAL="$BOLD$TOTAL tests executed$RESET" -PASS="$SUCCESS passed" -FAIL="$FAILED failed" -SKIP="$SKIPPED skipped" -TIME="time ${TOTAL_TIME}s" -MEM="mem ${TOTAL_MEM}MB" - -[ "$SUCCESS" -gt 0 ] && PASS="$GREEN$PASS$DEFAULT" -[ "$FAILED" -gt 0 ] && FAIL="$RED$FAIL$DEFAULT" -[ "$SKIPPED" -gt 0 ] && SKIP="$BLUE$SKIP$DEFAULT" - -echo -en "$TOTAL, $PASS, $FAIL, $SKIP$RESET" >&3 -[ $HAVE_EXT -eq 1 ] && echo -n " ($TIME, $MEM)" >&3 -echo >&3 -echo "Result log stored in $LOGFILE" >&3 - -if [ "$FAILED" -gt 0 ] ; then - exit 1 -fi - -exit 0 diff --git a/worker/deps/lcov/test/bin/testsuite_init b/worker/deps/lcov/test/bin/testsuite_init deleted file mode 100755 index f901e35f13..0000000000 --- a/worker/deps/lcov/test/bin/testsuite_init +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright IBM Corp. 2017 -# -# Usage: testsuite_init -# -# Announce start of test suite and prepare log files. -# - -TOPDIR=$(realpath $(dirname $0)/..) && source "$TOPDIR/bin/common" - -echo -e $BOLD"Starting tests"$RESET -echo "start_time $(date +%s.%N)" >"$COUNTFILE" -exec >"$LOGFILE" 2>&1 - -t_detail "DATE" "$(t_timestamp)" - -t_detail "LCOV" "" -lcov --version 2>&1 | t_indent - -t_detail "GCOV" "" -gcov --version 2>&1 | t_indent - -t_detail "CPUINFO" "" -t_indent < /proc/cpuinfo - -t_detail "MEMINFO" "" -t_indent < /proc/meminfo diff --git a/worker/deps/lcov/test/common.mak b/worker/deps/lcov/test/common.mak deleted file mode 100644 index 55f31eb99c..0000000000 --- a/worker/deps/lcov/test/common.mak +++ /dev/null @@ -1,50 +0,0 @@ -TOPDIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) -TESTDIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) -PARENTDIR := $(dir $(patsubst %/,%,$(TOPDIR))) -RELDIR := $(TESTDIR:$(PARENTDIR)%=%) -ZEROINFO := $(TOPDIR)zero.info -ZEROCOUNTS := $(TOPDIR)zero.counts -FULLINFO := $(TOPDIR)full.info -FULLCOUNTS := $(TOPDIR)full.counts -TARGETINFO := $(TOPDIR)target.info -TARGETCOUNTS := $(TOPDIR)target.counts -PART1INFO := $(TOPDIR)part1.info -PART1COUNTS := $(TOPDIR)part1.counts -PART2INFO := $(TOPDIR)part2.info -PART2COUNTS := $(TOPDIR)part2.counts -INFOFILES := $(ZEROINFO) $(FULLINFO) $(TARGETINFO) $(PART1INFO) $(PART2INFO) -COUNTFILES := $(ZEROCOUNTS) $(FULLCOUNTS) $(TARGETCOUNTS) $(PART1COUNTS) \ - $(PART2COUNTS) -LCOVRC := $(TOPDIR)lcovrc -LCOVFLAGS := --config-file $(LCOVRC) -SIZE := small -CC := gcc - -export LCOV := lcov $(LCOVFLAGS) -export GENHTML := genhtml $(LCOVFLAGS) -export PATH := $(TOPDIR)/../bin:$(TOPDIR)/bin:$(PATH) -export LANG := C - -all: prepare init test exit - -init: - testsuite_init - -exit: - testsuite_exit - -prepare: $(INFOFILES) $(COUNTFILES) - -clean: clean_common - -clean_common: - echo " CLEAN $(patsubst %/,%,$(RELDIR))" - -$(INFOFILES) $(COUNTFILES): - cd $(TOPDIR) && mkinfo profiles/$(SIZE) -o src/ - -ifneq ($(V),2) -.SILENT: -endif - -.PHONY: all init exit prepare clean clean_common diff --git a/worker/deps/lcov/test/genhtml_output/Makefile b/worker/deps/lcov/test/genhtml_output/Makefile deleted file mode 100644 index 0fbd882670..0000000000 --- a/worker/deps/lcov/test/genhtml_output/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -include ../common.mak - -GENHTML_TEST := ./genhtml_test - -TESTS := genhtml_output_zero genhtml_output_full genhtml_output_target \ - genhtml_output_part1 genhtml_output_part2 genhtml_output_combined - -test: $(TESTS) - -genhtml_output_zero: - @test_run genhtml_output_zero $(GENHTML) $(ZEROINFO) -o out_zero/ - -genhtml_output_full: - @test_run genhtml_output_full $(GENHTML) $(FULLINFO) -o out_full/ - -genhtml_output_target: - @test_run genhtml_output_target $(GENHTML) $(TARGETINFO) -o out_target/ - -genhtml_output_part1: - @test_run genhtml_output_part1 $(GENHTML) $(PART1INFO) -o out_part1/ - -genhtml_output_part2: - @test_run genhtml_output_part2 $(GENHTML) $(PART2INFO) -o out_part2/ - -genhtml_output_combined: genhtml_output_target - @test_run genhtml_output_combined $(GENHTML_TEST) $(TARGETINFO) $(PART1INFO) $(PART2INFO) - -clean: - rm -rf out_*/ - -.PHONY: test $(TESTS) clean diff --git a/worker/deps/lcov/test/genhtml_output/genhtml_test b/worker/deps/lcov/test/genhtml_output/genhtml_test deleted file mode 100755 index 0b0f834918..0000000000 --- a/worker/deps/lcov/test/genhtml_output/genhtml_test +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright IBM Corp. 2017 -# -# Usage: genhtml_test [...] -# -# Compare genhtml output of a reference coverage data file with that of -# a combination of multiple files. -# - -function die() -{ - echo "Error: $@" >&2 - exit 1 -} - -GENHTMLFLAGS="-t title" -REFFILE=$1 -shift - -if [ -z "$REFFILE" -o -z "$*" ] ; then - echo "Usage: $0 [...]" >&2 - exit 2 -fi - -OUTREF="out_$(basename $REFFILE .info)" -OUTCOMBINED="out_combined" - -$GENHTML $GENHTMLFLAGS "$REFFILE" -o "$OUTREF" || \ - die "Could not generate HTML for reference file" - -$GENHTML $GENHTMLFLAGS "$@" -o "$OUTCOMBINED" || \ - die "Could not generate HTML for combined files" - -diff -ur "$OUTREF" "$OUTCOMBINED" -I "headerValue" || \ - die "Mismatch in generated output" diff --git a/worker/deps/lcov/test/lcov_add_files/Makefile b/worker/deps/lcov/test/lcov_add_files/Makefile deleted file mode 100644 index 87937a1558..0000000000 --- a/worker/deps/lcov/test/lcov_add_files/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -include ../common.mak - -ADDTEST := ./add_test - -TESTS := lcov_add_zero lcov_add_zero2 lcov_add_full lcov_add_full2 \ - lcov_add_part lcov_add_part2 lcov_add_concatenated4 - - -test: $(TESTS) - -lcov_add_zero: - # Add single zero coverage file - output should be same as input - test_run lcov_add_zero $(ADDTEST) 1 "$(ZEROINFO)" "$(ZEROINFO)" - -lcov_add_zero2: - # Add two zero coverage files - output should be same as input - test_run lcov_add_zero2 $(ADDTEST) 1 "$(ZEROINFO)" "$(ZEROINFO)" "$(ZEROINFO)" - -lcov_add_full: - # Add single 100% coverage file - output should be same as input - test_run lcov_add_full $(ADDTEST) 1 "$(FULLINFO)" "$(FULLINFO)" - -lcov_add_full2: - # Add two 100% coverage file and reduce counts to 1/2 - output should - # be same as input - test_run lcov_add_full2 $(ADDTEST) 0.5 "$(FULLINFO)" "$(FULLINFO)" "$(FULLINFO)" - -lcov_add_part: - # Add single coverage file with random coverage rate - output should - # be same as input - test_run lcov_add_part $(ADDTEST) 1 "$(PART1INFO)" "$(PART1INFO)" - -lcov_add_part2: - # Add two coverage files that were split from target file - output - # should be same as target file - test_run lcov_add_part2 $(ADDTEST) 1 "$(TARGETINFO)" "$(PART1INFO)" "$(PART2INFO)" - -lcov_add_concatenated4: - # Add coverage file that consists of 4 concatenation of target files - # and reduce counts to 1/4 - output should be the same as input - cat $(TARGETINFO) $(TARGETINFO) $(TARGETINFO) $(TARGETINFO) >concatenated.info - test_run lcov_add_concatenated4 $(ADDTEST) 0.25 $(TARGETINFO) concatenated.info - -clean: - rm -f *.info - -.PHONY: test $(TESTS) clean diff --git a/worker/deps/lcov/test/lcov_add_files/add_test b/worker/deps/lcov/test/lcov_add_files/add_test deleted file mode 100755 index 4ff5ffeb6c..0000000000 --- a/worker/deps/lcov/test/lcov_add_files/add_test +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright IBM Corp. 2017 -# -# Usage: add_test [...] -# -# Add multiple coverage data files, normalize the output and multiply counts -# with multiplier. Compare against reference file. Report deviations. -# - -MULTI=$1 -REFFILE=$2 -shift 2 - -ADD= -for INFO in $* ; do - ADD="$ADD -a $INFO" -done - -if [ -z "$MULTI" -o -z "$REFFILE" -o -z "$ADD" ] ; then - echo "Usage: $0 [...]" >&2 - exit 1 -fi - -OUTFILE="add_"$(basename "$REFFILE") -SORTFILE="norm_$OUTFILE" - -set -x - -echo "Adding files..." -if ! $LCOV $ADD -o "$OUTFILE" ; then - echo "Error: lcov returned with non-zero exit code $?" >&2 - exit 1 -fi - -echo "Normalizing result..." -if ! norminfo "$OUTFILE" "$MULTI" > "$SORTFILE" ; then - echo "Error: Normalization of lcov result file failed" >&2 - exit 1 -fi - -echo "Comparing with reference..." -if ! diff -u "$REFFILE" "$SORTFILE" ; then - echo "Error: Result of combination differs from reference file" >&2 - exit 1 -fi diff --git a/worker/deps/lcov/test/lcov_diff/Makefile b/worker/deps/lcov/test/lcov_diff/Makefile deleted file mode 100644 index d2d4dd6621..0000000000 --- a/worker/deps/lcov/test/lcov_diff/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../common.mak - -test: - test_run lcov_diff_apply ./diff_test - -clean: - make -C old clean - make -C new clean - rm -f *.info diff diff --git a/worker/deps/lcov/test/lcov_diff/diff_test b/worker/deps/lcov/test/lcov_diff/diff_test deleted file mode 100755 index e0f8c0b308..0000000000 --- a/worker/deps/lcov/test/lcov_diff/diff_test +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright IBM Corp. 2017 -# -# Usage: diff_test -# -# Check lcov's diff function: -# - Compile two slightly different test programs -# - Run the programs and collect coverage data -# - Generate a patch containing the difference between the source code -# - Apply the patch to the coverage data -# - Compare the resulting patched coverage data file with the data from the -# patched source file -# - -function die() -{ - echo "Error: $@" >&2 - exit 1 -} - -make -C old || die "Failed to compile old source" -make -C new || die "Failed to compile new source" -diff -u $PWD/old/prog.c $PWD/new/prog.c > diff - -$LCOV --diff old/prog.info diff --convert-filenames -o patched.info -t bla || \ - die "Failed to apply patch to coverage data file" -norminfo new/prog.info > new_normalized.info -norminfo patched.info > patched_normalized.info -sed -i -e 's/^TN:.*$/TN:/' patched_normalized.info - -diff -u patched_normalized.info new_normalized.info || \ - die "Mismatch in patched coverage data file" - -echo "Patched coverage data file matches expected file" diff --git a/worker/deps/lcov/test/lcov_diff/new/Makefile b/worker/deps/lcov/test/lcov_diff/new/Makefile deleted file mode 100644 index 51005c71dd..0000000000 --- a/worker/deps/lcov/test/lcov_diff/new/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -prog.info: - -include ../../common.mak - -prog.info: prog.gcda - $(LCOV) -c -d . -o prog.info - -prog.gcda: prog - ./prog || true - -prog: prog.c - $(CC) prog.c -o prog --coverage - -clean: - rm -f prog prog.gcda prog.gcno prog.info - -.PHONY: all clean diff --git a/worker/deps/lcov/test/lcov_diff/new/prog.c b/worker/deps/lcov/test/lcov_diff/new/prog.c deleted file mode 100644 index 6f4607cc4f..0000000000 --- a/worker/deps/lcov/test/lcov_diff/new/prog.c +++ /dev/null @@ -1,41 +0,0 @@ - - - -int fn(int x) -{ - switch (x) { - case -1: return 0; - - - case 0: return 2; - case 2: return 3; - - - case 12: return 7; - default: return 255; - } - - - -} - -int fn2() -{ - - - return 7; -} - - - -int main(int argc, char *argv[]) -{ - - - if (argc > 1) - return fn(argc); - - return fn2(); - - -} diff --git a/worker/deps/lcov/test/lcov_diff/old/Makefile b/worker/deps/lcov/test/lcov_diff/old/Makefile deleted file mode 100644 index 51005c71dd..0000000000 --- a/worker/deps/lcov/test/lcov_diff/old/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -prog.info: - -include ../../common.mak - -prog.info: prog.gcda - $(LCOV) -c -d . -o prog.info - -prog.gcda: prog - ./prog || true - -prog: prog.c - $(CC) prog.c -o prog --coverage - -clean: - rm -f prog prog.gcda prog.gcno prog.info - -.PHONY: all clean diff --git a/worker/deps/lcov/test/lcov_diff/old/prog.c b/worker/deps/lcov/test/lcov_diff/old/prog.c deleted file mode 100644 index a4eda25557..0000000000 --- a/worker/deps/lcov/test/lcov_diff/old/prog.c +++ /dev/null @@ -1,22 +0,0 @@ -int fn(int x) -{ - switch (x) { - case -1: return 0; - case 0: return 2; - case 2: return 3; - case 12: return 7; - default: return 255; - } -} - -int fn2() -{ - return 7; -} - -int main(int argc, char *argv[]) -{ - if (argc > 1) - return fn(argc); - return fn2(); -} diff --git a/worker/deps/lcov/test/lcov_misc/Makefile b/worker/deps/lcov/test/lcov_misc/Makefile deleted file mode 100644 index d3bcc4ab28..0000000000 --- a/worker/deps/lcov/test/lcov_misc/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../common.mak - -test: - @test_run lcov_version lcov --version - @test_run lcov_help lcov --help diff --git a/worker/deps/lcov/test/lcov_summary/Makefile b/worker/deps/lcov/test/lcov_summary/Makefile deleted file mode 100644 index f48d0bc766..0000000000 --- a/worker/deps/lcov/test/lcov_summary/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -include ../common.mak - -CHECK := ./check_counts -TESTS := lcov_summary_zero lcov_summary_full lcov_summary_target \ - lcov_summary_part1 lcov_summary_part2 lcov_summary_concatenated \ - lcov_summary_concatenated2 - -test: $(TESTS) - -lcov_summary_zero: - # Compare output of lcov --summary with generated counts - test_run lcov_summary_zero $(CHECK) $(ZEROCOUNTS) $(ZEROINFO) -lcov_summary_full: - # Compare output of lcov --summary with generated counts - test_run lcov_summary_full $(CHECK) $(FULLCOUNTS) $(FULLINFO) -lcov_summary_target: - # Compare output of lcov --summary with generated counts - test_run lcov_summary_target $(CHECK) $(TARGETCOUNTS) $(TARGETINFO) -lcov_summary_part1: - # Compare output of lcov --summary with generated counts - test_run lcov_summary_part1 $(CHECK) $(PART1COUNTS) $(PART1INFO) -lcov_summary_part2: - # Compare output of lcov --summary with generated counts - test_run lcov_summary_part2 $(CHECK) $(PART2COUNTS) $(PART2INFO) -lcov_summary_concatenated: - # Compare output of lcov --summary with generated counts for a - # concatenated coverage data file - cat $(TARGETINFO) $(TARGETINFO) > concatenated.info - test_run lcov_summary_concatenated $(CHECK) $(TARGETCOUNTS) concatenated.info -lcov_summary_concatenated2: - # Compare output of lcov --summary with generated counts for a - # concatenated coverage data file (part1+part2=target) - cat $(PART1INFO) $(PART2INFO) > concatenated2.info - test_run lcov_summary_concatenated2 $(CHECK) $(TARGETCOUNTS) concatenated2.info - - - -clean: - rm -f *.info - -.PHONY: test $(TESTS) clean diff --git a/worker/deps/lcov/test/lcov_summary/check_counts b/worker/deps/lcov/test/lcov_summary/check_counts deleted file mode 100755 index 32d454230c..0000000000 --- a/worker/deps/lcov/test/lcov_summary/check_counts +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright IBM Corp. 2017 -# -# Usage: check_counts -# -# Compare the output of "lcov --summary" for with the -# coverage data counts specified in . This file has the following -# format (all in a single line): -# -# lnhit lnfound fnhit fnfound brhit brfound2 -# - -use strict; -use warnings; - -sub do_cmp($$$) -{ - my ($title, $a, $b) = @_; - - if ($a == $b) { - print("$title: $a == $b\n"); - return 0; - } else { - print("$title: $a != $b => mismatch!\n"); - return 1; - } -} - -my $lcov = $ENV{"LCOV"}; -my ($counts, $info) = @ARGV; -my $fd; -my $cmdline; -my ($lnhit, $lnfound, $fnhit, $fnfound, $brhit, $brfound) = (0, 0, 0, 0, 0, 0); -my ($lnhit2, $lnfound2, $fnhit2, $fnfound2, $brhit2, $brfound2); -my $rc = 0; - -die("$0: LCOV environment variable not defined\n") if (!defined($lcov)); -if (!defined($counts) || !defined($info)) { - die("Usage: $0 \n"); -} - -$cmdline = "$lcov --summary $info"; -open($fd, "-|", $cmdline) or die("$0: Could not run $cmdline: $!\n"); -while (<$fd>) { - ($lnhit, $lnfound) = ($1, $2) if (/(\d+) of (\d+) lines/); - ($fnhit, $fnfound) = ($1, $2) if (/(\d+) of (\d+) functions/); - ($brhit, $brfound) = ($1, $2) if (/(\d+) of (\d+) branches/); -} -close($fd); - -die("$0: Non-zero result code ($?) of command: $cmdline\n") if ($? != 0); - -open($fd, "<", $counts) or die("$0: Could not open $counts: $!\n"); -if (<$fd> !~ /^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/) { - die("$0: Invalid count file: $counts\n"); -} -($lnhit2, $lnfound2, $fnhit2, $fnfound2, $brhit2, $brfound2) = - ($1, $2, $3, $4, $5, $6); -close($fd); - -print("Comparing --summary output for $info and $counts:\n"); -$rc |= do_cmp("line hit", $lnhit, $lnhit2); -$rc |= do_cmp("line found", $lnfound, $lnfound2); -$rc |= do_cmp("functions hit", $fnhit, $fnhit2); -$rc |= do_cmp("functions found", $fnfound, $fnfound2); -$rc |= do_cmp("branches hit", $brhit, $brhit2); -$rc |= do_cmp("branches found", $brfound, $brfound2); - -exit($rc); diff --git a/worker/deps/lcov/test/lcovrc b/worker/deps/lcov/test/lcovrc deleted file mode 100644 index 5005f637d5..0000000000 --- a/worker/deps/lcov/test/lcovrc +++ /dev/null @@ -1,4 +0,0 @@ -# lcovrc file used during tests - -lcov_function_coverage = 1 -lcov_branch_coverage = 1 diff --git a/worker/deps/lcov/test/profiles/large b/worker/deps/lcov/test/profiles/large deleted file mode 100644 index 31788b0409..0000000000 --- a/worker/deps/lcov/test/profiles/large +++ /dev/null @@ -1,51 +0,0 @@ -# Profile of a large source code project. Use with mkinfo to generate fake test -# source code and coverage data. - -[tests] -# List of test names -names = test1 test2 - -[files] -# Create this many files -numfiles = 500 -# Generate paths from these components (top/sub/subsub/prefix_suffix.ext) -top = lib tools test bin img scripts -sub = build debug release include target sys config -subsub = work www utils gui info log basic -prefix = main misc report tune mem list -suffix = a b c top work proto final fast -ext = .c .h - -[lines] -# Generate line coverage data -enabled = 1 -# Line coverage rate -covered = 80 -# Percentage of lines covered -instrumented = 80 -# Maximum number of lines per file -maxlines = 2000 - -[functions] -# Generate function coverage data -enabled = 1 -# Function coverage rate -covered = 60 -# Percent of instrumented lines containing function definitions -perinstrumented = 10 -# Generate function names from these components (verb_adj_noun) -verb = get set find read write stat add sub combine -adj = first last best min max avg -noun = bit byte file str num obj data - -[branches] -# Generate branch coverage data -enabled = 1 -# Branch coverage rate -covered = 20 -# Percent of instrumented lines containing branches -perinstrumented = 5 -# List of blocks to use -blocks = 0 4294967295 -# Distribution of number of branches per block (num:probability) -branchdist = 2:50 3:25 5:20 100:5 diff --git a/worker/deps/lcov/test/profiles/medium b/worker/deps/lcov/test/profiles/medium deleted file mode 100644 index 56598e8682..0000000000 --- a/worker/deps/lcov/test/profiles/medium +++ /dev/null @@ -1,51 +0,0 @@ -# Profile of a medium-sized source code project. Use with mkinfo to generate -# fake test source code and coverage data. - -[tests] -# List of test names -names = test1 test2 test3 - -[files] -# Create this many files -numfiles = 50 -# Generate paths from these components (top/sub/subsub/prefix_suffix.ext) -top = lib tools test bin img scripts -sub = build debug release include target sys config -subsub = work www utils gui info log basic -prefix = main misc report tune mem list -suffix = a b c top work proto final fast -ext = .c .h - -[lines] -# Generate line coverage data -enabled = 1 -# Line coverage rate -covered = 80 -# Percentage of lines covered -instrumented = 50 -# Maximum number of lines per file -maxlines = 1000 - -[functions] -# Generate function coverage data -enabled = 1 -# Function coverage rate -covered = 60 -# Percent of instrumented lines containing function definitions -perinstrumented = 5 -# Generate function names from these components (verb_adj_noun) -verb = get set find read write stat add sub combine -adj = first last best min max avg -noun = bit byte file str num obj data - -[branches] -# Generate branch coverage data -enabled = 1 -# Branch coverage rate -covered = 20 -# Percent of instrumented lines containing branches -perinstrumented = 50 -# List of blocks to use -blocks = 0 4294967295 -# Distribution of number of branches per block (num:probability) -branchdist = 2:50 3:50 diff --git a/worker/deps/lcov/test/profiles/small b/worker/deps/lcov/test/profiles/small deleted file mode 100644 index 388d2a3bb5..0000000000 --- a/worker/deps/lcov/test/profiles/small +++ /dev/null @@ -1,51 +0,0 @@ -# Profile of a small source code project. Use with mkinfo to generate fake test -# source code and coverage data. - -[tests] -# List of test names -names = test1 test2 - -[files] -# Create this many files -numfiles = 5 -# Generate paths from these components (top/sub/subsub/prefix_suffix.ext) -top = lib tools test bin img scripts -sub = build debug release include target sys config -subsub = work www utils gui info log basic -prefix = main misc report tune mem list -suffix = a b c top work proto final fast -ext = .c .h - -[lines] -# Generate line coverage data -enabled = 1 -# Line coverage rate -covered = 80 -# Percentage of lines covered -instrumented = 50 -# Maximum number of lines per file -maxlines = 500 - -[functions] -# Generate function coverage data -enabled = 1 -# Function coverage rate -covered = 60 -# Percent of instrumented lines containing function definitions -perinstrumented = 5 -# Generate function names from these components (verb_adj_noun) -verb = get set find read write stat add sub combine -adj = first last best min max avg -noun = bit byte file str num obj data - -[branches] -# Generate branch coverage data -enabled = 1 -# Branch coverage rate -covered = 20 -# Percent of instrumented lines containing branches -perinstrumented = 50 -# List of blocks to use -blocks = 0 4294967295 -# Distribution of number of branches per block (num:probability) -branchdist = 2:50 3:45 50:5 diff --git a/worker/scripts/lcov.sh b/worker/scripts/lcov.sh index 8052478092..7170e6f284 100755 --- a/worker/scripts/lcov.sh +++ b/worker/scripts/lcov.sh @@ -21,14 +21,12 @@ make test echo ">>> [INFO] generating coverage info file..." $LCOV --no-external --capture --directory ./ --output-file ${COVERAGE_INFO} -echo ">>> [INFO] removing tests from coverage info file..." -$LCOV -r ${COVERAGE_INFO} "$(pwd)/test/*" -o ${COVERAGE_INFO} - -echo ">>> [INFO] removing deps from coverage info file..." +echo ">>> [INFO] removing subdirectories from coverage info file..." $LCOV -r ${COVERAGE_INFO} "$(pwd)/deps/*" -o ${COVERAGE_INFO} - -echo ">>> [INFO] removing json.hpp from coverage info file..." -$LCOV -r ${COVERAGE_INFO} "$(pwd)/include/json.hpp" -o ${COVERAGE_INFO} +$LCOV -r ${COVERAGE_INFO} "$(pwd)/fbs/*" -o ${COVERAGE_INFO} +$LCOV -r ${COVERAGE_INFO} "$(pwd)/fuzzer/*" -o ${COVERAGE_INFO} +$LCOV -r ${COVERAGE_INFO} "$(pwd)/subprojects/*" -o ${COVERAGE_INFO} +$LCOV -r ${COVERAGE_INFO} "$(pwd)/test/*" -o ${COVERAGE_INFO} echo ">>> [INFO] clearing previous report data..." if [[ -d ${HTML_REPORT_DIR} ]] ; then diff --git a/worker/tasks.py b/worker/tasks.py index a04b031edb..404dbe2ee4 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -65,7 +65,6 @@ NINJA_VERSION = os.getenv('NINJA_VERSION') or '1.10.2.4'; PYLINT_VERSION = os.getenv('PYLINT_VERSION') or '3.0.2'; NPM = os.getenv('NPM') or 'npm'; -LCOV = f'{WORKER_DIR}/deps/lcov/bin/lcov'; DOCKER = os.getenv('DOCKER') or 'docker'; # pty=True in ctx.run() is not available on Windows so if stdout is not a TTY # let's assume PTY is not supported. Related issue in invoke project: @@ -396,15 +395,6 @@ def test(ctx): mediasoup_worker_test = 'mediasoup-worker-test.exe' if os.name == 'nt' else 'mediasoup-worker-test'; mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or ''; - # On Windows lcov doesn't work (at least not yet). - if os.name != 'nt': - ctx.run( - f'"{LCOV}" --directory "{WORKER_DIR}" --zerocounters', - echo=True, - pty=PTY_SUPPORTED, - shell=SHELL - ); - with ctx.cd(WORKER_DIR): ctx.run( f'"{BUILD_DIR}/{mediasoup_worker_test}" --invisibles --colour-mode=ansi {mediasoup_test_tags}', From d3bd7293f01118c9e4b94ae4bf749b536c4160c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jan 2024 19:24:21 +0100 Subject: [PATCH 279/525] Rust: remove unnecessary underscore in variable name --- rust/src/router/data_consumer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/src/router/data_consumer.rs b/rust/src/router/data_consumer.rs index bafaffd240..c00c79cdae 100644 --- a/rust/src/router/data_consumer.rs +++ b/rust/src/router/data_consumer.rs @@ -952,7 +952,7 @@ impl DataConsumer { impl DirectDataConsumer { /// Sends direct messages from the Rust process. pub async fn send(&self, message: WebRtcMessage<'_>) -> Result<(), RequestError> { - let (ppid, _payload) = message.into_ppid_and_payload(); + let (ppid, payload) = message.into_ppid_and_payload(); self.inner .channel @@ -960,7 +960,7 @@ impl DirectDataConsumer { self.inner.id, DataConsumerSendRequest { ppid, - payload: _payload.into_owned(), + payload: payload.into_owned(), }, ) .await From bf501b2c1bd12a706f5d8c7989a383bc7f26d5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jan 2024 19:30:32 +0100 Subject: [PATCH 280/525] Rust: remove anoher unnecessary unedrscore --- rust/src/router/data_producer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/src/router/data_producer.rs b/rust/src/router/data_producer.rs index 8660a89c92..fb6396e49d 100644 --- a/rust/src/router/data_producer.rs +++ b/rust/src/router/data_producer.rs @@ -549,13 +549,13 @@ impl DirectDataProducer { subchannels: Option>, required_subchannel: Option, ) -> Result<(), NotificationError> { - let (ppid, _payload) = message.into_ppid_and_payload(); + let (ppid, payload) = message.into_ppid_and_payload(); self.inner.channel.notify( self.inner.id, DataProducerSendNotification { ppid, - payload: _payload.into_owned(), + payload: payload.into_owned(), subchannels, required_subchannel, }, From 5c7ce6c3ff7f9fba9738dd54bb84c4453a1a2f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jan 2024 20:29:34 +0100 Subject: [PATCH 281/525] Rust: expose DataChannel string message as binary (#1289) --- rust/CHANGELOG.md | 4 ++ rust/src/data_structures.rs | 14 +++--- rust/tests/integration/direct_transport.rs | 54 +++++++++++++--------- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index c6148b0170..aeb6714680 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +# NEXT + +* Expose DataChannel string message as binary (PR #1289). + # 0.14.0 * Updates from mediasoup TypeScript `3.13.8..=3.13.12`. diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index a5c2cc1856..b4d41a6167 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -1047,7 +1047,7 @@ impl TraceEventDirection { #[derive(Debug, Clone)] pub enum WebRtcMessage<'a> { /// String - String(String), + String(Cow<'a, [u8]>), /// Binary Binary(Cow<'a, [u8]>), /// EmptyString @@ -1070,9 +1070,7 @@ impl<'a> WebRtcMessage<'a> { pub(crate) fn new(ppid: u32, payload: Cow<'a, [u8]>) -> Result { match ppid { - 51 => Ok(WebRtcMessage::String( - String::from_utf8(payload.to_vec()).unwrap(), - )), + 51 => Ok(WebRtcMessage::String(payload)), 53 => Ok(WebRtcMessage::Binary(payload)), 56 => Ok(WebRtcMessage::EmptyString), 57 => Ok(WebRtcMessage::EmptyBinary), @@ -1082,9 +1080,9 @@ impl<'a> WebRtcMessage<'a> { pub(crate) fn into_ppid_and_payload(self) -> (u32, Cow<'a, [u8]>) { match self { - WebRtcMessage::String(string) => (51_u32, Cow::from(string.into_bytes())), + WebRtcMessage::String(binary) => (51_u32, binary), WebRtcMessage::Binary(binary) => (53_u32, binary), - WebRtcMessage::EmptyString => (56_u32, Cow::from(b" ".as_ref())), + WebRtcMessage::EmptyString => (56_u32, Cow::from(vec![0_u8])), WebRtcMessage::EmptyBinary => (57_u32, Cow::from(vec![0_u8])), } } @@ -1092,7 +1090,7 @@ impl<'a> WebRtcMessage<'a> { /// Convert to owned message pub fn into_owned(self) -> OwnedWebRtcMessage { match self { - WebRtcMessage::String(string) => OwnedWebRtcMessage::String(string), + WebRtcMessage::String(binary) => OwnedWebRtcMessage::String(binary.into_owned()), WebRtcMessage::Binary(binary) => OwnedWebRtcMessage::Binary(binary.into_owned()), WebRtcMessage::EmptyString => OwnedWebRtcMessage::EmptyString, WebRtcMessage::EmptyBinary => OwnedWebRtcMessage::EmptyBinary, @@ -1105,7 +1103,7 @@ impl<'a> WebRtcMessage<'a> { #[derive(Debug, Clone)] pub enum OwnedWebRtcMessage { /// String - String(String), + String(Vec), /// Binary Binary(Vec), /// EmptyString diff --git a/rust/tests/integration/direct_transport.rs b/rust/tests/integration/direct_transport.rs index 6053de0208..e3f9db4bf5 100644 --- a/rust/tests/integration/direct_transport.rs +++ b/rust/tests/integration/direct_transport.rs @@ -202,19 +202,19 @@ fn send_succeeds() { move |message| { let id: usize = match message { - WebRtcMessage::String(string) => { - recv_message_bytes.fetch_add(string.as_bytes().len(), Ordering::SeqCst); - string.parse().unwrap() + WebRtcMessage::String(binary) => { + recv_message_bytes.fetch_add(binary.len(), Ordering::SeqCst); + String::from_utf8(binary.to_vec()).unwrap().parse().unwrap() } WebRtcMessage::Binary(binary) => { recv_message_bytes.fetch_add(binary.len(), Ordering::SeqCst); String::from_utf8(binary.to_vec()).unwrap().parse().unwrap() } WebRtcMessage::EmptyString => { - panic!("Unexpected empty messages!"); + panic!("Unexpected empty message!"); } WebRtcMessage::EmptyBinary => { - panic!("Unexpected empty messages!"); + panic!("Unexpected empty message!"); } }; @@ -266,14 +266,14 @@ fn send_succeeds() { } let message = if id < num_messages / 2 { - let content = id.to_string(); + let content = id.to_string().into_bytes(); sent_message_bytes += content.len(); if !data_producer.paused() && !data_consumer.paused() { effectively_sent_message_bytes += content.len(); } - WebRtcMessage::String(content) + WebRtcMessage::String(Cow::from(content)) } else { let content = id.to_string().into_bytes(); sent_message_bytes += content.len(); @@ -388,9 +388,9 @@ fn send_with_subchannels_succeeds() { move |message| { let text: String = match message { - WebRtcMessage::String(string) => string.parse().unwrap(), + WebRtcMessage::String(binary) => String::from_utf8(binary.to_vec()).unwrap(), _ => { - panic!("Unexpected empty messages!"); + panic!("Unexpected empty message!"); } }; @@ -409,9 +409,9 @@ fn send_with_subchannels_succeeds() { move |message| { let text: String = match message { - WebRtcMessage::String(string) => string.parse().unwrap(), + WebRtcMessage::String(binary) => String::from_utf8(binary.to_vec()).unwrap(), _ => { - panic!("Unexpected empty messages!"); + panic!("Unexpected empty message!"); } }; @@ -444,13 +444,17 @@ fn send_with_subchannels_succeeds() { // Must be received by dataConsumer1 and dataConsumer2. direct_data_producer - .send(WebRtcMessage::String(both.to_string()), None, None) + .send( + WebRtcMessage::String(Cow::Borrowed(both.as_bytes())), + None, + None, + ) .expect("Failed to send message"); // Must be received by dataConsumer1 and dataConsumer2. direct_data_producer .send( - WebRtcMessage::String(both.to_string()), + WebRtcMessage::String(Cow::Borrowed(both.as_bytes())), Some(vec![1, 2]), None, ) @@ -459,7 +463,7 @@ fn send_with_subchannels_succeeds() { // Must be received by dataConsumer1 and dataConsumer2. direct_data_producer .send( - WebRtcMessage::String(both.to_string()), + WebRtcMessage::String(Cow::Borrowed(both.as_bytes())), Some(vec![11, 22, 33]), Some(666), ) @@ -468,7 +472,7 @@ fn send_with_subchannels_succeeds() { // Must not be received by neither dataConsumer1 nor dataConsumer2. direct_data_producer .send( - WebRtcMessage::String(none.to_string()), + WebRtcMessage::String(Cow::Borrowed(none.as_bytes())), Some(vec![3]), Some(666), ) @@ -477,7 +481,7 @@ fn send_with_subchannels_succeeds() { // Must not be received by neither dataConsumer1 nor dataConsumer2. direct_data_producer .send( - WebRtcMessage::String(none.to_string()), + WebRtcMessage::String(Cow::Borrowed(none.as_bytes())), Some(vec![666]), Some(3), ) @@ -485,18 +489,26 @@ fn send_with_subchannels_succeeds() { // Must be received by dataConsumer1. direct_data_producer - .send(WebRtcMessage::String(dc1.to_string()), Some(vec![1]), None) + .send( + WebRtcMessage::String(Cow::Borrowed(dc1.as_bytes())), + Some(vec![1]), + None, + ) .expect("Failed to send message"); // Must be received by dataConsumer1. direct_data_producer - .send(WebRtcMessage::String(dc1.to_string()), Some(vec![11]), None) + .send( + WebRtcMessage::String(Cow::Borrowed(dc1.as_bytes())), + Some(vec![11]), + None, + ) .expect("Failed to send message"); // Must be received by dataConsumer1. direct_data_producer .send( - WebRtcMessage::String(dc1.to_string()), + WebRtcMessage::String(Cow::Borrowed(dc1.as_bytes())), Some(vec![666]), Some(11), ) @@ -505,7 +517,7 @@ fn send_with_subchannels_succeeds() { // Must be received by dataConsumer2. direct_data_producer .send( - WebRtcMessage::String(dc2.to_string()), + WebRtcMessage::String(Cow::Borrowed(dc2.as_bytes())), Some(vec![666]), Some(2), ) @@ -522,7 +534,7 @@ fn send_with_subchannels_succeeds() { // Must be received by dataConsumer2. direct_data_producer .send( - WebRtcMessage::String(both.to_string()), + WebRtcMessage::String(Cow::Borrowed(both.as_bytes())), Some(vec![1]), Some(666), ) From 885f69dae55f323576254e03942093933aa325a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jan 2024 20:34:28 +0100 Subject: [PATCH 282/525] Update Cargo versions (#1290) --- Cargo.lock | 4 ++-- rust/CHANGELOG.md | 2 +- rust/Cargo.toml | 4 ++-- worker/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa5dfcfb45..cf796abe99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1354,7 +1354,7 @@ checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" [[package]] name = "mediasoup" -version = "0.14.0" +version = "0.15.0" dependencies = [ "actix", "actix-web", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "mediasoup-sys" -version = "0.7.1" +version = "0.7.2" dependencies = [ "planus", "planus-codegen", diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index aeb6714680..3295e1d7d6 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -# NEXT +# 0.15.0 * Expose DataChannel string message as binary (PR #1289). diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 66ed81c861..270c2e4758 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup" -version = "0.14.0" +version = "0.15.0" description = "Cutting Edge WebRTC Video Conferencing in Rust" categories = ["api-bindings", "multimedia", "network-programming"] authors = ["Nazar Mokrynskyi "] @@ -46,7 +46,7 @@ version = "0.8.1" [dependencies.mediasoup-sys] path = "../worker" -version = "0.7.1" +version = "0.7.2" [dependencies.parking_lot] version = "0.12.1" diff --git a/worker/Cargo.toml b/worker/Cargo.toml index c3911071e9..1a55b6831c 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup-sys" -version = "0.7.1" +version = "0.7.2" description = "FFI bindings to C++ libmediasoup-worker" authors = ["Nazar Mokrynskyi "] edition = "2021" From 0823b67210cf1b265168b0b59f3ceb133f6f7d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jan 2024 21:05:59 +0100 Subject: [PATCH 283/525] codeql CI action: upgrade to v3 --- .github/workflows/codeql.yaml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 16625708a3..0c297c1cb2 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -23,6 +23,7 @@ jobs: analyze: name: Analyze runs-on: ubuntu-latest + timeout-minutes: 360 permissions: actions: read contents: read @@ -31,8 +32,10 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'cpp', 'javascript', 'python' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + language: [ 'c-cpp', 'javascript-typescript', 'python' ] + # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] + # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support env: @@ -44,7 +47,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -61,7 +64,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -74,6 +77,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: '/language:${{matrix.language}}' From a36f2c29c03714617a917b41752a7d3e35d47203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 2 Jan 2024 10:39:25 +0100 Subject: [PATCH 284/525] jest: ignore /target folder This changes avoids warning like this: ``` jest-haste-map: Haste module naming collision: mediasoup-worker-dev-tools The following files share their name; please adjust your hasteImpl: * /target/package/mediasoup-sys-0.7.1/scripts/package.json * /target/package/mediasoup-sys-0.7.2/scripts/package.json ``` --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e0ca6a86ae..84607ed4a3 100644 --- a/package.json +++ b/package.json @@ -92,8 +92,9 @@ ], "cacheDirectory": ".cache/jest", "modulePathIgnorePatterns": [ - "worker/", - "rust/" + "worker", + "rust", + "target" ] }, "dependencies": { From ac2bbcb7259f2b73bcb71f1474034ea74af3ebda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 11:42:36 +0100 Subject: [PATCH 285/525] ListenInfo: Add transport socket flags (#1291) --- .github/workflows/mediasoup-node.yaml | 1 + .../workflows/mediasoup-worker-prebuild.yaml | 1 + .github/workflows/mediasoup-worker.yaml | 1 + CHANGELOG.md | 1 + node/src/Router.ts | 17 ++- node/src/Transport.ts | 21 ++++ node/src/Worker.ts | 3 +- node/src/tests/test-PlainTransport.ts | 80 +++++++++++++ npm-scripts.mjs | 8 +- rust/benches/producer.rs | 1 + rust/examples/echo.rs | 1 + rust/examples/multiopus.rs | 2 + rust/examples/svc-simulcast.rs | 1 + rust/examples/videoroom.rs | 1 + rust/src/data_structures.rs | 28 +++++ rust/src/router.rs | 8 ++ rust/src/router/consumer/tests.rs | 1 + rust/src/router/data_consumer/tests.rs | 3 + rust/src/router/data_producer/tests.rs | 1 + rust/src/router/pipe_transport/tests.rs | 1 + rust/src/router/plain_transport.rs | 4 +- rust/src/router/plain_transport/tests.rs | 1 + rust/src/router/producer/tests.rs | 1 + rust/src/router/webrtc_transport/tests.rs | 5 + rust/src/webrtc_server/tests.rs | 1 + rust/tests/integration/consumer.rs | 1 + rust/tests/integration/data_consumer.rs | 4 + rust/tests/integration/data_producer.rs | 2 + rust/tests/integration/multiopus.rs | 1 + rust/tests/integration/pipe_transport.rs | 7 ++ rust/tests/integration/plain_transport.rs | 113 ++++++++++++++++++ rust/tests/integration/producer.rs | 1 + rust/tests/integration/smoke.rs | 2 + rust/tests/integration/webrtc_server.rs | 11 ++ rust/tests/integration/webrtc_transport.rs | 17 +++ worker/fbs/transport.fbs | 10 +- worker/include/Logger.hpp | 13 ++ worker/include/RTC/PortManager.hpp | 23 ++-- worker/include/RTC/TcpServer.hpp | 13 +- worker/include/RTC/Transport.hpp | 7 ++ worker/include/RTC/UdpSocket.hpp | 5 +- worker/src/RTC/PipeTransport.cpp | 23 ++-- worker/src/RTC/PlainTransport.cpp | 48 +++----- worker/src/RTC/PortManager.cpp | 73 ++++++++--- worker/src/RTC/TcpServer.cpp | 18 ++- worker/src/RTC/UdpSocket.cpp | 9 +- worker/src/RTC/WebRtcServer.cpp | 13 +- worker/src/RTC/WebRtcTransport.cpp | 13 +- 48 files changed, 519 insertions(+), 101 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 5e61e6bc1a..0618603bc7 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -28,6 +28,7 @@ jobs: env: MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' + MEDIASOUP_LOCAL_DEV: 'true' steps: - name: Checkout diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index b399fbe89d..1291c95adc 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -32,6 +32,7 @@ jobs: CC: ${{ matrix.build.cc }} CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' + MEDIASOUP_LOCAL_DEV: 'true' steps: - name: Checkout diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 5405601601..6192e75475 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -44,6 +44,7 @@ jobs: CC: ${{ matrix.build.cc }} CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' + MEDIASOUP_LOCAL_DEV: 'true' steps: - name: Checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index f24bb46fc8..0f01d306c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### NEXT * Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). +* `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). ### 3.13.13 diff --git a/node/src/Router.ts b/node/src/Router.ts index 9b836f67ad..9de04034d5 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -7,7 +7,8 @@ import { Transport, TransportListenInfo, TransportListenIp, - TransportProtocol + TransportProtocol, + TransportSocketFlags } from './Transport'; import { WebRtcTransport, WebRtcTransportOptions, parseWebRtcTransportDumpResponse } from './WebRtcTransport'; import { PlainTransport, PlainTransportOptions, parsePlainTransportDumpResponse } from './PlainTransport'; @@ -570,6 +571,7 @@ export class Router listenInfo.ip, listenInfo.announcedIp, listenInfo.port, + socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, listenInfo.recvBufferSize )); @@ -749,6 +751,7 @@ export class Router listenInfo!.ip, listenInfo!.announcedIp, listenInfo!.port, + socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, listenInfo!.recvBufferSize ), @@ -759,6 +762,7 @@ export class Router rtcpListenInfo.ip, rtcpListenInfo.announcedIp, rtcpListenInfo.port, + socketFlagsToFbs(rtcpListenInfo.flags), rtcpListenInfo.sendBufferSize, rtcpListenInfo.recvBufferSize ) : undefined, @@ -897,6 +901,7 @@ export class Router listenInfo!.ip, listenInfo!.announcedIp, listenInfo!.port, + socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, listenInfo!.recvBufferSize ), @@ -1619,3 +1624,13 @@ export function parseRouterDumpResponse( mapDataConsumerIdDataProducerId : parseStringStringVector(binary, 'mapDataConsumerIdDataProducerId') }; } + +export function socketFlagsToFbs( + flags: TransportSocketFlags = {} +): FbsTransport.SocketFlagsT +{ + return new FbsTransport.SocketFlagsT( + Boolean(flags.ipv6Only), + Boolean(flags.udpReusePort) + ); +} diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 7ae79d39df..d04f863927 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -73,6 +73,11 @@ export type TransportListenInfo = */ port?: number; + /** + * Socket flags. + */ + flags?: TransportSocketFlags; + /** * Send buffer size (bytes). */ @@ -107,6 +112,22 @@ export type TransportListenIp = */ export type TransportProtocol = 'udp' | 'tcp'; +/** + * UDP/TCP socket flags. + */ +export type TransportSocketFlags = +{ + /** + * Disable dual-stack support so only IPv6 is used (only if ip is IPv6). + */ + ipv6Only?: boolean; + /** + * Make different transports bind to the same ip and port (only for UDP). + * Useful for multicast scenarios with plain transport. Use with caution. + */ + udpReusePort?: boolean; +}; + export type TransportTuple = { localIp: string; diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 44cee98b4b..56a6d7c813 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -6,7 +6,7 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import * as ortc from './ortc'; import { Channel } from './Channel'; -import { Router, RouterOptions } from './Router'; +import { Router, RouterOptions, socketFlagsToFbs } from './Router'; import { WebRtcServer, WebRtcServerOptions } from './WebRtcServer'; import { RtpCodecCapability } from './RtpParameters'; import { AppData } from './types'; @@ -699,6 +699,7 @@ export class Worker listenInfo.ip, listenInfo.announcedIp, listenInfo.port, + socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, listenInfo.recvBufferSize) ); diff --git a/node/src/tests/test-PlainTransport.ts b/node/src/tests/test-PlainTransport.ts index 3e75c50586..554d07444a 100644 --- a/node/src/tests/test-PlainTransport.ts +++ b/node/src/tests/test-PlainTransport.ts @@ -1,7 +1,10 @@ +import * as os from 'node:os'; // @ts-ignore import * as pickPort from 'pick-port'; import * as mediasoup from '../'; +const IS_WINDOWS = os.platform() === 'win32'; + let worker: mediasoup.types.Worker; let router: mediasoup.types.Router; let transport: mediasoup.types.PlainTransport; @@ -316,6 +319,83 @@ test('router.createPlainTransport() with non bindable IP rejects with Error', as .toThrow(Error); }, 2000); +if (!IS_WINDOWS) +{ + test('two transports binding to the same IP:port with udpReusePort flag succeed', async () => + { + let transport1: mediasoup.types.PlainTransport | undefined; + let transport2: mediasoup.types.PlainTransport | undefined; + + await expect(async () => + { + const multicastIp = '224.0.0.1'; + const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); + + transport1 = await router.createPlainTransport( + { + listenInfo : + { + protocol : 'udp', + ip : multicastIp, + port : port, + flags : { udpReusePort: true } + } + }); + + transport2 = await router.createPlainTransport( + { + listenInfo : + { + protocol : 'udp', + ip : multicastIp, + port : port, + flags : { udpReusePort: true } + } + }); + }).not.toThrow(); + + transport1?.close(); + transport2?.close(); + }, 2000); + + test('two transports binding to the same IP:port without udpReusePort flag fails', async () => + { + let transport1: mediasoup.types.PlainTransport | undefined; + let transport2: mediasoup.types.PlainTransport | undefined; + + await expect(async () => + { + const multicastIp = '224.0.0.1'; + const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); + + transport1 = await router.createPlainTransport( + { + listenInfo : + { + protocol : 'udp', + ip : multicastIp, + port : port, + flags : { udpReusePort: false } + } + }); + + transport2 = await router.createPlainTransport( + { + listenInfo : + { + protocol : 'udp', + ip : multicastIp, + port : port, + flags : { udpReusePort: false } + } + }); + }).rejects.toThrow(); + + transport1?.close(); + transport2?.close(); + }, 2000); +} + test('plainTransport.getStats() succeeds', async () => { const data = await transport.getStats(); diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 6dab36a258..a734c35e33 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -1,7 +1,7 @@ -import process from 'node:process'; -import os from 'node:os'; -import fs from 'node:fs'; -import path from 'node:path'; +import * as process from 'node:process'; +import * as os from 'node:os'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; import { execSync } from 'node:child_process'; import fetch from 'node-fetch'; import tar from 'tar'; diff --git a/rust/benches/producer.rs b/rust/benches/producer.rs index a6a5e87c64..c9b98870dc 100644 --- a/rust/benches/producer.rs +++ b/rust/benches/producer.rs @@ -67,6 +67,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/examples/echo.rs b/rust/examples/echo.rs index fd8027d83c..c64ed714d4 100644 --- a/rust/examples/echo.rs +++ b/rust/examples/echo.rs @@ -187,6 +187,7 @@ impl EchoConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/examples/multiopus.rs b/rust/examples/multiopus.rs index 341c9d8a0c..a4f2f7be02 100644 --- a/rust/examples/multiopus.rs +++ b/rust/examples/multiopus.rs @@ -150,6 +150,7 @@ impl EchoConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -235,6 +236,7 @@ impl EchoConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), diff --git a/rust/examples/svc-simulcast.rs b/rust/examples/svc-simulcast.rs index 3cfd318b9b..959d7ce056 100644 --- a/rust/examples/svc-simulcast.rs +++ b/rust/examples/svc-simulcast.rs @@ -207,6 +207,7 @@ impl SvcSimulcastConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/examples/videoroom.rs b/rust/examples/videoroom.rs index ef818d8be2..ff7a6a0794 100644 --- a/rust/examples/videoroom.rs +++ b/rust/examples/videoroom.rs @@ -501,6 +501,7 @@ mod participant { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index b4d41a6167..07fb5247af 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -62,6 +62,9 @@ pub struct ListenInfo { /// Listening port. #[serde(skip_serializing_if = "Option::is_none")] pub port: Option, + /// Socket flags. + #[serde(skip_serializing_if = "Option::is_none")] + pub flags: Option, /// Send buffer size (bytes). #[serde(skip_serializing_if = "Option::is_none")] pub send_buffer_size: Option, @@ -80,12 +83,37 @@ impl ListenInfo { ip: self.ip.to_string(), announced_ip: self.announced_ip.map(|ip| ip.to_string()), port: self.port.unwrap_or(0), + flags: Box::new(self.flags.unwrap_or_default().to_fbs()), send_buffer_size: self.send_buffer_size.unwrap_or(0), recv_buffer_size: self.recv_buffer_size.unwrap_or(0), } } } +/// UDP/TCP socket flags. +#[derive( + Default, Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize, +)] +#[serde(rename_all = "camelCase")] +pub struct SocketFlags { + /// Disable dual-stack support so only IPv6 is used (only if ip is IPv6). + /// Defaults to false. + pub ipv6_only: bool, + /// Make different transports bind to the same ip and port (only for UDP). + /// Useful for multicast scenarios with plain transport. Use with caution. + /// Defaults to false. + pub udp_reuse_port: bool, +} + +impl SocketFlags { + pub(crate) fn to_fbs(self) -> transport::SocketFlags { + transport::SocketFlags { + ipv6_only: self.ipv6_only, + udp_reuse_port: self.udp_reuse_port, + } + } +} + /// ICE role. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] diff --git a/rust/src/router.rs b/rust/src/router.rs index c2d09a0228..931593932c 100644 --- a/rust/src/router.rs +++ b/rust/src/router.rs @@ -147,6 +147,7 @@ impl PipeToRouterOptions { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }, @@ -609,6 +610,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), /// port: None, + /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, /// }, @@ -696,6 +698,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), /// port: None, + /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, /// })) @@ -761,6 +764,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), /// port: None, + /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, /// })) @@ -971,6 +975,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), /// port: None, + /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, /// }, @@ -1013,6 +1018,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), /// port: None, + /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, /// }, @@ -1198,6 +1204,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), /// port: None, + /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, /// }, @@ -1229,6 +1236,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_ip: Some("9.9.9.1".parse().unwrap()), /// port: None, + /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, /// }, diff --git a/rust/src/router/consumer/tests.rs b/rust/src/router/consumer/tests.rs index 8f4fe2a74a..94a5b2f9b6 100644 --- a/rust/src/router/consumer/tests.rs +++ b/rust/src/router/consumer/tests.rs @@ -87,6 +87,7 @@ async fn init() -> (Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/src/router/data_consumer/tests.rs b/rust/src/router/data_consumer/tests.rs index 7ef9a80588..64a2dd884f 100644 --- a/rust/src/router/data_consumer/tests.rs +++ b/rust/src/router/data_consumer/tests.rs @@ -41,6 +41,7 @@ async fn init() -> (Router, DataProducer) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); @@ -74,6 +75,7 @@ fn data_producer_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -127,6 +129,7 @@ fn transport_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); diff --git a/rust/src/router/data_producer/tests.rs b/rust/src/router/data_producer/tests.rs index 3bbb34db02..52b585b162 100644 --- a/rust/src/router/data_producer/tests.rs +++ b/rust/src/router/data_producer/tests.rs @@ -41,6 +41,7 @@ async fn init() -> (Router, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/src/router/pipe_transport/tests.rs b/rust/src/router/pipe_transport/tests.rs index 54a1f22a48..4e57984bcf 100644 --- a/rust/src/router/pipe_transport/tests.rs +++ b/rust/src/router/pipe_transport/tests.rs @@ -103,6 +103,7 @@ async fn init() -> (Router, Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/src/router/plain_transport.rs b/rust/src/router/plain_transport.rs index 8988b6d37b..33debb2fbf 100644 --- a/rust/src/router/plain_transport.rs +++ b/rust/src/router/plain_transport.rs @@ -837,8 +837,8 @@ impl PlainTransport { /// # async fn f( /// # plain_transport: mediasoup::plain_transport::PlainTransport, /// # ) -> Result<(), Box> { - /// // Calling connect() on a PlainTransport created with comedia unset, rtcpMux - /// // set and enableSrtp enabled. + /// // Calling connect() on a PlainTransport created with comedia unset, + /// // rtcp_mux set and enableSrtp enabled. /// plain_transport /// .connect(PlainTransportRemoteParameters { /// ip: Some("1.2.3.4".parse().unwrap()), diff --git a/rust/src/router/plain_transport/tests.rs b/rust/src/router/plain_transport/tests.rs index fcff706c5f..a0f0af8d16 100644 --- a/rust/src/router/plain_transport/tests.rs +++ b/rust/src/router/plain_transport/tests.rs @@ -42,6 +42,7 @@ fn router_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); diff --git a/rust/src/router/producer/tests.rs b/rust/src/router/producer/tests.rs index 92533c3c32..21e18c21d7 100644 --- a/rust/src/router/producer/tests.rs +++ b/rust/src/router/producer/tests.rs @@ -72,6 +72,7 @@ async fn init() -> (Router, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/src/router/webrtc_transport/tests.rs b/rust/src/router/webrtc_transport/tests.rs index 42d54678ee..fe8a81de43 100644 --- a/rust/src/router/webrtc_transport/tests.rs +++ b/rust/src/router/webrtc_transport/tests.rs @@ -57,6 +57,7 @@ fn create_with_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port1), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -65,6 +66,7 @@ fn create_with_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port2), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -233,6 +235,7 @@ fn router_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -274,6 +277,7 @@ fn webrtc_server_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port1), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -282,6 +286,7 @@ fn webrtc_server_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port2), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); diff --git a/rust/src/webrtc_server/tests.rs b/rust/src/webrtc_server/tests.rs index a07c32c648..95f257bc77 100644 --- a/rust/src/webrtc_server/tests.rs +++ b/rust/src/webrtc_server/tests.rs @@ -38,6 +38,7 @@ fn worker_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port), + flags: None, send_buffer_size: None, recv_buffer_size: None, }, diff --git a/rust/tests/integration/consumer.rs b/rust/tests/integration/consumer.rs index 8a4746365b..54338b00a2 100644 --- a/rust/tests/integration/consumer.rs +++ b/rust/tests/integration/consumer.rs @@ -352,6 +352,7 @@ async fn init() -> ( ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/tests/integration/data_consumer.rs b/rust/tests/integration/data_consumer.rs index d18e21d540..8ae3ed3cf1 100644 --- a/rust/tests/integration/data_consumer.rs +++ b/rust/tests/integration/data_consumer.rs @@ -68,6 +68,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, DataProducer) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); @@ -99,6 +100,7 @@ fn consume_data_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -208,6 +210,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -572,6 +575,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); diff --git a/rust/tests/integration/data_producer.rs b/rust/tests/integration/data_producer.rs index e753ff5eb5..31516da931 100644 --- a/rust/tests/integration/data_producer.rs +++ b/rust/tests/integration/data_producer.rs @@ -54,6 +54,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); @@ -72,6 +73,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); diff --git a/rust/tests/integration/multiopus.rs b/rust/tests/integration/multiopus.rs index 650b450cd0..f05170401e 100644 --- a/rust/tests/integration/multiopus.rs +++ b/rust/tests/integration/multiopus.rs @@ -135,6 +135,7 @@ async fn init() -> (Router, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/tests/integration/pipe_transport.rs b/rust/tests/integration/pipe_transport.rs index 242c37a483..32a8170e96 100644 --- a/rust/tests/integration/pipe_transport.rs +++ b/rust/tests/integration/pipe_transport.rs @@ -261,6 +261,7 @@ async fn init() -> ( ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); @@ -605,6 +606,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -639,6 +641,7 @@ fn create_with_fixed_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port), + flags: None, send_buffer_size: None, recv_buffer_size: None, }) @@ -662,6 +665,7 @@ fn create_with_enable_rtx_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -774,6 +778,7 @@ fn create_with_enable_srtp_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -829,6 +834,7 @@ fn create_with_invalid_srtp_parameters_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })) @@ -1155,6 +1161,7 @@ fn pipe_to_router_called_twice_generates_single_pair() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/tests/integration/plain_transport.rs b/rust/tests/integration/plain_transport.rs index c968c395b5..5fc334fca6 100644 --- a/rust/tests/integration/plain_transport.rs +++ b/rust/tests/integration/plain_transport.rs @@ -1,5 +1,7 @@ use futures_lite::future; use hash_hasher::HashedSet; +#[cfg(not(target_os = "windows"))] +use mediasoup::data_structures::SocketFlags; use mediasoup::data_structures::{AppData, ListenInfo, Protocol, SctpState, TransportTuple}; use mediasoup::plain_transport::{PlainTransportOptions, PlainTransportRemoteParameters}; use mediasoup::prelude::*; @@ -94,6 +96,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -132,6 +135,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -205,6 +209,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -215,6 +220,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(rtcp_port), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -282,6 +288,7 @@ fn create_with_fixed_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), port: Some(port), + flags: None, send_buffer_size: None, recv_buffer_size: None, }) @@ -305,6 +312,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -338,6 +346,7 @@ fn create_enable_srtp_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -403,6 +412,7 @@ fn create_non_bindable_ip() { ip: "8.8.8.8".parse().unwrap(), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })) @@ -412,6 +422,105 @@ fn create_non_bindable_ip() { }); } +#[cfg(not(target_os = "windows"))] +#[test] +fn create_two_transports_binding_to_same_ip_port_with_udp_reuse_port_flag_succeed() { + future::block_on(async move { + let (_worker, router) = init().await; + + let multicast_ip = "224.0.0.1".parse().unwrap(); + let port = pick_unused_port().unwrap(); + + let transport1 = router + .create_plain_transport({ + PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, + ip: multicast_ip, + announced_ip: None, + port: Some(port), + flags: Some(SocketFlags { + ipv6_only: false, + udp_reuse_port: true, + }), + send_buffer_size: None, + recv_buffer_size: None, + }) + }) + .await + .expect("Failed to create first Plain transport"); + + let transport2 = router + .create_plain_transport({ + PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, + ip: multicast_ip, + announced_ip: None, + port: Some(port), + flags: Some(SocketFlags { + ipv6_only: false, + udp_reuse_port: true, + }), + send_buffer_size: None, + recv_buffer_size: None, + }) + }) + .await + .expect("Failed to create second Plain transport"); + + assert_eq!(transport1.tuple().local_port(), port); + assert_eq!(transport2.tuple().local_port(), port); + }); +} + +#[cfg(not(target_os = "windows"))] +#[test] +fn create_two_transports_binding_to_same_ip_port_without_udp_reuse_port_flag_fails() { + future::block_on(async move { + let (_worker, router) = init().await; + + let multicast_ip = "224.0.0.1".parse().unwrap(); + let port = pick_unused_port().unwrap(); + + let transport1 = router + .create_plain_transport({ + PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, + ip: multicast_ip, + announced_ip: None, + port: Some(port), + flags: Some(SocketFlags { + ipv6_only: false, + udp_reuse_port: false, + }), + send_buffer_size: None, + recv_buffer_size: None, + }) + }) + .await + .expect("Failed to create first Plain transport"); + + assert!(matches!( + router + .create_plain_transport(PlainTransportOptions::new(ListenInfo { + protocol: Protocol::Udp, + ip: multicast_ip, + announced_ip: None, + port: Some(port), + flags: Some(SocketFlags { + ipv6_only: false, + udp_reuse_port: false, + }), + send_buffer_size: None, + recv_buffer_size: None, + })) + .await, + Err(RequestError::Response { .. }), + )); + + assert_eq!(transport1.tuple().local_port(), port); + }); +} + #[test] fn get_stats_succeeds() { future::block_on(async move { @@ -424,6 +533,7 @@ fn get_stats_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -481,6 +591,7 @@ fn connect_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -556,6 +667,7 @@ fn connect_wrong_arguments() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -596,6 +708,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("4.4.4.4".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); diff --git a/rust/tests/integration/producer.rs b/rust/tests/integration/producer.rs index 7b05c34083..909d5cbac4 100644 --- a/rust/tests/integration/producer.rs +++ b/rust/tests/integration/producer.rs @@ -207,6 +207,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); diff --git a/rust/tests/integration/smoke.rs b/rust/tests/integration/smoke.rs index 2f1a46f658..7008ad5e83 100644 --- a/rust/tests/integration/smoke.rs +++ b/rust/tests/integration/smoke.rs @@ -88,6 +88,7 @@ fn smoke() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, })); @@ -274,6 +275,7 @@ fn smoke() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); diff --git a/rust/tests/integration/webrtc_server.rs b/rust/tests/integration/webrtc_server.rs index f02cb765be..76b25a8dc7 100644 --- a/rust/tests/integration/webrtc_server.rs +++ b/rust/tests/integration/webrtc_server.rs @@ -64,6 +64,7 @@ fn create_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port1), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -72,6 +73,7 @@ fn create_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), port: Some(port2), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -158,6 +160,7 @@ fn create_webrtc_server_without_specifying_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -166,6 +169,7 @@ fn create_webrtc_server_without_specifying_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -239,6 +243,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port1), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -247,6 +252,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)), announced_ip: None, port: Some(port2), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -270,6 +276,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port1), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -278,6 +285,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), port: Some(port1), + flags: None, send_buffer_size: None, recv_buffer_size: None, }); @@ -301,6 +309,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port1), + flags: None, send_buffer_size: None, recv_buffer_size: None, }, @@ -315,6 +324,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port1), + flags: None, send_buffer_size: None, recv_buffer_size: None, }, @@ -343,6 +353,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: Some(port), + flags: None, send_buffer_size: None, recv_buffer_size: None, }, diff --git a/rust/tests/integration/webrtc_transport.rs b/rust/tests/integration/webrtc_transport.rs index e8c45b6761..9eec456aa4 100644 --- a/rust/tests/integration/webrtc_transport.rs +++ b/rust/tests/integration/webrtc_transport.rs @@ -100,6 +100,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -137,6 +138,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }, @@ -145,6 +147,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::UNSPECIFIED), announced_ip: Some("9.9.9.2".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }, @@ -153,6 +156,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }, @@ -263,6 +267,7 @@ fn create_with_fixed_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: Some(port), + flags: None, send_buffer_size: None, recv_buffer_size: None, })) @@ -286,6 +291,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -316,6 +322,7 @@ fn create_non_bindable_ip() { ip: "8.8.8.8".parse().unwrap(), announced_ip: None, port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, },) @@ -338,6 +345,7 @@ fn get_stats_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -389,6 +397,7 @@ fn connect_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -438,6 +447,7 @@ fn set_max_incoming_bitrate_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -470,6 +480,7 @@ fn set_max_outgoing_bitrate_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -502,6 +513,7 @@ fn set_min_outgoing_bitrate_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -534,6 +546,7 @@ fn set_max_outgoing_bitrate_fails_if_value_is_lower_than_current_min_limit() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -571,6 +584,7 @@ fn set_min_outgoing_bitrate_fails_if_value_is_higher_than_current_max_limit() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -608,6 +622,7 @@ fn restart_ice_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -643,6 +658,7 @@ fn enable_trace_event_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), @@ -718,6 +734,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_ip: Some("9.9.9.1".parse().unwrap()), port: None, + flags: None, send_buffer_size: None, recv_buffer_size: None, }), diff --git a/worker/fbs/transport.fbs b/worker/fbs/transport.fbs index d2a77d4ae9..001661b89f 100644 --- a/worker/fbs/transport.fbs +++ b/worker/fbs/transport.fbs @@ -13,11 +13,17 @@ enum Protocol: uint8 { TCP } +table SocketFlags { + ipv6_only: bool = false; + udp_reuse_port: bool = false; +} + table ListenInfo { - protocol: FBS.Transport.Protocol = UDP; + protocol: Protocol = UDP; ip: string (required); announced_ip: string; port: uint16 = 0; + flags: SocketFlags (required); send_buffer_size: uint32 = 0; recv_buffer_size: uint32 = 0; } @@ -85,7 +91,7 @@ table Tuple { local_port: uint16; remote_ip: string; remote_port: uint16; - protocol: FBS.Transport.Protocol = UDP; + protocol: Protocol = UDP; } table RtpListener { diff --git a/worker/include/Logger.hpp b/worker/include/Logger.hpp index 53c16f32a4..e3c22bb71f 100644 --- a/worker/include/Logger.hpp +++ b/worker/include/Logger.hpp @@ -126,6 +126,19 @@ ((value & 0x02) ? '1' : '0'), \ ((value & 0x01) ? '1' : '0') +// Usage: +// MS_DEBUG_DEV("Leading text "MS_UINT8_TO_BINARY_PATTERN, MS_UINT8_TO_BINARY(value)); +#define MS_UINT8_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c" +#define MS_UINT8_TO_BINARY(value) \ + ((value & 0x80) ? '1' : '0'), \ + ((value & 0x40) ? '1' : '0'), \ + ((value & 0x20) ? '1' : '0'), \ + ((value & 0x10) ? '1' : '0'), \ + ((value & 0x08) ? '1' : '0'), \ + ((value & 0x04) ? '1' : '0'), \ + ((value & 0x02) ? '1' : '0'), \ + ((value & 0x01) ? '1' : '0') + class Logger { public: diff --git a/worker/include/RTC/PortManager.hpp b/worker/include/RTC/PortManager.hpp index 4300548385..17294f24ca 100644 --- a/worker/include/RTC/PortManager.hpp +++ b/worker/include/RTC/PortManager.hpp @@ -3,6 +3,7 @@ #include "common.hpp" #include "Settings.hpp" +#include "RTC/Transport.hpp" #include #include #include @@ -20,21 +21,21 @@ namespace RTC }; public: - static uv_udp_t* BindUdp(std::string& ip) + static uv_udp_t* BindUdp(std::string& ip, RTC::Transport::SocketFlags& flags) { - return reinterpret_cast(Bind(Transport::UDP, ip)); + return reinterpret_cast(Bind(Transport::UDP, ip, flags)); } - static uv_udp_t* BindUdp(std::string& ip, uint16_t port) + static uv_udp_t* BindUdp(std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) { - return reinterpret_cast(Bind(Transport::UDP, ip, port)); + return reinterpret_cast(Bind(Transport::UDP, ip, port, flags)); } - static uv_tcp_t* BindTcp(std::string& ip) + static uv_tcp_t* BindTcp(std::string& ip, RTC::Transport::SocketFlags& flags) { - return reinterpret_cast(Bind(Transport::TCP, ip)); + return reinterpret_cast(Bind(Transport::TCP, ip, flags)); } - static uv_tcp_t* BindTcp(std::string& ip, uint16_t port) + static uv_tcp_t* BindTcp(std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) { - return reinterpret_cast(Bind(Transport::TCP, ip, port)); + return reinterpret_cast(Bind(Transport::TCP, ip, port, flags)); } static void UnbindUdp(std::string& ip, uint16_t port) { @@ -46,10 +47,12 @@ namespace RTC } private: - static uv_handle_t* Bind(Transport transport, std::string& ip); - static uv_handle_t* Bind(Transport transport, std::string& ip, uint16_t port); + static uv_handle_t* Bind(Transport transport, std::string& ip, RTC::Transport::SocketFlags& flags); + static uv_handle_t* Bind( + Transport transport, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); static void Unbind(Transport transport, std::string& ip, uint16_t port); static std::vector& GetPorts(Transport transport, const std::string& ip); + static uint8_t ConvertSocketFlags(RTC::Transport::SocketFlags& flags); private: thread_local static absl::flat_hash_map> mapUdpIpPorts; diff --git a/worker/include/RTC/TcpServer.hpp b/worker/include/RTC/TcpServer.hpp index 89e03ca6b8..6d1aeb7376 100644 --- a/worker/include/RTC/TcpServer.hpp +++ b/worker/include/RTC/TcpServer.hpp @@ -3,6 +3,7 @@ #include "common.hpp" #include "RTC/TcpConnection.hpp" +#include "RTC/Transport.hpp" #include "handles/TcpConnectionHandle.hpp" #include "handles/TcpServerHandle.hpp" #include @@ -23,9 +24,17 @@ namespace RTC }; public: - TcpServer(Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip); TcpServer( - Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, uint16_t port); + Listener* listener, + RTC::TcpConnection::Listener* connListener, + std::string& ip, + RTC::Transport::SocketFlags& flags); + TcpServer( + Listener* listener, + RTC::TcpConnection::Listener* connListener, + std::string& ip, + uint16_t port, + RTC::Transport::SocketFlags& flags); ~TcpServer() override; /* Pure virtual methods inherited from ::TcpServerHandle. */ diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index 61bdd3ec65..95814a4920 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -119,11 +119,18 @@ namespace RTC }; public: + struct SocketFlags + { + bool ipv6Only{ false }; + bool udpReusePort{ false }; + }; + struct ListenInfo { std::string ip; std::string announcedIp; uint16_t port{ 0u }; + SocketFlags flags; uint32_t sendBufferSize{ 0u }; uint32_t recvBufferSize{ 0u }; }; diff --git a/worker/include/RTC/UdpSocket.hpp b/worker/include/RTC/UdpSocket.hpp index 46e90f3edd..ad9bde10d6 100644 --- a/worker/include/RTC/UdpSocket.hpp +++ b/worker/include/RTC/UdpSocket.hpp @@ -2,6 +2,7 @@ #define MS_RTC_UDP_SOCKET_HPP #include "common.hpp" +#include "RTC/Transport.hpp" #include "handles/UdpSocketHandle.hpp" #include @@ -21,8 +22,8 @@ namespace RTC }; public: - UdpSocket(Listener* listener, std::string& ip); - UdpSocket(Listener* listener, std::string& ip, uint16_t port); + UdpSocket(Listener* listener, std::string& ip, RTC::Transport::SocketFlags& flags); + UdpSocket(Listener* listener, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); ~UdpSocket() override; /* Pure virtual methods inherited from ::UdpSocketHandle. */ diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index 950697b111..8706f5a60b 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -50,19 +50,11 @@ namespace RTC this->listenInfo.announcedIp.assign(options->listenInfo()->announcedIp()->str()); } - this->listenInfo.port = options->listenInfo()->port(); - - if (flatbuffers::IsFieldPresent( - options->listenInfo(), FBS::Transport::ListenInfo::VT_SENDBUFFERSIZE)) - { - this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); - } - - if (flatbuffers::IsFieldPresent( - options->listenInfo(), FBS::Transport::ListenInfo::VT_RECVBUFFERSIZE)) - { - this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); - } + this->listenInfo.port = options->listenInfo()->port(); + this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); + this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); + this->listenInfo.flags.ipv6Only = options->listenInfo()->flags()->ipv6Only(); + this->listenInfo.flags.udpReusePort = options->listenInfo()->flags()->udpReusePort(); this->rtx = options->enableRtx(); @@ -77,11 +69,12 @@ namespace RTC // This may throw. if (this->listenInfo.port != 0) { - this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.port); + this->udpSocket = new RTC::UdpSocket( + this, this->listenInfo.ip, this->listenInfo.port, this->listenInfo.flags); } else { - this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip); + this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.flags); } if (this->listenInfo.sendBufferSize != 0) diff --git a/worker/src/RTC/PlainTransport.cpp b/worker/src/RTC/PlainTransport.cpp index 305e67516f..672fe54cc2 100644 --- a/worker/src/RTC/PlainTransport.cpp +++ b/worker/src/RTC/PlainTransport.cpp @@ -52,19 +52,11 @@ namespace RTC this->listenInfo.announcedIp.assign(options->listenInfo()->announcedIp()->str()); } - this->listenInfo.port = options->listenInfo()->port(); - - if (flatbuffers::IsFieldPresent( - options->listenInfo(), FBS::Transport::ListenInfo::VT_SENDBUFFERSIZE)) - { - this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); - } - - if (flatbuffers::IsFieldPresent( - options->listenInfo(), FBS::Transport::ListenInfo::VT_RECVBUFFERSIZE)) - { - this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); - } + this->listenInfo.port = options->listenInfo()->port(); + this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); + this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); + this->listenInfo.flags.ipv6Only = options->listenInfo()->flags()->ipv6Only(); + this->listenInfo.flags.udpReusePort = options->listenInfo()->flags()->udpReusePort(); this->rtcpMux = options->rtcpMux(); this->comedia = options->comedia(); @@ -90,19 +82,11 @@ namespace RTC this->rtcpListenInfo.announcedIp.assign(options->rtcpListenInfo()->announcedIp()->str()); } - this->rtcpListenInfo.port = options->rtcpListenInfo()->port(); - - if (flatbuffers::IsFieldPresent( - options->rtcpListenInfo(), FBS::Transport::ListenInfo::VT_SENDBUFFERSIZE)) - { - this->rtcpListenInfo.sendBufferSize = options->rtcpListenInfo()->sendBufferSize(); - } - - if (flatbuffers::IsFieldPresent( - options->rtcpListenInfo(), FBS::Transport::ListenInfo::VT_RECVBUFFERSIZE)) - { - this->rtcpListenInfo.recvBufferSize = options->rtcpListenInfo()->recvBufferSize(); - } + this->rtcpListenInfo.port = options->rtcpListenInfo()->port(); + this->rtcpListenInfo.sendBufferSize = options->rtcpListenInfo()->sendBufferSize(); + this->rtcpListenInfo.recvBufferSize = options->rtcpListenInfo()->recvBufferSize(); + this->rtcpListenInfo.flags.ipv6Only = options->rtcpListenInfo()->flags()->ipv6Only(); + this->rtcpListenInfo.flags.udpReusePort = options->rtcpListenInfo()->flags()->udpReusePort(); } // If rtcpListenInfo is not given, just clone listenInfo. else @@ -160,11 +144,12 @@ namespace RTC // This may throw. if (this->listenInfo.port != 0) { - this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.port); + this->udpSocket = new RTC::UdpSocket( + this, this->listenInfo.ip, this->listenInfo.port, this->listenInfo.flags); } else { - this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip); + this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.flags); } if (this->listenInfo.sendBufferSize != 0) @@ -184,12 +169,13 @@ namespace RTC // This may throw. if (this->rtcpListenInfo.port != 0) { - this->rtcpUdpSocket = - new RTC::UdpSocket(this, this->rtcpListenInfo.ip, this->rtcpListenInfo.port); + this->rtcpUdpSocket = new RTC::UdpSocket( + this, this->rtcpListenInfo.ip, this->rtcpListenInfo.port, this->rtcpListenInfo.flags); } else { - this->rtcpUdpSocket = new RTC::UdpSocket(this, this->rtcpListenInfo.ip); + this->rtcpUdpSocket = + new RTC::UdpSocket(this, this->rtcpListenInfo.ip, this->rtcpListenInfo.flags); } if (this->rtcpListenInfo.sendBufferSize != 0) diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index 0d19d686f3..051a318d45 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -38,7 +38,7 @@ namespace RTC /* Class methods. */ - uv_handle_t* PortManager::Bind(Transport transport, std::string& ip) + uv_handle_t* PortManager::Bind(Transport transport, std::string& ip, RTC::Transport::SocketFlags& flags) { MS_TRACE(); @@ -49,23 +49,29 @@ namespace RTC const int family = Utils::IP::GetFamily(ip); struct sockaddr_storage bindAddr; // NOLINT(cppcoreguidelines-pro-type-member-init) size_t portIdx; - int flags{ 0 }; std::vector& ports = PortManager::GetPorts(transport, ip); size_t attempt{ 0u }; const size_t numAttempts = ports.size(); uv_handle_t* uvHandle{ nullptr }; uint16_t port; std::string transportStr; + uint8_t bitFlags = ConvertSocketFlags(flags); switch (transport) { case Transport::UDP: + { transportStr.assign("udp"); + break; + } case Transport::TCP: + { transportStr.assign("tcp"); + break; + } } switch (family) @@ -91,9 +97,6 @@ namespace RTC MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); } - // Don't also bind into IPv4 when listening in IPv6. - flags |= UV_UDP_IPV6ONLY; - break; } @@ -160,12 +163,18 @@ namespace RTC switch (family) { case AF_INET: + { (reinterpret_cast(&bindAddr))->sin_port = htons(port); + break; + } case AF_INET6: + { (reinterpret_cast(&bindAddr))->sin6_port = htons(port); + break; + } } // Try to bind on it. @@ -220,7 +229,7 @@ namespace RTC err = uv_udp_bind( reinterpret_cast(uvHandle), reinterpret_cast(&bindAddr), - flags); + bitFlags); if (err != 0) { @@ -242,7 +251,7 @@ namespace RTC err = uv_tcp_bind( reinterpret_cast(uvHandle), reinterpret_cast(&bindAddr), - flags); + bitFlags); if (err != 0) { @@ -356,7 +365,8 @@ namespace RTC return static_cast(uvHandle); } - uv_handle_t* PortManager::Bind(Transport transport, std::string& ip, uint16_t port) + uv_handle_t* PortManager::Bind( + Transport transport, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) { MS_TRACE(); @@ -366,19 +376,25 @@ namespace RTC int err; const int family = Utils::IP::GetFamily(ip); struct sockaddr_storage bindAddr; // NOLINT(cppcoreguidelines-pro-type-member-init) - int flags{ 0 }; uv_handle_t* uvHandle{ nullptr }; std::string transportStr; + uint8_t bitFlags = ConvertSocketFlags(flags); switch (transport) { case Transport::UDP: + { transportStr.assign("udp"); + break; + } case Transport::TCP: + { transportStr.assign("tcp"); + break; + } } switch (family) @@ -404,9 +420,6 @@ namespace RTC MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); } - // Don't also bind into IPv4 when listening in IPv6. - flags |= UV_UDP_IPV6ONLY; - break; } @@ -421,27 +434,39 @@ namespace RTC switch (family) { case AF_INET: + { (reinterpret_cast(&bindAddr))->sin_port = htons(port); + break; + } case AF_INET6: + { (reinterpret_cast(&bindAddr))->sin6_port = htons(port); + break; + } } // Try to bind on it. switch (transport) { case Transport::UDP: + { uvHandle = reinterpret_cast(new uv_udp_t()); err = uv_udp_init_ex( DepLibUV::GetLoop(), reinterpret_cast(uvHandle), UV_UDP_RECVMMSG); + break; + } case Transport::TCP: + { uvHandle = reinterpret_cast(new uv_tcp_t()); err = uv_tcp_init(DepLibUV::GetLoop(), reinterpret_cast(uvHandle)); + break; + } } if (err != 0) @@ -475,7 +500,7 @@ namespace RTC err = uv_udp_bind( reinterpret_cast(uvHandle), reinterpret_cast(&bindAddr), - flags); + bitFlags); if (err != 0) { @@ -498,7 +523,7 @@ namespace RTC err = uv_tcp_bind( reinterpret_cast(uvHandle), reinterpret_cast(&bindAddr), - flags); + bitFlags); if (err != 0) { @@ -666,4 +691,24 @@ namespace RTC return emptyPorts; } + + uint8_t PortManager::ConvertSocketFlags(RTC::Transport::SocketFlags& flags) + { + MS_TRACE(); + + uint8_t bitFlags{ 0b00000000 }; + + if (flags.ipv6Only) + { + bitFlags |= UV_UDP_IPV6ONLY; + bitFlags |= UV_TCP_IPV6ONLY; // Same flag number but anyway. + } + + if (flags.udpReusePort) + { + bitFlags |= UV_UDP_REUSEADDR; + } + + return bitFlags; + } } // namespace RTC diff --git a/worker/src/RTC/TcpServer.cpp b/worker/src/RTC/TcpServer.cpp index ddd1d2da82..0cef5aa800 100644 --- a/worker/src/RTC/TcpServer.cpp +++ b/worker/src/RTC/TcpServer.cpp @@ -10,19 +10,27 @@ namespace RTC { /* Instance methods. */ - TcpServer::TcpServer(Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip) + TcpServer::TcpServer( + Listener* listener, + RTC::TcpConnection::Listener* connListener, + std::string& ip, + RTC::Transport::SocketFlags& flags) : // This may throw. - ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip)), listener(listener), + ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, flags)), listener(listener), connListener(connListener) { MS_TRACE(); } TcpServer::TcpServer( - Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, uint16_t port) + Listener* listener, + RTC::TcpConnection::Listener* connListener, + std::string& ip, + uint16_t port, + RTC::Transport::SocketFlags& flags) : // This may throw. - ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, port)), listener(listener), - connListener(connListener), fixedPort(true) + ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, port, flags)), + listener(listener), connListener(connListener), fixedPort(true) { MS_TRACE(); } diff --git a/worker/src/RTC/UdpSocket.cpp b/worker/src/RTC/UdpSocket.cpp index 6c47ab4671..b599620f25 100644 --- a/worker/src/RTC/UdpSocket.cpp +++ b/worker/src/RTC/UdpSocket.cpp @@ -10,16 +10,17 @@ namespace RTC { /* Instance methods. */ - UdpSocket::UdpSocket(Listener* listener, std::string& ip) + UdpSocket::UdpSocket(Listener* listener, std::string& ip, RTC::Transport::SocketFlags& flags) : // This may throw. - ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip)), listener(listener) + ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip, flags)), listener(listener) { MS_TRACE(); } - UdpSocket::UdpSocket(Listener* listener, std::string& ip, uint16_t port) + UdpSocket::UdpSocket( + Listener* listener, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) : // This may throw. - ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip, port)), listener(listener), + ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip, port, flags)), listener(listener), fixedPort(true) { MS_TRACE(); diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 8fe9f760a3..a1f234c9db 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -60,6 +60,11 @@ namespace RTC announcedIp = listenInfo->announcedIp()->str(); } + RTC::Transport::SocketFlags flags; + + flags.ipv6Only = listenInfo->flags()->ipv6Only(); + flags.udpReusePort = listenInfo->flags()->udpReusePort(); + if (listenInfo->protocol() == FBS::Transport::Protocol::UDP) { // This may throw. @@ -67,11 +72,11 @@ namespace RTC if (listenInfo->port() != 0) { - udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port()); + udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port(), flags); } else { - udpSocket = new RTC::UdpSocket(this, ip); + udpSocket = new RTC::UdpSocket(this, ip, flags); } this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, announcedIp); @@ -99,11 +104,11 @@ namespace RTC if (listenInfo->port() != 0) { - tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port()); + tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port(), flags); } else { - tcpServer = new RTC::TcpServer(this, this, ip); + tcpServer = new RTC::TcpServer(this, this, ip, flags); } this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, announcedIp); diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 19e33d5f6d..6eb1f9717d 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -62,6 +62,11 @@ namespace RTC announcedIp = listenInfo->announcedIp()->str(); } + RTC::Transport::SocketFlags flags; + + flags.ipv6Only = listenInfo->flags()->ipv6Only(); + flags.udpReusePort = listenInfo->flags()->udpReusePort(); + const uint16_t iceLocalPreference = IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; const uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); @@ -72,11 +77,11 @@ namespace RTC if (listenInfo->port() != 0) { - udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port()); + udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port(), flags); } else { - udpSocket = new RTC::UdpSocket(this, ip); + udpSocket = new RTC::UdpSocket(this, ip, flags); } this->udpSockets[udpSocket] = announcedIp; @@ -114,11 +119,11 @@ namespace RTC if (listenInfo->port() != 0) { - tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port()); + tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port(), flags); } else { - tcpServer = new RTC::TcpServer(this, this, ip); + tcpServer = new RTC::TcpServer(this, this, ip, flags); } this->tcpServers[tcpServer] = announcedIp; From 5ef48f6065a3b44d0c24310bc3fa0f1893e8a0fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 11:50:20 +0100 Subject: [PATCH 286/525] C++: always add this->xxx to reference class members --- worker/src/RTC/TcpServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/TcpServer.cpp b/worker/src/RTC/TcpServer.cpp index 0cef5aa800..685c0b1118 100644 --- a/worker/src/RTC/TcpServer.cpp +++ b/worker/src/RTC/TcpServer.cpp @@ -39,7 +39,7 @@ namespace RTC { MS_TRACE(); - if (!fixedPort) + if (!this->fixedPort) { RTC::PortManager::UnbindTcp(this->localIp, this->localPort); } From 160b19c493f9020c647049954868fac0fe6939e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 11:52:16 +0100 Subject: [PATCH 287/525] Same as previous commit --- worker/src/RTC/UdpSocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/UdpSocket.cpp b/worker/src/RTC/UdpSocket.cpp index b599620f25..c6d4ff5500 100644 --- a/worker/src/RTC/UdpSocket.cpp +++ b/worker/src/RTC/UdpSocket.cpp @@ -30,7 +30,7 @@ namespace RTC { MS_TRACE(); - if (!fixedPort) + if (!this->fixedPort) { PortManager::UnbindUdp(this->localIp, this->localPort); } From ddcd72f19ec1349a5469f9902aef592d29bf0708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 13:01:05 +0100 Subject: [PATCH 288/525] meson: remove -Db_pie=true -Db_staticpic=true args (#1293) --- CHANGELOG.md | 1 + worker/tasks.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f01d306c1..d2be144502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). * `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). +* Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). ### 3.13.13 diff --git a/worker/tasks.py b/worker/tasks.py index 404dbe2ee4..64476777de 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -142,7 +142,7 @@ def setup(ctx): if MEDIASOUP_BUILDTYPE == 'Release': with ctx.cd(WORKER_DIR): ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true {MESON_ARGS} "{BUILD_DIR}"', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -150,7 +150,7 @@ def setup(ctx): elif MEDIASOUP_BUILDTYPE == 'Debug': with ctx.cd(WORKER_DIR): ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug {MESON_ARGS} "{BUILD_DIR}"', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -158,7 +158,7 @@ def setup(ctx): else: with ctx.cd(WORKER_DIR): ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"', + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release {MESON_ARGS} "{BUILD_DIR}"', echo=True, pty=PTY_SUPPORTED, shell=SHELL From 87032a8b29f728d49dab7639a449a6964aef1c17 Mon Sep 17 00:00:00 2001 From: GithubUser8080 <84914135+GithubUser8080@users.noreply.github.com> Date: Wed, 3 Jan 2024 14:02:46 +0200 Subject: [PATCH 289/525] Add sender report trace event (#1267) --- node/src/Producer.ts | 12 ++++++++++- rust/src/data_structures.rs | 35 ++++++++++++++++++++++++++++++- rust/src/router/producer.rs | 28 ++++++++++++++++++++++++- worker/fbs/producer.fbs | 11 ++++++++++ worker/include/RTC/Producer.hpp | 2 ++ worker/src/RTC/Producer.cpp | 37 +++++++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 3 deletions(-) diff --git a/node/src/Producer.ts b/node/src/Producer.ts index dcae6545ea..9deb4a931c 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -52,7 +52,7 @@ export type ProducerOptions = /** * Valid types for 'trace' event. */ -export type ProducerTraceEventType = 'rtp' | 'keyframe' | 'nack' | 'pli' | 'fir'; +export type ProducerTraceEventType = 'rtp' | 'keyframe' | 'nack' | 'pli' | 'fir' | 'sr'; /** * 'trace' event data. @@ -702,6 +702,11 @@ function producerTraceEventTypeToFbs(eventType: ProducerTraceEventType) return FbsProducer.TraceEventType.RTP; } + case 'sr': + { + return FbsProducer.TraceEventType.SR; + } + default: { throw new TypeError(`invalid ProducerTraceEventType: ${eventType}`); @@ -738,6 +743,11 @@ function producerTraceEventTypeFromFbs(eventType: FbsProducer.TraceEventType) { return 'rtp'; } + + case FbsProducer.TraceEventType.SR: + { + return 'sr'; + } } } diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index 07fb5247af..0b4901ae7a 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -3,7 +3,9 @@ #[cfg(test)] mod tests; -use mediasoup_sys::fbs::{common, rtp_packet, sctp_association, transport, web_rtc_transport}; +use mediasoup_sys::fbs::{ + common, producer, rtp_packet, sctp_association, transport, web_rtc_transport, +}; use serde::de::{MapAccess, Visitor}; use serde::ser::SerializeStruct; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -1262,3 +1264,34 @@ impl BweTraceInfo { } } } + +/// BWE info in trace event. +#[derive(Debug, Copy, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct SrTraceInfo { + /// Stream SSRC + ssrc: u32, + /// NTP : most significant word + ntp_sec: u32, + /// NTP : least significant word + ntp_frac: u32, + /// RTP timestamp + rtp_ts: u32, + /// Sender packet count + packet_count: u32, + /// Sender octet count + octet_count: u32, +} + +impl SrTraceInfo { + pub(crate) fn from_fbs(info: producer::SrTraceInfo) -> Self { + Self { + ssrc: info.ssrc, + ntp_sec: info.ntp_sec, + ntp_frac: info.ntp_frac, + rtp_ts: info.rtp_ts, + packet_count: info.packet_count, + octet_count: info.octet_count, + } + } +} diff --git a/rust/src/router/producer.rs b/rust/src/router/producer.rs index b25c40a711..61a22a56f0 100644 --- a/rust/src/router/producer.rs +++ b/rust/src/router/producer.rs @@ -2,7 +2,9 @@ mod tests; use crate::consumer::{RtpStreamParams, RtxStreamParams}; -use crate::data_structures::{AppData, RtpPacketTraceInfo, SsrcTraceInfo, TraceEventDirection}; +use crate::data_structures::{ + AppData, RtpPacketTraceInfo, SrTraceInfo, SsrcTraceInfo, TraceEventDirection, +}; use crate::messages::{ ProducerCloseRequest, ProducerDumpRequest, ProducerEnableTraceEventRequest, ProducerGetStatsRequest, ProducerPauseRequest, ProducerResumeRequest, ProducerSendNotification, @@ -394,6 +396,15 @@ pub enum ProducerTraceEventData { /// SSRC info. info: SsrcTraceInfo, }, + /// RTCP Sender report. + Sr { + /// Event timestamp. + timestamp: u64, + /// Event direction. + direction: TraceEventDirection, + /// SSRC info. + info: SrTraceInfo, + }, } impl ProducerTraceEventData { @@ -447,6 +458,17 @@ impl ProducerTraceEventData { SsrcTraceInfo { ssrc: info.ssrc } }, }, + producer::TraceEventType::Sr => ProducerTraceEventData::Sr { + timestamp: data.timestamp, + direction: TraceEventDirection::from_fbs(data.direction), + info: { + let Some(producer::TraceInfo::SrTraceInfo(info)) = data.info else { + panic!("Wrong message from worker: {data:?}"); + }; + + SrTraceInfo::from_fbs(*info) + }, + }, } } } @@ -465,6 +487,8 @@ pub enum ProducerTraceEventType { Pli, /// RTCP FIR packet. Fir, + /// RTCP Sender report. + SR, } impl ProducerTraceEventType { @@ -475,6 +499,7 @@ impl ProducerTraceEventType { ProducerTraceEventType::Nack => producer::TraceEventType::Nack, ProducerTraceEventType::Pli => producer::TraceEventType::Pli, ProducerTraceEventType::Fir => producer::TraceEventType::Fir, + ProducerTraceEventType::SR => producer::TraceEventType::Sr, } } @@ -485,6 +510,7 @@ impl ProducerTraceEventType { producer::TraceEventType::Nack => ProducerTraceEventType::Nack, producer::TraceEventType::Pli => ProducerTraceEventType::Pli, producer::TraceEventType::Fir => ProducerTraceEventType::Fir, + producer::TraceEventType::Sr => ProducerTraceEventType::SR, } } } diff --git a/worker/fbs/producer.fbs b/worker/fbs/producer.fbs index d3ec14a7b8..8913cb9222 100644 --- a/worker/fbs/producer.fbs +++ b/worker/fbs/producer.fbs @@ -11,6 +11,7 @@ enum TraceEventType: uint8 { NACK, PLI, RTP, + SR, } table EnableTraceEventRequest { @@ -60,6 +61,7 @@ union TraceInfo { FirTraceInfo, PliTraceInfo, RtpTraceInfo, + SrTraceInfo, } table KeyFrameTraceInfo { @@ -80,6 +82,15 @@ table RtpTraceInfo { is_rtx: bool; } +table SrTraceInfo { + ssrc: uint32; + ntp_sec: uint32; + ntp_frac: uint32; + rtp_ts: uint32; + packet_count: uint32; + octet_count: uint32; +} + table TraceNotification { type: TraceEventType; timestamp: uint64; diff --git a/worker/include/RTC/Producer.hpp b/worker/include/RTC/Producer.hpp index 59e7ddab00..a7c3e14fae 100644 --- a/worker/include/RTC/Producer.hpp +++ b/worker/include/RTC/Producer.hpp @@ -89,6 +89,7 @@ namespace RTC bool nack{ false }; bool pli{ false }; bool fir{ false }; + bool sr{ false }; }; public: @@ -160,6 +161,7 @@ namespace RTC void EmitTraceEventPliType(uint32_t ssrc) const; void EmitTraceEventFirType(uint32_t ssrc) const; void EmitTraceEventNackType() const; + void EmitTraceEventSrType(RTC::RTCP::SenderReport* report) const; void EmitTraceEvent(flatbuffers::Offset& notification) const; /* Pure virtual methods inherited from RTC::RtpStreamRecv::Listener. */ diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index d8bd6a1f2c..5e2f195675 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -486,6 +486,12 @@ namespace RTC { newTraceEventTypes.rtp = true; + break; + } + case FBS::Producer::TraceEventType::SR: + { + newTraceEventTypes.sr = true; + break; } } @@ -706,6 +712,8 @@ namespace RTC this->listener->OnProducerRtcpSenderReport(this, rtpStream, first); + EmitTraceEventSrType(report); + return; } @@ -1576,6 +1584,35 @@ namespace RTC EmitTraceEvent(notification); } + inline void Producer::EmitTraceEventSrType(RTC::RTCP::SenderReport* report) const + { + MS_TRACE(); + + if (!this->traceEventTypes.sr) + { + return; + } + + auto traceInfo = FBS::Producer::CreateSrTraceInfo( + this->shared->channelNotifier->GetBufferBuilder(), + report->GetSsrc(), + report->GetNtpSec(), + report->GetNtpFrac(), + report->GetRtpTs(), + report->GetPacketCount(), + report->GetOctetCount()); + + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceEventType::SR, + DepLibUV::GetTimeMs(), + FBS::Common::TraceDirection::DIRECTION_IN, + FBS::Producer::TraceInfo::SrTraceInfo, + traceInfo.Union()); + + EmitTraceEvent(notification); + } + inline void Producer::EmitTraceEvent( flatbuffers::Offset& notification) const { From 0930806471304c863e848ede36265cf773c52a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 13:07:20 +0100 Subject: [PATCH 290/525] Update CHANGELOG and fix typos in previous PRs --- CHANGELOG.md | 1 + rust/src/data_structures.rs | 2 +- rust/src/router/producer.rs | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2be144502..12075eba84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). * `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). * Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). +* Add RTCP Sender Report trace event ([PR #1267](https://github.com/versatica/mediasoup/pull/1267) by @GithubUser8080). ### 3.13.13 diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index 0b4901ae7a..f0e7aa4d5c 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -1265,7 +1265,7 @@ impl BweTraceInfo { } } -/// BWE info in trace event. +/// RTCP Sender Report info in trace event. #[derive(Debug, Copy, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct SrTraceInfo { diff --git a/rust/src/router/producer.rs b/rust/src/router/producer.rs index 61a22a56f0..1b9d1c7478 100644 --- a/rust/src/router/producer.rs +++ b/rust/src/router/producer.rs @@ -396,7 +396,7 @@ pub enum ProducerTraceEventData { /// SSRC info. info: SsrcTraceInfo, }, - /// RTCP Sender report. + /// RTCP Sender Report. Sr { /// Event timestamp. timestamp: u64, @@ -487,7 +487,7 @@ pub enum ProducerTraceEventType { Pli, /// RTCP FIR packet. Fir, - /// RTCP Sender report. + /// RTCP Sender Report. SR, } From 2d98c72470dc004b0796418ead4d90dbf514d740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 13:08:28 +0100 Subject: [PATCH 291/525] Update NPM eslint deps --- package-lock.json | 346 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 176 insertions(+), 176 deletions(-) diff --git a/package-lock.json b/package-lock.json index b78c5d146a..8888457b9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,10 +22,10 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.6", - "@typescript-eslint/eslint-plugin": "^6.16.0", - "@typescript-eslint/parser": "^6.16.0", + "@typescript-eslint/eslint-plugin": "^6.17.0", + "@typescript-eslint/parser": "^6.17.0", "eslint": "^8.56.0", - "eslint-plugin-jest": "^27.6.0", + "eslint-plugin-jest": "^27.6.1", "jest": "^29.7.0", "marked": "^11.1.1", "open-cli": "^7.2.0", @@ -1659,16 +1659,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.16.0.tgz", - "integrity": "sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.17.0.tgz", + "integrity": "sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.16.0", - "@typescript-eslint/type-utils": "6.16.0", - "@typescript-eslint/utils": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/type-utils": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1694,13 +1694,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", - "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0" + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1711,9 +1711,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", - "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1724,13 +1724,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", - "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1752,17 +1752,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz", - "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", + "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.16.0", - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/typescript-estree": "6.16.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", "semver": "^7.5.4" }, "engines": { @@ -1777,12 +1777,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", - "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/types": "6.17.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1818,15 +1818,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.16.0.tgz", - "integrity": "sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.17.0.tgz", + "integrity": "sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.16.0", - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/typescript-estree": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4" }, "engines": { @@ -1846,13 +1846,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", - "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0" + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1863,9 +1863,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", - "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1876,13 +1876,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", - "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1904,12 +1904,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", - "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/types": "6.17.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1962,13 +1962,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.16.0.tgz", - "integrity": "sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.17.0.tgz", + "integrity": "sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.16.0", - "@typescript-eslint/utils": "6.16.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/utils": "6.17.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1989,13 +1989,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", - "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0" + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2006,9 +2006,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", - "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2019,13 +2019,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", - "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2047,17 +2047,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz", - "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", + "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.16.0", - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/typescript-estree": "6.16.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", "semver": "^7.5.4" }, "engines": { @@ -2072,12 +2072,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", - "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/types": "6.17.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3151,9 +3151,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.0.tgz", - "integrity": "sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng==", + "version": "27.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", + "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -8124,16 +8124,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.16.0.tgz", - "integrity": "sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.17.0.tgz", + "integrity": "sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.16.0", - "@typescript-eslint/type-utils": "6.16.0", - "@typescript-eslint/utils": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/type-utils": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8143,29 +8143,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", - "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0" + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" } }, "@typescript-eslint/types": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", - "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", - "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8175,27 +8175,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz", - "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", + "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.16.0", - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/typescript-estree": "6.16.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", - "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/types": "6.17.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -8220,42 +8220,42 @@ } }, "@typescript-eslint/parser": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.16.0.tgz", - "integrity": "sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.17.0.tgz", + "integrity": "sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.16.0", - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/typescript-estree": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", - "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0" + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" } }, "@typescript-eslint/types": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", - "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", - "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8265,12 +8265,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", - "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/types": "6.17.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -8305,41 +8305,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.16.0.tgz", - "integrity": "sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.17.0.tgz", + "integrity": "sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.16.0", - "@typescript-eslint/utils": "6.16.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/utils": "6.17.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", - "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0" + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" } }, "@typescript-eslint/types": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", - "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", - "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8349,27 +8349,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz", - "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", + "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.16.0", - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/typescript-estree": "6.16.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", - "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/types": "6.17.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -9146,9 +9146,9 @@ } }, "eslint-plugin-jest": { - "version": "27.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.0.tgz", - "integrity": "sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng==", + "version": "27.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", + "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" diff --git a/package.json b/package.json index 84607ed4a3..9f4f406ee0 100644 --- a/package.json +++ b/package.json @@ -110,10 +110,10 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.6", - "@typescript-eslint/eslint-plugin": "^6.16.0", - "@typescript-eslint/parser": "^6.16.0", + "@typescript-eslint/eslint-plugin": "^6.17.0", + "@typescript-eslint/parser": "^6.17.0", "eslint": "^8.56.0", - "eslint-plugin-jest": "^27.6.0", + "eslint-plugin-jest": "^27.6.1", "jest": "^29.7.0", "marked": "^11.1.1", "open-cli": "^7.2.0", From 1971b9c4259340ef464c5e444b77aaef95c240de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 14:17:03 +0100 Subject: [PATCH 292/525] ListenInfo: Ignore given socket flags if not suitable for given IP family or transport (#1294) --- CHANGELOG.md | 1 + node/src/tests/test-PlainTransport.ts | 3 ++- node/src/tests/test-WebRtcTransport.ts | 8 ++++-- rust/tests/integration/plain_transport.rs | 3 ++- worker/include/RTC/PortManager.hpp | 3 ++- worker/src/RTC/PortManager.cpp | 33 +++++++++++++++++------ 6 files changed, 38 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12075eba84..38e4fb823d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). * `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). +* `ListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). * Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). * Add RTCP Sender Report trace event ([PR #1267](https://github.com/versatica/mediasoup/pull/1267) by @GithubUser8080). diff --git a/node/src/tests/test-PlainTransport.ts b/node/src/tests/test-PlainTransport.ts index 554d07444a..770d0bbfce 100644 --- a/node/src/tests/test-PlainTransport.ts +++ b/node/src/tests/test-PlainTransport.ts @@ -338,7 +338,8 @@ if (!IS_WINDOWS) protocol : 'udp', ip : multicastIp, port : port, - flags : { udpReusePort: true } + // NOTE: ipv6Only flag will be ignored since ip is IPv4. + flags : { udpReusePort: true, ipv6Only: true } } }); diff --git a/node/src/tests/test-WebRtcTransport.ts b/node/src/tests/test-WebRtcTransport.ts index 7bb950eb08..b08b32c342 100644 --- a/node/src/tests/test-WebRtcTransport.ts +++ b/node/src/tests/test-WebRtcTransport.ts @@ -641,10 +641,14 @@ test('WebRtcTransport methods reject if closed', async () => test('router.createWebRtcTransport() with fixed port succeeds', async () => { - const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); const webRtcTransport = await router.createWebRtcTransport( { - listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port } ] + listenInfos : + [ + // NOTE: udpReusePort flag will be ignored since protocol is TCP. + { protocol: 'tcp', ip: '127.0.0.1', port, flags: { udpReusePort: true } } + ] }); expect(webRtcTransport.iceCandidates[0].port).toEqual(port); diff --git a/rust/tests/integration/plain_transport.rs b/rust/tests/integration/plain_transport.rs index 5fc334fca6..e40e79fb2c 100644 --- a/rust/tests/integration/plain_transport.rs +++ b/rust/tests/integration/plain_transport.rs @@ -438,8 +438,9 @@ fn create_two_transports_binding_to_same_ip_port_with_udp_reuse_port_flag_succee ip: multicast_ip, announced_ip: None, port: Some(port), + // NOTE: ipv6Only flag will be ignored since ip is IPv4. flags: Some(SocketFlags { - ipv6_only: false, + ipv6_only: true, udp_reuse_port: true, }), send_buffer_size: None, diff --git a/worker/include/RTC/PortManager.hpp b/worker/include/RTC/PortManager.hpp index 17294f24ca..f8c102b6b9 100644 --- a/worker/include/RTC/PortManager.hpp +++ b/worker/include/RTC/PortManager.hpp @@ -52,7 +52,8 @@ namespace RTC Transport transport, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); static void Unbind(Transport transport, std::string& ip, uint16_t port); static std::vector& GetPorts(Transport transport, const std::string& ip); - static uint8_t ConvertSocketFlags(RTC::Transport::SocketFlags& flags); + static uint8_t ConvertSocketFlags( + RTC::Transport::SocketFlags& flags, Transport transport, int family); private: thread_local static absl::flat_hash_map> mapUdpIpPorts; diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index 051a318d45..eea8dbb97c 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -1,4 +1,4 @@ -#define MS_CLASS "RTC::PortManager" +#define MS_CLASS "PortManager" // #define MS_LOG_DEV_LEVEL 3 #include "RTC/PortManager.hpp" @@ -55,7 +55,7 @@ namespace RTC uv_handle_t* uvHandle{ nullptr }; uint16_t port; std::string transportStr; - uint8_t bitFlags = ConvertSocketFlags(flags); + uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); switch (transport) { @@ -378,7 +378,7 @@ namespace RTC struct sockaddr_storage bindAddr; // NOLINT(cppcoreguidelines-pro-type-member-init) uv_handle_t* uvHandle{ nullptr }; std::string transportStr; - uint8_t bitFlags = ConvertSocketFlags(flags); + uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); switch (transport) { @@ -692,19 +692,36 @@ namespace RTC return emptyPorts; } - uint8_t PortManager::ConvertSocketFlags(RTC::Transport::SocketFlags& flags) + uint8_t PortManager::ConvertSocketFlags( + RTC::Transport::SocketFlags& flags, Transport transport, int family) { MS_TRACE(); uint8_t bitFlags{ 0b00000000 }; - if (flags.ipv6Only) + // Ignore ipv6Only in IPv4, otherwise libuv will throw. + if (flags.ipv6Only && family == AF_INET6) { - bitFlags |= UV_UDP_IPV6ONLY; - bitFlags |= UV_TCP_IPV6ONLY; // Same flag number but anyway. + switch (transport) + { + case Transport::UDP: + { + bitFlags |= UV_UDP_IPV6ONLY; + + break; + } + + case Transport::TCP: + { + bitFlags |= UV_TCP_IPV6ONLY; + + break; + } + } } - if (flags.udpReusePort) + // Ignore udpReusePort in TCP, otherwise libuv will throw. + if (flags.udpReusePort && transport == Transport::UDP) { bitFlags |= UV_UDP_REUSEADDR; } From 7eda844767ec43931cea45c7b6f63929b23b6200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 14:21:00 +0100 Subject: [PATCH 293/525] 3.13.14 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38e4fb823d..046bb06b35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### NEXT +### 3.13.14 * Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). * `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). diff --git a/package-lock.json b/package-lock.json index 8888457b9b..c2555cc1f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.13", + "version": "3.13.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.13", + "version": "3.13.14", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 9f4f406ee0..6414d977be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.13", + "version": "3.13.14", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From f8bcb0339b617edfab825202b928a5fc277f49da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 18:43:34 +0100 Subject: [PATCH 294/525] cosmetic --- node/.eslintrc.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/node/.eslintrc.js b/node/.eslintrc.js index 1d0f1e8728..687dcf1898 100644 --- a/node/.eslintrc.js +++ b/node/.eslintrc.js @@ -244,11 +244,13 @@ eslintConfig.overrides.push( eslintConfig.overrides.push( { files : [ '*.ts' ], - env : { + env : + { ...eslintConfig.env, 'jest/globals' : true }, - plugins : [ + plugins : + [ ...eslintConfig.plugins, 'jest' ] From 71d8c11ba92db2724d9d3444784567c56cb66903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 4 Jan 2024 11:30:15 +0100 Subject: [PATCH 295/525] Make Node tests independent (part 1) (#1295) - Make each `test()` independent of other tests in same file. The goal is that a failing test doesn't make other tests also fail. - For now just done in `test-Worker.ts` as a POC. - Rename `node/src/tests/` to `node/src/test/` for consistency and convention. - Make it possible to pass Jest command line args to `npm run test:node` script. --- doc/Building.md | 32 ++-- node/src/{tests => test}/data/dtls-cert.pem | 0 node/src/{tests => test}/data/dtls-key.pem | 0 .../test-ActiveSpeakerObserver.ts | 0 .../test-AudioLevelObserver.ts | 0 node/src/{tests => test}/test-Consumer.ts | 0 node/src/{tests => test}/test-DataConsumer.ts | 0 node/src/{tests => test}/test-DataProducer.ts | 0 .../{tests => test}/test-DirectTransport.ts | 0 .../src/{tests => test}/test-PipeTransport.ts | 0 .../{tests => test}/test-PlainTransport.ts | 0 node/src/{tests => test}/test-Producer.ts | 0 node/src/{tests => test}/test-Router.ts | 0 node/src/{tests => test}/test-WebRtcServer.ts | 0 .../{tests => test}/test-WebRtcTransport.ts | 0 node/src/{tests => test}/test-Worker.ts | 168 +++++++++--------- node/src/{tests => test}/test-mediasoup.ts | 0 node/src/{tests => test}/test-multiopus.ts | 0 node/src/{tests => test}/test-node-sctp.ts | 0 node/src/{tests => test}/test-ortc.ts | 0 npm-scripts.mjs | 18 +- package.json | 4 +- 22 files changed, 109 insertions(+), 113 deletions(-) rename node/src/{tests => test}/data/dtls-cert.pem (100%) rename node/src/{tests => test}/data/dtls-key.pem (100%) rename node/src/{tests => test}/test-ActiveSpeakerObserver.ts (100%) rename node/src/{tests => test}/test-AudioLevelObserver.ts (100%) rename node/src/{tests => test}/test-Consumer.ts (100%) rename node/src/{tests => test}/test-DataConsumer.ts (100%) rename node/src/{tests => test}/test-DataProducer.ts (100%) rename node/src/{tests => test}/test-DirectTransport.ts (100%) rename node/src/{tests => test}/test-PipeTransport.ts (100%) rename node/src/{tests => test}/test-PlainTransport.ts (100%) rename node/src/{tests => test}/test-Producer.ts (100%) rename node/src/{tests => test}/test-Router.ts (100%) rename node/src/{tests => test}/test-WebRtcServer.ts (100%) rename node/src/{tests => test}/test-WebRtcTransport.ts (100%) rename node/src/{tests => test}/test-Worker.ts (64%) rename node/src/{tests => test}/test-mediasoup.ts (100%) rename node/src/{tests => test}/test-multiopus.ts (100%) rename node/src/{tests => test}/test-node-sctp.ts (100%) rename node/src/{tests => test}/test-ortc.ts (100%) diff --git a/doc/Building.md b/doc/Building.md index 7408111f9e..3ca30758e7 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -8,11 +8,11 @@ The `package.json` file in the main folder includes the following scripts: ### `npm run typescript:build` -Compiles mediasoup TypeScript code (`lib` folder) JavaScript and places it into the `lib` directory. +Compiles mediasoup TypeScript code (`node/src` folder) JavaScript and places it into the `node/lib` directory. ### `npm run typescript:watch` -Compiles mediasoup TypeScript code (`lib` folder) JavaScript, places it into the `lib` directory an watches for changes in the TypeScript files. +Compiles mediasoup TypeScript code (`node/src` folder) JavaScript, places it into the `node/lib` directory an watches for changes in the TypeScript files. ### `npm run worker:build` @@ -56,11 +56,17 @@ Runs both `npm run test:node` and `npm run test:worker`. ### `npm run test:node` -Runs [Jest](https://jestjs.io) test units located at `test/` folder. +Runs [Jest](https://jestjs.io) test units located at `node/test` folder. + +Jest command arguments can be given using `--` as follows: + +```bash +npm run test:node -- --testPathPattern "test-Worker.ts" --testNamePattern "createWorker" +``` ### `npm run test:worker` -Runs [Catch2](https://github.com/catchorg/Catch2) test units located at `worker/test/` folder. It invokes `invoke test` below. +Runs [Catch2](https://github.com/catchorg/Catch2) test units located at `worker/test` folder. It invokes `invoke test` below. ### `npm run coverage:node` @@ -78,7 +84,7 @@ It is not necessary for normal usage of mediasoup as a dependency. ## Python Invoke and `tasks.py` file -mediasoup uses Python [Invoke](https://www.pyinvoke.org/) library for managing and organizing tasks in the `worker` folder (mediasoup worker C++ subproject). `Invoke` is basically a replacemente of `make` + `Makefile` written in Python. mediasoup automatically installs `Invoke` in a local custom path during the installation process (in both Node and Rust) so the user doesn't need to worry about it. +mediasoup uses Python [Invoke](https://www.pyinvoke.org) library for managing and organizing tasks in the `worker` folder (mediasoup worker C++ subproject). `Invoke` is basically a replacemente of `make` + `Makefile` written in Python. mediasoup automatically installs `Invoke` in a local custom path during the installation process (in both Node and Rust) so the user doesn't need to worry about it. Tasks are defined in `worker/tasks.py`. For development purposes, developers or contributors can install `Invoke` using `pip3 install invoke` and run tasks below within the `worker` folder. @@ -129,7 +135,7 @@ invoke update-wrap-file openssl ### `invoke mediasoup-worker` -Builds the `mediasoup-worker` binary at `worker/out/Release/`. +Builds the `mediasoup-worker` binary at `worker/out/Release`. If the "MEDIASOUP_MAX_CORES" environment variable is set, the build process will use that number of CPU cores. Otherwise it will auto-detect the number of cores in the machine. @@ -153,7 +159,7 @@ MEDIASOUP_WORKER_BIN="/home/xxx/src/foo/mediasoup-worker" node myapp.js ### `invoke libmediasoup-worker` -Builds the `libmediasoup-worker` static library at `worker/out/Release/`. +Builds the `libmediasoup-worker` static library at `worker/out/Release`. "MEDIASOUP_MAX_CORES"` and "MEDIASOUP_BUILDTYPE" environment variables from above still apply for static library build. @@ -171,7 +177,7 @@ Rewrites mediasoup worker C++ files using [clang-format](https://clang.llvm.org/ ### `invoke test` -Builds and runs the `mediasoup-worker-test` binary at `worker/out/Release/` (or at `worker/out/Debug/` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"), which uses [Catch2](https://github.com/catchorg/Catch2) to run test units located at `worker/test/` folder. +Builds and runs the `mediasoup-worker-test` binary at `worker/out/Release` (or at `worker/out/Debug` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"), which uses [Catch2](https://github.com/catchorg/Catch2) to run test units located at `worker/test` folder. ### `invoke test-asan` @@ -179,19 +185,19 @@ Run test with Address Sanitizer. ### `invoke tidy` -Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy/) and performs C++ code checks following `worker/.clang-tidy` rules. +Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy) and performs C++ code checks following `worker/.clang-tidy` rules. **Requirements:** * `invoke clean` and `invoke mediasoup-worker` must have been called first. -* [PyYAML](https://pyyaml.org/) is required. +* [PyYAML](https://pyyaml.org) is required. - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. "MEDIASOUP_TIDY_CHECKS" environment variable with a comma separated list of checks overrides the checks defined in `.clang-tidy` file. ### `invoke fuzzer` -Builds the `mediasoup-worker-fuzzer` binary (which uses [libFuzzer](http://llvm.org/docs/LibFuzzer.html)) at `worker/out/Release/` (or at `worker/out/Debug/` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"). +Builds the `mediasoup-worker-fuzzer` binary (which uses [libFuzzer](http://llvm.org/docs/LibFuzzer.html)) at `worker/out/Release` (or at `worker/out/Debug/` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"). **Requirements:** @@ -218,7 +224,7 @@ scripts/get-dep.sh clang-fuzzer ### `invoke docker-run` -Runs a container of the Ubuntu Docker image created with `invoke docker`. It automatically executes a `bash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. +Runs a container of the Ubuntu Docker image created with `invoke docker`. It automatically executes a `bash` session in the `/mediasoup` directory, which is a Docker volume that points to the mediasoup root folder. **NOTE:** To install and run mediasoup in the container, previous installation (if any) must be properly cleaned by entering the `worker` directory and running `invoke clean-all`. @@ -228,7 +234,7 @@ Builds a Linux Alpine Docker image with all dependencies to run mediasoup. ### `invoke docker-alpine-run` -Runs a container of the Alpine Docker image created with `invoke docker-alpine`. It automatically executes an `ash` session in the `/mediasoup` directory, which is a Docker volume that points to the real `mediasoup` directory. +Runs a container of the Alpine Docker image created with `invoke docker-alpine`. It automatically executes an `ash` session in the `/mediasoup` directory, which is a Docker volume that points to the mediasoup root folder. **NOTE:** To install and run mediasoup in the container, previous installation (if any) must be properly cleaned by entering the `worker` directory and running `invoke clean-all`. diff --git a/node/src/tests/data/dtls-cert.pem b/node/src/test/data/dtls-cert.pem similarity index 100% rename from node/src/tests/data/dtls-cert.pem rename to node/src/test/data/dtls-cert.pem diff --git a/node/src/tests/data/dtls-key.pem b/node/src/test/data/dtls-key.pem similarity index 100% rename from node/src/tests/data/dtls-key.pem rename to node/src/test/data/dtls-key.pem diff --git a/node/src/tests/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts similarity index 100% rename from node/src/tests/test-ActiveSpeakerObserver.ts rename to node/src/test/test-ActiveSpeakerObserver.ts diff --git a/node/src/tests/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts similarity index 100% rename from node/src/tests/test-AudioLevelObserver.ts rename to node/src/test/test-AudioLevelObserver.ts diff --git a/node/src/tests/test-Consumer.ts b/node/src/test/test-Consumer.ts similarity index 100% rename from node/src/tests/test-Consumer.ts rename to node/src/test/test-Consumer.ts diff --git a/node/src/tests/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts similarity index 100% rename from node/src/tests/test-DataConsumer.ts rename to node/src/test/test-DataConsumer.ts diff --git a/node/src/tests/test-DataProducer.ts b/node/src/test/test-DataProducer.ts similarity index 100% rename from node/src/tests/test-DataProducer.ts rename to node/src/test/test-DataProducer.ts diff --git a/node/src/tests/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts similarity index 100% rename from node/src/tests/test-DirectTransport.ts rename to node/src/test/test-DirectTransport.ts diff --git a/node/src/tests/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts similarity index 100% rename from node/src/tests/test-PipeTransport.ts rename to node/src/test/test-PipeTransport.ts diff --git a/node/src/tests/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts similarity index 100% rename from node/src/tests/test-PlainTransport.ts rename to node/src/test/test-PlainTransport.ts diff --git a/node/src/tests/test-Producer.ts b/node/src/test/test-Producer.ts similarity index 100% rename from node/src/tests/test-Producer.ts rename to node/src/test/test-Producer.ts diff --git a/node/src/tests/test-Router.ts b/node/src/test/test-Router.ts similarity index 100% rename from node/src/tests/test-Router.ts rename to node/src/test/test-Router.ts diff --git a/node/src/tests/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts similarity index 100% rename from node/src/tests/test-WebRtcServer.ts rename to node/src/test/test-WebRtcServer.ts diff --git a/node/src/tests/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts similarity index 100% rename from node/src/tests/test-WebRtcTransport.ts rename to node/src/test/test-WebRtcTransport.ts diff --git a/node/src/tests/test-Worker.ts b/node/src/test/test-Worker.ts similarity index 64% rename from node/src/tests/test-Worker.ts rename to node/src/test/test-Worker.ts index 47cdfed464..9be4451f5b 100644 --- a/node/src/tests/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -4,12 +4,7 @@ import * as path from 'node:path'; import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; -let worker: mediasoup.types.Worker; - -beforeEach(() => worker && !worker.closed && worker.close()); -afterEach(() => worker && !worker.closed && worker.close()); - -test('Worker.workerBin matches mediasoup-worker absolute path', async () => +test('Worker.workerBin matches mediasoup-worker absolute path', () => { const workerBin = process.env.MEDIASOUP_WORKER_BIN ? process.env.MEDIASOUP_WORKER_BIN @@ -26,22 +21,21 @@ test('createWorker() succeeds', async () => mediasoup.observer.once('newworker', onObserverNewWorker); - worker = await mediasoup.createWorker(); + const worker1 = await mediasoup.createWorker(); expect(onObserverNewWorker).toHaveBeenCalledTimes(1); - expect(onObserverNewWorker).toHaveBeenCalledWith(worker); - expect(worker.constructor.name).toBe('Worker'); - expect(typeof worker.pid).toBe('number'); - expect(worker.closed).toBe(false); - expect(worker.died).toBe(false); + expect(onObserverNewWorker).toHaveBeenCalledWith(worker1); + expect(worker1.constructor.name).toBe('Worker'); + expect(typeof worker1.pid).toBe('number'); + expect(worker1.closed).toBe(false); + expect(worker1.died).toBe(false); - worker.close(); + worker1.close(); - expect(worker.closed).toBe(true); - expect(worker.died).toBe(false); + expect(worker1.closed).toBe(true); + expect(worker1.died).toBe(false); - // eslint-disable-next-line require-atomic-updates - worker = await mediasoup.createWorker<{ foo: number; bar?: string }>( + const worker2 = await mediasoup.createWorker<{ foo: number; bar?: string }>( { logLevel : 'debug', logTags : [ 'info' ], @@ -52,16 +46,17 @@ test('createWorker() succeeds', async () => libwebrtcFieldTrials : 'WebRTC-Bwe-AlrLimitedBackoff/Disabled/', appData : { foo: 456 } }); - expect(worker.constructor.name).toBe('Worker'); - expect(typeof worker.pid).toBe('number'); - expect(worker.closed).toBe(false); - expect(worker.died).toBe(false); - expect(worker.appData).toEqual({ foo: 456 }); - worker.close(); + expect(worker2.constructor.name).toBe('Worker'); + expect(typeof worker2.pid).toBe('number'); + expect(worker2.closed).toBe(false); + expect(worker2.died).toBe(false); + expect(worker2.appData).toEqual({ foo: 456 }); - expect(worker.closed).toBe(true); - expect(worker.died).toBe(false); + worker2.close(); + + expect(worker2.closed).toBe(true); + expect(worker2.died).toBe(false); }, 2000); test('createWorker() with wrong settings rejects with TypeError', async () => @@ -96,7 +91,7 @@ test('createWorker() with wrong settings rejects with TypeError', async () => test('worker.updateSettings() succeeds', async () => { - worker = await mediasoup.createWorker(); + const worker = await mediasoup.createWorker(); await expect(worker.updateSettings({ logLevel: 'debug', logTags: [ 'ice' ] })) .resolves @@ -107,7 +102,7 @@ test('worker.updateSettings() succeeds', async () => test('worker.updateSettings() with wrong settings rejects with TypeError', async () => { - worker = await mediasoup.createWorker(); + const worker = await mediasoup.createWorker(); // @ts-ignore await expect(worker.updateSettings({ logLevel: 'chicken' })) @@ -119,19 +114,18 @@ test('worker.updateSettings() with wrong settings rejects with TypeError', async test('worker.updateSettings() rejects with InvalidStateError if closed', async () => { - worker = await mediasoup.createWorker(); + const worker = await mediasoup.createWorker(); + worker.close(); await expect(worker.updateSettings({ logLevel: 'error' })) .rejects .toThrow(InvalidStateError); - - worker.close(); }, 2000); test('worker.dump() succeeds', async () => { - worker = await mediasoup.createWorker(); + const worker = await mediasoup.createWorker(); await expect(worker.dump()) .resolves @@ -152,19 +146,18 @@ test('worker.dump() succeeds', async () => test('worker.dump() rejects with InvalidStateError if closed', async () => { - worker = await mediasoup.createWorker(); + const worker = await mediasoup.createWorker(); + worker.close(); await expect(worker.dump()) .rejects .toThrow(InvalidStateError); - - worker.close(); }, 2000); test('worker.getResourceUsage() succeeds', async () => { - worker = await mediasoup.createWorker(); + const worker = await mediasoup.createWorker(); await expect(worker.getResourceUsage()) .resolves @@ -175,8 +168,7 @@ test('worker.getResourceUsage() succeeds', async () => test('worker.close() succeeds', async () => { - worker = await mediasoup.createWorker({ logLevel: 'warn' }); - + const worker = await mediasoup.createWorker({ logLevel: 'warn' }); const onObserverClose = jest.fn(); worker.observer.once('close', onObserverClose); @@ -192,24 +184,26 @@ test('Worker emits "died" if worker process died unexpectedly', async () => let onDied: ReturnType; let onObserverClose: ReturnType; - worker = await mediasoup.createWorker({ logLevel: 'warn' }); + const worker1 = await mediasoup.createWorker({ logLevel: 'warn' }); + onDied = jest.fn(); onObserverClose = jest.fn(); - worker.observer.once('close', onObserverClose); + worker1.observer.once('close', onObserverClose); await new Promise((resolve, reject) => { - worker.on('died', () => + worker1.on('died', () => { onDied(); if (onObserverClose.mock.calls.length > 0) { reject( - new Error('observer "close" event emitted before worker "died" event')); + new Error('observer "close" event emitted before worker "died" event') + ); } - else if (worker.closed) + else if (worker1.closed) { resolve(); } @@ -219,33 +213,34 @@ test('Worker emits "died" if worker process died unexpectedly', async () => } }); - process.kill(worker.pid, 'SIGINT'); + process.kill(worker1.pid, 'SIGINT'); }); expect(onDied).toHaveBeenCalledTimes(1); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(worker.closed).toBe(true); - expect(worker.died).toBe(true); + expect(worker1.closed).toBe(true); + expect(worker1.died).toBe(true); + + const worker2 = await mediasoup.createWorker({ logLevel: 'warn' }); - // eslint-disable-next-line require-atomic-updates - worker = await mediasoup.createWorker({ logLevel: 'warn' }); onDied = jest.fn(); onObserverClose = jest.fn(); - worker.observer.once('close', onObserverClose); + worker2.observer.once('close', onObserverClose); await new Promise((resolve, reject) => { - worker.on('died', () => + worker2.on('died', () => { onDied(); if (onObserverClose.mock.calls.length > 0) { reject( - new Error('observer "close" event emitted before worker "died" event')); + new Error('observer "close" event emitted before worker "died" event') + ); } - else if (worker.closed) + else if (worker2.closed) { resolve(); } @@ -255,33 +250,34 @@ test('Worker emits "died" if worker process died unexpectedly', async () => } }); - process.kill(worker.pid, 'SIGTERM'); + process.kill(worker2.pid, 'SIGTERM'); }); expect(onDied).toHaveBeenCalledTimes(1); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(worker.closed).toBe(true); - expect(worker.died).toBe(true); + expect(worker2.closed).toBe(true); + expect(worker2.died).toBe(true); + + const worker3 = await mediasoup.createWorker({ logLevel: 'warn' }); - // eslint-disable-next-line require-atomic-updates - worker = await mediasoup.createWorker({ logLevel: 'warn' }); onDied = jest.fn(); onObserverClose = jest.fn(); - worker.observer.once('close', onObserverClose); + worker3.observer.once('close', onObserverClose); await new Promise((resolve, reject) => { - worker.on('died', () => + worker3.on('died', () => { onDied(); if (onObserverClose.mock.calls.length > 0) { reject( - new Error('observer "close" event emitted before worker "died" event')); + new Error('observer "close" event emitted before worker "died" event') + ); } - else if (worker.closed) + else if (worker3.closed) { resolve(); } @@ -291,42 +287,40 @@ test('Worker emits "died" if worker process died unexpectedly', async () => } }); - process.kill(worker.pid, 'SIGKILL'); + process.kill(worker3.pid, 'SIGKILL'); }); expect(onDied).toHaveBeenCalledTimes(1); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(worker.closed).toBe(true); - expect(worker.died).toBe(true); + expect(worker3.closed).toBe(true); + expect(worker3.died).toBe(true); }, 5000); -test('worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () => +// Windows doesn't have some signals such as SIGPIPE, SIGALRM, SIGUSR1, SIGUSR2 +// so we just skip this test in Windows. +if (os.platform() !== 'win32') { - // Windows doesn't have some signals such as SIGPIPE, SIGALRM, SIGUSR1, SIGUSR2 - // so we just skip this test in Windows. - if (os.platform() === 'win32') + test('worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () => { - return; - } + const worker = await mediasoup.createWorker({ logLevel: 'warn' }); - worker = await mediasoup.createWorker({ logLevel: 'warn' }); - - await new Promise((resolve, reject) => - { - worker.on('died', reject); + await new Promise((resolve, reject) => + { + worker.on('died', reject); - process.kill(worker.pid, 'SIGPIPE'); - process.kill(worker.pid, 'SIGHUP'); - process.kill(worker.pid, 'SIGALRM'); - process.kill(worker.pid, 'SIGUSR1'); - process.kill(worker.pid, 'SIGUSR2'); + process.kill(worker.pid, 'SIGPIPE'); + process.kill(worker.pid, 'SIGHUP'); + process.kill(worker.pid, 'SIGALRM'); + process.kill(worker.pid, 'SIGUSR1'); + process.kill(worker.pid, 'SIGUSR2'); - setTimeout(() => - { - expect(worker.closed).toBe(false); + setTimeout(() => + { + expect(worker.closed).toBe(false); - worker.close(); - resolve(); - }, 2000); - }); -}, 3000); + worker.close(); + resolve(); + }, 2000); + }); + }, 3000); +} diff --git a/node/src/tests/test-mediasoup.ts b/node/src/test/test-mediasoup.ts similarity index 100% rename from node/src/tests/test-mediasoup.ts rename to node/src/test/test-mediasoup.ts diff --git a/node/src/tests/test-multiopus.ts b/node/src/test/test-multiopus.ts similarity index 100% rename from node/src/tests/test-multiopus.ts rename to node/src/test/test-multiopus.ts diff --git a/node/src/tests/test-node-sctp.ts b/node/src/test/test-node-sctp.ts similarity index 100% rename from node/src/tests/test-node-sctp.ts rename to node/src/test/test-node-sctp.ts diff --git a/node/src/tests/test-ortc.ts b/node/src/test/test-ortc.ts similarity index 100% rename from node/src/tests/test-ortc.ts rename to node/src/test/test-ortc.ts diff --git a/npm-scripts.mjs b/npm-scripts.mjs index a734c35e33..28b5b8bc46 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -21,7 +21,8 @@ const WORKER_PREBUILD_TAR_PATH = `${WORKER_PREBUILD_DIR}/${WORKER_PREBUILD_TAR}` const GH_OWNER = 'versatica'; const GH_REPO = 'mediasoup'; -const task = process.argv.slice(2).join(' '); +const task = process.argv[2]; +const args = process.argv.slice(3).join(' '); // PYTHONPATH env must be updated now so all invoke calls below will find the // pip invoke module. @@ -45,6 +46,8 @@ run(); async function run() { + logInfo(args ? `[args:"${args}"]` : ''); + switch (task) { // As per NPM documentation (https://docs.npmjs.com/cli/v9/using-npm/scripts) @@ -125,7 +128,7 @@ async function run() case 'typescript:watch': { deleteNodeLib(); - executeCmd('tsc --project node --watch'); + executeCmd(`tsc --project node --watch ${args}`); break; } @@ -199,7 +202,7 @@ async function run() case 'coverage:node': { buildTypescript({ force: false }); - executeCmd('jest --coverage'); + executeCmd(`jest --coverage ${args}`); executeCmd('open-cli coverage/lcov-report/index.html'); break; @@ -438,14 +441,7 @@ function testNode() { logInfo('testNode()'); - if (!process.env.TEST_FILE) - { - executeCmd('jest'); - } - else - { - executeCmd(`jest --testPathPattern "${process.env.TEST_FILE}"`); - } + executeCmd(`jest ${args}`); } function testWorker() diff --git a/package.json b/package.json index 6414d977be..847cd5d798 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "jest": { "verbose": true, "testEnvironment": "node", - "testRegex": "node/src/tests/test-.*\\.ts", + "testRegex": "node/src/test/test-.*\\.ts", "transform": { "^.*\\.ts$": [ "ts-jest", @@ -88,7 +88,7 @@ }, "coveragePathIgnorePatterns": [ "node/src/fbs", - "node/src/tests" + "node/src/test" ], "cacheDirectory": ".cache/jest", "modulePathIgnorePatterns": [ From e51b47bdbfd3bd4d23d3288ab4832c10f5a662b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 4 Jan 2024 12:34:48 +0100 Subject: [PATCH 296/525] Make Node tests independent (part 2) (#1296) - Just done in `test-Router.ts` as POC. - Avoid declaring global variables in test files. Put them into `ctx: TestContext` instead. - Things in `ctx` should be const/frozen or reset in each `test()` execution. - So use a new `utils.deepFreeze()` function which freezes the object and would throw upon any modification attempt. --- node/src/test/test-Router.ts | 128 ++++++++++++++++++----------------- node/src/utils.ts | 23 +++++++ 2 files changed, 89 insertions(+), 62 deletions(-) diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index d6147cf55f..4eb0f4443e 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -1,55 +1,69 @@ import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; +import * as utils from '../utils'; -let worker: mediasoup.types.Worker; +type TestContext = +{ + worker?: mediasoup.types.Worker; + mediaCodecs: mediasoup.types.RtpCodecCapability[]; +}; -beforeEach(() => worker && !worker.closed && worker.close()); -afterEach(() => worker && !worker.closed && worker.close()); +const ctx: TestContext = +{ + mediaCodecs : utils.deepFreeze( + [ + { + kind : 'audio', + mimeType : 'audio/opus', + clockRate : 48000, + channels : 2, + parameters : + { + useinbandfec : 1, + foo : 'bar' + } + }, + { + kind : 'video', + mimeType : 'video/VP8', + clockRate : 90000 + }, + { + kind : 'video', + mimeType : 'video/H264', + clockRate : 90000, + parameters : + { + 'level-asymmetry-allowed' : 1, + 'packetization-mode' : 1, + 'profile-level-id' : '4d0032' + }, + rtcpFeedback : [] // Will be ignored. + } + ] + ) +}; + +beforeEach(async () => +{ + ctx.worker = await mediasoup.createWorker(); +}); -const mediaCodecs: mediasoup.types.RtpCodecCapability[] = -[ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } - }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 - }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : [] // Will be ignored. - } -]; +afterEach(() => +{ + ctx.worker?.close(); +}); test('worker.createRouter() succeeds', async () => { - worker = await mediasoup.createWorker(); - const onObserverNewRouter = jest.fn(); - worker.observer.once('newrouter', onObserverNewRouter); + ctx.worker!.observer.once('newrouter', onObserverNewRouter); - const router = await worker.createRouter<{ foo: number; bar?: string }>( + const router = await ctx.worker!.createRouter<{ foo: number; bar?: string }>( { - mediaCodecs, - appData : { foo: 123 } + mediaCodecs : ctx.mediaCodecs, + appData : { foo: 123 } }); expect(onObserverNewRouter).toHaveBeenCalledTimes(1); @@ -63,11 +77,11 @@ test('worker.createRouter() succeeds', async () => expect(() => (router.appData = { foo: 222, bar: 'BBB' })).not.toThrow(); - await expect(worker.dump()) + await expect(ctx.worker!.dump()) .resolves .toMatchObject( { - pid : worker.pid, + pid : ctx.worker!.pid, webRtcServerIds : [], routerIds : [ router.id ], channelMessageHandlers : @@ -92,49 +106,41 @@ test('worker.createRouter() succeeds', async () => }); // Private API. - expect(worker.routersForTesting.size).toBe(1); + expect(ctx.worker!.routersForTesting.size).toBe(1); - worker.close(); + ctx.worker!.close(); expect(router.closed).toBe(true); // Private API. - expect(worker.routersForTesting.size).toBe(0); + expect(ctx.worker!.routersForTesting.size).toBe(0); }, 2000); test('worker.createRouter() with wrong arguments rejects with TypeError', async () => { - worker = await mediasoup.createWorker(); - // @ts-ignore - await expect(worker.createRouter({ mediaCodecs: {} })) + await expect(ctx.worker!.createRouter({ mediaCodecs: {} })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(worker.createRouter({ appData: 'NOT-AN-OBJECT' })) + await expect(ctx.worker!.createRouter({ appData: 'NOT-AN-OBJECT' })) .rejects .toThrow(TypeError); - - worker.close(); }, 2000); test('worker.createRouter() rejects with InvalidStateError if Worker is closed', async () => { - worker = await mediasoup.createWorker(); - - worker.close(); + ctx.worker!.close(); - await expect(worker.createRouter({ mediaCodecs })) + await expect(ctx.worker!.createRouter({ mediaCodecs: ctx.mediaCodecs })) .rejects .toThrow(InvalidStateError); }, 2000); test('router.close() succeeds', async () => { - worker = await mediasoup.createWorker(); - - const router = await worker.createRouter({ mediaCodecs }); + const router = await ctx.worker!.createRouter({ mediaCodecs: ctx.mediaCodecs }); const onObserverClose = jest.fn(); router.observer.once('close', onObserverClose); @@ -146,9 +152,7 @@ test('router.close() succeeds', async () => test('Router emits "workerclose" if Worker is closed', async () => { - worker = await mediasoup.createWorker(); - - const router = await worker.createRouter({ mediaCodecs }); + const router = await ctx.worker!.createRouter({ mediaCodecs: ctx.mediaCodecs }); const onObserverClose = jest.fn(); router.observer.once('close', onObserverClose); @@ -156,7 +160,7 @@ test('Router emits "workerclose" if Worker is closed', async () => await new Promise((resolve) => { router.on('workerclose', resolve); - worker.close(); + ctx.worker!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); diff --git a/node/src/utils.ts b/node/src/utils.ts index 439f1fcaaf..f0ad39ff1e 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -197,3 +197,26 @@ export function parseStringStringArrayVector( return array; } + +/** + * Make an object or array recursively immutable. + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze. + */ +export function deepFreeze(object: T): T +{ + // Retrieve the property names defined on object. + const propNames = Reflect.ownKeys(object as any); + + // Freeze properties before freezing self. + for (const name of propNames) + { + const value = (object as any)[name]; + + if ((value && typeof value === 'object') || typeof value === 'function') + { + deepFreeze(value); + } + } + + return Object.freeze(object); +} From 913cf8fe0cf080feff4b306033944282ac9d84fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 4 Jan 2024 15:15:31 +0100 Subject: [PATCH 297/525] Make Node test independent (part 3) (#1297) - Done in `test-WebRtcServer` and `test-multiopus.ts`. - This helped fixing a bug since `rtpCapabilities` given to `router.canConsume()` were modified internally! Now we clone them. - Also avoid super long `import` lines in some random files. --- node/src/Router.ts | 57 ++++++-- node/src/Transport.ts | 2 +- node/src/test/test-WebRtcServer.ts | 102 +++++++-------- node/src/test/test-multiopus.ts | 204 ++++++++++++++++------------- 4 files changed, 203 insertions(+), 162 deletions(-) diff --git a/node/src/Router.ts b/node/src/Router.ts index 9de04034d5..4c986870da 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -10,22 +10,50 @@ import { TransportProtocol, TransportSocketFlags } from './Transport'; -import { WebRtcTransport, WebRtcTransportOptions, parseWebRtcTransportDumpResponse } from './WebRtcTransport'; -import { PlainTransport, PlainTransportOptions, parsePlainTransportDumpResponse } from './PlainTransport'; -import { PipeTransport, PipeTransportOptions, parsePipeTransportDumpResponse } from './PipeTransport'; -import { DirectTransport, DirectTransportOptions, parseDirectTransportDumpResponse } from './DirectTransport'; +import { + WebRtcTransport, + WebRtcTransportOptions, + parseWebRtcTransportDumpResponse +} from './WebRtcTransport'; +import { + PlainTransport, + PlainTransportOptions, + parsePlainTransportDumpResponse +} from './PlainTransport'; +import { + PipeTransport, + PipeTransportOptions, + parsePipeTransportDumpResponse +} from './PipeTransport'; +import { + DirectTransport, + DirectTransportOptions, + parseDirectTransportDumpResponse +} from './DirectTransport'; import { Producer } from './Producer'; import { Consumer } from './Consumer'; import { DataProducer } from './DataProducer'; import { DataConsumer } from './DataConsumer'; import { RtpObserver } from './RtpObserver'; -import { ActiveSpeakerObserver, ActiveSpeakerObserverOptions } from './ActiveSpeakerObserver'; -import { AudioLevelObserver, AudioLevelObserverOptions } from './AudioLevelObserver'; +import { + ActiveSpeakerObserver, + ActiveSpeakerObserverOptions +} from './ActiveSpeakerObserver'; +import { + AudioLevelObserver, + AudioLevelObserverOptions +} from './AudioLevelObserver'; import { RtpCapabilities, RtpCodecCapability } from './RtpParameters'; import { cryptoSuiteToFbs } from './SrtpParameters'; import { NumSctpStreams } from './SctpParameters'; import { AppData, Either } from './types'; -import { generateUUIDv4, parseVector, parseStringStringVector, parseStringStringArrayVector } from './utils'; +import { + clone, + generateUUIDv4, + parseVector, + parseStringStringVector, + parseStringStringArrayVector +} from './utils'; import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; import * as FbsRequest from './fbs/request'; @@ -1441,7 +1469,7 @@ export class Router { throw new TypeError('if given, interval must be an number'); } - if (appData && typeof appData !== 'object') + else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } @@ -1511,15 +1539,15 @@ export class Router { throw new TypeError('if given, maxEntries must be a positive number'); } - if (typeof threshold !== 'number' || threshold < -127 || threshold > 0) + else if (typeof threshold !== 'number' || threshold < -127 || threshold > 0) { throw new TypeError('if given, threshole must be a negative number greater than -127'); } - if (typeof interval !== 'number') + else if (typeof interval !== 'number') { throw new TypeError('if given, interval must be an number'); } - if (appData && typeof appData !== 'object') + else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } @@ -1596,9 +1624,14 @@ export class Router return false; } + // Clone given RTP capabilities to not modify input data. + const clonedRtpCapabilities = clone(rtpCapabilities); + try { - return ortc.canConsume(producer.consumableRtpParameters, rtpCapabilities); + return ortc.canConsume( + producer.consumableRtpParameters, clonedRtpCapabilities + ); } catch (error) { diff --git a/node/src/Transport.ts b/node/src/Transport.ts index d04f863927..c189a848ae 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -1286,7 +1286,7 @@ export class Transport { throw new TypeError('types must be an array'); } - if (types.find((type) => typeof type !== 'string')) + else if (types.find((type) => typeof type !== 'string')) { throw new TypeError('every type must be a string'); } diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index 24b7ca0688..909863975a 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -3,23 +3,33 @@ import * as pickPort from 'pick-port'; import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; -let worker: mediasoup.types.Worker; +type TestContext = +{ + worker?: mediasoup.types.Worker; +}; -beforeEach(() => worker && !worker.closed && worker.close()); -afterEach(() => worker && !worker.closed && worker.close()); +const ctx: TestContext = {}; -test('worker.createWebRtcServer() succeeds', async () => +beforeEach(async () => +{ + ctx.worker = await mediasoup.createWorker(); +}); + +afterEach(() => { - worker = await mediasoup.createWorker(); + ctx.worker?.close(); +}); +test('worker.createWebRtcServer() succeeds', async () => +{ const onObserverNewWebRtcServer = jest.fn(); - worker.observer.once('newwebrtcserver', onObserverNewWebRtcServer); + ctx.worker!.observer.once('newwebrtcserver', onObserverNewWebRtcServer); const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await worker.createWebRtcServer<{ foo?: number }>( + const webRtcServer = await ctx.worker!.createWebRtcServer<{ foo?: number }>( { listenInfos : [ @@ -44,11 +54,11 @@ test('worker.createWebRtcServer() succeeds', async () => expect(webRtcServer.closed).toBe(false); expect(webRtcServer.appData).toEqual({ foo: 123 }); - await expect(worker.dump()) + await expect(ctx.worker!.dump()) .resolves .toMatchObject( { - pid : worker.pid, + pid : ctx.worker!.pid, webRtcServerIds : [ webRtcServer.id ], routerIds : [], channelMessageHandlers : @@ -77,25 +87,23 @@ test('worker.createWebRtcServer() succeeds', async () => }); // Private API. - expect(worker.webRtcServersForTesting.size).toBe(1); + expect(ctx.worker!.webRtcServersForTesting.size).toBe(1); - worker.close(); + ctx.worker!.close(); expect(webRtcServer.closed).toBe(true); // Private API. - expect(worker.webRtcServersForTesting.size).toBe(0); + expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); }, 2000); test('worker.createWebRtcServer() without specifying port succeeds', async () => { - worker = await mediasoup.createWorker(); - const onObserverNewWebRtcServer = jest.fn(); - worker.observer.once('newwebrtcserver', onObserverNewWebRtcServer); + ctx.worker!.observer.once('newwebrtcserver', onObserverNewWebRtcServer); - const webRtcServer = await worker.createWebRtcServer( + const webRtcServer = await ctx.worker!.createWebRtcServer( { listenInfos : [ @@ -118,11 +126,11 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => expect(webRtcServer.closed).toBe(false); expect(webRtcServer.appData).toEqual({ foo: 123 }); - await expect(worker.dump()) + await expect(ctx.worker!.dump()) .resolves .toMatchObject( { - pid : worker.pid, + pid : ctx.worker!.pid, webRtcServerIds : [ webRtcServer.id ], routerIds : [], channelMessageHandlers : @@ -151,52 +159,47 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => }); // Private API. - expect(worker.webRtcServersForTesting.size).toBe(1); + expect(ctx.worker!.webRtcServersForTesting.size).toBe(1); - worker.close(); + ctx.worker!.close(); expect(webRtcServer.closed).toBe(true); // Private API. - expect(worker.webRtcServersForTesting.size).toBe(0); + expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); }, 2000); test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', async () => { - worker = await mediasoup.createWorker(); - // @ts-ignore - await expect(worker.createWebRtcServer({})) + await expect(ctx.worker!.createWebRtcServer({})) .rejects .toThrow(TypeError); // @ts-ignore - await expect(worker.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' })) + await expect(ctx.worker!.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(worker.createWebRtcServer({ listenInfos: [ 'NOT-AN-OBJECT' ] })) + await expect(ctx.worker!.createWebRtcServer({ listenInfos: [ 'NOT-AN-OBJECT' ] })) .rejects .toThrow(Error); // Empty listenInfos so should fail. - await expect(worker.createWebRtcServer({ listenInfos: [] })) + await expect(ctx.worker!.createWebRtcServer({ listenInfos: [] })) .rejects .toThrow(TypeError); - - worker.close(); }, 2000); test('worker.createWebRtcServer() with unavailable listenInfos rejects with Error', async () => { - const worker1 = await mediasoup.createWorker(); const worker2 = await mediasoup.createWorker(); const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); // Using an unavailable listen IP. - await expect(worker1.createWebRtcServer( + await expect(ctx.worker!.createWebRtcServer( { listenInfos : [ @@ -216,7 +219,7 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro .toThrow(Error); // Using the same UDP port in two listenInfos. - await expect(worker1.createWebRtcServer( + await expect(ctx.worker!.createWebRtcServer( { listenInfos : [ @@ -236,7 +239,7 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro .rejects .toThrow(Error); - await worker1.createWebRtcServer( + await ctx.worker!.createWebRtcServer( { listenInfos : [ @@ -263,19 +266,16 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro .rejects .toThrow(Error); - worker1.close(); worker2.close(); }, 2000); test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is closed', async () => { - worker = await mediasoup.createWorker(); - - worker.close(); + ctx.worker!.close(); const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - await expect(worker.createWebRtcServer( + await expect(ctx.worker!.createWebRtcServer( { listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port } ] })) @@ -285,10 +285,8 @@ test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is cl test('webRtcServer.close() succeeds', async () => { - worker = await mediasoup.createWorker(); - const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await worker.createWebRtcServer( + const webRtcServer = await ctx.worker!.createWebRtcServer( { listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port } ] }); @@ -303,10 +301,8 @@ test('webRtcServer.close() succeeds', async () => test('WebRtcServer emits "workerclose" if Worker is closed', async () => { - worker = await mediasoup.createWorker(); - const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await worker.createWebRtcServer( + const webRtcServer = await ctx.worker!.createWebRtcServer( { listenInfos : [ { protocol: 'tcp', ip: '127.0.0.1', port } ] }); @@ -317,7 +313,7 @@ test('WebRtcServer emits "workerclose" if Worker is closed', async () => await new Promise((resolve) => { webRtcServer.on('workerclose', resolve); - worker.close(); + ctx.worker!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); @@ -326,11 +322,9 @@ test('WebRtcServer emits "workerclose" if Worker is closed', async () => test('router.createWebRtcTransport() with webRtcServer succeeds and transport is closed', async () => { - worker = await mediasoup.createWorker(); - const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await worker.createWebRtcServer( + const webRtcServer = await ctx.worker!.createWebRtcServer( { listenInfos : [ @@ -345,7 +339,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is webRtcServer.observer.once('webrtctransporthandled', onObserverWebRtcTransportHandled); webRtcServer.observer.once('webrtctransportunhandled', onObserverWebRtcTransportUnhandled); - const router = await worker.createRouter(); + const router = await ctx.worker!.createRouter(); const onObserverNewTransport = jest.fn(); @@ -436,11 +430,9 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer is closed', async () => { - worker = await mediasoup.createWorker(); - const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await worker.createWebRtcServer( + const webRtcServer = await ctx.worker!.createWebRtcServer( { listenInfos : [ @@ -455,7 +447,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer webRtcServer.observer.once('webrtctransporthandled', onObserverWebRtcTransportHandled); webRtcServer.observer.once('webrtctransportunhandled', onObserverWebRtcTransportUnhandled); - const router = await worker.createRouter(); + const router = await ctx.worker!.createRouter(); const transport = await router.createWebRtcTransport( { webRtcServer, @@ -563,11 +555,11 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); expect(router.transportsForTesting.size).toBe(0); - await expect(worker.dump()) + await expect(ctx.worker!.dump()) .resolves .toMatchObject( { - pid : worker.pid, + pid : ctx.worker!.pid, webRtcServerIds : [], routerIds : [ router.id ], channelMessageHandlers : diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index 0cb4991239..23322095de 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -1,34 +1,44 @@ import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; +import * as utils from '../utils'; -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let transport: mediasoup.types.WebRtcTransport; - -const mediaCodecs: mediasoup.types.RtpCodecCapability[] = -[ - { - kind : 'audio', - mimeType : 'audio/multiopus', - clockRate : 48000, - channels : 6, - parameters : - { - useinbandfec : 1, - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 - } - } -]; +type TestContext = +{ + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; + transport?: mediasoup.types.WebRtcTransport; + mediaCodecs: mediasoup.types.RtpCodecCapability[]; + audioProducerParameters: mediasoup.types.ProducerOptions; + consumerDeviceCapabilities: mediasoup.types.RtpCapabilities; +}; -const audioProducerParameters: mediasoup.types.ProducerOptions = +const ctx: TestContext = { - kind : 'audio', - rtpParameters : + mediaCodecs : utils.deepFreeze( + [ + { + kind : 'audio', + mimeType : 'audio/multiopus', + preferredPayloadType : 100, + clockRate : 48000, + channels : 6, + parameters : + { + useinbandfec : 1, + 'channel_mapping' : '0,4,1,2,3,5', + 'num_streams' : 4, + 'coupled_streams' : 2 + } + } + ] + ), + audioProducerParameters : utils.deepFreeze( { - mid : 'AUDIO', - codecs : + kind : 'audio', + rtpParameters : + { + mid : 'AUDIO', + codecs : [ { mimeType : 'audio/multiopus', @@ -36,15 +46,15 @@ const audioProducerParameters: mediasoup.types.ProducerOptions = clockRate : 48000, channels : 6, parameters : - { - useinbandfec : 1, - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 - } + { + useinbandfec : 1, + 'channel_mapping' : '0,4,1,2,3,5', + 'num_streams' : 4, + 'coupled_streams' : 2 + } } ], - headerExtensions : + headerExtensions : [ { uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', @@ -55,65 +65,70 @@ const audioProducerParameters: mediasoup.types.ProducerOptions = id : 12 } ] + } } -}; - -const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = -{ - codecs : - [ - { - mimeType : 'audio/multiopus', - kind : 'audio', - preferredPayloadType : 100, - clockRate : 48000, - channels : 6, - parameters : + ), + consumerDeviceCapabilities : utils.deepFreeze( + { + codecs : + [ + { + mimeType : 'audio/multiopus', + kind : 'audio', + preferredPayloadType : 100, + clockRate : 48000, + channels : 6, + parameters : { 'channel_mapping' : '0,4,1,2,3,5', 'num_streams' : 4, 'coupled_streams' : 2 } - } - ], - headerExtensions : - [ - { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false - }, - { - kind : 'audio', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId : 4, - preferredEncrypt : false - }, - { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 10, - preferredEncrypt : false - } - ] + } + ], + headerExtensions : + [ + { + kind : 'audio', + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId : 1, + preferredEncrypt : false + }, + { + kind : 'audio', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId : 4, + preferredEncrypt : false + }, + { + kind : 'audio', + uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId : 10, + preferredEncrypt : false + } + ] + } + ) }; -beforeAll(async () => +beforeEach(async () => { - worker = await mediasoup.createWorker(); - router = await worker.createRouter({ mediaCodecs }); - transport = await router.createWebRtcTransport( + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); + ctx.transport = await ctx.router.createWebRtcTransport( { - listenIps : [ '127.0.0.1' ] + listenInfos : [ { protocol: 'udp', ip: '127.0.0.1' } ] }); }); -afterAll(() => worker.close()); +afterEach(() => +{ + ctx.worker?.close(); +}); -test('produce/consume succeeds', async () => +test('produce() and consume() succeed', async () => { - const audioProducer = await transport.produce(audioProducerParameters); + const audioProducer = await ctx.transport!.produce(ctx.audioProducerParameters); expect(audioProducer.rtpParameters.codecs).toEqual([ { @@ -122,25 +137,26 @@ test('produce/consume succeeds', async () => clockRate : 48000, channels : 6, parameters : - { - useinbandfec : 1, - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 - }, + { + useinbandfec : 1, + 'channel_mapping' : '0,4,1,2,3,5', + 'num_streams' : 4, + 'coupled_streams' : 2 + }, rtcpFeedback : [] } ]); - expect(router.canConsume({ - producerId : audioProducer.id, - rtpCapabilities : consumerDeviceCapabilities - })) - .toBe(true); + expect(ctx.router!.canConsume( + { + producerId : audioProducer.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }) + ).toBe(true); - const audioConsumer = await transport.consume({ + const audioConsumer = await ctx.transport!.consume({ producerId : audioProducer.id, - rtpCapabilities : consumerDeviceCapabilities + rtpCapabilities : ctx.consumerDeviceCapabilities }); expect(audioConsumer.rtpParameters.codecs).toEqual([ @@ -166,7 +182,7 @@ test('produce/consume succeeds', async () => test('fails to produce wrong parameters', async () => { - await expect(transport.produce({ + await expect(ctx.transport!.produce({ kind : 'audio', rtpParameters : { @@ -191,7 +207,7 @@ test('fails to produce wrong parameters', async () => .rejects .toThrow(UnsupportedError); - await expect(transport.produce({ + await expect(ctx.transport!.produce({ kind : 'audio', rtpParameters : { @@ -219,7 +235,7 @@ test('fails to produce wrong parameters', async () => test('fails to consume wrong channels', async () => { - const audioProducer = await transport.produce(audioProducerParameters); + const audioProducer = await ctx.transport!.produce(ctx.audioProducerParameters); const localConsumerDeviceCapabilities: mediasoup.types.RtpCapabilities = { codecs : @@ -240,13 +256,13 @@ test('fails to consume wrong channels', async () => ] }; - expect(!router.canConsume({ + expect(!ctx.router!.canConsume({ producerId : audioProducer.id, rtpCapabilities : localConsumerDeviceCapabilities })) .toBe(true); - await expect(transport.consume({ + await expect(ctx.transport!.consume({ producerId : audioProducer.id, rtpCapabilities : localConsumerDeviceCapabilities })) From f09861c69fa3fb1ea85acd66abe56088f5cc2200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Thu, 4 Jan 2024 22:29:08 +0100 Subject: [PATCH 298/525] C++: qualified auto (#1299) --- worker/include/RTC/RTCP/Packet.hpp | 2 +- worker/include/RTC/RtpPacket.hpp | 2 +- worker/include/RTC/TransportTuple.hpp | 8 +++++--- worker/src/RTC/PlainTransport.cpp | 2 +- worker/src/RTC/WebRtcServer.cpp | 2 +- worker/src/Settings.cpp | 2 +- worker/src/Utils/IP.cpp | 2 +- worker/src/Utils/String.cpp | 4 ++-- worker/src/Worker.cpp | 8 ++++---- worker/src/handles/TcpConnectionHandle.cpp | 2 +- worker/src/handles/UdpSocketHandle.cpp | 2 +- worker/test/src/Utils/TestIP.cpp | 2 +- 12 files changed, 20 insertions(+), 18 deletions(-) diff --git a/worker/include/RTC/RTCP/Packet.hpp b/worker/include/RTC/RTCP/Packet.hpp index bf771fad22..f60731e271 100644 --- a/worker/include/RTC/RTCP/Packet.hpp +++ b/worker/include/RTC/RTCP/Packet.hpp @@ -52,7 +52,7 @@ namespace RTC static const size_t CommonHeaderSize{ 4 }; static bool IsRtcp(const uint8_t* data, size_t len) { - auto header = const_cast(reinterpret_cast(data)); + auto* header = const_cast(reinterpret_cast(data)); // clang-format off return ( diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index 0ff85ed150..81be74fe4f 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -120,7 +120,7 @@ namespace RTC { // NOTE: RtcpPacket::IsRtcp() must always be called before this method. - auto header = const_cast(reinterpret_cast(data)); + auto* header = const_cast(reinterpret_cast(data)); // clang-format off return ( diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 772539c391..d282de036b 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -190,7 +190,7 @@ namespace RTC { case AF_INET: { - auto* remoteSockAddrIn = reinterpret_cast(remoteSockAddr); + const auto* remoteSockAddrIn = reinterpret_cast(remoteSockAddr); const uint64_t address = ntohl(remoteSockAddrIn->sin_addr.s_addr); const uint64_t port = (ntohs(remoteSockAddrIn->sin_port)); @@ -204,8 +204,10 @@ namespace RTC case AF_INET6: { - auto* remoteSockAddrIn6 = reinterpret_cast(remoteSockAddr); - auto* a = reinterpret_cast(std::addressof(remoteSockAddrIn6->sin6_addr)); + const auto* remoteSockAddrIn6 = + reinterpret_cast(remoteSockAddr); + const auto* a = + reinterpret_cast(std::addressof(remoteSockAddrIn6->sin6_addr)); const auto address1 = a[0] ^ a[1] ^ a[2] ^ a[3]; const auto address2 = a[0]; diff --git a/worker/src/RTC/PlainTransport.cpp b/worker/src/RTC/PlainTransport.cpp index 672fe54cc2..f985dc8fa8 100644 --- a/worker/src/RTC/PlainTransport.cpp +++ b/worker/src/RTC/PlainTransport.cpp @@ -429,7 +429,7 @@ namespace RTC MS_THROW_TYPE_ERROR("missing srtpParameters (SRTP enabled)"); } - const auto srtpParameters = body->srtpParameters(); + const auto* const srtpParameters = body->srtpParameters(); // Update out SRTP crypto suite with the one used by the remote. auto previousSrtpCryptoSuite = this->srtpCryptoSuite; diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index a1f234c9db..94801fe5a2 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -273,7 +273,7 @@ namespace RTC std::vector iceCandidates; uint16_t iceLocalPreferenceDecrement{ 0 }; - for (auto& item : this->udpSocketOrTcpServers) + for (const auto& item : this->udpSocketOrTcpServers) { if (item.udpSocket && enableUdp) { diff --git a/worker/src/Settings.cpp b/worker/src/Settings.cpp index 8f271fc908..655e1b2b1e 100644 --- a/worker/src/Settings.cpp +++ b/worker/src/Settings.cpp @@ -303,7 +303,7 @@ void Settings::HandleRequest(Channel::ChannelRequest* request) { case Channel::ChannelRequest::Method::WORKER_UPDATE_SETTINGS: { - auto body = request->data->body_as(); + const auto* body = request->data->body_as(); if (flatbuffers::IsFieldPresent(body, FBS::Worker::UpdateSettingsRequest::VT_LOGLEVEL)) { diff --git a/worker/src/Utils/IP.cpp b/worker/src/Utils/IP.cpp index 9460fc2488..0ba2416fbf 100644 --- a/worker/src/Utils/IP.cpp +++ b/worker/src/Utils/IP.cpp @@ -17,7 +17,7 @@ namespace Utils return AF_UNSPEC; } - auto ipPtr = ip.c_str(); + const auto* ipPtr = ip.c_str(); char ipBuffer[INET6_ADDRSTRLEN] = { 0 }; if (uv_inet_pton(AF_INET, ipPtr, ipBuffer) == 0) diff --git a/worker/src/Utils/String.cpp b/worker/src/Utils/String.cpp index 8c9f250907..77fe74c0ca 100644 --- a/worker/src/Utils/String.cpp +++ b/worker/src/Utils/String.cpp @@ -84,7 +84,7 @@ namespace Utils { MS_TRACE(); - auto* data = reinterpret_cast(str.c_str()); + const auto* data = reinterpret_cast(str.c_str()); return Base64Encode(data, str.size()); } @@ -186,7 +186,7 @@ namespace Utils { MS_TRACE(); - auto* data = reinterpret_cast(str.c_str()); + const auto* data = reinterpret_cast(str.c_str()); return Base64Decode(data, str.size(), outLen); } diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index f6795d94bd..04ccee6c31 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -310,7 +310,7 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) { try { - const auto body = request->data->body_as(); + const auto* const body = request->data->body_as(); std::string webRtcServerId = body->webRtcServerId()->str(); @@ -340,7 +340,7 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) { RTC::WebRtcServer* webRtcServer{ nullptr }; - auto body = request->data->body_as(); + const auto* body = request->data->body_as(); auto webRtcServerId = body->webRtcServerId()->str(); @@ -367,7 +367,7 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) case Channel::ChannelRequest::Method::WORKER_CREATE_ROUTER: { - auto body = request->data->body_as(); + const auto* body = request->data->body_as(); auto routerId = body->routerId()->str(); @@ -395,7 +395,7 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) { RTC::Router* router{ nullptr }; - auto body = request->data->body_as(); + const auto* body = request->data->body_as(); auto routerId = body->routerId()->str(); diff --git a/worker/src/handles/TcpConnectionHandle.cpp b/worker/src/handles/TcpConnectionHandle.cpp index c2de7515d8..6a3799becd 100644 --- a/worker/src/handles/TcpConnectionHandle.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -38,7 +38,7 @@ inline static void onWrite(uv_write_t* req, int status) auto* writeData = static_cast(req->data); auto* handle = req->handle; auto* connection = static_cast(handle->data); - auto* cb = writeData->cb; + const auto* cb = writeData->cb; if (connection) { diff --git a/worker/src/handles/UdpSocketHandle.cpp b/worker/src/handles/UdpSocketHandle.cpp index a963957c6d..2f30180a0e 100644 --- a/worker/src/handles/UdpSocketHandle.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -43,7 +43,7 @@ inline static void onSend(uv_udp_send_t* req, int status) auto* sendData = static_cast(req->data); auto* handle = req->handle; auto* socket = static_cast(handle->data); - auto* cb = sendData->cb; + const auto* cb = sendData->cb; if (socket) { diff --git a/worker/test/src/Utils/TestIP.cpp b/worker/test/src/Utils/TestIP.cpp index 154be007e1..3b6731c443 100644 --- a/worker/test/src/Utils/TestIP.cpp +++ b/worker/test/src/Utils/TestIP.cpp @@ -127,7 +127,7 @@ SCENARIO("Utils::IP::GetAddressInfo()") sin.sin_port = htons(10251); sin.sin_addr.s_addr = inet_addr("82.99.219.114"); - auto* addr = reinterpret_cast(&sin); + const auto* addr = reinterpret_cast(&sin); int family; std::string ip; uint16_t port; From a9c05772279bacc0b0f458e8341c0842f84dd1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 5 Jan 2024 13:31:59 +0100 Subject: [PATCH 299/525] Make Node tests independent (part 4) (#1298) --- .github/workflows/mediasoup-node.yaml | 2 +- node/src/Channel.ts | 56 +- node/src/test/test-ActiveSpeakerObserver.ts | 107 +- node/src/test/test-AudioLevelObserver.ts | 105 +- node/src/test/test-Consumer.ts | 1024 +++++++++++-------- node/src/test/test-DataProducer.ts | 216 ++-- node/src/test/test-Producer.ts | 582 ++++++----- node/src/test/test-Router.ts | 2 +- node/src/test/test-multiopus.ts | 11 +- node/src/test/test-node-sctp.ts | 151 ++- 10 files changed, 1270 insertions(+), 986 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 0618603bc7..aad43a1210 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -57,4 +57,4 @@ jobs: run: npm run lint:node - name: npm run test:node - run: npm run test:node + run: npm run test:node -- --silent false diff --git a/node/src/Channel.ts b/node/src/Channel.ts index 7f41ca9f2f..4dc430c02a 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -83,7 +83,8 @@ export class Channel extends EnhancedEventEmitter { this.#recvBuffer = Buffer.concat( [ this.#recvBuffer, buffer ], - this.#recvBuffer.length + buffer.length); + this.#recvBuffer.length + buffer.length + ); } if (this.#recvBuffer.length > PAYLOAD_MAX_LEN) @@ -110,7 +111,8 @@ export class Channel extends EnhancedEventEmitter const dataView = new DataView( this.#recvBuffer.buffer, - this.#recvBuffer.byteOffset + msgStart); + this.#recvBuffer.byteOffset + msgStart + ); const msgLen = dataView.getUint32(0, IS_LITTLE_ENDIAN); if (readLen < 4 + msgLen) @@ -119,7 +121,8 @@ export class Channel extends EnhancedEventEmitter break; } - const payload = this.#recvBuffer.subarray(msgStart + 4, msgStart + 4 + msgLen); + const payload = + this.#recvBuffer.subarray(msgStart + 4, msgStart + 4 + msgLen); msgStart += 4 + msgLen; @@ -167,8 +170,7 @@ export class Channel extends EnhancedEventEmitter { // eslint-disable-next-line no-console console.warn( - `worker[pid:${pid}] unexpected data: %s`, - payload.toString('utf8', 1) + `worker[pid:${pid}] unexpected data: ${payload.toString('utf8', 1)}` ); } } @@ -176,8 +178,8 @@ export class Channel extends EnhancedEventEmitter catch (error) { logger.error( - 'received invalid message from the worker process: %s', - String(error)); + `received invalid message from the worker process: ${error}` + ); } } @@ -192,7 +194,7 @@ export class Channel extends EnhancedEventEmitter )); this.#consumerSocket.on('error', (error) => ( - logger.error('Consumer Channel error: %s', String(error)) + logger.error(`Consumer Channel error: ${error}`) )); this.#producerSocket.on('end', () => ( @@ -200,7 +202,7 @@ export class Channel extends EnhancedEventEmitter )); this.#producerSocket.on('error', (error) => ( - logger.error('Producer Channel error: %s', String(error)) + logger.error(`Producer Channel error: ${error}`) )); } @@ -262,11 +264,13 @@ export class Channel extends EnhancedEventEmitter handlerId?: string ): void { - logger.debug('notify() [event:%s]', Event[event]); + logger.debug(`notify() [event:${Event[event]}]`); if (this.#closed) { - throw new InvalidStateError('Channel closed'); + throw new InvalidStateError( + `Channel closed, cannot send notification [event:${Event[event]}]` + ); } const handlerIdOffset = this.#bufferBuilder.createString(handlerId); @@ -302,7 +306,7 @@ export class Channel extends EnhancedEventEmitter if (buffer.byteLength > MESSAGE_MAX_LEN) { - throw new Error('Channel request too big'); + throw new Error(`notification too big [event:${Event[event]}]`); } try @@ -312,7 +316,7 @@ export class Channel extends EnhancedEventEmitter } catch (error) { - logger.warn('notify() | sending notification failed: %s', String(error)); + logger.warn(`notify() | sending notification failed: ${error}`); return; } @@ -324,9 +328,13 @@ export class Channel extends EnhancedEventEmitter bodyOffset?: number, handlerId?: string): Promise { + logger.debug(`request() [method:${Method[method]}]`); + if (this.#closed) { - throw new InvalidStateError('Channel closed'); + throw new InvalidStateError( + `Channel closed, cannot send request [method:${Method[method]}]` + ); } this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1); @@ -366,7 +374,7 @@ export class Channel extends EnhancedEventEmitter if (buffer.byteLength > MESSAGE_MAX_LEN) { - throw new Error('Channel request too big'); + throw new Error(`request too big [method:${Method[method]}]`); } // This may throw if closed or remote side ended. @@ -398,7 +406,9 @@ export class Channel extends EnhancedEventEmitter }, close : () => { - pReject(new InvalidStateError('Channel closed')); + pReject(new InvalidStateError( + `Channel closed, pending request aborted [method:${Method[method]}, id:${id}]` + )); } }; @@ -414,7 +424,8 @@ export class Channel extends EnhancedEventEmitter if (!sent) { logger.error( - 'received response does not match any sent request [id:%s]', response.id); + `received response does not match any sent request [id:${response.id}]` + ); return; } @@ -422,15 +433,16 @@ export class Channel extends EnhancedEventEmitter if (response.accepted()) { logger.debug( - 'request succeeded [method:%s, id:%s]', sent.method, sent.id); + `request succeeded [method:${sent.method}, id:${sent.id}]` + ); sent.resolve(response); } else if (response.error()) { logger.warn( - 'request failed [method:%s, id:%s]: %s', - sent.method, sent.id, response.reason()); + `request failed [method:${sent.method}, id:${sent.id}]: ${response.reason()}` + ); switch (response.error()!) { @@ -450,8 +462,8 @@ export class Channel extends EnhancedEventEmitter else { logger.error( - 'received response is not accepted nor rejected [method:%s, id:%s]', - sent.method, sent.id); + `received response is not accepted nor rejected [method:${sent.method}, id:${sent.id}]` + ); } } diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index 4da61e1753..2570abb171 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -1,39 +1,50 @@ import * as mediasoup from '../'; +import * as utils from '../utils'; -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let activeSpeakerObserver: mediasoup.types.ActiveSpeakerObserver; +type TestContext = +{ + mediaCodecs: mediasoup.types.RtpCodecCapability[]; + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; +}; -const mediaCodecs: mediasoup.types.RtpCodecCapability[] = -[ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } - } -]; - -beforeAll(async () => +const ctx: TestContext = +{ + mediaCodecs : utils.deepFreeze( + [ + { + kind : 'audio', + mimeType : 'audio/opus', + clockRate : 48000, + channels : 2, + parameters : + { + useinbandfec : 1, + foo : 'bar' + } + } + ] + ) +}; + +beforeEach(async () => { - worker = await mediasoup.createWorker(); - router = await worker.createRouter({ mediaCodecs }); + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterAll(() => worker.close()); +afterEach(() => +{ + ctx.worker?.close(); +}); test('router.createActiveSpeakerObserver() succeeds', async () => { const onObserverNewRtpObserver = jest.fn(); - router.observer.once('newrtpobserver', onObserverNewRtpObserver); + ctx.router!.observer.once('newrtpobserver', onObserverNewRtpObserver); - activeSpeakerObserver = await router.createActiveSpeakerObserver(); + const activeSpeakerObserver = await ctx.router!.createActiveSpeakerObserver(); expect(onObserverNewRtpObserver).toHaveBeenCalledTimes(1); expect(onObserverNewRtpObserver).toHaveBeenCalledWith(activeSpeakerObserver); @@ -42,7 +53,7 @@ test('router.createActiveSpeakerObserver() succeeds', async () => expect(activeSpeakerObserver.paused).toBe(false); expect(activeSpeakerObserver.appData).toEqual({}); - await expect(router.dump()) + await expect(ctx.router!.dump()) .resolves .toMatchObject( { @@ -52,19 +63,25 @@ test('router.createActiveSpeakerObserver() succeeds', async () => test('router.createActiveSpeakerObserver() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore - await expect(router.createActiveSpeakerObserver({ interval: false })) + await expect(ctx.router!.createActiveSpeakerObserver( + // @ts-ignore + { interval: false } + )) .rejects .toThrow(TypeError); - // @ts-ignore - await expect(router.createActiveSpeakerObserver({ appData: 'NOT-AN-OBJECT' })) + await expect(ctx.router!.createActiveSpeakerObserver( + // @ts-ignore + { appData: 'NOT-AN-OBJECT' } + )) .rejects .toThrow(TypeError); }, 2000); test('activeSpeakerObserver.pause() and resume() succeed', async () => { + const activeSpeakerObserver = await ctx.router!.createActiveSpeakerObserver(); + await activeSpeakerObserver.pause(); expect(activeSpeakerObserver.paused).toBe(true); @@ -76,45 +93,43 @@ test('activeSpeakerObserver.pause() and resume() succeed', async () => test('activeSpeakerObserver.close() succeeds', async () => { - // We need different a AudioLevelObserver instance here. - const activeSpeakerObserver2 = - await router.createAudioLevelObserver({ maxEntries: 8 }); + const activeSpeakerObserver = + await ctx.router!.createAudioLevelObserver({ maxEntries: 8 }); - let dump = await router.dump(); + let dump = await ctx.router!.dump(); - expect(dump.rtpObserverIds.length).toBe(2); - - activeSpeakerObserver2.close(); + expect(dump.rtpObserverIds.length).toBe(1); - expect(activeSpeakerObserver2.closed).toBe(true); + activeSpeakerObserver.close(); - dump = await router.dump(); + expect(activeSpeakerObserver.closed).toBe(true); - expect(dump.rtpObserverIds.length).toBe(1); + dump = await ctx.router!.dump(); + expect(dump.rtpObserverIds.length).toBe(0); }, 2000); test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () => { - // We need different Router and AudioLevelObserver instances here. - const router2 = await worker.createRouter({ mediaCodecs }); - const activeSpeakerObserver2 = await router2.createAudioLevelObserver(); + const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); await new Promise((resolve) => { - activeSpeakerObserver2.on('routerclose', resolve); - router2.close(); + activeSpeakerObserver.on('routerclose', resolve); + ctx.router!.close(); }); - expect(activeSpeakerObserver2.closed).toBe(true); + expect(activeSpeakerObserver.closed).toBe(true); }, 2000); test('ActiveSpeakerObserver emits "routerclose" if Worker is closed', async () => { + const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); + await new Promise((resolve) => { activeSpeakerObserver.on('routerclose', resolve); - worker.close(); + ctx.worker!.close(); }); expect(activeSpeakerObserver.closed).toBe(true); diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index 77487218b8..763ec2be30 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -1,39 +1,50 @@ import * as mediasoup from '../'; +import * as utils from '../utils'; -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let audioLevelObserver: mediasoup.types.AudioLevelObserver; +type TestContext = +{ + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; + mediaCodecs: mediasoup.types.RtpCodecCapability[]; +}; -const mediaCodecs: mediasoup.types.RtpCodecCapability[] = -[ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } - } -]; - -beforeAll(async () => +const ctx: TestContext = +{ + mediaCodecs : utils.deepFreeze( + [ + { + kind : 'audio', + mimeType : 'audio/opus', + clockRate : 48000, + channels : 2, + parameters : + { + useinbandfec : 1, + foo : 'bar' + } + } + ] + ) +}; + +beforeEach(async () => { - worker = await mediasoup.createWorker(); - router = await worker.createRouter({ mediaCodecs }); + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterAll(() => worker.close()); +afterEach(() => +{ + ctx.worker?.close(); +}); test('router.createAudioLevelObserver() succeeds', async () => { const onObserverNewRtpObserver = jest.fn(); - router.observer.once('newrtpobserver', onObserverNewRtpObserver); + ctx.router!.observer.once('newrtpobserver', onObserverNewRtpObserver); - audioLevelObserver = await router.createAudioLevelObserver(); + const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); expect(onObserverNewRtpObserver).toHaveBeenCalledTimes(1); expect(onObserverNewRtpObserver).toHaveBeenCalledWith(audioLevelObserver); @@ -42,7 +53,7 @@ test('router.createAudioLevelObserver() succeeds', async () => expect(audioLevelObserver.paused).toBe(false); expect(audioLevelObserver.appData).toEqual({}); - await expect(router.dump()) + await expect(ctx.router!.dump()) .resolves .toMatchObject( { @@ -52,32 +63,34 @@ test('router.createAudioLevelObserver() succeeds', async () => test('router.createAudioLevelObserver() with wrong arguments rejects with TypeError', async () => { - await expect(router.createAudioLevelObserver({ maxEntries: 0 })) + await expect(ctx.router!.createAudioLevelObserver({ maxEntries: 0 })) .rejects .toThrow(TypeError); - await expect(router.createAudioLevelObserver({ maxEntries: -10 })) + await expect(ctx.router!.createAudioLevelObserver({ maxEntries: -10 })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(router.createAudioLevelObserver({ threshold: 'foo' })) + await expect(ctx.router!.createAudioLevelObserver({ threshold: 'foo' })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(router.createAudioLevelObserver({ interval: false })) + await expect(ctx.router!.createAudioLevelObserver({ interval: false })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(router.createAudioLevelObserver({ appData: 'NOT-AN-OBJECT' })) + await expect(ctx.router!.createAudioLevelObserver({ appData: 'NOT-AN-OBJECT' })) .rejects .toThrow(TypeError); }, 2000); test('audioLevelObserver.pause() and resume() succeed', async () => { + const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); + await audioLevelObserver.pause(); expect(audioLevelObserver.paused).toBe(true); @@ -89,45 +102,43 @@ test('audioLevelObserver.pause() and resume() succeed', async () => test('audioLevelObserver.close() succeeds', async () => { - // We need different a AudioLevelObserver instance here. - const audioLevelObserver2 = - await router.createAudioLevelObserver({ maxEntries: 8 }); + const audioLevelObserver = + await ctx.router!.createAudioLevelObserver({ maxEntries: 8 }); - let dump = await router.dump(); + let dump = await ctx.router!.dump(); - expect(dump.rtpObserverIds.length).toBe(2); - - audioLevelObserver2.close(); + expect(dump.rtpObserverIds.length).toBe(1); - expect(audioLevelObserver2.closed).toBe(true); + audioLevelObserver.close(); - dump = await router.dump(); + expect(audioLevelObserver.closed).toBe(true); - expect(dump.rtpObserverIds.length).toBe(1); + dump = await ctx.router!.dump(); + expect(dump.rtpObserverIds.length).toBe(0); }, 2000); test('AudioLevelObserver emits "routerclose" if Router is closed', async () => { - // We need different Router and AudioLevelObserver instances here. - const router2 = await worker.createRouter({ mediaCodecs }); - const audioLevelObserver2 = await router2.createAudioLevelObserver(); + const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); await new Promise((resolve) => { - audioLevelObserver2.on('routerclose', resolve); - router2.close(); + audioLevelObserver.on('routerclose', resolve); + ctx.router!.close(); }); - expect(audioLevelObserver2.closed).toBe(true); + expect(audioLevelObserver.closed).toBe(true); }, 2000); test('AudioLevelObserver emits "routerclose" if Worker is closed', async () => { + const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); + await new Promise((resolve) => { audioLevelObserver.on('routerclose', resolve); - worker.close(); + ctx.worker!.close(); }); expect(audioLevelObserver.closed).toBe(true); diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index 722d84c29b..2700ae77bc 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -1,293 +1,306 @@ import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; -import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; +import * as utils from '../utils'; +import { + Notification, + Body as NotificationBody, + Event +} from '../fbs/notification'; import * as FbsConsumer from '../fbs/consumer'; -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let transport1: mediasoup.types.WebRtcTransport; -let transport2: mediasoup.types.WebRtcTransport; -let audioProducer: mediasoup.types.Producer; -let videoProducer: mediasoup.types.Producer; -let audioConsumer: mediasoup.types.Consumer; -let videoConsumer: mediasoup.types.Consumer; -let videoPipeConsumer: mediasoup.types.Consumer; - -const mediaCodecs: mediasoup.types.RtpCodecCapability[] = -[ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - foo : 'bar' - } - }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 - }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - foo : 'bar' - } - } -]; +type TestContext = +{ + mediaCodecs: mediasoup.types.RtpCodecCapability[]; + audioProducerParameters: mediasoup.types.ProducerOptions; + videoProducerParameters: mediasoup.types.ProducerOptions; + consumerDeviceCapabilities: mediasoup.types.RtpCapabilities; + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; + transport1?: mediasoup.types.WebRtcTransport; + transport2?: mediasoup.types.WebRtcTransport; + audioProducer?: mediasoup.types.Producer; + videoProducer?: mediasoup.types.Producer; +}; -const audioProducerParameters: mediasoup.types.ProducerOptions = +const ctx: TestContext = { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : + mediaCodecs : utils.deepFreeze( [ { - mimeType : 'audio/opus', - payloadType : 111, - clockRate : 48000, - channels : 2, - parameters : + kind : 'audio', + mimeType : 'audio/opus', + clockRate : 48000, + channels : 2, + parameters : { - useinbandfec : 1, - usedtx : 1, - foo : 222.222, - bar : '333' + foo : 'bar' } - } - ], - headerExtensions : - [ + }, { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 + kind : 'video', + mimeType : 'video/VP8', + clockRate : 90000 }, { - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id : 12 + kind : 'video', + mimeType : 'video/H264', + clockRate : 90000, + parameters : + { + 'level-asymmetry-allowed' : 1, + 'packetization-mode' : 1, + 'profile-level-id' : '4d0032', + foo : 'bar' + } } - ], - encodings : [ { ssrc: 11111111 } ], - rtcp : + ] + ), + audioProducerParameters : utils.deepFreeze( { - cname : 'FOOBAR' - } - }, - appData : { foo: 1, bar: '2' } -}; - -const videoProducerParameters: mediasoup.types.ProducerOptions = -{ - kind : 'video', - rtpParameters : - { - mid : 'VIDEO', - codecs : - [ + kind : 'audio', + rtpParameters : { - mimeType : 'video/h264', - payloadType : 112, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : + mid : 'AUDIO', + codecs : [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'goog-remb', parameter: '' } - ] + { + mimeType : 'audio/opus', + payloadType : 111, + clockRate : 48000, + channels : 2, + parameters : + { + useinbandfec : 1, + usedtx : 1, + foo : 222.222, + bar : '333' + } + } + ], + headerExtensions : + [ + { + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + id : 10 + }, + { + uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + id : 12 + } + ], + encodings : [ { ssrc: 11111111 } ], + rtcp : + { + cname : 'FOOBAR' + } }, + appData : { foo: 1, bar: '2' } + } + ), + videoProducerParameters : utils.deepFreeze( + { + kind : 'video', + rtpParameters : { - mimeType : 'video/rtx', - payloadType : 113, - clockRate : 90000, - parameters : { apt: 112 } - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 + mid : 'VIDEO', + codecs : + [ + { + mimeType : 'video/h264', + payloadType : 112, + clockRate : 90000, + parameters : + { + 'packetization-mode' : 1, + 'profile-level-id' : '4d0032' + }, + rtcpFeedback : + [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'goog-remb', parameter: '' } + ] + }, + { + mimeType : 'video/rtx', + payloadType : 113, + clockRate : 90000, + parameters : { apt: 112 } + } + ], + headerExtensions : + [ + { + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + id : 10 + }, + { + uri : 'urn:3gpp:video-orientation', + id : 13 + } + ], + encodings : + [ + { ssrc: 22222222, rtx: { ssrc: 22222223 } }, + { ssrc: 22222224, rtx: { ssrc: 22222225 } }, + { ssrc: 22222226, rtx: { ssrc: 22222227 } }, + { ssrc: 22222228, rtx: { ssrc: 22222229 } } + ], + rtcp : + { + cname : 'FOOBAR' + } }, - { - uri : 'urn:3gpp:video-orientation', - id : 13 - } - ], - encodings : - [ - { ssrc: 22222222, rtx: { ssrc: 22222223 } }, - { ssrc: 22222224, rtx: { ssrc: 22222225 } }, - { ssrc: 22222226, rtx: { ssrc: 22222227 } }, - { ssrc: 22222228, rtx: { ssrc: 22222229 } } - ], - rtcp : - { - cname : 'FOOBAR' + appData : { foo: 1, bar: '2' } } - }, - appData : { foo: 1, bar: '2' } -}; - -const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = -{ - codecs : - [ + ), + consumerDeviceCapabilities : utils.deepFreeze( { - mimeType : 'audio/opus', - kind : 'audio', - preferredPayloadType : 100, - clockRate : 48000, - channels : 2, - rtcpFeedback : + codecs : [ - { type: 'nack', parameter: '' } - ] - }, - { - mimeType : 'video/H264', - kind : 'video', - preferredPayloadType : 101, - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : + { + mimeType : 'audio/opus', + kind : 'audio', + preferredPayloadType : 100, + clockRate : 48000, + channels : 2, + rtcpFeedback : + [ + { type: 'nack', parameter: '' } + ] + }, + { + mimeType : 'video/H264', + kind : 'video', + preferredPayloadType : 101, + clockRate : 90000, + parameters : + { + 'level-asymmetry-allowed' : 1, + 'packetization-mode' : 1, + 'profile-level-id' : '4d0032' + }, + rtcpFeedback : + [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb', parameter: '' } + ] + }, + { + mimeType : 'video/rtx', + kind : 'video', + preferredPayloadType : 102, + clockRate : 90000, + parameters : + { + apt : 101 + }, + rtcpFeedback : [] + } + ], + headerExtensions : [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb', parameter: '' } + { + kind : 'audio', + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId : 1, + preferredEncrypt : false + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId : 1, + preferredEncrypt : false + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', + preferredId : 2, + preferredEncrypt : false + }, + { + kind : 'audio', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId : 4, + preferredEncrypt : false + }, + { + kind : 'video', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId : 4, + preferredEncrypt : false + }, + { + kind : 'audio', + uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId : 10, + preferredEncrypt : false + }, + { + kind : 'video', + uri : 'urn:3gpp:video-orientation', + preferredId : 11, + preferredEncrypt : false + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:toffset', + preferredId : 12, + preferredEncrypt : false + } ] - }, - { - mimeType : 'video/rtx', - kind : 'video', - preferredPayloadType : 102, - clockRate : 90000, - parameters : - { - apt : 101 - }, - rtcpFeedback : [] } - ], - headerExtensions : - [ - { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', - preferredId : 2, - preferredEncrypt : false - }, - { - kind : 'audio', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId : 4, - preferredEncrypt : false - }, - { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId : 4, - preferredEncrypt : false - }, - { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 10, - preferredEncrypt : false - }, - { - kind : 'video', - uri : 'urn:3gpp:video-orientation', - preferredId : 11, - preferredEncrypt : false - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:toffset', - preferredId : 12, - preferredEncrypt : false - } - ] + ) }; -beforeAll(async () => +beforeEach(async () => { - worker = await mediasoup.createWorker(); - router = await worker.createRouter({ mediaCodecs }); - transport1 = await router.createWebRtcTransport( + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); + ctx.transport1 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ] }); - transport2 = await router.createWebRtcTransport( + ctx.transport2 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ] }); - audioProducer = await transport1.produce(audioProducerParameters); - videoProducer = await transport1.produce(videoProducerParameters); - - // Pause the videoProducer. - await videoProducer.pause(); + ctx.audioProducer = await ctx.transport1.produce(ctx.audioProducerParameters); + ctx.videoProducer = await ctx.transport1.produce(ctx.videoProducerParameters); }); -afterAll(() => worker.close()); +afterEach(() => +{ + ctx.worker?.close(); +}); test('transport.consume() succeeds', async () => { const onObserverNewConsumer1 = jest.fn(); - transport2.observer.once('newconsumer', onObserverNewConsumer1); + ctx.transport2!.observer.once('newconsumer', onObserverNewConsumer1); - expect(router.canConsume( + expect(ctx.router!.canConsume( { - producerId : audioProducer.id, - rtpCapabilities : consumerDeviceCapabilities + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities })) .toBe(true); - audioConsumer = await transport2.consume( + const audioConsumer = await ctx.transport2!.consume( { - producerId : audioProducer.id, - rtpCapabilities : consumerDeviceCapabilities, + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities, appData : { baz: 'LOL' } }); expect(onObserverNewConsumer1).toHaveBeenCalledTimes(1); expect(onObserverNewConsumer1).toHaveBeenCalledWith(audioConsumer); expect(typeof audioConsumer.id).toBe('string'); - expect(audioConsumer.producerId).toBe(audioProducer.id); + expect(audioConsumer.producerId).toBe(ctx.audioProducer!.id); expect(audioConsumer.closed).toBe(false); expect(audioConsumer.kind).toBe('audio'); expect(typeof audioConsumer.rtpParameters).toBe('object'); @@ -318,42 +331,47 @@ test('transport.consume() succeeds', async () => expect(audioConsumer.currentLayers).toBeUndefined(); expect(audioConsumer.appData).toEqual({ baz: 'LOL' }); - let dump = await router.dump(); + const dump1 = await ctx.router!.dump(); - expect(dump.mapProducerIdConsumerIds) - .toEqual(expect.arrayContaining([ - { key: audioProducer.id, values: [ audioConsumer.id ] } - ])); + expect(dump1.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining( + [ + { key: ctx.audioProducer!.id, values: [ audioConsumer.id ] } + ])); - expect(dump.mapConsumerIdProducerId) - .toEqual(expect.arrayContaining([ - { key: audioConsumer.id, value: audioProducer.id } - ])); + expect(dump1.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining( + [ + { key: audioConsumer.id, value: ctx.audioProducer!.id } + ])); - await expect(transport2.dump()) + await expect(ctx.transport2!.dump()) .resolves .toMatchObject( { - id : transport2.id, + id : ctx.transport2!.id, producerIds : [], consumerIds : [ audioConsumer.id ] }); const onObserverNewConsumer2 = jest.fn(); - transport2.observer.once('newconsumer', onObserverNewConsumer2); + ctx.transport2!.observer.once('newconsumer', onObserverNewConsumer2); - expect(router.canConsume( + expect(ctx.router!.canConsume( { - producerId : videoProducer.id, - rtpCapabilities : consumerDeviceCapabilities + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities })) .toBe(true); - videoConsumer = await transport2.consume( + // Pause videoProducer. + ctx.videoProducer!.pause(); + + const videoConsumer = await ctx.transport2!.consume( { - producerId : videoProducer.id, - rtpCapabilities : consumerDeviceCapabilities, + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities, paused : true, preferredLayers : { spatialLayer: 12 }, appData : { baz: 'LOL' } @@ -362,7 +380,7 @@ test('transport.consume() succeeds', async () => expect(onObserverNewConsumer2).toHaveBeenCalledTimes(1); expect(onObserverNewConsumer2).toHaveBeenCalledWith(videoConsumer); expect(typeof videoConsumer.id).toBe('string'); - expect(videoConsumer.producerId).toBe(videoProducer.id); + expect(videoConsumer.producerId).toBe(ctx.videoProducer!.id); expect(videoConsumer.closed).toBe(false); expect(videoConsumer.kind).toBe('video'); expect(typeof videoConsumer.rtpParameters).toBe('object'); @@ -406,26 +424,26 @@ test('transport.consume() succeeds', async () => const onObserverNewConsumer3 = jest.fn(); - transport2.observer.once('newconsumer', onObserverNewConsumer3); + ctx.transport2!.observer.once('newconsumer', onObserverNewConsumer3); - expect(router.canConsume( + expect(ctx.router!.canConsume( { - producerId : videoProducer.id, - rtpCapabilities : consumerDeviceCapabilities + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities })) .toBe(true); - videoPipeConsumer = await transport2.consume( + const videoPipeConsumer = await ctx.transport2!.consume( { - producerId : videoProducer.id, - rtpCapabilities : consumerDeviceCapabilities, + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities, pipe : true }); expect(onObserverNewConsumer3).toHaveBeenCalledTimes(1); expect(onObserverNewConsumer3).toHaveBeenCalledWith(videoPipeConsumer); expect(typeof videoPipeConsumer.id).toBe('string'); - expect(videoPipeConsumer.producerId).toBe(videoProducer.id); + expect(videoPipeConsumer.producerId).toBe(ctx.videoProducer!.id); expect(videoPipeConsumer.closed).toBe(false); expect(videoPipeConsumer.kind).toBe('video'); expect(typeof videoPipeConsumer.rtpParameters).toBe('object'); @@ -467,42 +485,37 @@ test('transport.consume() succeeds', async () => expect(videoPipeConsumer.currentLayers).toBeUndefined(); expect(videoPipeConsumer.appData).toBeUndefined; - dump = await router.dump(); + const dump2 = await ctx.router!.dump(); - // Sort values for mapProducerIdConsumerIds. - expect(Array.isArray(dump.mapProducerIdConsumerIds)).toBe(true); - dump.mapProducerIdConsumerIds.forEach((entry: any) => - { - entry.values = entry.values.sort(); - }); + expect(Array.isArray(dump2.mapProducerIdConsumerIds)).toBe(true); + + expect(dump2.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining( + [ + { + key : ctx.audioProducer!.id, + values : [ audioConsumer.id ] + }, + { + key : ctx.videoProducer!.id, + values : expect.arrayContaining( + [ videoConsumer.id, videoPipeConsumer.id ] + ) + } + ])); + expect(dump2.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining( + [ + { key: audioConsumer.id, value: ctx.audioProducer!.id }, + { key: videoConsumer.id, value: ctx.videoProducer!.id }, + { key: videoPipeConsumer.id, value: ctx.videoProducer!.id } + ])); - expect(dump.mapProducerIdConsumerIds) - .toEqual(expect.arrayContaining([ - { key: audioProducer.id, values: [ audioConsumer.id ] } - ])); - expect(dump.mapProducerIdConsumerIds) - .toEqual(expect.arrayContaining([ - { key: videoProducer.id, values: [ videoConsumer.id, videoPipeConsumer.id ].sort() } - ])); - - expect(dump.mapConsumerIdProducerId) - .toEqual(expect.arrayContaining([ - { key: audioConsumer.id, value: audioProducer.id } - ])); - expect(dump.mapConsumerIdProducerId) - .toEqual(expect.arrayContaining([ - { key: videoConsumer.id, value: videoProducer.id } - ])); - expect(dump.mapConsumerIdProducerId) - .toEqual(expect.arrayContaining([ - { key: videoPipeConsumer.id, value: videoProducer.id } - ])); - - await expect(transport2.dump()) + await expect(ctx.transport2!.dump()) .resolves .toMatchObject( { - id : transport2.id, + id : ctx.transport2!.id, producerIds : [], consumerIds : expect.arrayContaining( [ @@ -515,10 +528,10 @@ test('transport.consume() succeeds', async () => test('transport.consume() with enableRtx succeeds', async () => { - const audioConsumer2 = await transport2.consume( + const audioConsumer2 = await ctx.transport2!.consume( { - producerId : audioProducer.id, - rtpCapabilities : consumerDeviceCapabilities, + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities, enableRtx : true }); @@ -539,44 +552,38 @@ test('transport.consume() with enableRtx succeeds', async () => }, rtcpFeedback : [ { type: 'nack', parameter: '' } ] }); - - audioConsumer2.close(); }, 2000); test('transport.consume() can be created with user provided mid', async () => { - const audioConsumer1 = await transport2.consume( + const audioConsumer1 = await ctx.transport2!.consume( { - producerId : audioProducer.id, - rtpCapabilities : consumerDeviceCapabilities + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities }); expect(audioConsumer1.rtpParameters.mid).toEqual( expect.stringMatching(/^[0-9]+/)); - const audioConsumer2 = await transport2.consume( + const audioConsumer2 = await ctx.transport2!.consume( { - producerId : audioProducer.id, + producerId : ctx.audioProducer!.id, mid : 'custom-mid', - rtpCapabilities : consumerDeviceCapabilities + rtpCapabilities : ctx.consumerDeviceCapabilities }); expect(audioConsumer2.rtpParameters.mid).toBe('custom-mid'); - const audioConsumer3 = await transport2.consume( + const audioConsumer3 = await ctx.transport2!.consume( { - producerId : audioProducer.id, - rtpCapabilities : consumerDeviceCapabilities + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities }); expect(audioConsumer3.rtpParameters.mid).toEqual( expect.stringMatching(/^[0-9]+/)); expect(Number(audioConsumer1.rtpParameters.mid) + 1).toBe( Number(audioConsumer3.rtpParameters.mid)); - - audioConsumer3.close(); - audioConsumer2.close(); - audioConsumer1.close(); }, 2000); test('transport.consume() with incompatible rtpCapabilities rejects with UnsupportedError', async () => @@ -598,13 +605,16 @@ test('transport.consume() with incompatible rtpCapabilities rejects with Unsuppo headerExtensions : [] }; - expect(router.canConsume( - { producerId: audioProducer.id, rtpCapabilities: invalidDeviceCapabilities })) + expect(ctx.router!.canConsume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : invalidDeviceCapabilities + })) .toBe(false); - await expect(transport2.consume( + await expect(ctx.transport2!.consume( { - producerId : audioProducer.id, + producerId : ctx.audioProducer!.id, rtpCapabilities : invalidDeviceCapabilities })) .rejects @@ -616,13 +626,16 @@ test('transport.consume() with incompatible rtpCapabilities rejects with Unsuppo headerExtensions : [] }; - expect(router.canConsume( - { producerId: audioProducer.id, rtpCapabilities: invalidDeviceCapabilities })) + expect(ctx.router!.canConsume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : invalidDeviceCapabilities + })) .toBe(false); - await expect(transport2.consume( + await expect(ctx.transport2!.consume( { - producerId : audioProducer.id, + producerId : ctx.audioProducer!.id, rtpCapabilities : invalidDeviceCapabilities })) .rejects @@ -631,21 +644,24 @@ test('transport.consume() with incompatible rtpCapabilities rejects with Unsuppo test('consumer.dump() succeeds', async () => { - let data; - - data = await audioConsumer.dump(); - - expect(data.id).toBe(audioConsumer.id); - expect(data.producerId).toBe(audioConsumer.producerId); - expect(data.kind).toBe(audioConsumer.kind); - expect(typeof data.rtpParameters).toBe('object'); - expect(Array.isArray(data.rtpParameters.codecs)).toBe(true); - expect(data.rtpParameters.codecs.length).toBe(1); - expect(data.rtpParameters.codecs[0].mimeType).toBe('audio/opus'); - expect(data.rtpParameters.codecs[0].payloadType).toBe(100); - expect(data.rtpParameters.codecs[0].clockRate).toBe(48000); - expect(data.rtpParameters.codecs[0].channels).toBe(2); - expect(data.rtpParameters.codecs[0].parameters) + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + const dump1 = await audioConsumer.dump(); + + expect(dump1.id).toBe(audioConsumer.id); + expect(dump1.producerId).toBe(audioConsumer.producerId); + expect(dump1.kind).toBe(audioConsumer.kind); + expect(typeof dump1.rtpParameters).toBe('object'); + expect(Array.isArray(dump1.rtpParameters.codecs)).toBe(true); + expect(dump1.rtpParameters.codecs.length).toBe(1); + expect(dump1.rtpParameters.codecs[0].mimeType).toBe('audio/opus'); + expect(dump1.rtpParameters.codecs[0].payloadType).toBe(100); + expect(dump1.rtpParameters.codecs[0].clockRate).toBe(48000); + expect(dump1.rtpParameters.codecs[0].channels).toBe(2); + expect(dump1.rtpParameters.codecs[0].parameters) .toEqual( { useinbandfec : 1, @@ -653,10 +669,10 @@ test('consumer.dump() succeeds', async () => foo : 222.222, bar : '333' }); - expect(data.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); - expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions!.length).toBe(3); - expect(data.rtpParameters.headerExtensions).toEqual( + expect(dump1.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); + expect(Array.isArray(dump1.rtpParameters.headerExtensions)).toBe(true); + expect(dump1.rtpParameters.headerExtensions!.length).toBe(3); + expect(dump1.rtpParameters.headerExtensions).toEqual( [ { uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', @@ -677,9 +693,9 @@ test('consumer.dump() succeeds', async () => encrypt : false } ]); - expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings!.length).toBe(1); - expect(data.rtpParameters.encodings).toEqual( + expect(Array.isArray(dump1.rtpParameters.encodings)).toBe(true); + expect(dump1.rtpParameters.encodings!.length).toBe(1); + expect(dump1.rtpParameters.encodings).toEqual( [ expect.objectContaining( { @@ -687,47 +703,55 @@ test('consumer.dump() succeeds', async () => ssrc : audioConsumer.rtpParameters.encodings?.[0].ssrc }) ]); - expect(data.type).toBe('simple'); - expect(Array.isArray(data.consumableRtpEncodings)).toBe(true); - expect(data.consumableRtpEncodings!.length).toBe(1); - expect(data.consumableRtpEncodings).toEqual( + expect(dump1.type).toBe('simple'); + expect(Array.isArray(dump1.consumableRtpEncodings)).toBe(true); + expect(dump1.consumableRtpEncodings!.length).toBe(1); + expect(dump1.consumableRtpEncodings).toEqual( [ expect.objectContaining( - { ssrc: audioProducer.consumableRtpParameters.encodings?.[0].ssrc }) + { + ssrc : ctx.audioProducer!.consumableRtpParameters.encodings?.[0].ssrc + }) ]); - expect(data.supportedCodecPayloadTypes).toEqual([ 100 ]); - expect(data.paused).toBe(false); - expect(data.producerPaused).toBe(false); - expect(data.priority).toBe(1); - - data = await videoConsumer.dump(); - - expect(data.id).toBe(videoConsumer.id); - expect(data.producerId).toBe(videoConsumer.producerId); - expect(data.kind).toBe(videoConsumer.kind); - expect(typeof data.rtpParameters).toBe('object'); - expect(Array.isArray(data.rtpParameters.codecs)).toBe(true); - expect(data.rtpParameters.codecs.length).toBe(2); - expect(data.rtpParameters.codecs[0].mimeType).toBe('video/H264'); - expect(data.rtpParameters.codecs[0].payloadType).toBe(103); - expect(data.rtpParameters.codecs[0].clockRate).toBe(90000); - expect(data.rtpParameters.codecs[0].channels).toBeUndefined(); - expect(data.rtpParameters.codecs[0].parameters) + expect(dump1.supportedCodecPayloadTypes).toEqual([ 100 ]); + expect(dump1.paused).toBe(false); + expect(dump1.producerPaused).toBe(false); + expect(dump1.priority).toBe(1); + + const videoConsumer = await ctx.transport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities, + paused : true + }); + const dump2 = await videoConsumer.dump(); + + expect(dump2.id).toBe(videoConsumer.id); + expect(dump2.producerId).toBe(videoConsumer.producerId); + expect(dump2.kind).toBe(videoConsumer.kind); + expect(typeof dump2.rtpParameters).toBe('object'); + expect(Array.isArray(dump2.rtpParameters.codecs)).toBe(true); + expect(dump2.rtpParameters.codecs.length).toBe(2); + expect(dump2.rtpParameters.codecs[0].mimeType).toBe('video/H264'); + expect(dump2.rtpParameters.codecs[0].payloadType).toBe(103); + expect(dump2.rtpParameters.codecs[0].clockRate).toBe(90000); + expect(dump2.rtpParameters.codecs[0].channels).toBeUndefined(); + expect(dump2.rtpParameters.codecs[0].parameters) .toEqual( { 'packetization-mode' : 1, 'profile-level-id' : '4d0032' }); - expect(data.rtpParameters.codecs[0].rtcpFeedback).toEqual( + expect(dump2.rtpParameters.codecs[0].rtcpFeedback).toEqual( [ { type: 'nack' }, { type: 'nack', parameter: 'pli' }, { type: 'ccm', parameter: 'fir' }, { type: 'goog-remb' } ]); - expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions!.length).toBe(4); - expect(data.rtpParameters.headerExtensions).toEqual( + expect(Array.isArray(dump2.rtpParameters.headerExtensions)).toBe(true); + expect(dump2.rtpParameters.headerExtensions!.length).toBe(4); + expect(dump2.rtpParameters.headerExtensions).toEqual( [ { uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', @@ -754,9 +778,9 @@ test('consumer.dump() succeeds', async () => encrypt : false } ]); - expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings!.length).toBe(1); - expect(data.rtpParameters.encodings).toMatchObject( + expect(Array.isArray(dump2.rtpParameters.encodings)).toBe(true); + expect(dump2.rtpParameters.encodings!.length).toBe(1); + expect(dump2.rtpParameters.encodings).toMatchObject( [ { codecPayloadType : 103, @@ -768,32 +792,42 @@ test('consumer.dump() succeeds', async () => scalabilityMode : 'L4T1' } ]); - expect(Array.isArray(data.consumableRtpEncodings)).toBe(true); - expect(data.consumableRtpEncodings!.length).toBe(4); - expect(data.consumableRtpEncodings![0]).toEqual( + expect(Array.isArray(dump2.consumableRtpEncodings)).toBe(true); + expect(dump2.consumableRtpEncodings!.length).toBe(4); + expect(dump2.consumableRtpEncodings![0]).toEqual( expect.objectContaining( - { ssrc: videoProducer.consumableRtpParameters.encodings?.[0].ssrc }) - ); - expect(data.consumableRtpEncodings![1]).toEqual( + { + ssrc : ctx.videoProducer!.consumableRtpParameters.encodings?.[0].ssrc + })); + expect(dump2.consumableRtpEncodings![1]).toEqual( expect.objectContaining( - { ssrc: videoProducer.consumableRtpParameters.encodings?.[1].ssrc }) - ); - expect(data.consumableRtpEncodings![2]).toEqual( + { + ssrc : ctx.videoProducer!.consumableRtpParameters.encodings?.[1].ssrc + })); + expect(dump2.consumableRtpEncodings![2]).toEqual( expect.objectContaining( - { ssrc: videoProducer.consumableRtpParameters.encodings?.[2].ssrc }) - ); - expect(data.consumableRtpEncodings![3]).toEqual( + { + ssrc : ctx.videoProducer!.consumableRtpParameters.encodings?.[2].ssrc + })); + expect(dump2.consumableRtpEncodings![3]).toEqual( expect.objectContaining( - { ssrc: videoProducer.consumableRtpParameters.encodings?.[3].ssrc }) - ); - expect(data.supportedCodecPayloadTypes).toEqual([ 103 ]); - expect(data.paused).toBe(true); - expect(data.producerPaused).toBe(true); - expect(data.priority).toBe(1); + { + ssrc : ctx.videoProducer!.consumableRtpParameters.encodings?.[3].ssrc + })); + expect(dump2.supportedCodecPayloadTypes).toEqual([ 103 ]); + expect(dump2.paused).toBe(true); + expect(dump2.producerPaused).toBe(false); + expect(dump2.priority).toBe(1); }, 2000); test('consumer.getStats() succeeds', async () => { + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + await expect(audioConsumer.getStats()) .resolves .toEqual( @@ -807,6 +841,12 @@ test('consumer.getStats() succeeds', async () => }) ]); + const videoConsumer = await ctx.transport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + await expect(videoConsumer.getStats()) .resolves .toEqual( @@ -823,6 +863,11 @@ test('consumer.getStats() succeeds', async () => test('consumer.pause() and resume() succeed', async () => { + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); const onObserverPause = jest.fn(); const onObserverResume = jest.fn(); @@ -858,21 +903,26 @@ test('consumer.pause() and resume() succeed', async () => test('producer.pause() and resume() emit events', async () => { + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); const promises = []; const events: string[] = []; - audioConsumer.observer.once('resume', () => + audioConsumer.observer.once('resume', () => { events.push('resume'); }); - audioConsumer.observer.once('pause', () => + audioConsumer.observer.once('pause', () => { events.push('pause'); }); - promises.push(audioProducer.pause()); - promises.push(audioProducer.resume()); + promises.push(ctx.audioProducer!.pause()); + promises.push(ctx.audioProducer!.resume()); await Promise.all(promises); @@ -885,15 +935,41 @@ test('producer.pause() and resume() emit events', async () => test('consumer.setPreferredLayers() succeed', async () => { - await audioConsumer.setPreferredLayers({ spatialLayer: 1, temporalLayer: 1 }); + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + const videoConsumer = await ctx.transport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + + await audioConsumer.setPreferredLayers( + { spatialLayer: 1, temporalLayer: 1 } + ); + expect(audioConsumer.preferredLayers).toBeUndefined(); - await videoConsumer.setPreferredLayers({ spatialLayer: 2, temporalLayer: 3 }); - expect(videoConsumer.preferredLayers).toEqual({ spatialLayer: 2, temporalLayer: 0 }); + await videoConsumer.setPreferredLayers( + { spatialLayer: 2, temporalLayer: 3 } + ); + + expect( + videoConsumer.preferredLayers).toEqual( + { spatialLayer: 2, temporalLayer: 0 } + ); }, 2000); test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError', async () => { + const videoConsumer = await ctx.transport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + // @ts-ignore await expect(videoConsumer.setPreferredLayers({})) .rejects @@ -918,12 +994,24 @@ test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError' test('consumer.setPriority() succeed', async () => { + const videoConsumer = await ctx.transport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + await videoConsumer.setPriority(2); expect(videoConsumer.priority).toBe(2); }, 2000); test('consumer.setPriority() with wrong arguments rejects with TypeError', async () => { + const videoConsumer = await ctx.transport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + // @ts-ignore await expect(videoConsumer.setPriority()) .rejects @@ -941,38 +1029,61 @@ test('consumer.setPriority() with wrong arguments rejects with TypeError', async test('consumer.unsetPriority() succeed', async () => { + const videoConsumer = await ctx.transport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + await videoConsumer.unsetPriority(); expect(videoConsumer.priority).toBe(1); }, 2000); test('consumer.enableTraceEvent() succeed', async () => { - let dump; + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); await audioConsumer.enableTraceEvent([ 'rtp', 'pli' ]); - dump = await audioConsumer.dump(); - expect(dump.traceEventTypes) + const dump1 = await audioConsumer.dump(); + + expect(dump1.traceEventTypes) .toEqual(expect.arrayContaining([ 'rtp', 'pli' ])); await audioConsumer.enableTraceEvent([]); - dump = await audioConsumer.dump(); - expect(dump.traceEventTypes) + + const dump2 = await audioConsumer.dump(); + + expect(dump2.traceEventTypes) .toEqual(expect.arrayContaining([])); // @ts-ignore await audioConsumer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); - dump = await audioConsumer.dump(); - expect(dump.traceEventTypes) + + const dump3 = await audioConsumer.dump(); + + expect(dump3.traceEventTypes) .toEqual(expect.arrayContaining([ 'nack', 'fir' ])); await audioConsumer.enableTraceEvent(); - dump = await audioConsumer.dump(); - expect(dump.traceEventTypes) + + const dump4 = await audioConsumer.dump(); + + expect(dump4.traceEventTypes) .toEqual(expect.arrayContaining([])); }, 2000); test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + // @ts-ignore await expect(audioConsumer.enableTraceEvent(123)) .rejects @@ -991,10 +1102,17 @@ test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', test('Consumer emits "producerpause" and "producerresume"', async () => { + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + await new Promise((resolve) => { audioConsumer.on('producerpause', resolve); - audioProducer.pause(); + + ctx.audioProducer!.pause().catch(() => {}); }); expect(audioConsumer.paused).toBe(false); @@ -1003,7 +1121,11 @@ test('Consumer emits "producerpause" and "producerresume"', async () => await new Promise((resolve) => { audioConsumer.on('producerresume', resolve); - audioProducer.resume(); + + // Let's catch rejection since the test will complete before we get the + // response to this channel request, and if we don't handle that rejection + // it will make Jest fail any other random test. + ctx.audioProducer!.resume().catch(() => {}); }); expect(audioConsumer.paused).toBe(false); @@ -1012,6 +1134,12 @@ test('Consumer emits "producerpause" and "producerresume"', async () => test('Consumer emits "score"', async () => { + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + // Private API. const channel = audioConsumer.channelForTesting; const onScore = jest.fn(); @@ -1021,7 +1149,8 @@ test('Consumer emits "score"', async () => // Simulate a 'score' notification coming through the channel. const builder = new flatbuffers.Builder(); const consumerScore = new FbsConsumer.ConsumerScoreT(9, 10, [ 8 ]); - const consumerScoreNotification = new FbsConsumer.ScoreNotificationT(consumerScore); + const consumerScoreNotification = + new FbsConsumer.ScoreNotificationT(consumerScore); const notificationOffset = Notification.createNotification( builder, builder.createString(audioConsumer.id), @@ -1033,7 +1162,8 @@ test('Consumer emits "score"', async () => builder.finish(notificationOffset); const notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array())); + new flatbuffers.ByteBuffer(builder.asUint8Array()) + ); channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); @@ -1046,6 +1176,16 @@ test('Consumer emits "score"', async () => test('consumer.close() succeeds', async () => { + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + const videoConsumer = await ctx.transport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); const onObserverClose = jest.fn(); audioConsumer.observer.once('close', onObserverClose); @@ -1054,37 +1194,41 @@ test('consumer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(audioConsumer.closed).toBe(true); - const routerDump = await router.dump(); + const routerDump = await ctx.router!.dump(); expect(routerDump.mapProducerIdConsumerIds) - .toEqual(expect.arrayContaining([ - { key: audioProducer.id, values: [ ] } - ])); - - expect(routerDump.mapConsumerIdProducerId) - .toEqual(expect.arrayContaining([ - { key: videoConsumer.id, value: videoProducer.id } - ])); + .toEqual(expect.arrayContaining( + [ + { key: ctx.audioProducer!.id, values: [] }, + { key: ctx.videoProducer!.id, values: [ videoConsumer.id ] } + ])); expect(routerDump.mapConsumerIdProducerId) - .toEqual(expect.arrayContaining([ - { key: videoPipeConsumer.id, value: videoProducer.id } - ])); - - const transportDump = await transport2.dump(); + .toEqual( + [ + { key: videoConsumer!.id, value: ctx.videoProducer!.id } + ]); - transportDump.consumerIds = transportDump.consumerIds.sort(); + const transportDump = await ctx.transport2!.dump(); expect(transportDump) .toMatchObject( { - id : transport2.id, + id : ctx.transport2!.id, producerIds : [], - consumerIds : [ videoConsumer.id, videoPipeConsumer.id ].sort() + consumerIds : [ videoConsumer.id ] }); }, 2000); test('Consumer methods reject if closed', async () => { + const audioConsumer = await ctx.transport2!.consume( + { + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); + + audioConsumer.close(); + await expect(audioConsumer.dump()) .rejects .toThrow(Error); @@ -1117,12 +1261,11 @@ test('Consumer methods reject if closed', async () => test('Consumer emits "producerclose" if Producer is closed', async () => { - audioConsumer = await transport2.consume( + const audioConsumer = await ctx.transport2!.consume( { - producerId : audioProducer.id, - rtpCapabilities : consumerDeviceCapabilities + producerId : ctx.audioProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities }); - const onObserverClose = jest.fn(); audioConsumer.observer.once('close', onObserverClose); @@ -1130,7 +1273,7 @@ test('Consumer emits "producerclose" if Producer is closed', async () => await new Promise((resolve) => { audioConsumer.on('producerclose', resolve); - audioProducer.close(); + ctx.audioProducer!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); @@ -1139,10 +1282,10 @@ test('Consumer emits "producerclose" if Producer is closed', async () => test('Consumer emits "transportclose" if Transport is closed', async () => { - videoConsumer = await transport2.consume( + const videoConsumer = await ctx.transport2!.consume( { - producerId : videoProducer.id, - rtpCapabilities : consumerDeviceCapabilities + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities }); const onObserverClose = jest.fn(); @@ -1152,17 +1295,22 @@ test('Consumer emits "transportclose" if Transport is closed', async () => await new Promise((resolve) => { videoConsumer.on('transportclose', resolve); - transport2.close(); + ctx.transport2!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(videoConsumer.closed).toBe(true); - await expect(router.dump()) + await expect(ctx.router!.dump()) .resolves .toMatchObject( { - mapProducerIdConsumerIds : {}, - mapConsumerIdProducerId : {} + mapProducerIdConsumerIds : expect.arrayContaining( + [ + { key: ctx.audioProducer!.id, values: [] }, + { key: ctx.videoProducer!.id, values: [] } + ] + ), + mapConsumerIdProducerId : [] }); }, 2000); diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index 8c0c6bd5aa..e6fff2b37f 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -1,46 +1,73 @@ import * as mediasoup from '../'; +import * as utils from '../utils'; -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let transport1: mediasoup.types.WebRtcTransport; -let transport2: mediasoup.types.PlainTransport; -let dataProducer1: mediasoup.types.DataProducer; -let dataProducer2: mediasoup.types.DataProducer; +type TestContext = +{ + dataProducerParameters1: mediasoup.types.DataProducerOptions; + dataProducerParameters2: mediasoup.types.DataProducerOptions; + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; + transport1?: mediasoup.types.WebRtcTransport; + transport2?: mediasoup.types.WebRtcTransport; +}; + +const ctx: TestContext = +{ + dataProducerParameters1 : utils.deepFreeze( + { + sctpStreamParameters : + { + streamId : 666 + }, + label : 'foo', + protocol : 'bar', + appData : { foo: 1, bar: '2' } + } + ), + dataProducerParameters2 : utils.deepFreeze( + { + sctpStreamParameters : + { + streamId : 777, + maxRetransmits : 3 + }, + label : 'foo', + protocol : 'bar', + paused : true, + appData : { foo: 1, bar: '2' } + } + ) +}; -beforeAll(async () => +beforeEach(async () => { - worker = await mediasoup.createWorker(); - router = await worker.createRouter(); - transport1 = await router.createWebRtcTransport( + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter(); + ctx.transport1 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ], enableSctp : true }); - transport2 = await router.createPlainTransport( + ctx.transport2 = await ctx.router.createWebRtcTransport( { - listenIp : '127.0.0.1', + listenIps : [ '127.0.0.1' ], enableSctp : true }); }); -afterAll(() => worker.close()); +afterEach(() => +{ + ctx.worker?.close(); +}); test('transport1.produceData() succeeds', async () => { const onObserverNewDataProducer = jest.fn(); - transport1.observer.once('newdataproducer', onObserverNewDataProducer); + ctx.transport1!.observer.once('newdataproducer', onObserverNewDataProducer); - dataProducer1 = await transport1.produceData( - { - sctpStreamParameters : - { - streamId : 666 - }, - label : 'foo', - protocol : 'bar', - appData : { foo: 1, bar: '2' } - }); + const dataProducer1 = + await ctx.transport1!.produceData(ctx.dataProducerParameters1); expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); expect(onObserverNewDataProducer).toHaveBeenCalledWith(dataProducer1); @@ -57,7 +84,7 @@ test('transport1.produceData() succeeds', async () => expect(dataProducer1.paused).toBe(false); expect(dataProducer1.appData).toEqual({ foo: 1, bar: '2' }); - const dump = await router.dump(); + const dump = await ctx.router!.dump(); expect(dump.mapDataProducerIdDataConsumerIds) .toEqual(expect.arrayContaining([ @@ -66,11 +93,11 @@ test('transport1.produceData() succeeds', async () => expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); - await expect(transport1.dump()) + await expect(ctx.transport1!.dump()) .resolves .toMatchObject( { - id : transport1.id, + id : ctx.transport1!.id, dataProducerIds : [ dataProducer1.id ], dataConsumerIds : [] }); @@ -80,20 +107,10 @@ test('transport2.produceData() succeeds', async () => { const onObserverNewDataProducer = jest.fn(); - transport2.observer.once('newdataproducer', onObserverNewDataProducer); + ctx.transport2!.observer.once('newdataproducer', onObserverNewDataProducer); - dataProducer2 = await transport2.produceData( - { - sctpStreamParameters : - { - streamId : 777, - maxRetransmits : 3 - }, - label : 'foo', - protocol : 'bar', - paused : true, - appData : { foo: 1, bar: '2' } - }); + const dataProducer2 = + await ctx.transport2!.produceData(ctx.dataProducerParameters2); expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); expect(onObserverNewDataProducer).toHaveBeenCalledWith(dataProducer2); @@ -110,7 +127,7 @@ test('transport2.produceData() succeeds', async () => expect(dataProducer2.paused).toBe(true); expect(dataProducer2.appData).toEqual({ foo: 1, bar: '2' }); - const dump = await router.dump(); + const dump = await ctx.router!.dump(); expect(dump.mapDataProducerIdDataConsumerIds) .toEqual(expect.arrayContaining([ @@ -119,11 +136,11 @@ test('transport2.produceData() succeeds', async () => expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); - await expect(transport2.dump()) + await expect(ctx.transport2!.dump()) .resolves .toMatchObject( { - id : transport2.id, + id : ctx.transport2!.id, dataProducerIds : [ dataProducer2.id ], dataConsumerIds : [] }); @@ -131,12 +148,12 @@ test('transport2.produceData() succeeds', async () => test('transport1.produceData() with wrong arguments rejects with TypeError', async () => { - await expect(transport1.produceData({})) + await expect(ctx.transport1!.produceData({})) .rejects .toThrow(TypeError); // Missing or empty sctpStreamParameters.streamId. - await expect(transport1.produceData( + await expect(ctx.transport1!.produceData( { // @ts-ignore sctpStreamParameters : { foo: 'foo' } @@ -147,7 +164,9 @@ test('transport1.produceData() with wrong arguments rejects with TypeError', asy test('transport.produceData() with already used streamId rejects with Error', async () => { - await expect(transport1.produceData( + await ctx.transport1!.produceData(ctx.dataProducerParameters1); + + await expect(ctx.transport1!.produceData( { sctpStreamParameters : { @@ -160,7 +179,7 @@ test('transport.produceData() with already used streamId rejects with Error', as test('transport.produceData() with ordered and maxPacketLifeTime rejects with TypeError', async () => { - await expect(transport1.produceData( + await expect(ctx.transport1!.produceData( { sctpStreamParameters : { @@ -175,37 +194,44 @@ test('transport.produceData() with ordered and maxPacketLifeTime rejects with Ty test('dataProducer.dump() succeeds', async () => { - let data; - - data = await dataProducer1.dump(); - - expect(data.id).toBe(dataProducer1.id); - expect(data.type).toBe('sctp'); - expect(typeof data.sctpStreamParameters).toBe('object'); - expect(data.sctpStreamParameters!.streamId).toBe(666); - expect(data.sctpStreamParameters!.ordered).toBe(true); - expect(data.sctpStreamParameters!.maxPacketLifeTime).toBeUndefined(); - expect(data.sctpStreamParameters!.maxRetransmits).toBeUndefined(); - expect(data.label).toBe('foo'); - expect(data.protocol).toBe('bar'); - expect(data.paused).toBe(false); - - data = await dataProducer2.dump(); - - expect(data.id).toBe(dataProducer2.id); - expect(data.type).toBe('sctp'); - expect(typeof data.sctpStreamParameters).toBe('object'); - expect(data.sctpStreamParameters!.streamId).toBe(777); - expect(data.sctpStreamParameters!.ordered).toBe(false); - expect(data.sctpStreamParameters!.maxPacketLifeTime).toBeUndefined(); - expect(data.sctpStreamParameters!.maxRetransmits).toBe(3); - expect(data.label).toBe('foo'); - expect(data.protocol).toBe('bar'); - expect(data.paused).toBe(true); + const dataProducer1 = + await ctx.transport1!.produceData(ctx.dataProducerParameters1); + + const dump1 = await dataProducer1.dump(); + + expect(dump1.id).toBe(dataProducer1.id); + expect(dump1.type).toBe('sctp'); + expect(typeof dump1.sctpStreamParameters).toBe('object'); + expect(dump1.sctpStreamParameters!.streamId).toBe(666); + expect(dump1.sctpStreamParameters!.ordered).toBe(true); + expect(dump1.sctpStreamParameters!.maxPacketLifeTime).toBeUndefined(); + expect(dump1.sctpStreamParameters!.maxRetransmits).toBeUndefined(); + expect(dump1.label).toBe('foo'); + expect(dump1.protocol).toBe('bar'); + expect(dump1.paused).toBe(false); + + const dataProducer2 = + await ctx.transport2!.produceData(ctx.dataProducerParameters2); + + const dump2 = await dataProducer2.dump(); + + expect(dump2.id).toBe(dataProducer2.id); + expect(dump2.type).toBe('sctp'); + expect(typeof dump2.sctpStreamParameters).toBe('object'); + expect(dump2.sctpStreamParameters!.streamId).toBe(777); + expect(dump2.sctpStreamParameters!.ordered).toBe(false); + expect(dump2.sctpStreamParameters!.maxPacketLifeTime).toBeUndefined(); + expect(dump2.sctpStreamParameters!.maxRetransmits).toBe(3); + expect(dump2.label).toBe('foo'); + expect(dump2.protocol).toBe('bar'); + expect(dump2.paused).toBe(true); }, 2000); test('dataProducer.getStats() succeeds', async () => { + const dataProducer1 = + await ctx.transport1!.produceData(ctx.dataProducerParameters1); + await expect(dataProducer1.getStats()) .resolves .toMatchObject( @@ -219,6 +245,9 @@ test('dataProducer.getStats() succeeds', async () => } ]); + const dataProducer2 = + await ctx.transport2!.produceData(ctx.dataProducerParameters2); + await expect(dataProducer2.getStats()) .resolves .toMatchObject( @@ -235,29 +264,30 @@ test('dataProducer.getStats() succeeds', async () => test('dataProducer.pause() and resume() succeed', async () => { + const dataProducer1 = + await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const onObserverPause = jest.fn(); const onObserverResume = jest.fn(); dataProducer1.observer.on('pause', onObserverPause); dataProducer1.observer.on('resume', onObserverResume); - let data; - await dataProducer1.pause(); expect(dataProducer1.paused).toBe(true); - data = await dataProducer1.dump(); + const dump1 = await dataProducer1.dump(); - expect(data.paused).toBe(true); + expect(dump1.paused).toBe(true); await dataProducer1.resume(); expect(dataProducer1.paused).toBe(false); - data = await dataProducer1.dump(); + const dump2 = await dataProducer1.dump(); - expect(data.paused).toBe(false); + expect(dump2.paused).toBe(false); // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. @@ -274,15 +304,18 @@ test('dataProducer.pause() and resume() succeed', async () => test('producer.pause() and resume() emit events', async () => { + const dataProducer1 = + await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const promises = []; const events: string[] = []; - dataProducer1.observer.once('resume', () => + dataProducer1.observer.once('resume', () => { events.push('resume'); }); - dataProducer1.observer.once('pause', () => + dataProducer1.observer.once('pause', () => { events.push('pause'); }); @@ -298,6 +331,9 @@ test('producer.pause() and resume() emit events', async () => test('dataProducer.close() succeeds', async () => { + const dataProducer1 = + await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const onObserverClose = jest.fn(); dataProducer1.observer.once('close', onObserverClose); @@ -306,7 +342,7 @@ test('dataProducer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataProducer1.closed).toBe(true); - await expect(router.dump()) + await expect(ctx.router!.dump()) .resolves .toMatchObject( { @@ -314,11 +350,11 @@ test('dataProducer.close() succeeds', async () => mapDataConsumerIdDataProducerId : {} }); - await expect(transport1.dump()) + await expect(ctx.transport1!.dump()) .resolves .toMatchObject( { - id : transport1.id, + id : ctx.transport1!.id, dataProducerIds : [], dataConsumerIds : [] }); @@ -326,6 +362,11 @@ test('dataProducer.close() succeeds', async () => test('DataProducer methods reject if closed', async () => { + const dataProducer1 = + await ctx.transport1!.produceData(ctx.dataProducerParameters1); + + dataProducer1.close(); + await expect(dataProducer1.dump()) .rejects .toThrow(Error); @@ -337,6 +378,9 @@ test('DataProducer methods reject if closed', async () => test('DataProducer emits "transportclose" if Transport is closed', async () => { + const dataProducer2 = + await ctx.transport2!.produceData(ctx.dataProducerParameters2); + const onObserverClose = jest.fn(); dataProducer2.observer.once('close', onObserverClose); @@ -344,7 +388,7 @@ test('DataProducer emits "transportclose" if Transport is closed', async () => await new Promise((resolve) => { dataProducer2.on('transportclose', resolve); - transport2.close(); + ctx.transport2!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index 75b9b66380..1861038370 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -1,71 +1,56 @@ import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; +import * as utils from '../utils'; import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; import * as FbsProducer from '../fbs/producer'; -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let transport1: mediasoup.types.WebRtcTransport; -let transport2: mediasoup.types.PlainTransport; -let audioProducer: mediasoup.types.Producer; -let videoProducer: mediasoup.types.Producer; - -const mediaCodecs: mediasoup.types.RtpCodecCapability[] = -[ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - foo : '111' - } - }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 - }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - foo : 'bar' - }, - rtcpFeedback : [] // Will be ignored. - } -]; - -beforeAll(async () => +type TestContext = { - worker = await mediasoup.createWorker(); - router = await worker.createRouter({ mediaCodecs }); - transport1 = await router.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ] - }); - transport2 = await router.createPlainTransport( - { - listenIp : '127.0.0.1' - }); -}); - -afterAll(() => worker.close()); - -test('transport1.produce() succeeds', async () => + mediaCodecs: mediasoup.types.RtpCodecCapability[]; + audioProducerParameters: mediasoup.types.ProducerOptions; + videoProducerParameters: mediasoup.types.ProducerOptions; + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; + transport1?: mediasoup.types.WebRtcTransport; + transport2?: mediasoup.types.WebRtcTransport; +}; + +const ctx: TestContext = { - const onObserverNewProducer = jest.fn(); - - transport1.observer.once('newproducer', onObserverNewProducer); - - audioProducer = await transport1.produce( + mediaCodecs : utils.deepFreeze( + [ + { + kind : 'audio', + mimeType : 'audio/opus', + clockRate : 48000, + channels : 2, + parameters : + { + foo : '111' + } + }, + { + kind : 'video', + mimeType : 'video/VP8', + clockRate : 90000 + }, + { + kind : 'video', + mimeType : 'video/H264', + clockRate : 90000, + parameters : + { + 'level-asymmetry-allowed' : 1, + 'packetization-mode' : 1, + 'profile-level-id' : '4d0032', + foo : 'bar' + }, + rtcpFeedback : [] // Will be ignored. + } + ] + ), + audioProducerParameters : utils.deepFreeze( { kind : 'audio', rtpParameters : @@ -105,46 +90,9 @@ test('transport1.produce() succeeds', async () => } }, appData : { foo: 1, bar: '2' } - }); - - expect(onObserverNewProducer).toHaveBeenCalledTimes(1); - expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer); - expect(typeof audioProducer.id).toBe('string'); - expect(audioProducer.closed).toBe(false); - expect(audioProducer.kind).toBe('audio'); - expect(typeof audioProducer.rtpParameters).toBe('object'); - expect(audioProducer.type).toBe('simple'); - // Private API. - expect(typeof audioProducer.consumableRtpParameters).toBe('object'); - expect(audioProducer.paused).toBe(false); - expect(audioProducer.score).toEqual([]); - expect(audioProducer.appData).toEqual({ foo: 1, bar: '2' }); - - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : [ { key: audioProducer.id, values: [] } ], - mapConsumerIdProducerId : [] - }); - - await expect(transport1.dump()) - .resolves - .toMatchObject( - { - id : transport1.id, - producerIds : [ audioProducer.id ], - consumerIds : [] - }); -}, 2000); - -test('transport2.produce() succeeds', async () => -{ - const onObserverNewProducer = jest.fn(); - - transport2.observer.once('newproducer', onObserverNewProducer); - - videoProducer = await transport2.produce( + } + ), + videoProducerParameters : utils.deepFreeze( { kind : 'video', rtpParameters : @@ -199,7 +147,77 @@ test('transport2.produce() succeeds', async () => } }, appData : { foo: 1, bar: '2' } + } + ) +}; + +beforeEach(async () => +{ + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); + ctx.transport1 = await ctx.router.createWebRtcTransport( + { + listenIps : [ '127.0.0.1' ] }); + ctx.transport2 = await ctx.router.createWebRtcTransport( + { + listenIps : [ '127.0.0.1' ] + }); +}); + +afterEach(() => +{ + ctx.worker?.close(); +}); + +test('transport1.produce() succeeds', async () => +{ + const onObserverNewProducer = jest.fn(); + + ctx.transport1!.observer.once('newproducer', onObserverNewProducer); + + const audioProducer = + await ctx.transport1!.produce(ctx.audioProducerParameters); + + expect(onObserverNewProducer).toHaveBeenCalledTimes(1); + expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer); + expect(typeof audioProducer.id).toBe('string'); + expect(audioProducer.closed).toBe(false); + expect(audioProducer.kind).toBe('audio'); + expect(typeof audioProducer.rtpParameters).toBe('object'); + expect(audioProducer.type).toBe('simple'); + // Private API. + expect(typeof audioProducer.consumableRtpParameters).toBe('object'); + expect(audioProducer.paused).toBe(false); + expect(audioProducer.score).toEqual([]); + expect(audioProducer.appData).toEqual({ foo: 1, bar: '2' }); + + await expect(ctx.router!.dump()) + .resolves + .toMatchObject( + { + mapProducerIdConsumerIds : [ { key: audioProducer.id, values: [] } ], + mapConsumerIdProducerId : [] + }); + + await expect(ctx.transport1!.dump()) + .resolves + .toMatchObject( + { + id : ctx.transport1!.id, + producerIds : [ audioProducer.id ], + consumerIds : [] + }); +}, 2000); + +test('transport2.produce() succeeds', async () => +{ + const onObserverNewProducer = jest.fn(); + + ctx.transport2!.observer.once('newproducer', onObserverNewProducer); + + const videoProducer = + await ctx.transport2!.produce(ctx.videoProducerParameters); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); expect(onObserverNewProducer).toHaveBeenCalledWith(videoProducer); @@ -214,22 +232,21 @@ test('transport2.produce() succeeds', async () => expect(videoProducer.score).toEqual([]); expect(videoProducer.appData).toEqual({ foo: 1, bar: '2' }); - const dump = await router.dump(); + const dump = await ctx.router!.dump(); expect(dump.mapProducerIdConsumerIds) - .toEqual( - expect.arrayContaining([ + .toEqual(expect.arrayContaining( + [ { key: videoProducer.id, values: [] } - ]) - ); + ])); expect(dump.mapConsumerIdProducerId.length).toBe(0); - await expect(transport2.dump()) + await expect(ctx.transport2!.dump()) .resolves .toMatchObject( { - id : transport2.id, + id : ctx.transport2!.id, producerIds : [ videoProducer.id ], consumerIds : [] }); @@ -239,9 +256,9 @@ test('transport1.produce() without header extensions and rtcp succeeds', async ( { const onObserverNewProducer = jest.fn(); - transport1.observer.once('newproducer', onObserverNewProducer); + ctx.transport1!.observer.once('newproducer', onObserverNewProducer); - const audioProducer2 = await transport1.produce( + const audioProducer = await ctx.transport1!.produce( { kind : 'audio', rtpParameters : @@ -268,24 +285,24 @@ test('transport1.produce() without header extensions and rtcp succeeds', async ( }); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); - expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer2); - expect(typeof audioProducer2.id).toBe('string'); - expect(audioProducer2.closed).toBe(false); - expect(audioProducer2.kind).toBe('audio'); - expect(typeof audioProducer2.rtpParameters).toBe('object'); - expect(audioProducer2.type).toBe('simple'); + expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer!); + expect(typeof audioProducer!.id).toBe('string'); + expect(audioProducer!.closed).toBe(false); + expect(audioProducer!.kind).toBe('audio'); + expect(typeof audioProducer!.rtpParameters).toBe('object'); + expect(audioProducer!.type).toBe('simple'); // Private API. - expect(typeof audioProducer2.consumableRtpParameters).toBe('object'); - expect(audioProducer2.paused).toBe(false); - expect(audioProducer2.score).toEqual([]); - expect(audioProducer2.appData).toEqual({ foo: 1, bar: '2' }); + expect(typeof audioProducer!.consumableRtpParameters).toBe('object'); + expect(audioProducer!.paused).toBe(false); + expect(audioProducer!.score).toEqual([]); + expect(audioProducer!.appData).toEqual({ foo: 1, bar: '2' }); - audioProducer2.close(); + audioProducer.close(); }, 2000); test('transport1.produce() with wrong arguments rejects with TypeError', async () => { - await expect(transport1.produce( + await expect(ctx.transport1!.produce( { // @ts-ignore kind : 'chicken', @@ -295,7 +312,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( .rejects .toThrow(TypeError); - await expect(transport1.produce( + await expect(ctx.transport1!.produce( { kind : 'audio', // @ts-ignore @@ -305,7 +322,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( .toThrow(TypeError); // Invalid ssrc. - await expect(transport1.produce( + await expect(ctx.transport1!.produce( { kind : 'audio', rtpParameters : @@ -321,7 +338,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( .toThrow(TypeError); // Missing or empty rtpParameters.encodings. - await expect(transport1.produce( + await expect(ctx.transport1!.produce( { kind : 'video', rtpParameters : @@ -354,7 +371,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( .toThrow(TypeError); // Wrong apt in RTX codec. - await expect(transport1.produce( + await expect(ctx.transport1!.produce( { kind : 'audio', rtpParameters : @@ -395,7 +412,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( test('transport1.produce() with unsupported codecs rejects with UnsupportedError', async () => { - await expect(transport1.produce( + await expect(ctx.transport1!.produce( { kind : 'audio', rtpParameters : @@ -417,7 +434,7 @@ test('transport1.produce() with unsupported codecs rejects with UnsupportedError .toThrow(UnsupportedError); // Invalid H264 profile-level-id. - await expect(transport1.produce( + await expect(ctx.transport1!.produce( { kind : 'video', rtpParameters : @@ -454,75 +471,78 @@ test('transport1.produce() with unsupported codecs rejects with UnsupportedError test('transport.produce() with already used MID or SSRC rejects with Error', async () => { - await expect(transport1.produce( + const audioProducerOptions: mediasoup.types.ProducerOptions = + { + kind : 'audio', + rtpParameters : { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ - { - mimeType : 'audio/opus', - payloadType : 0, - clockRate : 48000, - channels : 2 - } - ], - headerExtensions : [], - encodings : [ { ssrc: 33333333 } ], - rtcp : + mid : 'AUDIO', + codecs : + [ { - cname : 'audio-2' + mimeType : 'audio/opus', + payloadType : 0, + clockRate : 48000, + channels : 2 } - } - })) - .rejects - .toThrow(Error); + ], + encodings : [ { ssrc: 33333333 } ] + } + }; - await expect(transport2.produce( + const videoProducerOptions: mediasoup.types.ProducerOptions = + { + kind : 'video', + rtpParameters : { - kind : 'video', - rtpParameters : - { - mid : 'VIDEO2', - codecs : - [ - { - mimeType : 'video/h264', - payloadType : 112, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - } - } - ], - headerExtensions : - [ + mid : 'VIDEO2', + codecs : + [ + { + mimeType : 'video/h264', + payloadType : 112, + clockRate : 90000, + parameters : { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 + 'packetization-mode' : 1, + 'profile-level-id' : '4d0032' } - ], - encodings : - [ - { ssrc: 22222222 } - ], - rtcp : + } + ], + headerExtensions : + [ { - cname : 'video-1' + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + id : 10 } + ], + encodings : + [ + { ssrc: 22222222 } + ], + rtcp : + { + cname : 'video-1' } - })) + } + }; + + await ctx.transport1!.produce(audioProducerOptions); + + await expect(ctx.transport1!.produce(audioProducerOptions)) + .rejects + .toThrow(Error); + + await ctx.transport2!.produce(videoProducerOptions); + + await expect(ctx.transport2!.produce(videoProducerOptions)) .rejects .toThrow(Error); }, 2000); test('transport.produce() with no MID and with single encoding without RID or SSRC rejects with Error', async () => { - await expect(transport1.produce( + await expect(ctx.transport1!.produce( { kind : 'audio', rtpParameters : @@ -536,11 +556,7 @@ test('transport.produce() with no MID and with single encoding without RID or SS channels : 2 } ], - encodings : [ {} ], - rtcp : - { - cname : 'audio-2' - } + encodings : [ {} ] } })) .rejects @@ -549,20 +565,21 @@ test('transport.produce() with no MID and with single encoding without RID or SS test('producer.dump() succeeds', async () => { - let data; - - data = await audioProducer.dump(); - - expect(data.id).toBe(audioProducer.id); - expect(data.kind).toBe(audioProducer.kind); - expect(typeof data.rtpParameters).toBe('object'); - expect(Array.isArray(data.rtpParameters.codecs)).toBe(true); - expect(data.rtpParameters.codecs.length).toBe(1); - expect(data.rtpParameters.codecs[0].mimeType).toBe('audio/opus'); - expect(data.rtpParameters.codecs[0].payloadType).toBe(0); - expect(data.rtpParameters.codecs[0].clockRate).toBe(48000); - expect(data.rtpParameters.codecs[0].channels).toBe(2); - expect(data.rtpParameters.codecs[0].parameters) + const audioProducer = + await ctx.transport1!.produce(ctx.audioProducerParameters); + + const dump1 = await audioProducer.dump(); + + expect(dump1.id).toBe(audioProducer.id); + expect(dump1.kind).toBe(audioProducer.kind); + expect(typeof dump1.rtpParameters).toBe('object'); + expect(Array.isArray(dump1.rtpParameters.codecs)).toBe(true); + expect(dump1.rtpParameters.codecs.length).toBe(1); + expect(dump1.rtpParameters.codecs[0].mimeType).toBe('audio/opus'); + expect(dump1.rtpParameters.codecs[0].payloadType).toBe(0); + expect(dump1.rtpParameters.codecs[0].clockRate).toBe(48000); + expect(dump1.rtpParameters.codecs[0].channels).toBe(2); + expect(dump1.rtpParameters.codecs[0].parameters) .toEqual( { useinbandfec : 1, @@ -570,10 +587,10 @@ test('producer.dump() succeeds', async () => foo : 222.222, bar : '333' }); - expect(data.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); - expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions!.length).toBe(2); - expect(data.rtpParameters.headerExtensions).toEqual( + expect(dump1.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); + expect(Array.isArray(dump1.rtpParameters.headerExtensions)).toBe(true); + expect(dump1.rtpParameters.headerExtensions!.length).toBe(2); + expect(dump1.rtpParameters.headerExtensions).toEqual( [ { uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', @@ -588,49 +605,52 @@ test('producer.dump() succeeds', async () => encrypt : false } ]); - expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings!.length).toBe(1); - expect(data.rtpParameters.encodings![0]).toEqual( + expect(Array.isArray(dump1.rtpParameters.encodings)).toBe(true); + expect(dump1.rtpParameters.encodings!.length).toBe(1); + expect(dump1.rtpParameters.encodings![0]).toEqual( expect.objectContaining( { codecPayloadType : 0 }) ); - expect(data.type).toBe('simple'); - - data = await videoProducer.dump(); - - expect(data.id).toBe(videoProducer.id); - expect(data.kind).toBe(videoProducer.kind); - expect(typeof data.rtpParameters).toBe('object'); - expect(Array.isArray(data.rtpParameters.codecs)).toBe(true); - expect(data.rtpParameters.codecs.length).toBe(2); - expect(data.rtpParameters.codecs[0].mimeType).toBe('video/H264'); - expect(data.rtpParameters.codecs[0].payloadType).toBe(112); - expect(data.rtpParameters.codecs[0].clockRate).toBe(90000); - expect(data.rtpParameters.codecs[0].channels).toBeUndefined(); - expect(data.rtpParameters.codecs[0].parameters) + expect(dump1.type).toBe('simple'); + + const videoProducer = + await ctx.transport2!.produce(ctx.videoProducerParameters); + + const dump2 = await videoProducer.dump(); + + expect(dump2.id).toBe(videoProducer.id); + expect(dump2.kind).toBe(videoProducer.kind); + expect(typeof dump2.rtpParameters).toBe('object'); + expect(Array.isArray(dump2.rtpParameters.codecs)).toBe(true); + expect(dump2.rtpParameters.codecs.length).toBe(2); + expect(dump2.rtpParameters.codecs[0].mimeType).toBe('video/H264'); + expect(dump2.rtpParameters.codecs[0].payloadType).toBe(112); + expect(dump2.rtpParameters.codecs[0].clockRate).toBe(90000); + expect(dump2.rtpParameters.codecs[0].channels).toBeUndefined(); + expect(dump2.rtpParameters.codecs[0].parameters) .toEqual( { 'packetization-mode' : 1, 'profile-level-id' : '4d0032' }); - expect(data.rtpParameters.codecs[0].rtcpFeedback) + expect(dump2.rtpParameters.codecs[0].rtcpFeedback) .toEqual( [ { type: 'nack' }, { type: 'nack', parameter: 'pli' }, { type: 'goog-remb' } ]); - expect(data.rtpParameters.codecs[1].mimeType).toBe('video/rtx'); - expect(data.rtpParameters.codecs[1].payloadType).toBe(113); - expect(data.rtpParameters.codecs[1].clockRate).toBe(90000); - expect(data.rtpParameters.codecs[1].channels).toBeUndefined(); - expect(data.rtpParameters.codecs[1].parameters).toEqual({ apt: 112 }); - expect(data.rtpParameters.codecs[1].rtcpFeedback).toEqual([]); - expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions!.length).toBe(2); - expect(data.rtpParameters.headerExtensions).toEqual( + expect(dump2.rtpParameters.codecs[1].mimeType).toBe('video/rtx'); + expect(dump2.rtpParameters.codecs[1].payloadType).toBe(113); + expect(dump2.rtpParameters.codecs[1].clockRate).toBe(90000); + expect(dump2.rtpParameters.codecs[1].channels).toBeUndefined(); + expect(dump2.rtpParameters.codecs[1].parameters).toEqual({ apt: 112 }); + expect(dump2.rtpParameters.codecs[1].rtcpFeedback).toEqual([]); + expect(Array.isArray(dump2.rtpParameters.headerExtensions)).toBe(true); + expect(dump2.rtpParameters.headerExtensions!.length).toBe(2); + expect(dump2.rtpParameters.headerExtensions).toEqual( [ { uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', @@ -645,9 +665,9 @@ test('producer.dump() succeeds', async () => encrypt : false } ]); - expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings!.length).toBe(4); - expect(data.rtpParameters.encodings).toMatchObject( + expect(Array.isArray(dump2.rtpParameters.encodings)).toBe(true); + expect(dump2.rtpParameters.encodings!.length).toBe(4); + expect(dump2.rtpParameters.encodings).toMatchObject( [ { codecPayloadType : 112, @@ -659,11 +679,17 @@ test('producer.dump() succeeds', async () => { codecPayloadType: 112, ssrc: 22222226, rtx: { ssrc: 22222227 } }, { codecPayloadType: 112, ssrc: 22222228, rtx: { ssrc: 22222229 } } ]); - expect(data.type).toBe('simulcast'); + expect(dump2.type).toBe('simulcast'); }, 2000); test('producer.getStats() succeeds', async () => { + const audioProducer = + await ctx.transport1!.produce(ctx.audioProducerParameters); + + const videoProducer = + await ctx.transport2!.produce(ctx.videoProducerParameters); + await expect(audioProducer.getStats()) .resolves .toEqual([]); @@ -675,6 +701,9 @@ test('producer.getStats() succeeds', async () => test('producer.pause() and resume() succeed', async () => { + const audioProducer = + await ctx.transport1!.produce(ctx.audioProducerParameters); + const onObserverPause = jest.fn(); const onObserverResume = jest.fn(); @@ -710,15 +739,18 @@ test('producer.pause() and resume() succeed', async () => test('producer.pause() and resume() emit events', async () => { + const audioProducer = + await ctx.transport1!.produce(ctx.audioProducerParameters); + const promises = []; const events: string[] = []; - audioProducer.observer.once('resume', () => + audioProducer.observer.once('resume', () => { events.push('resume'); }); - audioProducer.observer.once('pause', () => + audioProducer.observer.once('pause', () => { events.push('pause'); }); @@ -734,32 +766,44 @@ test('producer.pause() and resume() emit events', async () => test('producer.enableTraceEvent() succeed', async () => { - let dump; + const audioProducer = + await ctx.transport1!.produce(ctx.audioProducerParameters); await audioProducer.enableTraceEvent([ 'rtp', 'pli' ]); - dump = await audioProducer.dump(); - expect(dump.traceEventTypes) + + const dump1 = await audioProducer.dump(); + + expect(dump1.traceEventTypes) .toEqual(expect.arrayContaining([ 'rtp', 'pli' ])); await audioProducer.enableTraceEvent([]); - dump = await audioProducer.dump(); - expect(dump.traceEventTypes) + + const dump2 = await audioProducer.dump(); + + expect(dump2.traceEventTypes) .toEqual(expect.arrayContaining([])); // @ts-ignore await audioProducer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); - dump = await audioProducer.dump(); - expect(dump.traceEventTypes) + + const dump3 = await audioProducer.dump(); + + expect(dump3.traceEventTypes) .toEqual(expect.arrayContaining([ 'nack', 'fir' ])); await audioProducer.enableTraceEvent(); - dump = await audioProducer.dump(); - expect(dump.traceEventTypes) + + const dump4 = await audioProducer.dump(); + + expect(dump4.traceEventTypes) .toEqual(expect.arrayContaining([])); }, 2000); test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { + const audioProducer = + await ctx.transport1!.produce(ctx.audioProducerParameters); + // @ts-ignore await expect(audioProducer.enableTraceEvent(123)) .rejects @@ -778,6 +822,9 @@ test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', test('Producer emits "score"', async () => { + const videoProducer = + await ctx.transport2!.produce(ctx.videoProducerParameters); + // Private API. const channel = videoProducer.channelForTesting; const onScore = jest.fn(); @@ -786,10 +833,21 @@ test('Producer emits "score"', async () => // Simulate a 'score' notification coming through the channel. const builder = new flatbuffers.Builder(); - const producerScoreNotification = new FbsProducer.ScoreNotificationT([ - new FbsProducer.ScoreT(/* encodingIdx */ 0, /* ssrc */ 11, /* rid */ undefined, /* score */ 10), - new FbsProducer.ScoreT(/* encodingIdx */ 1, /* ssrc */ 22, /* rid */ undefined, /* score */ 9) - ]); + const producerScoreNotification = new FbsProducer.ScoreNotificationT( + [ + new FbsProducer.ScoreT( + /* encodingIdx */ 0, + /* ssrc */ 11, + /* rid */ undefined, + /* score */ 10 + ), + new FbsProducer.ScoreT( + /* encodingIdx */ 1, + /* ssrc */ 22, + /* rid */ undefined, + /* score */ 9 + ) + ]); const notificationOffset = Notification.createNotification( builder, builder.createString(videoProducer.id), @@ -801,7 +859,8 @@ test('Producer emits "score"', async () => builder.finish(notificationOffset); const notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array())); + new flatbuffers.ByteBuffer(builder.asUint8Array()) + ); channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); @@ -817,6 +876,9 @@ test('Producer emits "score"', async () => test('producer.close() succeeds', async () => { + const audioProducer = + await ctx.transport1!.produce(ctx.audioProducerParameters); + const onObserverClose = jest.fn(); audioProducer.observer.once('close', onObserverClose); @@ -825,19 +887,19 @@ test('producer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(audioProducer.closed).toBe(true); - await expect(router.dump()) + await expect(ctx.router!.dump()) .resolves .toMatchObject( { - mapProducerIdConsumerIds : {}, - mapConsumerIdProducerId : {} + mapProducerIdConsumerIds : [], + mapConsumerIdProducerId : [] }); - await expect(transport1.dump()) + await expect(ctx.transport1!.dump()) .resolves .toMatchObject( { - id : transport1.id, + id : ctx.transport1!.id, producerIds : [], consumerIds : [] }); @@ -845,6 +907,11 @@ test('producer.close() succeeds', async () => test('Producer methods reject if closed', async () => { + const audioProducer = + await ctx.transport1!.produce(ctx.audioProducerParameters); + + audioProducer.close(); + await expect(audioProducer.dump()) .rejects .toThrow(Error); @@ -864,6 +931,9 @@ test('Producer methods reject if closed', async () => test('Producer emits "transportclose" if Transport is closed', async () => { + const videoProducer = + await ctx.transport2!.produce(ctx.videoProducerParameters); + const onObserverClose = jest.fn(); videoProducer.observer.once('close', onObserverClose); @@ -871,7 +941,7 @@ test('Producer emits "transportclose" if Transport is closed', async () => await new Promise((resolve) => { videoProducer.on('transportclose', resolve); - transport2.close(); + ctx.transport2!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index 4eb0f4443e..5aab850ac2 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -4,8 +4,8 @@ import * as utils from '../utils'; type TestContext = { - worker?: mediasoup.types.Worker; mediaCodecs: mediasoup.types.RtpCodecCapability[]; + worker?: mediasoup.types.Worker; }; const ctx: TestContext = diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index 23322095de..27715f6e76 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -4,12 +4,12 @@ import * as utils from '../utils'; type TestContext = { - worker?: mediasoup.types.Worker; - router?: mediasoup.types.Router; - transport?: mediasoup.types.WebRtcTransport; mediaCodecs: mediasoup.types.RtpCodecCapability[]; audioProducerParameters: mediasoup.types.ProducerOptions; consumerDeviceCapabilities: mediasoup.types.RtpCapabilities; + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; + transport?: mediasoup.types.WebRtcTransport; }; const ctx: TestContext = @@ -175,9 +175,6 @@ test('produce() and consume() succeed', async () => rtcpFeedback : [] } ]); - - audioProducer.close(); - audioConsumer.close(); }, 2000); test('fails to produce wrong parameters', async () => @@ -268,6 +265,4 @@ test('fails to consume wrong channels', async () => })) .rejects .toThrow(Error); - - audioProducer.close(); }, 2000); diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index 31804c6962..12bef370f2 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -3,24 +3,29 @@ import * as dgram from 'node:dgram'; import * as sctp from 'sctp'; import * as mediasoup from '../'; -// Set node-sctp default PMTU to 1200. -sctp.defaults({ PMTU: 1200 }); - -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let transport: mediasoup.types.PlainTransport; -let dataProducer: mediasoup.types.DataProducer; -let dataConsumer: mediasoup.types.DataConsumer; -let udpSocket: dgram.Socket; -let sctpSocket: any; -let sctpSendStreamId: number; -let sctpSendStream: any; - -beforeAll(async () => +type TestContext = { - worker = await mediasoup.createWorker(); - router = await worker.createRouter(); - transport = await router.createPlainTransport( + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; + transport?: mediasoup.types.PlainTransport; + dataProducer?: mediasoup.types.DataProducer; + dataConsumer?: mediasoup.types.DataConsumer; + udpSocket?: dgram.Socket; + sctpSocket?: any; + sctpSendStreamId?: number; + sctpSendStream?: any; +}; + +const ctx: TestContext = {}; + +beforeEach(async () => +{ + // Set node-sctp default PMTU to 1200. + sctp.defaults({ PMTU: 1200 }); + + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter(); + ctx.transport = await ctx.router.createPlainTransport( { listenIp : '127.0.0.1', // https://github.com/nodejs/node/issues/14900 comedia : true, // So we don't need to call transport.connect(). @@ -29,64 +34,46 @@ beforeAll(async () => }); // Node UDP socket for SCTP. - udpSocket = dgram.createSocket({ type: 'udp4' }); + ctx.udpSocket = dgram.createSocket({ type: 'udp4' }); - await new Promise((resolve) => udpSocket.bind(0, '127.0.0.1', resolve)); + await new Promise((resolve) => + { + ctx.udpSocket!.bind(0, '127.0.0.1', resolve); + }); - const remoteUdpIp = transport.tuple.localIp; - const remoteUdpPort = transport.tuple.localPort; - const { OS, MIS } = transport.sctpParameters!; + const remoteUdpIp = ctx.transport.tuple.localIp; + const remoteUdpPort = ctx.transport.tuple.localPort; + const { OS, MIS } = ctx.transport.sctpParameters!; - // Use UDP connected socket if Node >= 12. - if (typeof udpSocket.connect === 'function') + await new Promise((resolve, reject) => { - await new Promise((resolve, reject) => + // @ts-ignore + ctx.udpSocket.connect(remoteUdpPort, remoteUdpIp, (error: Error) => { - // @ts-ignore - udpSocket.connect(remoteUdpPort, remoteUdpIp, (error: Error) => + if (error) { - if (error) - { - reject(error); - - return; - } + reject(error); - sctpSocket = sctp.connect( - { - localPort : 5000, // Required for SCTP over UDP in mediasoup. - port : 5000, // Required for SCTP over UDP in mediasoup. - OS : OS, - MIS : MIS, - udpTransport : udpSocket - }); + return; + } - resolve(); - }); - }); - } - // Use UDP disconnected socket if Node < 12. - else - { - sctpSocket = sctp.connect( - { - localPort : 5000, // Required for SCTP over UDP in mediasoup. - port : 5000, // Required for SCTP over UDP in mediasoup. - OS : OS, - MIS : MIS, - udpTransport : udpSocket, - udpPeer : + ctx.sctpSocket = sctp.connect( { - address : remoteUdpIp, - port : remoteUdpPort - } - }); - } + localPort : 5000, // Required for SCTP over UDP in mediasoup. + port : 5000, // Required for SCTP over UDP in mediasoup. + OS : OS, + MIS : MIS, + udpTransport : ctx.udpSocket + }); + + resolve(); + }); + }); // Wait for the SCTP association to be open. await Promise.race( [ - new Promise((resolve) => sctpSocket.on('connect', resolve)), + new Promise((resolve) => ctx.sctpSocket.on('connect', resolve)), new Promise((resolve, reject) => ( setTimeout(() => reject(new Error('SCTP connection timeout')), 3000) )) @@ -94,15 +81,15 @@ beforeAll(async () => // Create an explicit SCTP outgoing stream with id 123 (id 0 is already used // by the implicit SCTP outgoing stream built-in the SCTP socket). - sctpSendStreamId = 123; - sctpSendStream = sctpSocket.createStream(sctpSendStreamId); + ctx.sctpSendStreamId = 123; + ctx.sctpSendStream = ctx.sctpSocket.createStream(ctx.sctpSendStreamId); // Create a DataProducer with the corresponding SCTP stream id. - dataProducer = await transport.produceData( + ctx.dataProducer = await ctx.transport.produceData( { sctpStreamParameters : { - streamId : sctpSendStreamId, + streamId : ctx.sctpSendStreamId, ordered : true }, label : 'node-sctp', @@ -111,14 +98,16 @@ beforeAll(async () => // Create a DataConsumer to receive messages from the DataProducer over the // same transport. - dataConsumer = await transport.consumeData({ dataProducerId: dataProducer.id }); + ctx.dataConsumer = await ctx.transport.consumeData( + { dataProducerId: ctx.dataProducer.id } + ); }); -afterAll(async () => +afterEach(async () => { - udpSocket.close(); - sctpSocket.end(); - worker.close(); + ctx.udpSocket?.close(); + ctx.sctpSocket?.end(); + ctx.worker?.close(); // NOTE: For some reason we have to wait a bit for the SCTP stuff to release // internal things, otherwise Jest reports open handles. We don't care much @@ -136,7 +125,7 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn let numReceivedMessages = 0; // It must be zero because it's the first DataConsumer on the transport. - expect(dataConsumer.sctpStreamParameters?.streamId).toBe(0); + expect(ctx.dataConsumer!.sctpStreamParameters?.streamId).toBe(0); // eslint-disable-next-line no-async-promise-executor await new Promise(async (resolve, reject) => @@ -161,7 +150,7 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn data.ppid = sctp.PPID.WEBRTC_BINARY; } - sctpSendStream.write(data); + ctx.sctpSendStream!.write(data); sentMessageBytes += data.byteLength; if (id < numMessages) @@ -170,11 +159,11 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn } } - sctpSocket.on('stream', onStream); + ctx.sctpSocket!.on('stream', onStream); // Handle the generated SCTP incoming stream and SCTP messages receives on it. // @ts-ignore - sctpSocket.on('stream', (stream, streamId) => + ctx.sctpSocket.on('stream', (stream, streamId) => { // It must be zero because it's the first SCTP incoming stream (so first // DataConsumer). @@ -228,27 +217,27 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn expect(numReceivedMessages).toBe(numMessages); expect(recvMessageBytes).toBe(sentMessageBytes); - await expect(dataProducer.getStats()) + await expect(ctx.dataProducer!.getStats()) .resolves .toMatchObject( [ { type : 'data-producer', - label : dataProducer.label, - protocol : dataProducer.protocol, + label : ctx.dataProducer!.label, + protocol : ctx.dataProducer!.protocol, messagesReceived : numMessages, bytesReceived : sentMessageBytes } ]); - await expect(dataConsumer.getStats()) + await expect(ctx.dataConsumer!.getStats()) .resolves .toMatchObject( [ { type : 'data-consumer', - label : dataConsumer.label, - protocol : dataConsumer.protocol, + label : ctx.dataConsumer!.label, + protocol : ctx.dataConsumer!.protocol, messagesSent : numMessages, bytesSent : recvMessageBytes } From cc16505873d5b27ac7260113c64e98a5000842b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 5 Jan 2024 13:43:57 +0100 Subject: [PATCH 300/525] Add worker prebuild binary for Linux kernel 6 (#1300) Fixes #1284 ### Details - Ubuntu 22.04.3 LTS has kernel 6.2. - CI job: No need to manually install `invoke` since `npm run worker:build` internally installs it if needed. --- .github/workflows/mediasoup-worker-prebuild.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 1291c95adc..6771289401 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -10,13 +10,18 @@ jobs: strategy: matrix: build: - # For Linux let's use an old version of Ubuntu (20.04) that builds the + # Worker prebuild for Linux with kernel version 5 Ubuntu (20.04). + # Let's use an old version of Ubuntu (20.04) that builds the # mediasoup-worker binary using an old version of GLib, so it will work # on Linux hosts running more modern GLib versions. # See https://github.com/versatica/mediasoup/issues/1089. - os: ubuntu-20.04 cc: gcc cxx: g++ + # Worker prebuild for Linux with kernel version 6 Ubuntu (22.04). + - os: ubuntu-22.04 + cc: gcc + cxx: g++ - os: macos-12 cc: clang cxx: clang++ @@ -43,15 +48,11 @@ jobs: with: node-version: ${{ matrix.node }} - # We need to install some NPM production deps for npm-scripts.mjs to work. + # We need to install some NPM production deps for npm-scripts.mjs to + # work. - name: npm ci --ignore-scripts run: npm ci --ignore-scripts --omit=dev --foreground-scripts - # However we also need to install pip invoke manually (since - # `--ignore-scripts` prevented invoke from being installed). - - name: pip3 install invoke - run: pip3 install invoke - - name: npm run worker:build run: npm run worker:build From 06fc7604206162365389f64b67c8c3f5421fa898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 5 Jan 2024 13:48:01 +0100 Subject: [PATCH 301/525] 3.13.15 --- CHANGELOG.md | 5 +++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 046bb06b35..693b5bea6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +### 3.13.15 + +* Add worker prebuild binary for Linux kernel 6 ([PR #1300](https://github.com/versatica/mediasoup/pull/1300)). + + ### 3.13.14 * Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). diff --git a/package-lock.json b/package-lock.json index c2555cc1f7..6368bf90f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.14", + "version": "3.13.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.14", + "version": "3.13.15", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 847cd5d798..2916632477 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.14", + "version": "3.13.15", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From f137a4d17ea104834b771b4b436b585bafffa794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 6 Jan 2024 19:03:40 +0100 Subject: [PATCH 302/525] Make node tests independent (part 5) (#1301) --- node/src/Channel.ts | 6 +- node/src/DataConsumer.ts | 5 +- node/src/DataProducer.ts | 5 +- node/src/PipeTransport.ts | 6 +- node/src/Router.ts | 6 +- node/src/RtpStream.ts | 5 +- node/src/Transport.ts | 18 +- node/src/WebRtcTransport.ts | 16 +- node/src/scalabilityModes.ts | 5 +- node/src/test/test-ActiveSpeakerObserver.ts | 4 +- node/src/test/test-AudioLevelObserver.ts | 6 +- node/src/test/test-Consumer.ts | 104 ++-- node/src/test/test-DataConsumer.ts | 376 +++++++----- node/src/test/test-DataProducer.ts | 110 ++-- node/src/test/test-DirectTransport.ts | 200 +++--- node/src/test/test-PipeTransport.ts | 642 +++++++++++--------- node/src/test/test-PlainTransport.ts | 494 ++++++++------- node/src/test/test-Producer.ts | 106 ++-- node/src/test/test-Router.ts | 11 +- node/src/test/test-WebRtcTransport.ts | 552 ++++++++++------- node/src/test/test-mediasoup.ts | 5 +- node/src/test/test-multiopus.ts | 142 +++-- node/src/test/test-node-sctp.ts | 24 +- node/src/test/test-ortc.ts | 18 +- 24 files changed, 1590 insertions(+), 1276 deletions(-) diff --git a/node/src/Channel.ts b/node/src/Channel.ts index 4dc430c02a..00d0d25ce1 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -7,7 +7,11 @@ import { InvalidStateError } from './errors'; import { Body as RequestBody, Method, Request } from './fbs/request'; import { Response } from './fbs/response'; import { Message, Body as MessageBody } from './fbs/message'; -import { Notification, Body as NotificationBody, Event } from './fbs/notification'; +import { + Notification, + Body as NotificationBody, + Event +} from './fbs/notification'; import { Log } from './fbs/log'; const IS_LITTLE_ENDIAN = os.endianness() === 'LE'; diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 799001cef0..3a3ca78a6f 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -2,7 +2,10 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; -import { parseSctpStreamParameters, SctpStreamParameters } from './SctpParameters'; +import { + SctpStreamParameters, + parseSctpStreamParameters +} from './SctpParameters'; import { AppData } from './types'; import * as utils from './utils'; import { Event, Notification } from './fbs/notification'; diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index ee3cf29ef8..b6464e740e 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -2,7 +2,10 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; -import { parseSctpStreamParameters, SctpStreamParameters } from './SctpParameters'; +import { + SctpStreamParameters, + parseSctpStreamParameters +} from './SctpParameters'; import { AppData } from './types'; import * as FbsTransport from './fbs/transport'; import * as FbsNotification from './fbs/notification'; diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index d0cd72d8cd..e3a10dc439 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -20,7 +20,11 @@ import { } from './Transport'; import { Consumer, ConsumerType } from './Consumer'; import { Producer } from './Producer'; -import { RtpParameters, serializeRtpEncodingParameters, serializeRtpParameters } from './RtpParameters'; +import { + RtpParameters, + serializeRtpEncodingParameters, + serializeRtpParameters +} from './RtpParameters'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; import { parseSrtpParameters, diff --git a/node/src/Router.ts b/node/src/Router.ts index 4c986870da..d42004d7bb 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -731,11 +731,11 @@ export class Router } // If rtcpMux is enabled, ignore rtcpListenInfo. - if (rtcpMux) + if (rtcpMux && rtcpListenInfo) { - logger.warn('createPlainTransport() | ignoring given rtcpListenInfo since rtcpMux is enabled'); + logger.warn('createPlainTransport() | ignoring rtcpMux since rtcpListenInfo is given'); - rtcpListenInfo = undefined; + rtcpMux = false; } // Convert deprecated TransportListenIps to TransportListenInfos. diff --git a/node/src/RtpStream.ts b/node/src/RtpStream.ts index ad863b19c2..434cfaf947 100644 --- a/node/src/RtpStream.ts +++ b/node/src/RtpStream.ts @@ -41,8 +41,9 @@ type BaseRtpStreamStats = rtxPacketsDiscarded?: number; }; -export function parseRtpStreamStats(binary: FbsRtpStream.Stats) - : RtpStreamRecvStats | RtpStreamSendStats +export function parseRtpStreamStats( + binary: FbsRtpStream.Stats +) : RtpStreamRecvStats | RtpStreamSendStats { if (binary.dataType() === FbsRtpStream.StatsData.RecvStats) { diff --git a/node/src/Transport.ts b/node/src/Transport.ts index c189a848ae..5fd110ba14 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -8,8 +8,18 @@ import { WebRtcTransportData } from './WebRtcTransport'; import { PlainTransportData } from './PlainTransport'; import { PipeTransportData } from './PipeTransport'; import { DirectTransportData } from './DirectTransport'; -import { Producer, ProducerOptions, producerTypeFromFbs, producerTypeToFbs } from './Producer'; -import { Consumer, ConsumerLayers, ConsumerOptions, ConsumerType } from './Consumer'; +import { + Producer, + ProducerOptions, + producerTypeFromFbs, + producerTypeToFbs +} from './Producer'; +import { + Consumer, + ConsumerOptions, + ConsumerType, + ConsumerLayers +} from './Consumer'; import { DataProducer, DataProducerOptions, @@ -1880,7 +1890,5 @@ function parseSctpListenerDump(binary: FbsTransport.SctpListener): SctpListenerD // Retrieve streamIdTable. const streamIdTable = utils.parseUint32StringVector(binary, 'streamIdTable'); - return { - streamIdTable - }; + return { streamIdTable }; } diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 64fec095e0..e822f5c5d0 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -899,7 +899,8 @@ function createConnectRequest( // Create request. return FbsWebRtcTransport.ConnectRequest.createConnectRequest( builder, - dtlsParametersOffset); + dtlsParametersOffset + ); } function parseGetStatsResponse( @@ -977,13 +978,17 @@ function serializeDtlsParameters( const algorithm = fingerprintAlgorithmToFbs(fingerprint.algorithm); const valueOffset = builder.createString(fingerprint.value); const fingerprintOffset = FbsWebRtcTransport.Fingerprint.createFingerprint( - builder, algorithm, valueOffset); + builder, algorithm, valueOffset + ); fingerprints.push(fingerprintOffset); } - const fingerprintsOffset = FbsWebRtcTransport.DtlsParameters.createFingerprintsVector( - builder, fingerprints); + const fingerprintsOffset = + FbsWebRtcTransport.DtlsParameters.createFingerprintsVector( + builder, fingerprints + ); + const role = dtlsParameters.role !== undefined ? dtlsRoleToFbs(dtlsParameters.role) : FbsWebRtcTransport.DtlsRole.AUTO; @@ -991,5 +996,6 @@ function serializeDtlsParameters( return FbsWebRtcTransport.DtlsParameters.createDtlsParameters( builder, fingerprintsOffset, - role); + role + ); } diff --git a/node/src/scalabilityModes.ts b/node/src/scalabilityModes.ts index 2ebf56f6a3..1c749ed1da 100644 --- a/node/src/scalabilityModes.ts +++ b/node/src/scalabilityModes.ts @@ -1,5 +1,6 @@ -const ScalabilityModeRegex = - new RegExp('^[LS]([1-9]\\d{0,1})T([1-9]\\d{0,1})(_KEY)?'); +const ScalabilityModeRegex = new RegExp( + '^[LS]([1-9]\\d{0,1})T([1-9]\\d{0,1})(_KEY)?' +); export type ScalabilityMode = { diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index 2570abb171..99e8686c34 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -30,7 +30,9 @@ const ctx: TestContext = beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); - ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); + ctx.router = await ctx.worker.createRouter( + { mediaCodecs: ctx.mediaCodecs } + ); }); afterEach(() => diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index 763ec2be30..3603d7da83 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -3,9 +3,9 @@ import * as utils from '../utils'; type TestContext = { + mediaCodecs: mediasoup.types.RtpCodecCapability[]; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; - mediaCodecs: mediasoup.types.RtpCodecCapability[]; }; const ctx: TestContext = @@ -30,7 +30,9 @@ const ctx: TestContext = beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); - ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); + ctx.router = await ctx.worker.createRouter( + { mediaCodecs: ctx.mediaCodecs } + ); }); afterEach(() => diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index 2700ae77bc..92bf19cd07 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -12,13 +12,13 @@ import * as FbsConsumer from '../fbs/consumer'; type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; - audioProducerParameters: mediasoup.types.ProducerOptions; - videoProducerParameters: mediasoup.types.ProducerOptions; + audioProducerOptions: mediasoup.types.ProducerOptions; + videoProducerOptions: mediasoup.types.ProducerOptions; consumerDeviceCapabilities: mediasoup.types.RtpCapabilities; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; - transport1?: mediasoup.types.WebRtcTransport; - transport2?: mediasoup.types.WebRtcTransport; + webRtcTransport1?: mediasoup.types.WebRtcTransport; + webRtcTransport2?: mediasoup.types.WebRtcTransport; audioProducer?: mediasoup.types.Producer; videoProducer?: mediasoup.types.Producer; }; @@ -56,7 +56,7 @@ const ctx: TestContext = } ] ), - audioProducerParameters : utils.deepFreeze( + audioProducerOptions : utils.deepFreeze( { kind : 'audio', rtpParameters : @@ -98,7 +98,7 @@ const ctx: TestContext = appData : { foo: 1, bar: '2' } } ), - videoProducerParameters : utils.deepFreeze( + videoProducerOptions : utils.deepFreeze( { kind : 'video', rtpParameters : @@ -260,16 +260,16 @@ beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); - ctx.transport1 = await ctx.router.createWebRtcTransport( + ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ] }); - ctx.transport2 = await ctx.router.createWebRtcTransport( + ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ] }); - ctx.audioProducer = await ctx.transport1.produce(ctx.audioProducerParameters); - ctx.videoProducer = await ctx.transport1.produce(ctx.videoProducerParameters); + ctx.audioProducer = await ctx.webRtcTransport1.produce(ctx.audioProducerOptions); + ctx.videoProducer = await ctx.webRtcTransport1.produce(ctx.videoProducerOptions); }); afterEach(() => @@ -281,7 +281,7 @@ test('transport.consume() succeeds', async () => { const onObserverNewConsumer1 = jest.fn(); - ctx.transport2!.observer.once('newconsumer', onObserverNewConsumer1); + ctx.webRtcTransport2!.observer.once('newconsumer', onObserverNewConsumer1); expect(ctx.router!.canConsume( { @@ -290,7 +290,7 @@ test('transport.consume() succeeds', async () => })) .toBe(true); - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities, @@ -345,18 +345,18 @@ test('transport.consume() succeeds', async () => { key: audioConsumer.id, value: ctx.audioProducer!.id } ])); - await expect(ctx.transport2!.dump()) + await expect(ctx.webRtcTransport2!.dump()) .resolves .toMatchObject( { - id : ctx.transport2!.id, + id : ctx.webRtcTransport2!.id, producerIds : [], consumerIds : [ audioConsumer.id ] }); const onObserverNewConsumer2 = jest.fn(); - ctx.transport2!.observer.once('newconsumer', onObserverNewConsumer2); + ctx.webRtcTransport2!.observer.once('newconsumer', onObserverNewConsumer2); expect(ctx.router!.canConsume( { @@ -368,7 +368,7 @@ test('transport.consume() succeeds', async () => // Pause videoProducer. ctx.videoProducer!.pause(); - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities, @@ -418,13 +418,15 @@ test('transport.consume() succeeds', async () => expect(videoConsumer.priority).toBe(1); expect(videoConsumer.score).toEqual( { score: 10, producerScore: 0, producerScores: [ 0, 0, 0, 0 ] }); - expect(videoConsumer.preferredLayers).toEqual({ spatialLayer: 3, temporalLayer: 0 }); + expect(videoConsumer.preferredLayers).toEqual( + { spatialLayer: 3, temporalLayer: 0 } + ); expect(videoConsumer.currentLayers).toBeUndefined(); expect(videoConsumer.appData).toEqual({ baz: 'LOL' }); const onObserverNewConsumer3 = jest.fn(); - ctx.transport2!.observer.once('newconsumer', onObserverNewConsumer3); + ctx.webRtcTransport2!.observer.once('newconsumer', onObserverNewConsumer3); expect(ctx.router!.canConsume( { @@ -433,7 +435,7 @@ test('transport.consume() succeeds', async () => })) .toBe(true); - const videoPipeConsumer = await ctx.transport2!.consume( + const videoPipeConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities, @@ -511,11 +513,11 @@ test('transport.consume() succeeds', async () => { key: videoPipeConsumer.id, value: ctx.videoProducer!.id } ])); - await expect(ctx.transport2!.dump()) + await expect(ctx.webRtcTransport2!.dump()) .resolves .toMatchObject( { - id : ctx.transport2!.id, + id : ctx.webRtcTransport2!.id, producerIds : [], consumerIds : expect.arrayContaining( [ @@ -528,7 +530,7 @@ test('transport.consume() succeeds', async () => test('transport.consume() with enableRtx succeeds', async () => { - const audioConsumer2 = await ctx.transport2!.consume( + const audioConsumer2 = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities, @@ -556,7 +558,7 @@ test('transport.consume() with enableRtx succeeds', async () => test('transport.consume() can be created with user provided mid', async () => { - const audioConsumer1 = await ctx.transport2!.consume( + const audioConsumer1 = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -565,7 +567,7 @@ test('transport.consume() can be created with user provided mid', async () => expect(audioConsumer1.rtpParameters.mid).toEqual( expect.stringMatching(/^[0-9]+/)); - const audioConsumer2 = await ctx.transport2!.consume( + const audioConsumer2 = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, mid : 'custom-mid', @@ -574,7 +576,7 @@ test('transport.consume() can be created with user provided mid', async () => expect(audioConsumer2.rtpParameters.mid).toBe('custom-mid'); - const audioConsumer3 = await ctx.transport2!.consume( + const audioConsumer3 = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -612,7 +614,7 @@ test('transport.consume() with incompatible rtpCapabilities rejects with Unsuppo })) .toBe(false); - await expect(ctx.transport2!.consume( + await expect(ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : invalidDeviceCapabilities @@ -633,7 +635,7 @@ test('transport.consume() with incompatible rtpCapabilities rejects with Unsuppo })) .toBe(false); - await expect(ctx.transport2!.consume( + await expect(ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : invalidDeviceCapabilities @@ -644,7 +646,7 @@ test('transport.consume() with incompatible rtpCapabilities rejects with Unsuppo test('consumer.dump() succeeds', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -718,7 +720,7 @@ test('consumer.dump() succeeds', async () => expect(dump1.producerPaused).toBe(false); expect(dump1.priority).toBe(1); - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities, @@ -822,7 +824,7 @@ test('consumer.dump() succeeds', async () => test('consumer.getStats() succeeds', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -841,7 +843,7 @@ test('consumer.getStats() succeeds', async () => }) ]); - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -863,7 +865,7 @@ test('consumer.getStats() succeeds', async () => test('consumer.pause() and resume() succeed', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -903,7 +905,7 @@ test('consumer.pause() and resume() succeed', async () => test('producer.pause() and resume() emit events', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -935,12 +937,12 @@ test('producer.pause() and resume() emit events', async () => test('consumer.setPreferredLayers() succeed', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities }); - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -964,7 +966,7 @@ test('consumer.setPreferredLayers() succeed', async () => test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError', async () => { - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -994,7 +996,7 @@ test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError' test('consumer.setPriority() succeed', async () => { - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1006,7 +1008,7 @@ test('consumer.setPriority() succeed', async () => test('consumer.setPriority() with wrong arguments rejects with TypeError', async () => { - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1029,7 +1031,7 @@ test('consumer.setPriority() with wrong arguments rejects with TypeError', async test('consumer.unsetPriority() succeed', async () => { - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1041,7 +1043,7 @@ test('consumer.unsetPriority() succeed', async () => test('consumer.enableTraceEvent() succeed', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1078,7 +1080,7 @@ test('consumer.enableTraceEvent() succeed', async () => test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1102,7 +1104,7 @@ test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', test('Consumer emits "producerpause" and "producerresume"', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1134,7 +1136,7 @@ test('Consumer emits "producerpause" and "producerresume"', async () => test('Consumer emits "score"', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1176,12 +1178,12 @@ test('Consumer emits "score"', async () => test('consumer.close() succeeds', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities }); - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1208,12 +1210,12 @@ test('consumer.close() succeeds', async () => { key: videoConsumer!.id, value: ctx.videoProducer!.id } ]); - const transportDump = await ctx.transport2!.dump(); + const transportDump = await ctx.webRtcTransport2!.dump(); expect(transportDump) .toMatchObject( { - id : ctx.transport2!.id, + id : ctx.webRtcTransport2!.id, producerIds : [], consumerIds : [ videoConsumer.id ] }); @@ -1221,7 +1223,7 @@ test('consumer.close() succeeds', async () => test('Consumer methods reject if closed', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1261,7 +1263,7 @@ test('Consumer methods reject if closed', async () => test('Consumer emits "producerclose" if Producer is closed', async () => { - const audioConsumer = await ctx.transport2!.consume( + const audioConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.audioProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1282,7 +1284,7 @@ test('Consumer emits "producerclose" if Producer is closed', async () => test('Consumer emits "transportclose" if Transport is closed', async () => { - const videoConsumer = await ctx.transport2!.consume( + const videoConsumer = await ctx.webRtcTransport2!.consume( { producerId : ctx.videoProducer!.id, rtpCapabilities : ctx.consumerDeviceCapabilities @@ -1295,7 +1297,7 @@ test('Consumer emits "transportclose" if Transport is closed', async () => await new Promise((resolve) => { videoConsumer.on('transportclose', resolve); - ctx.transport2!.close(); + ctx.webRtcTransport2!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index 66bfae338b..74de277b8a 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -1,55 +1,66 @@ import * as mediasoup from '../'; +import * as utils from '../utils'; -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let transport1: mediasoup.types.WebRtcTransport; -let transport2: mediasoup.types.PlainTransport; -let transport3: mediasoup.types.DirectTransport; -let dataProducer: mediasoup.types.DataProducer; -let dataConsumer1: mediasoup.types.DataConsumer; -let dataConsumer2: mediasoup.types.DataConsumer; +type TestContext = +{ + dataProducerOptions: mediasoup.types.DataProducerOptions; + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; + webRtcTransport1?: mediasoup.types.WebRtcTransport; + webRtcTransport2?: mediasoup.types.WebRtcTransport; + directTransport?: mediasoup.types.DirectTransport; + dataProducer?: mediasoup.types.DataProducer; +}; -const dataProducerParameters: mediasoup.types.DataProducerOptions = +const ctx: TestContext = { - sctpStreamParameters : - { - streamId : 12345, - ordered : false, - maxPacketLifeTime : 5000 - }, - label : 'foo', - protocol : 'bar' + dataProducerOptions : utils.deepFreeze( + { + sctpStreamParameters : + { + streamId : 12345, + ordered : false, + maxPacketLifeTime : 5000 + }, + label : 'foo', + protocol : 'bar' + } + ) }; -beforeAll(async () => +beforeEach(async () => { - worker = await mediasoup.createWorker(); - router = await worker.createRouter(); - transport1 = await router.createWebRtcTransport( + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter(); + ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ], enableSctp : true }); - transport2 = await router.createPlainTransport( + ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport( { - listenIp : '127.0.0.1', + listenIps : [ '127.0.0.1' ], enableSctp : true }); - transport3 = await router.createDirectTransport(); - dataProducer = await transport1.produceData(dataProducerParameters); + ctx.directTransport = await ctx.router.createDirectTransport(); + ctx.dataProducer = + await ctx.webRtcTransport1.produceData(ctx.dataProducerOptions); }); -afterAll(() => worker.close()); +afterEach(() => +{ + ctx.worker?.close(); +}); test('transport.consumeData() succeeds', async () => { const onObserverNewDataConsumer = jest.fn(); - transport2.observer.once('newdataconsumer', onObserverNewDataConsumer); + ctx.webRtcTransport2!.observer.once('newdataconsumer', onObserverNewDataConsumer); - dataConsumer1 = await transport2.consumeData( + const dataConsumer1 = await ctx.webRtcTransport2!.consumeData( { - dataProducerId : dataProducer.id, + dataProducerId : ctx.dataProducer!.id, maxPacketLifeTime : 4000, // Valid values are 0...65535 so others and duplicated ones will be // discarded. @@ -60,7 +71,7 @@ test('transport.consumeData() succeeds', async () => expect(onObserverNewDataConsumer).toHaveBeenCalledTimes(1); expect(onObserverNewDataConsumer).toHaveBeenCalledWith(dataConsumer1); expect(typeof dataConsumer1.id).toBe('string'); - expect(dataConsumer1.dataProducerId).toBe(dataProducer.id); + expect(dataConsumer1.dataProducerId).toBe(ctx.dataProducer!.id); expect(dataConsumer1.closed).toBe(false); expect(dataConsumer1.type).toBe('sctp'); expect(typeof dataConsumer1.sctpStreamParameters).toBe('object'); @@ -71,27 +82,28 @@ test('transport.consumeData() succeeds', async () => expect(dataConsumer1.label).toBe('foo'); expect(dataConsumer1.protocol).toBe('bar'); expect(dataConsumer1.paused).toBe(false); - expect(dataConsumer1.subchannels.sort((a, b) => a - b)) - .toEqual([ 0, 1, 2, 100, 65535 ]); + expect(dataConsumer1.subchannels).toEqual( + expect.arrayContaining([ 0, 1, 2, 100, 65535 ]) + ); expect(dataConsumer1.appData).toEqual({ baz: 'LOL' }); - const dump = await router.dump(); + const dump = await ctx.router!.dump(); expect(dump.mapDataProducerIdDataConsumerIds) .toEqual(expect.arrayContaining([ - { key: dataProducer.id, values: [ dataConsumer1.id ] } + { key: ctx.dataProducer!.id, values: [ dataConsumer1.id ] } ])); expect(dump.mapDataConsumerIdDataProducerId) .toEqual(expect.arrayContaining([ - { key: dataConsumer1.id, value: dataProducer.id } + { key: dataConsumer1.id, value: ctx.dataProducer!.id } ])); - await expect(transport2.dump()) + await expect(ctx.webRtcTransport2!.dump()) .resolves .toMatchObject( { - id : transport2.id, + id : ctx.webRtcTransport2!.id, dataProducerIds : [], dataConsumerIds : [ dataConsumer1.id ] }); @@ -99,32 +111,51 @@ test('transport.consumeData() succeeds', async () => test('dataConsumer.dump() succeeds', async () => { - const data = await dataConsumer1.dump(); - - expect(data.id).toBe(dataConsumer1.id); - expect(data.dataProducerId).toBe(dataConsumer1.dataProducerId); - expect(data.type).toBe('sctp'); - expect(typeof data.sctpStreamParameters).toBe('object'); - expect(data.sctpStreamParameters!.streamId) - .toBe(dataConsumer1.sctpStreamParameters?.streamId); - expect(data.sctpStreamParameters!.ordered).toBe(false); - expect(data.sctpStreamParameters!.maxPacketLifeTime).toBe(4000); - expect(data.sctpStreamParameters!.maxRetransmits).toBeUndefined(); - expect(data.label).toBe('foo'); - expect(data.protocol).toBe('bar'); - expect(data.paused).toBe(false); + const dataConsumer = await ctx.webRtcTransport2!.consumeData( + { + dataProducerId : ctx.dataProducer!.id, + maxPacketLifeTime : 4000, + // Valid values are 0...65535 so others and duplicated ones will be + // discarded. + subchannels : [ 0, 1, 1, 1, 2, 65535, 65536, 65537, 100 ], + appData : { baz: 'LOL' } + }); + + const dump = await dataConsumer.dump(); + + expect(dump.id).toBe(dataConsumer.id); + expect(dump.dataProducerId).toBe(dataConsumer.dataProducerId); + expect(dump.type).toBe('sctp'); + expect(typeof dump.sctpStreamParameters).toBe('object'); + expect(dump.sctpStreamParameters!.streamId) + .toBe(dataConsumer.sctpStreamParameters?.streamId); + expect(dump.sctpStreamParameters!.ordered).toBe(false); + expect(dump.sctpStreamParameters!.maxPacketLifeTime).toBe(4000); + expect(dump.sctpStreamParameters!.maxRetransmits).toBeUndefined(); + expect(dump.label).toBe('foo'); + expect(dump.protocol).toBe('bar'); + expect(dump.paused).toBe(false); + expect(dump.dataProducerPaused).toBe(false); + expect(dump.subchannels).toEqual( + expect.arrayContaining([ 0, 1, 2, 100, 65535 ]) + ); }, 2000); test('dataConsumer.getStats() succeeds', async () => { - await expect(dataConsumer1.getStats()) + const dataConsumer = await ctx.webRtcTransport2!.consumeData( + { + dataProducerId : ctx.dataProducer!.id + }); + + await expect(dataConsumer.getStats()) .resolves .toMatchObject( [ { type : 'data-consumer', - label : dataConsumer1.label, - protocol : dataConsumer1.protocol, + label : dataConsumer.label, + protocol : dataConsumer.protocol, messagesSent : 0, bytesSent : 0 } @@ -133,94 +164,119 @@ test('dataConsumer.getStats() succeeds', async () => test('dataConsumer.setSubchannels() succeeds', async () => { - await dataConsumer1.setSubchannels([ 999, 999, 998, 65536 ]); + const dataConsumer = await ctx.webRtcTransport2!.consumeData( + { + dataProducerId : ctx.dataProducer!.id + }); - expect(dataConsumer1.subchannels.sort((a, b) => a - b)) - .toEqual([ 0, 998, 999 ]); + await dataConsumer.setSubchannels([ 999, 999, 998, 65536 ]); + + expect(dataConsumer.subchannels).toEqual( + expect.arrayContaining([ 0, 998, 999 ]) + ); }, 2000); test('dataConsumer.addSubchannel() and .removeSubchannel() succeed', async () => { - await dataConsumer1.setSubchannels([ ]); - expect(dataConsumer1.subchannels).toEqual([ ]); + const dataConsumer = await ctx.webRtcTransport2!.consumeData( + { + dataProducerId : ctx.dataProducer!.id + }); - await dataConsumer1.addSubchannel(5); - expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 5 ]); + await dataConsumer.setSubchannels([]); + expect(dataConsumer.subchannels).toEqual([]); - await dataConsumer1.addSubchannel(10); - expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 5, 10 ]); + await dataConsumer.addSubchannel(5); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 5 ])); - await dataConsumer1.addSubchannel(5); - expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 5, 10 ]); + await dataConsumer.addSubchannel(10); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 5, 10 ])); - await dataConsumer1.removeSubchannel(666); - expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 5, 10 ]); + await dataConsumer.addSubchannel(5); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 5, 10 ])); - await dataConsumer1.removeSubchannel(5); - expect(dataConsumer1.subchannels.sort((a, b) => a - b)).toEqual([ 10 ]); + await dataConsumer.removeSubchannel(666); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 5, 10 ])); - await dataConsumer1.setSubchannels([ ]); - expect(dataConsumer1.subchannels).toEqual([ ]); + await dataConsumer.removeSubchannel(5); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 10 ])); + + await dataConsumer.setSubchannels([]); + expect(dataConsumer.subchannels).toEqual([]); }, 2000); test('transport.consumeData() on a DirectTransport succeeds', async () => { const onObserverNewDataConsumer = jest.fn(); - transport3.observer.once('newdataconsumer', onObserverNewDataConsumer); + ctx.directTransport!.observer.once( + 'newdataconsumer', onObserverNewDataConsumer + ); - dataConsumer2 = await transport3.consumeData( + const dataConsumer = await ctx.directTransport!.consumeData( { - dataProducerId : dataProducer.id, + dataProducerId : ctx.dataProducer!.id, paused : true, appData : { hehe: 'HEHE' } }); expect(onObserverNewDataConsumer).toHaveBeenCalledTimes(1); - expect(onObserverNewDataConsumer).toHaveBeenCalledWith(dataConsumer2); - expect(typeof dataConsumer2.id).toBe('string'); - expect(dataConsumer2.dataProducerId).toBe(dataProducer.id); - expect(dataConsumer2.closed).toBe(false); - expect(dataConsumer2.type).toBe('direct'); - expect(dataConsumer2.sctpStreamParameters).toBeUndefined(); - expect(dataConsumer2.label).toBe('foo'); - expect(dataConsumer2.protocol).toBe('bar'); - expect(dataConsumer2.paused).toBe(true); - expect(dataConsumer2.appData).toEqual({ hehe: 'HEHE' }); - - await expect(transport3.dump()) + expect(onObserverNewDataConsumer).toHaveBeenCalledWith(dataConsumer); + expect(typeof dataConsumer.id).toBe('string'); + expect(dataConsumer.dataProducerId).toBe(ctx.dataProducer!.id); + expect(dataConsumer.closed).toBe(false); + expect(dataConsumer.type).toBe('direct'); + expect(dataConsumer.sctpStreamParameters).toBeUndefined(); + expect(dataConsumer.label).toBe('foo'); + expect(dataConsumer.protocol).toBe('bar'); + expect(dataConsumer.paused).toBe(true); + expect(dataConsumer.appData).toEqual({ hehe: 'HEHE' }); + + await expect(ctx.directTransport!.dump()) .resolves .toMatchObject( { - id : transport3.id, + id : ctx.directTransport!.id, dataProducerIds : [], - dataConsumerIds : [ dataConsumer2.id ] + dataConsumerIds : [ dataConsumer.id ] }); }, 2000); test('dataConsumer.dump() on a DirectTransport succeeds', async () => { - const data = await dataConsumer2.dump(); - - expect(data.id).toBe(dataConsumer2.id); - expect(data.dataProducerId).toBe(dataConsumer2.dataProducerId); - expect(data.type).toBe('direct'); - expect(data.sctpStreamParameters).toBeUndefined(); - expect(data.label).toBe('foo'); - expect(data.protocol).toBe('bar'); - expect(data.paused).toBe(true); + const dataConsumer = await ctx.directTransport!.consumeData( + { + dataProducerId : ctx.dataProducer!.id, + paused : true + }); + + const dump = await dataConsumer.dump(); + + expect(dump.id).toBe(dataConsumer.id); + expect(dump.dataProducerId).toBe(dataConsumer.dataProducerId); + expect(dump.type).toBe('direct'); + expect(dump.sctpStreamParameters).toBeUndefined(); + expect(dump.label).toBe('foo'); + expect(dump.protocol).toBe('bar'); + expect(dump.paused).toBe(true); + expect(dump.subchannels).toEqual([]); }, 2000); test('dataConsumer.getStats() on a DirectTransport succeeds', async () => { - await expect(dataConsumer2.getStats()) + const dataConsumer = await ctx.directTransport!.consumeData( + { + dataProducerId : ctx.dataProducer!.id + }); + + await expect(dataConsumer.getStats()) .resolves .toMatchObject( [ { type : 'data-consumer', - label : dataConsumer2.label, - protocol : dataConsumer2.protocol, + label : dataConsumer.label, + protocol : dataConsumer.protocol, messagesSent : 0, bytesSent : 0 } @@ -232,35 +288,38 @@ test('dataConsumer.pause() and resume() succeed', async () => const onObserverPause = jest.fn(); const onObserverResume = jest.fn(); - dataConsumer1.observer.on('pause', onObserverPause); - dataConsumer1.observer.on('resume', onObserverResume); + const dataConsumer = await ctx.webRtcTransport2!.consumeData( + { + dataProducerId : ctx.dataProducer!.id + }); - let data; + dataConsumer.observer.on('pause', onObserverPause); + dataConsumer.observer.on('resume', onObserverResume); - await dataConsumer1.pause(); + await dataConsumer.pause(); - expect(dataConsumer1.paused).toBe(true); + expect(dataConsumer.paused).toBe(true); - data = await dataConsumer1.dump(); + const dump1 = await dataConsumer.dump(); - expect(data.paused).toBe(true); + expect(dump1.paused).toBe(true); - await dataConsumer1.resume(); + await dataConsumer.resume(); - expect(dataConsumer1.paused).toBe(false); + expect(dataConsumer.paused).toBe(false); - data = await dataConsumer1.dump(); + const dump2 = await dataConsumer.dump(); - expect(data.paused).toBe(false); + expect(dump2.paused).toBe(false); // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. - dataConsumer1.pause(); - dataConsumer1.resume(); - dataConsumer1.pause(); - dataConsumer1.pause(); - dataConsumer1.pause(); - await dataConsumer1.resume(); + dataConsumer.pause(); + dataConsumer.resume(); + dataConsumer.pause(); + dataConsumer.pause(); + dataConsumer.pause(); + await dataConsumer.resume(); expect(onObserverPause).toHaveBeenCalledTimes(3); expect(onObserverResume).toHaveBeenCalledTimes(3); @@ -268,58 +327,63 @@ test('dataConsumer.pause() and resume() succeed', async () => test('dataProducer.pause() and resume() emit events', async () => { + const dataConsumer = await ctx.webRtcTransport2!.consumeData( + { + dataProducerId : ctx.dataProducer!.id + }); const promises = []; const events: string[] = []; - - dataConsumer1.observer.once('resume', () => + + dataConsumer.observer.once('resume', () => { events.push('resume'); }); - dataConsumer1.observer.once('pause', () => + dataConsumer.observer.once('pause', () => { events.push('pause'); }); - promises.push(dataProducer.pause()); - promises.push(dataProducer.resume()); + promises.push(ctx.dataProducer!.pause()); + promises.push(ctx.dataProducer!.resume()); await Promise.all(promises); // Must also wait a bit for the corresponding events in the data consumer. await new Promise((resolve) => setTimeout(resolve, 100)); - + expect(events).toEqual([ 'pause', 'resume' ]); - expect(dataConsumer1.paused).toBe(false); + expect(dataConsumer.paused).toBe(false); }, 2000); test('dataConsumer.close() succeeds', async () => { const onObserverClose = jest.fn(); + const dataConsumer = await ctx.webRtcTransport2!.consumeData( + { + dataProducerId : ctx.dataProducer!.id + }); - dataConsumer1.observer.once('close', onObserverClose); - dataConsumer1.close(); + dataConsumer.observer.once('close', onObserverClose); + dataConsumer.close(); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(dataConsumer1.closed).toBe(true); + expect(dataConsumer.closed).toBe(true); - const dump = await router.dump(); + const dump = await ctx.router!.dump(); expect(dump.mapDataProducerIdDataConsumerIds) .toEqual(expect.arrayContaining([ - { key: dataProducer.id, values: [ dataConsumer2.id ] } + { key: ctx.dataProducer!.id, values: [] } ])); - expect(dump.mapDataConsumerIdDataProducerId) - .toEqual(expect.arrayContaining([ - { key: dataConsumer2.id, value: dataProducer.id } - ])); + expect(dump.mapDataConsumerIdDataProducerId).toEqual([]); - await expect(transport2.dump()) + await expect(ctx.webRtcTransport2!.dump()) .resolves .toMatchObject( { - id : transport2.id, + id : ctx.webRtcTransport2!.id, dataProducerIds : [], dataConsumerIds : [] }); @@ -327,58 +391,64 @@ test('dataConsumer.close() succeeds', async () => test('Consumer methods reject if closed', async () => { - await expect(dataConsumer1.dump()) + const dataConsumer = await ctx.webRtcTransport2!.consumeData( + { + dataProducerId : ctx.dataProducer!.id + }); + + dataConsumer.close(); + + await expect(dataConsumer.dump()) .rejects .toThrow(Error); - await expect(dataConsumer1.getStats()) + await expect(dataConsumer.getStats()) .rejects .toThrow(Error); }, 2000); test('DataConsumer emits "dataproducerclose" if DataProducer is closed', async () => { - dataConsumer1 = await transport2.consumeData( + const dataConsumer = await ctx.webRtcTransport2!.consumeData( { - dataProducerId : dataProducer.id + dataProducerId : ctx.dataProducer!.id }); - const onObserverClose = jest.fn(); - dataConsumer1.observer.once('close', onObserverClose); + dataConsumer.observer.once('close', onObserverClose); await new Promise((resolve) => { - dataConsumer1.on('dataproducerclose', resolve); - dataProducer.close(); + dataConsumer.on('dataproducerclose', resolve); + + ctx.dataProducer!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(dataConsumer1.closed).toBe(true); + expect(dataConsumer.closed).toBe(true); }, 2000); test('DataConsumer emits "transportclose" if Transport is closed', async () => { - dataProducer = await transport1.produceData(dataProducerParameters); - dataConsumer1 = await transport2.consumeData( + const dataConsumer = await ctx.webRtcTransport2!.consumeData( { - dataProducerId : dataProducer.id + dataProducerId : ctx.dataProducer!.id }); - const onObserverClose = jest.fn(); - dataConsumer1.observer.once('close', onObserverClose); + dataConsumer.observer.once('close', onObserverClose); await new Promise((resolve) => { - dataConsumer1.on('transportclose', resolve); - transport2.close(); + dataConsumer.on('transportclose', resolve); + + ctx.webRtcTransport2!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(dataConsumer1.closed).toBe(true); + expect(dataConsumer.closed).toBe(true); - await expect(router.dump()) + await expect(ctx.router!.dump()) .resolves .toMatchObject( { diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index e6fff2b37f..54dcbc734e 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -3,17 +3,17 @@ import * as utils from '../utils'; type TestContext = { - dataProducerParameters1: mediasoup.types.DataProducerOptions; - dataProducerParameters2: mediasoup.types.DataProducerOptions; + dataProducerOptions1: mediasoup.types.DataProducerOptions; + dataProducerOptions2: mediasoup.types.DataProducerOptions; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; - transport1?: mediasoup.types.WebRtcTransport; - transport2?: mediasoup.types.WebRtcTransport; + webRtcTransport1?: mediasoup.types.WebRtcTransport; + webRtcTransport2?: mediasoup.types.WebRtcTransport; }; const ctx: TestContext = { - dataProducerParameters1 : utils.deepFreeze( + dataProducerOptions1 : utils.deepFreeze( { sctpStreamParameters : { @@ -24,7 +24,7 @@ const ctx: TestContext = appData : { foo: 1, bar: '2' } } ), - dataProducerParameters2 : utils.deepFreeze( + dataProducerOptions2 : utils.deepFreeze( { sctpStreamParameters : { @@ -43,12 +43,12 @@ beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter(); - ctx.transport1 = await ctx.router.createWebRtcTransport( + ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ], enableSctp : true }); - ctx.transport2 = await ctx.router.createWebRtcTransport( + ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ], enableSctp : true @@ -60,14 +60,17 @@ afterEach(() => ctx.worker?.close(); }); -test('transport1.produceData() succeeds', async () => +test('webRtcTransport1.produceData() succeeds', async () => { const onObserverNewDataProducer = jest.fn(); - ctx.transport1!.observer.once('newdataproducer', onObserverNewDataProducer); + ctx.webRtcTransport1!.observer.once( + 'newdataproducer', onObserverNewDataProducer + ); - const dataProducer1 = - await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const dataProducer1 = await ctx.webRtcTransport1!.produceData( + ctx.dataProducerOptions1 + ); expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); expect(onObserverNewDataProducer).toHaveBeenCalledWith(dataProducer1); @@ -93,24 +96,27 @@ test('transport1.produceData() succeeds', async () => expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); - await expect(ctx.transport1!.dump()) + await expect(ctx.webRtcTransport1!.dump()) .resolves .toMatchObject( { - id : ctx.transport1!.id, + id : ctx.webRtcTransport1!.id, dataProducerIds : [ dataProducer1.id ], dataConsumerIds : [] }); }, 2000); -test('transport2.produceData() succeeds', async () => +test('webRtcTransport2.produceData() succeeds', async () => { const onObserverNewDataProducer = jest.fn(); - ctx.transport2!.observer.once('newdataproducer', onObserverNewDataProducer); + ctx.webRtcTransport2!.observer.once( + 'newdataproducer', onObserverNewDataProducer + ); - const dataProducer2 = - await ctx.transport2!.produceData(ctx.dataProducerParameters2); + const dataProducer2 = await ctx.webRtcTransport2!.produceData( + ctx.dataProducerOptions2 + ); expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); expect(onObserverNewDataProducer).toHaveBeenCalledWith(dataProducer2); @@ -136,24 +142,24 @@ test('transport2.produceData() succeeds', async () => expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); - await expect(ctx.transport2!.dump()) + await expect(ctx.webRtcTransport2!.dump()) .resolves .toMatchObject( { - id : ctx.transport2!.id, + id : ctx.webRtcTransport2!.id, dataProducerIds : [ dataProducer2.id ], dataConsumerIds : [] }); }, 2000); -test('transport1.produceData() with wrong arguments rejects with TypeError', async () => +test('webRtcTransport1.produceData() with wrong arguments rejects with TypeError', async () => { - await expect(ctx.transport1!.produceData({})) + await expect(ctx.webRtcTransport1!.produceData({})) .rejects .toThrow(TypeError); // Missing or empty sctpStreamParameters.streamId. - await expect(ctx.transport1!.produceData( + await expect(ctx.webRtcTransport1!.produceData( { // @ts-ignore sctpStreamParameters : { foo: 'foo' } @@ -164,9 +170,9 @@ test('transport1.produceData() with wrong arguments rejects with TypeError', asy test('transport.produceData() with already used streamId rejects with Error', async () => { - await ctx.transport1!.produceData(ctx.dataProducerParameters1); + await ctx.webRtcTransport1!.produceData(ctx.dataProducerOptions1); - await expect(ctx.transport1!.produceData( + await expect(ctx.webRtcTransport1!.produceData( { sctpStreamParameters : { @@ -179,7 +185,7 @@ test('transport.produceData() with already used streamId rejects with Error', as test('transport.produceData() with ordered and maxPacketLifeTime rejects with TypeError', async () => { - await expect(ctx.transport1!.produceData( + await expect(ctx.webRtcTransport1!.produceData( { sctpStreamParameters : { @@ -194,8 +200,9 @@ test('transport.produceData() with ordered and maxPacketLifeTime rejects with Ty test('dataProducer.dump() succeeds', async () => { - const dataProducer1 = - await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const dataProducer1 = await ctx.webRtcTransport1!.produceData( + ctx.dataProducerOptions1 + ); const dump1 = await dataProducer1.dump(); @@ -210,8 +217,9 @@ test('dataProducer.dump() succeeds', async () => expect(dump1.protocol).toBe('bar'); expect(dump1.paused).toBe(false); - const dataProducer2 = - await ctx.transport2!.produceData(ctx.dataProducerParameters2); + const dataProducer2 = await ctx.webRtcTransport2!.produceData( + ctx.dataProducerOptions2 + ); const dump2 = await dataProducer2.dump(); @@ -229,8 +237,9 @@ test('dataProducer.dump() succeeds', async () => test('dataProducer.getStats() succeeds', async () => { - const dataProducer1 = - await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const dataProducer1 = await ctx.webRtcTransport1!.produceData( + ctx.dataProducerOptions1 + ); await expect(dataProducer1.getStats()) .resolves @@ -245,8 +254,9 @@ test('dataProducer.getStats() succeeds', async () => } ]); - const dataProducer2 = - await ctx.transport2!.produceData(ctx.dataProducerParameters2); + const dataProducer2 = await ctx.webRtcTransport2!.produceData( + ctx.dataProducerOptions2 + ); await expect(dataProducer2.getStats()) .resolves @@ -264,8 +274,9 @@ test('dataProducer.getStats() succeeds', async () => test('dataProducer.pause() and resume() succeed', async () => { - const dataProducer1 = - await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const dataProducer1 = await ctx.webRtcTransport1!.produceData( + ctx.dataProducerOptions1 + ); const onObserverPause = jest.fn(); const onObserverResume = jest.fn(); @@ -304,8 +315,9 @@ test('dataProducer.pause() and resume() succeed', async () => test('producer.pause() and resume() emit events', async () => { - const dataProducer1 = - await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const dataProducer1 = await ctx.webRtcTransport1!.produceData( + ctx.dataProducerOptions1 + ); const promises = []; const events: string[] = []; @@ -331,8 +343,9 @@ test('producer.pause() and resume() emit events', async () => test('dataProducer.close() succeeds', async () => { - const dataProducer1 = - await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const dataProducer1 = await ctx.webRtcTransport1!.produceData( + ctx.dataProducerOptions1 + ); const onObserverClose = jest.fn(); @@ -350,11 +363,11 @@ test('dataProducer.close() succeeds', async () => mapDataConsumerIdDataProducerId : {} }); - await expect(ctx.transport1!.dump()) + await expect(ctx.webRtcTransport1!.dump()) .resolves .toMatchObject( { - id : ctx.transport1!.id, + id : ctx.webRtcTransport1!.id, dataProducerIds : [], dataConsumerIds : [] }); @@ -362,8 +375,9 @@ test('dataProducer.close() succeeds', async () => test('DataProducer methods reject if closed', async () => { - const dataProducer1 = - await ctx.transport1!.produceData(ctx.dataProducerParameters1); + const dataProducer1 = await ctx.webRtcTransport1!.produceData( + ctx.dataProducerOptions1 + ); dataProducer1.close(); @@ -378,8 +392,9 @@ test('DataProducer methods reject if closed', async () => test('DataProducer emits "transportclose" if Transport is closed', async () => { - const dataProducer2 = - await ctx.transport2!.produceData(ctx.dataProducerParameters2); + const dataProducer2 = await ctx.webRtcTransport2!.produceData( + ctx.dataProducerOptions2 + ); const onObserverClose = jest.fn(); @@ -388,7 +403,8 @@ test('DataProducer emits "transportclose" if Transport is closed', async () => await new Promise((resolve) => { dataProducer2.on('transportclose', resolve); - ctx.transport2!.close(); + + ctx.webRtcTransport2!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index d4324b212a..60608b7e95 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -1,116 +1,119 @@ import * as mediasoup from '../'; -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let transport: mediasoup.types.DirectTransport; - -beforeAll(async () => +type TestContext = { - worker = await mediasoup.createWorker(); - router = await worker.createRouter(); -}); + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; +}; -afterAll(() => worker.close()); +const ctx: TestContext = {}; beforeEach(async () => { - transport = await router.createDirectTransport(); + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter(); }); -afterEach(() => transport.close()); +afterEach(() => +{ + ctx.worker?.close(); +}); test('router.createDirectTransport() succeeds', async () => { - await expect(router.dump()) - .resolves - .toMatchObject({ transportIds: [ transport.id ] }); - const onObserverNewTransport = jest.fn(); - router.observer.once('newtransport', onObserverNewTransport); + ctx.router!.observer.once('newtransport', onObserverNewTransport); - // Create a separate transport here. - const transport1 = await router.createDirectTransport( + const directTransport = await ctx.router!.createDirectTransport( { maxMessageSize : 1024, appData : { foo: 'bar' } }); + await expect(ctx.router!.dump()) + .resolves + .toMatchObject({ transportIds: [ directTransport.id ] }); + expect(onObserverNewTransport).toHaveBeenCalledTimes(1); - expect(onObserverNewTransport).toHaveBeenCalledWith(transport1); - expect(typeof transport1.id).toBe('string'); - expect(transport1.closed).toBe(false); - expect(transport1.appData).toEqual({ foo: 'bar' }); - - const data1 = await transport1.dump(); - - expect(data1.id).toBe(transport1.id); - expect(data1.direct).toBe(true); - expect(data1.producerIds).toEqual([]); - expect(data1.consumerIds).toEqual([]); - expect(data1.dataProducerIds).toEqual([]); - expect(data1.dataConsumerIds).toEqual([]); - expect(data1.recvRtpHeaderExtensions).toBeDefined(); - expect(typeof data1.rtpListener).toBe('object'); - - transport1.close(); - expect(transport1.closed).toBe(true); + expect(onObserverNewTransport).toHaveBeenCalledWith(directTransport); + expect(typeof directTransport.id).toBe('string'); + expect(directTransport.closed).toBe(false); + expect(directTransport.appData).toEqual({ foo: 'bar' }); + + const dump = await directTransport.dump(); + + expect(dump.id).toBe(directTransport.id); + expect(dump.direct).toBe(true); + expect(dump.producerIds).toEqual([]); + expect(dump.consumerIds).toEqual([]); + expect(dump.dataProducerIds).toEqual([]); + expect(dump.dataConsumerIds).toEqual([]); + expect(dump.recvRtpHeaderExtensions).toBeDefined(); + expect(typeof dump.rtpListener).toBe('object'); + + directTransport.close(); + expect(directTransport.closed).toBe(true); }, 2000); test('router.createDirectTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore - await expect(router.createDirectTransport({ maxMessageSize: 'foo' })) + await expect(ctx.router!.createDirectTransport({ maxMessageSize: 'foo' })) .rejects .toThrow(TypeError); - await expect(router.createDirectTransport({ maxMessageSize: -2000 })) + await expect(ctx.router!.createDirectTransport({ maxMessageSize: -2000 })) .rejects .toThrow(TypeError); }, 2000); test('directTransport.getStats() succeeds', async () => { - const data = await transport.getStats(); - - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBe(1); - expect(data[0].type).toBe('direct-transport'); - expect(data[0].transportId).toBe(transport.id); - expect(typeof data[0].timestamp).toBe('number'); - expect(data[0].bytesReceived).toBe(0); - expect(data[0].recvBitrate).toBe(0); - expect(data[0].bytesSent).toBe(0); - expect(data[0].sendBitrate).toBe(0); - expect(data[0].rtpBytesReceived).toBe(0); - expect(data[0].rtpRecvBitrate).toBe(0); - expect(data[0].rtpBytesSent).toBe(0); - expect(data[0].rtpSendBitrate).toBe(0); - expect(data[0].rtxBytesReceived).toBe(0); - expect(data[0].rtxRecvBitrate).toBe(0); - expect(data[0].rtxBytesSent).toBe(0); - expect(data[0].rtxSendBitrate).toBe(0); - expect(data[0].probationBytesSent).toBe(0); - expect(data[0].probationSendBitrate).toBe(0); + const directTransport = await ctx.router!.createDirectTransport(); + + const stats = await directTransport.getStats(); + + expect(Array.isArray(stats)).toBe(true); + expect(stats.length).toBe(1); + expect(stats[0].type).toBe('direct-transport'); + expect(stats[0].transportId).toBe(directTransport.id); + expect(typeof stats[0].timestamp).toBe('number'); + expect(stats[0].bytesReceived).toBe(0); + expect(stats[0].recvBitrate).toBe(0); + expect(stats[0].bytesSent).toBe(0); + expect(stats[0].sendBitrate).toBe(0); + expect(stats[0].rtpBytesReceived).toBe(0); + expect(stats[0].rtpRecvBitrate).toBe(0); + expect(stats[0].rtpBytesSent).toBe(0); + expect(stats[0].rtpSendBitrate).toBe(0); + expect(stats[0].rtxBytesReceived).toBe(0); + expect(stats[0].rtxRecvBitrate).toBe(0); + expect(stats[0].rtxBytesSent).toBe(0); + expect(stats[0].rtxSendBitrate).toBe(0); + expect(stats[0].probationBytesSent).toBe(0); + expect(stats[0].probationSendBitrate).toBe(0); }, 2000); test('directTransport.connect() succeeds', async () => { - await expect(transport.connect()) + const directTransport = await ctx.router!.createDirectTransport(); + + await expect(directTransport.connect()) .resolves .toBeUndefined(); }, 2000); test('dataProducer.send() succeeds', async () => { - const transport2 = await router.createDirectTransport(); - const dataProducer = await transport2.produceData( + const directTransport = await ctx.router!.createDirectTransport(); + const dataProducer = await directTransport.produceData( { label : 'foo', protocol : 'bar', appData : { foo: 'bar' } }); - const dataConsumer = await transport2.consumeData( + const dataConsumer = await directTransport.consumeData( { dataProducerId : dataProducer.id }); @@ -135,16 +138,16 @@ test('dataProducer.send() succeeds', async () => { dataProducer.on('listenererror', (eventName, error) => { - reject( - new Error(`dataProducer 'listenererror' [eventName:${eventName}]: ${error}`) - ); + reject(new Error( + `dataProducer 'listenererror' [eventName:${eventName}]: ${error}` + )); }); dataConsumer.on('listenererror', (eventName, error) => { - reject( - new Error(`dataConsumer 'listenererror' [eventName:${eventName}]: ${error}`) - ); + reject(new Error( + `dataConsumer 'listenererror' [eventName:${eventName}]: ${error}` + )); }); sendNextMessage(); @@ -152,8 +155,7 @@ test('dataProducer.send() succeeds', async () => async function sendNextMessage(): Promise { const id = ++numSentMessages; - let ppid; - let message; + let message: Buffer | string; if (id === pauseSendingAtMessage) { @@ -183,7 +185,7 @@ test('dataProducer.send() succeeds', async () => message = Buffer.from(String(id)); } - dataProducer.send(message, ppid); + dataProducer.send(message); const messageSize = Buffer.from(message).byteLength; @@ -216,16 +218,16 @@ test('dataProducer.send() succeeds', async () => // PPID of WebRTC DataChannel string. else if (id < numMessages / 2 && ppid !== 51) { - reject( - new Error(`ppid in message with id ${id} should be 51 but it is ${ppid}`) - ); + reject(new Error( + `ppid in message with id ${id} should be 51 but it is ${ppid}` + )); } // PPID of WebRTC DataChannel binary. else if (id > numMessages / 2 && ppid !== 53) { - reject( - new Error(`ppid in message with id ${id} should be 53 but it is ${ppid}`) - ); + reject(new Error( + `ppid in message with id ${id} should be 53 but it is ${ppid}` + )); } }); }); @@ -263,14 +265,14 @@ test('dataProducer.send() succeeds', async () => test('dataProducer.send() with subchannels succeeds', async () => { - const transport2 = await router.createDirectTransport(); - const dataProducer = await transport2.produceData(); - const dataConsumer1 = await transport2.consumeData( + const directTransport = await ctx.router!.createDirectTransport(); + const dataProducer = await directTransport.produceData(); + const dataConsumer1 = await directTransport.consumeData( { dataProducerId : dataProducer.id, subchannels : [ 1, 11, 666 ] }); - const dataConsumer2 = await transport2.consumeData( + const dataConsumer2 = await directTransport.consumeData( { dataProducerId : dataProducer.id, subchannels : [ 2, 22, 666 ] @@ -412,54 +414,56 @@ test('dataProducer.send() with subchannels succeeds', async () => test('DirectTransport methods reject if closed', async () => { + const directTransport = await ctx.router!.createDirectTransport(); const onObserverClose = jest.fn(); - transport.observer.once('close', onObserverClose); - transport.close(); + directTransport.observer.once('close', onObserverClose); + directTransport.close(); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(transport.closed).toBe(true); + expect(directTransport.closed).toBe(true); - await expect(transport.dump()) + await expect(directTransport.dump()) .rejects .toThrow(Error); - await expect(transport.getStats()) + await expect(directTransport.getStats()) .rejects .toThrow(Error); }, 2000); test('DirectTransport emits "routerclose" if Router is closed', async () => { - // We need different Router and DirectTransport instances here. - const router2 = await worker.createRouter(); - const transport2 = await router2.createDirectTransport(); + const directTransport = await ctx.router!.createDirectTransport(); const onObserverClose = jest.fn(); - transport2.observer.once('close', onObserverClose); + directTransport.observer.once('close', onObserverClose); await new Promise((resolve) => { - transport2.on('routerclose', resolve); - router2.close(); + directTransport.on('routerclose', resolve); + + ctx.router!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(transport2.closed).toBe(true); + expect(directTransport.closed).toBe(true); }, 2000); test('DirectTransport emits "routerclose" if Worker is closed', async () => { + const directTransport = await ctx.router!.createDirectTransport(); const onObserverClose = jest.fn(); - transport.observer.once('close', onObserverClose); + directTransport.observer.once('close', onObserverClose); await new Promise((resolve) => { - transport.on('routerclose', resolve); - worker.close(); + directTransport.on('routerclose', resolve); + + ctx.worker!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(transport.closed).toBe(true); + expect(directTransport.closed).toBe(true); }, 2000); diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index af8dc9d06a..fa92483e01 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -1,247 +1,266 @@ // @ts-ignore import * as pickPort from 'pick-port'; import * as mediasoup from '../'; +import * as utils from '../utils'; -let worker1: mediasoup.types.Worker; -let worker2: mediasoup.types.Worker; -let router1: mediasoup.types.Router; -let router2: mediasoup.types.Router; -let transport1: mediasoup.types.WebRtcTransport; -let audioProducer: mediasoup.types.Producer; -let videoProducer: mediasoup.types.Producer; -let transport2: mediasoup.types.WebRtcTransport; -let videoConsumer: mediasoup.types.Consumer; -let dataProducer: mediasoup.types.DataProducer; -let dataConsumer: mediasoup.types.DataConsumer; - -const mediaCodecs: mediasoup.types.RtpCodecCapability[] = -[ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2 - }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 - } -]; +type TestContext = +{ + mediaCodecs: mediasoup.types.RtpCodecCapability[]; + audioProducerOptions: mediasoup.types.ProducerOptions; + videoProducerOptions: mediasoup.types.ProducerOptions; + dataProducerOptions: mediasoup.types.DataProducerOptions; + consumerDeviceCapabilities: mediasoup.types.RtpCapabilities; + worker1?: mediasoup.types.Worker; + worker2?: mediasoup.types.Worker; + router1?: mediasoup.types.Router; + router2?: mediasoup.types.Router; + webRtcTransport1?: mediasoup.types.WebRtcTransport; + webRtcTransport2?: mediasoup.types.WebRtcTransport; + audioProducer?: mediasoup.types.Producer; + videoProducer?: mediasoup.types.Producer; + videoConsumer?: mediasoup.types.Consumer; + dataProducer?: mediasoup.types.DataProducer; + dataConsumer?: mediasoup.types.DataConsumer; +}; -const audioProducerParameters: mediasoup.types.ProducerOptions = +const ctx: TestContext = { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : + mediaCodecs : utils.deepFreeze( [ { - mimeType : 'audio/opus', - payloadType : 111, - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar1' - } - } - ], - headerExtensions : - [ + kind : 'audio', + mimeType : 'audio/opus', + clockRate : 48000, + channels : 2 + }, { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 + kind : 'video', + mimeType : 'video/VP8', + clockRate : 90000 } - ], - encodings : [ { ssrc: 11111111 } ], - rtcp : + ] + ), + audioProducerOptions : utils.deepFreeze( { - cname : 'FOOBAR' - } - }, - appData : { foo: 'bar1' } -}; - -const videoProducerParameters: mediasoup.types.ProducerOptions = -{ - kind : 'video', - rtpParameters : - { - mid : 'VIDEO', - codecs : - [ + kind : 'audio', + rtpParameters : { - mimeType : 'video/VP8', - payloadType : 112, - clockRate : 90000, - rtcpFeedback : + mid : 'AUDIO', + codecs : [ - { type: 'nack' }, - { type: 'nack', parameter: 'pli' }, - { type: 'goog-remb' }, - { type: 'lalala' } - ] - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 + { + mimeType : 'audio/opus', + payloadType : 111, + clockRate : 48000, + channels : 2, + parameters : + { + useinbandfec : 1, + foo : 'bar1' + } + } + ], + headerExtensions : + [ + { + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + id : 10 + } + ], + encodings : [ { ssrc: 11111111 } ], + rtcp : + { + cname : 'FOOBAR' + } }, + appData : { foo: 'bar1' } + } + ), + videoProducerOptions : utils.deepFreeze( + { + kind : 'video', + rtpParameters : { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - id : 11 + mid : 'VIDEO', + codecs : + [ + { + mimeType : 'video/VP8', + payloadType : 112, + clockRate : 90000, + rtcpFeedback : + [ + { type: 'nack' }, + { type: 'nack', parameter: 'pli' }, + { type: 'goog-remb' }, + { type: 'lalala' } + ] + } + ], + headerExtensions : + [ + { + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + id : 10 + }, + { + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + id : 11 + }, + { + uri : 'urn:3gpp:video-orientation', + id : 13 + } + ], + encodings : + [ + { ssrc: 22222222 }, + { ssrc: 22222223 }, + { ssrc: 22222224 } + ], + rtcp : + { + cname : 'FOOBAR' + } }, - { - uri : 'urn:3gpp:video-orientation', - id : 13 - } - ], - encodings : - [ - { ssrc: 22222222 }, - { ssrc: 22222223 }, - { ssrc: 22222224 } - ], - rtcp : - { - cname : 'FOOBAR' + appData : { foo: 'bar2' } } - }, - appData : { foo: 'bar2' } -}; - -const dataProducerParameters: mediasoup.types.DataProducerOptions = -{ - sctpStreamParameters : - { - streamId : 666, - ordered : false, - maxPacketLifeTime : 5000 - }, - label : 'foo', - protocol : 'bar' -}; - -const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = -{ - codecs : - [ + ), + dataProducerOptions : utils.deepFreeze( { - kind : 'audio', - mimeType : 'audio/opus', - preferredPayloadType : 100, - clockRate : 48000, - channels : 2 - }, - { - kind : 'video', - mimeType : 'video/VP8', - preferredPayloadType : 101, - clockRate : 90000, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'transport-cc' } - ] - }, - { - kind : 'video', - mimeType : 'video/rtx', - preferredPayloadType : 102, - clockRate : 90000, - parameters : + sctpStreamParameters : { - apt : 101 + streamId : 666, + ordered : false, + maxPacketLifeTime : 5000 }, - rtcpFeedback : [] + label : 'foo', + protocol : 'bar' } - ], - headerExtensions : - [ - { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId : 4, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'video', - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - preferredId : 5, - preferredEncrypt : false - }, + ), + consumerDeviceCapabilities : utils.deepFreeze( { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 10, - preferredEncrypt : false + codecs : + [ + { + kind : 'audio', + mimeType : 'audio/opus', + preferredPayloadType : 100, + clockRate : 48000, + channels : 2 + }, + { + kind : 'video', + mimeType : 'video/VP8', + preferredPayloadType : 101, + clockRate : 90000, + rtcpFeedback : + [ + { type: 'nack' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'transport-cc' } + ] + }, + { + kind : 'video', + mimeType : 'video/rtx', + preferredPayloadType : 102, + clockRate : 90000, + parameters : + { + apt : 101 + }, + rtcpFeedback : [] + } + ], + headerExtensions : + [ + { + kind : 'video', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + preferredId : 4, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'video', + uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + preferredId : 5, + preferredEncrypt : false + }, + { + kind : 'audio', + uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId : 10, + preferredEncrypt : false + } + ] } - ] + ) }; -beforeAll(async () => +beforeEach(async () => { - worker1 = await mediasoup.createWorker(); - worker2 = await mediasoup.createWorker(); - router1 = await worker1.createRouter({ mediaCodecs }); - router2 = await worker2.createRouter({ mediaCodecs }); - transport1 = await router1.createWebRtcTransport( + ctx.worker1 = await mediasoup.createWorker(); + ctx.worker2 = await mediasoup.createWorker(); + ctx.router1 = await ctx.worker1.createRouter( + { mediaCodecs: ctx.mediaCodecs } + ); + ctx.router2 = await ctx.worker2.createRouter( + { mediaCodecs: ctx.mediaCodecs } + ); + ctx.webRtcTransport1 = await ctx.router1.createWebRtcTransport( { listenInfos : [ { protocol: 'udp', ip: '127.0.0.1' } ], enableSctp : true }); - transport2 = await router2.createWebRtcTransport( + ctx.webRtcTransport2 = await ctx.router2.createWebRtcTransport( { listenIps : [ '127.0.0.1' ], enableSctp : true }); - audioProducer = await transport1.produce(audioProducerParameters); - videoProducer = await transport1.produce(videoProducerParameters); - dataProducer = await transport1.produceData(dataProducerParameters); - - // Pause the videoProducer. - await videoProducer.pause(); + ctx.audioProducer = await ctx.webRtcTransport1.produce( + ctx.audioProducerOptions + ); + ctx.videoProducer = await ctx.webRtcTransport1.produce( + ctx.videoProducerOptions + ); + ctx.dataProducer = await ctx.webRtcTransport1.produceData( + ctx.dataProducerOptions + ); }); -afterAll(() => +afterEach(() => { - worker1.close(); - worker2.close(); + ctx.worker1?.close(); + ctx.worker2?.close(); }); test('router.pipeToRouter() succeeds with audio', async () => { - let dump; - - const { pipeConsumer, pipeProducer } = await router1.pipeToRouter( + const { pipeConsumer, pipeProducer } = await ctx.router1!.pipeToRouter( + { + producerId : ctx.audioProducer!.id, + router : ctx.router2! + }) as { - producerId : audioProducer.id, - router : router2 - }) as { pipeConsumer: mediasoup.types.Consumer; pipeProducer: mediasoup.types.Producer; }; - dump = await router1.dump(); + const dump1 = await ctx.router1!.dump(); // There should be two Transports in router1: // - WebRtcTransport for audioProducer and videoProducer. // - PipeTransport between router1 and router2. - expect(dump.transportIds.length).toBe(2); + expect(dump1.transportIds.length).toBe(2); - dump = await router2.dump(); + const dump2 = await ctx.router2!.dump(); // There should be two Transports in router2: // - WebRtcTransport for audioConsumer and videoConsumer. // - PipeTransport between router2 and router1. - expect(dump.transportIds.length).toBe(2); + expect(dump2.transportIds.length).toBe(2); expect(typeof pipeConsumer.id).toBe('string'); expect(pipeConsumer.closed).toBe(false); @@ -286,7 +305,7 @@ test('router.pipeToRouter() succeeds with audio', async () => { score: 10, producerScore: 10, producerScores: [] }); expect(pipeConsumer.appData).toEqual({}); - expect(pipeProducer.id).toBe(audioProducer.id); + expect(pipeProducer.id).toBe(ctx.audioProducer!.id); expect(pipeProducer.closed).toBe(false); expect(pipeProducer.kind).toBe('audio'); expect(typeof pipeProducer.rtpParameters).toBe('object'); @@ -326,26 +345,27 @@ test('router.pipeToRouter() succeeds with audio', async () => test('router.pipeToRouter() succeeds with video', async () => { - let dump; + await ctx.videoProducer!.pause(); - const { pipeConsumer, pipeProducer } = await router1.pipeToRouter( + const { pipeConsumer, pipeProducer } = await ctx.router1!.pipeToRouter( + { + producerId : ctx.videoProducer!.id, + router : ctx.router2! + }) as { - producerId : videoProducer.id, - router : router2 - }) as { pipeConsumer: mediasoup.types.Consumer; pipeProducer: mediasoup.types.Producer; }; - dump = await router1.dump(); + const dump1 = await ctx.router1!.dump(); // No new PipeTransport should has been created. The existing one is used. - expect(dump.transportIds.length).toBe(2); + expect(dump1.transportIds.length).toBe(2); - dump = await router2.dump(); + const dump2 = await ctx.router2!.dump(); // No new PipeTransport should has been created. The existing one is used. - expect(dump.transportIds.length).toBe(2); + expect(dump2.transportIds.length).toBe(2); expect(typeof pipeConsumer.id).toBe('string'); expect(pipeConsumer.closed).toBe(false); @@ -408,7 +428,7 @@ test('router.pipeToRouter() succeeds with video', async () => { score: 10, producerScore: 10, producerScores: [] }); expect(pipeConsumer.appData).toEqual({}); - expect(pipeProducer.id).toBe(videoProducer.id); + expect(pipeProducer.id).toBe(ctx.videoProducer!.id); expect(pipeProducer.closed).toBe(false); expect(pipeProducer.kind).toBe('video'); expect(typeof pipeProducer.rtpParameters).toBe('object'); @@ -467,27 +487,27 @@ test('router.pipeToRouter() succeeds with video', async () => test('router.createPipeTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore - await expect(router1.createPipeTransport({})) + await expect(ctx.router1!.createPipeTransport({})) .rejects .toThrow(TypeError); - await expect(router1.createPipeTransport({ listenIp: '123' })) + await expect(ctx.router1!.createPipeTransport({ listenIp: '123' })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(router1.createPipeTransport({ listenIp: [ '127.0.0.1' ] })) + await expect(ctx.router1!.createPipeTransport({ listenIp: [ '127.0.0.1' ] })) .rejects .toThrow(TypeError); - await expect(router1.createPipeTransport( + await expect(ctx.router1!.createPipeTransport( { listenInfo : { protocol: 'tcp', ip: '127.0.0.1' } })) .rejects .toThrow(TypeError); - await expect(router1.createPipeTransport( + await expect(ctx.router1!.createPipeTransport( { listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, // @ts-ignore @@ -499,14 +519,14 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', test('router.createPipeTransport() with enableRtx succeeds', async () => { - const pipeTransport = await router1.createPipeTransport( + const pipeTransport = await ctx.router1!.createPipeTransport( { listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, enableRtx : true }); const pipeConsumer = - await pipeTransport.consume({ producerId: videoProducer.id }); + await pipeTransport.consume({ producerId: ctx.videoProducer!.id }); expect(typeof pipeConsumer.id).toBe('string'); expect(pipeConsumer.closed).toBe(false); @@ -572,17 +592,16 @@ test('router.createPipeTransport() with enableRtx succeeds', async () => expect(pipeConsumer.type).toBe('pipe'); expect(pipeConsumer.paused).toBe(false); - expect(pipeConsumer.producerPaused).toBe(true); + expect(pipeConsumer.producerPaused).toBe(false); expect(pipeConsumer.score).toEqual( - { score: 10, producerScore: 10, producerScores: [] }); + { score: 10, producerScore: 10, producerScores: [] } + ); expect(pipeConsumer.appData).toEqual({}); - - pipeTransport.close(); }, 2000); test('pipeTransport.connect() with valid SRTP parameters succeeds', async () => { - const pipeTransport = await router1.createPipeTransport( + const pipeTransport = await ctx.router1!.createPipeTransport( { listenIp : '127.0.0.1', enableSrtp : true @@ -605,13 +624,11 @@ test('pipeTransport.connect() with valid SRTP parameters succeeds', async () => })) .resolves .toBeUndefined(); - - pipeTransport.close(); }, 2000); test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', async () => { - const pipeTransport = await router1.createPipeTransport( + const pipeTransport = await ctx.router1!.createPipeTransport( { listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, enableRtx : true @@ -643,13 +660,11 @@ test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', })) .rejects .toThrow(TypeError); - - pipeTransport.close(); }); test('pipeTransport.connect() with invalid srtpParameters fails', async () => { - const pipeTransport = await router1.createPipeTransport( + const pipeTransport = await ctx.router1!.createPipeTransport( { listenIp : '127.0.0.1', enableSrtp : true @@ -752,29 +767,31 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => })) .rejects .toThrow(TypeError); - - pipeTransport.close(); }, 2000); test('router.createPipeTransport() with fixed port succeeds', async () => { const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const pipeTransport = await router1.createPipeTransport( + const pipeTransport = await ctx.router1!.createPipeTransport( { listenInfo : { protocol: 'udp', ip: '127.0.0.1', port } }); expect(pipeTransport.tuple.localPort).toEqual(port); - - pipeTransport.close(); }, 2000); test('transport.consume() for a pipe Producer succeeds', async () => { - videoConsumer = await transport2.consume( + await ctx.router1!.pipeToRouter( { - producerId : videoProducer.id, - rtpCapabilities : consumerDeviceCapabilities + producerId : ctx.videoProducer!.id, + router : ctx.router2! + }); + + const videoConsumer = await ctx.webRtcTransport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities }); expect(typeof videoConsumer.id).toBe('string'); @@ -828,34 +845,50 @@ test('transport.consume() for a pipe Producer succeeds', async () => expect(typeof videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc).toBe('number'); expect(videoConsumer.type).toBe('simulcast'); expect(videoConsumer.paused).toBe(false); - expect(videoConsumer.producerPaused).toBe(true); + expect(videoConsumer.producerPaused).toBe(false); expect(videoConsumer.score).toEqual( - { score: 10, producerScore: 0, producerScores: [ 0, 0, 0 ] }); + { score: 10, producerScore: 0, producerScores: [ 0, 0, 0 ] } + ); expect(videoConsumer.appData).toEqual({}); }, 2000); test('producer.pause() and producer.resume() are transmitted to pipe Consumer', async () => { - // NOTE: Let's use a Promise since otherwise there may be race conditions - // between events and await lines below. - let promise; + await ctx.videoProducer!.pause(); + await ctx.router1!.pipeToRouter( + { + producerId : ctx.videoProducer!.id, + router : ctx.router2! + }); + + const videoConsumer = await ctx.webRtcTransport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); - expect(videoProducer.paused).toBe(true); + expect(ctx.videoProducer!.paused).toBe(true); expect(videoConsumer.producerPaused).toBe(true); expect(videoConsumer.paused).toBe(false); - promise = new Promise((resolve) => videoConsumer.once('producerresume', resolve)); + // NOTE: Let's use a Promise since otherwise there may be race conditions + // between events and await lines below. + const promise1 = new Promise( + (resolve) => videoConsumer.once('producerresume', resolve) + ); - await videoProducer.resume(); - await promise; + await ctx.videoProducer!.resume(); + await promise1; expect(videoConsumer.producerPaused).toBe(false); expect(videoConsumer.paused).toBe(false); - promise = new Promise((resolve) => videoConsumer.once('producerpause', resolve)); + const promise2 = new Promise( + (resolve) => videoConsumer.once('producerpause', resolve) + ); - await videoProducer.pause(); - await promise; + await ctx.videoProducer!.pause(); + await promise2; expect(videoConsumer.producerPaused).toBe(true); expect(videoConsumer.paused).toBe(false); @@ -863,13 +896,27 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', test('producer.close() is transmitted to pipe Consumer', async () => { - await videoProducer.close(); + await ctx.router1!.pipeToRouter( + { + producerId : ctx.videoProducer!.id, + router : ctx.router2! + }); + + const videoConsumer = await ctx.webRtcTransport2!.consume( + { + producerId : ctx.videoProducer!.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); - expect(videoProducer.closed).toBe(true); + await ctx.videoProducer!.close(); + + expect(ctx.videoProducer!.closed).toBe(true); if (!videoConsumer.closed) { - await new Promise((resolve) => videoConsumer.once('producerclose', resolve)); + await new Promise( + (resolve) => videoConsumer.once('producerclose', resolve) + ); } expect(videoConsumer.closed).toBe(true); @@ -877,45 +924,44 @@ test('producer.close() is transmitted to pipe Consumer', async () => test('router.pipeToRouter() fails if both Routers belong to the same Worker', async () => { - const router1bis = await worker1.createRouter({ mediaCodecs }); + const router1bis = await ctx.worker1!.createRouter( + { mediaCodecs: ctx.mediaCodecs } + ); - await expect(router1.pipeToRouter( + await expect(ctx.router1!.pipeToRouter( { - producerId : videoProducer.id, + producerId : ctx.videoProducer!.id, router : router1bis })) .rejects .toThrow(Error); - - router1bis.close(); }, 2000); test('router.pipeToRouter() succeeds with data', async () => { - let dump; - - const { pipeDataConsumer, pipeDataProducer } = await router1.pipeToRouter( + const { pipeDataConsumer, pipeDataProducer } = await ctx.router1!.pipeToRouter( + { + dataProducerId : ctx.dataProducer!.id, + router : ctx.router2! + }) as { - dataProducerId : dataProducer.id, - router : router2 - }) as { pipeDataConsumer: mediasoup.types.DataConsumer; pipeDataProducer: mediasoup.types.DataProducer; }; - dump = await router1.dump(); + const dump1 = await ctx.router1!.dump(); // There should be two Transports in router1: // - WebRtcTransport for audioProducer, videoProducer and dataProducer. // - PipeTransport between router1 and router2. - expect(dump.transportIds.length).toBe(2); + expect(dump1.transportIds.length).toBe(2); - dump = await router2.dump(); + const dump2 = await ctx.router2!.dump(); // There should be two Transports in router2: // - WebRtcTransport for audioConsumer, videoConsumer and dataConsumer. // - PipeTransport between router2 and router1. - expect(dump.transportIds.length).toBe(2); + expect(dump2.transportIds.length).toBe(2); expect(typeof pipeDataConsumer.id).toBe('string'); expect(pipeDataConsumer.closed).toBe(false); @@ -928,7 +974,7 @@ test('router.pipeToRouter() succeeds with data', async () => expect(pipeDataConsumer.label).toBe('foo'); expect(pipeDataConsumer.protocol).toBe('bar'); - expect(pipeDataProducer.id).toBe(dataProducer.id); + expect(pipeDataProducer.id).toBe(ctx.dataProducer!.id); expect(pipeDataProducer.closed).toBe(false); expect(pipeDataProducer.type).toBe('sctp'); expect(typeof pipeDataProducer.sctpStreamParameters).toBe('object'); @@ -942,9 +988,15 @@ test('router.pipeToRouter() succeeds with data', async () => test('transport.dataConsume() for a pipe DataProducer succeeds', async () => { - dataConsumer = await transport2.consumeData( + await ctx.router1!.pipeToRouter( + { + dataProducerId : ctx.dataProducer!.id, + router : ctx.router2! + }); + + const dataConsumer = await ctx.webRtcTransport2!.consumeData( { - dataProducerId : dataProducer.id + dataProducerId : ctx.dataProducer!.id }); expect(typeof dataConsumer.id).toBe('string'); @@ -961,13 +1013,26 @@ test('transport.dataConsume() for a pipe DataProducer succeeds', async () => test('dataProducer.close() is transmitted to pipe DataConsumer', async () => { - await dataProducer.close(); + await ctx.router1!.pipeToRouter( + { + dataProducerId : ctx.dataProducer!.id, + router : ctx.router2! + }); - expect(dataProducer.closed).toBe(true); + const dataConsumer = await ctx.webRtcTransport2!.consumeData( + { + dataProducerId : ctx.dataProducer!.id + }); + + await ctx.dataProducer!.close(); + + expect(ctx.dataProducer!.closed).toBe(true); if (!dataConsumer.closed) { - await new Promise((resolve) => dataConsumer.once('dataproducerclose', resolve)); + await new Promise( + (resolve) => dataConsumer.once('dataproducerclose', resolve) + ); } expect(dataConsumer.closed).toBe(true); @@ -975,13 +1040,16 @@ test('dataProducer.close() is transmitted to pipe DataConsumer', async () => test('router.pipeToRouter() called twice generates a single PipeTransport pair', async () => { - const routerA = await worker1.createRouter({ mediaCodecs }); - const routerB = await worker2.createRouter({ mediaCodecs }); - const transportA1 = await routerA.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); - const transportA2 = await routerA.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); - const audioProducerA1 = await transportA1.produce(audioProducerParameters); - const audioProducerA2 = await transportA2.produce(audioProducerParameters); - let dump; + const routerA = + await ctx.worker1!.createRouter({ mediaCodecs: ctx.mediaCodecs }); + const routerB = + await ctx.worker2!.createRouter({ mediaCodecs: ctx.mediaCodecs }); + const transportA1 = + await routerA.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); + const transportA2 + = await routerA.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); + const audioProducerA1 = await transportA1.produce(ctx.audioProducerOptions); + const audioProducerA2 = await transportA2.produce(ctx.audioProducerOptions); await Promise.all( [ @@ -997,36 +1065,32 @@ test('router.pipeToRouter() called twice generates a single PipeTransport pair', }) ]); - dump = await routerA.dump(); + const dump1 = await routerA.dump(); // There should be 3 Transports in routerA: // - WebRtcTransport for audioProducerA1 and audioProducerA2. // - PipeTransport between routerA and routerB. - expect(dump.transportIds.length).toBe(3); + expect(dump1.transportIds.length).toBe(3); - dump = await routerB.dump(); + const dump2 = await routerB.dump(); // There should be 1 Transport in routerB: // - PipeTransport between routerA and routerB. - expect(dump.transportIds.length).toBe(1); - - routerA.close(); - routerB.close(); + expect(dump2.transportIds.length).toBe(1); }, 2000); test('router.pipeToRouter() called in two Routers passing one to each other as argument generates a single a single PipeTransport pair', async () => { - // We must close other Routers so previously generated PipeTransports are - // closed and removed from the map. - router1.close(); - router2.close(); - - const routerA = await worker1.createRouter({ mediaCodecs }); - const routerB = await worker2.createRouter({ mediaCodecs }); - const transportA = await routerA.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); - const transportB = await routerB.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); - const audioProducerA = await transportA.produce(audioProducerParameters); - const audioProducerB = await transportB.produce(audioProducerParameters); + const routerA = + await ctx.worker1!.createRouter({ mediaCodecs: ctx.mediaCodecs }); + const routerB = + await ctx.worker2!.createRouter({ mediaCodecs: ctx.mediaCodecs }); + const transportA = + await routerA.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); + const transportB = + await routerB.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); + const audioProducerA = await transportA.produce(ctx.audioProducerOptions); + const audioProducerB = await transportB.produce(ctx.audioProducerOptions); const pipeTransportsA = new Map(); const pipeTransportsB = new Map(); @@ -1038,7 +1102,6 @@ test('router.pipeToRouter() called in two Routers passing one to each other as a } pipeTransportsA.set(transport.id, transport); - transport.observer.on('close', () => pipeTransportsA.delete(transport.id)); }); @@ -1050,7 +1113,6 @@ test('router.pipeToRouter() called in two Routers passing one to each other as a } pipeTransportsB.set(transport.id, transport); - transport.observer.on('close', () => pipeTransportsB.delete(transport.id)); }); @@ -1084,6 +1146,4 @@ test('router.pipeToRouter() called in two Routers passing one to each other as a expect(pipeTransportsA.size).toBe(0); expect(pipeTransportsB.size).toBe(0); - - routerB.close(); }, 2000); diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index 770d0bbfce..c6c1ce2966 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -2,131 +2,134 @@ import * as os from 'node:os'; // @ts-ignore import * as pickPort from 'pick-port'; import * as mediasoup from '../'; +import * as utils from '../utils'; const IS_WINDOWS = os.platform() === 'win32'; -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let transport: mediasoup.types.PlainTransport; - -const mediaCodecs: mediasoup.types.RtpCodecCapability[] = -[ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } - }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 - }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - foo : 'bar' - }, - rtcpFeedback : [] // Will be ignored. - } -]; - -beforeAll(async () => +type TestContext = { - worker = await mediasoup.createWorker(); - router = await worker.createRouter({ mediaCodecs }); -}); + mediaCodecs: mediasoup.types.RtpCodecCapability[]; + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; +}; -afterAll(() => worker.close()); +const ctx: TestContext = +{ + mediaCodecs : utils.deepFreeze( + [ + { + kind : 'audio', + mimeType : 'audio/opus', + clockRate : 48000, + channels : 2, + parameters : + { + useinbandfec : 1, + foo : 'bar' + } + }, + { + kind : 'video', + mimeType : 'video/VP8', + clockRate : 90000 + }, + { + kind : 'video', + mimeType : 'video/H264', + clockRate : 90000, + parameters : + { + 'level-asymmetry-allowed' : 1, + 'packetization-mode' : 1, + 'profile-level-id' : '4d0032', + foo : 'bar' + }, + rtcpFeedback : [] // Will be ignored. + } + ] + ) +}; beforeEach(async () => { - transport = await router.createPlainTransport( - { - listenInfo : { protocol: 'udp', ip: '127.0.0.1', announcedIp: '4.4.4.4' }, - rtcpMux : false - }); + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => transport.close()); +afterEach(() => +{ + ctx.worker?.close(); +}); test('router.createPlainTransport() succeeds', async () => { - await expect(router.dump()) + const plainTransport = await ctx.router!.createPlainTransport( + { listenInfo: { protocol: 'udp', ip: '127.0.0.1' } } + ); + + await expect(ctx.router!.dump()) .resolves - .toMatchObject({ transportIds: [ transport.id ] }); + .toMatchObject({ transportIds: [ plainTransport.id ] }); const onObserverNewTransport = jest.fn(); - router.observer.once('newtransport', onObserverNewTransport); + ctx.router!.observer.once('newtransport', onObserverNewTransport); // Create a separate transport here. - const transport1 = await router.createPlainTransport( + const plainTransport2 = await ctx.router!.createPlainTransport( { listenInfo : { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, - rtcpMux : true, enableSctp : true, appData : { foo: 'bar' } }); expect(onObserverNewTransport).toHaveBeenCalledTimes(1); - expect(onObserverNewTransport).toHaveBeenCalledWith(transport1); - expect(typeof transport1.id).toBe('string'); - expect(transport1.closed).toBe(false); - expect(transport1.appData).toEqual({ foo: 'bar' }); - expect(typeof transport1.tuple).toBe('object'); - expect(transport1.tuple.localIp).toBe('9.9.9.1'); - expect(typeof transport1.tuple.localPort).toBe('number'); - expect(transport1.tuple.protocol).toBe('udp'); - expect(transport1.rtcpTuple).toBeUndefined(); - expect(transport1.sctpParameters).toMatchObject( + expect(onObserverNewTransport).toHaveBeenCalledWith(plainTransport2); + expect(typeof plainTransport2.id).toBe('string'); + expect(plainTransport2.closed).toBe(false); + expect(plainTransport2.appData).toEqual({ foo: 'bar' }); + expect(typeof plainTransport2.tuple).toBe('object'); + expect(plainTransport2.tuple.localIp).toBe('9.9.9.1'); + expect(typeof plainTransport2.tuple.localPort).toBe('number'); + expect(plainTransport2.tuple.protocol).toBe('udp'); + expect(plainTransport2.rtcpTuple).toBeUndefined(); + expect(plainTransport2.sctpParameters).toMatchObject( { port : 5000, OS : 1024, MIS : 1024, maxMessageSize : 262144 }); - expect(transport1.sctpState).toBe('new'); - expect(transport1.srtpParameters).toBeUndefined(); + expect(plainTransport2.sctpState).toBe('new'); + expect(plainTransport2.srtpParameters).toBeUndefined(); - const data1 = await transport1.dump(); + const dump1 = await plainTransport2.dump(); - expect(data1.id).toBe(transport1.id); - expect(data1.direct).toBe(false); - expect(data1.producerIds).toEqual([]); - expect(data1.consumerIds).toEqual([]); - expect(data1.tuple).toEqual(transport1.tuple); - expect(data1.rtcpTuple).toEqual(transport1.rtcpTuple); - expect(data1.sctpParameters).toEqual(transport1.sctpParameters); - expect(data1.sctpState).toBe('new'); - expect(data1.recvRtpHeaderExtensions).toBeDefined(); - expect(typeof data1.rtpListener).toBe('object'); + expect(dump1.id).toBe(plainTransport2.id); + expect(dump1.direct).toBe(false); + expect(dump1.producerIds).toEqual([]); + expect(dump1.consumerIds).toEqual([]); + expect(dump1.tuple).toEqual(plainTransport2.tuple); + expect(dump1.rtcpTuple).toEqual(plainTransport2.rtcpTuple); + expect(dump1.sctpParameters).toEqual(plainTransport2.sctpParameters); + expect(dump1.sctpState).toBe('new'); + expect(dump1.recvRtpHeaderExtensions).toBeDefined(); + expect(typeof dump1.rtpListener).toBe('object'); - transport1.close(); - expect(transport1.closed).toBe(true); + plainTransport2.close(); + expect(plainTransport2.closed).toBe(true); - const anotherTransport = await router.createPlainTransport({ listenIp: '127.0.0.1' }); + const anotherTransport = + await ctx.router!.createPlainTransport({ listenIp: '127.0.0.1' }); expect(typeof anotherTransport).toBe('object'); const rtpPort = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const rtcpPort = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const transport2 = await router.createPlainTransport( + const transport2 = await ctx.router!.createPlainTransport( { listenInfo : { protocol: 'udp', ip: '127.0.0.1', port: rtpPort }, - rtcpListenInfo : { protocol: 'udp', ip: '127.0.0.1', port: rtcpPort }, - rtcpMux : false + rtcpListenInfo : { protocol: 'udp', ip: '127.0.0.1', port: rtcpPort } }); expect(typeof transport2.id).toBe('string'); @@ -143,39 +146,39 @@ test('router.createPlainTransport() succeeds', async () => expect(transport2.sctpParameters).toBeUndefined(); expect(transport2.sctpState).toBeUndefined(); - const data2 = await transport2.dump(); + const dump2 = await transport2.dump(); - expect(data2.id).toBe(transport2.id); - expect(data2.direct).toBe(false); - expect(data2.tuple).toEqual(transport2.tuple); - expect(data2.rtcpTuple).toEqual(transport2.rtcpTuple); - expect(data2.sctpState).toBeUndefined(); + expect(dump2.id).toBe(transport2.id); + expect(dump2.direct).toBe(false); + expect(dump2.tuple).toEqual(transport2.tuple); + expect(dump2.rtcpTuple).toEqual(transport2.rtcpTuple); + expect(dump2.sctpState).toBeUndefined(); }, 2000); test('router.createPlainTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore - await expect(router.createPlainTransport({})) + await expect(ctx.router!.createPlainTransport({})) .rejects .toThrow(TypeError); - await expect(router.createPlainTransport({ listenIp: '123' })) + await expect(ctx.router!.createPlainTransport({ listenIp: '123' })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(router.createPlainTransport({ listenIp: [ '127.0.0.1' ] })) + await expect(ctx.router!.createPlainTransport({ listenIp: [ '127.0.0.1' ] })) .rejects .toThrow(TypeError); - await expect(router.createPipeTransport( + await expect(ctx.router!.createPipeTransport( { listenInfo : { protocol: 'tcp', ip: '127.0.0.1' } })) .rejects .toThrow(TypeError); - await expect(router.createPlainTransport( + await expect(ctx.router!.createPlainTransport( { listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, // @ts-ignore @@ -188,19 +191,19 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' test('router.createPlainTransport() with enableSrtp succeeds', async () => { // Use default cryptoSuite: 'AES_CM_128_HMAC_SHA1_80'. - const transport1 = await router.createPlainTransport( + const plainTransport = await ctx.router!.createPlainTransport( { listenIp : '127.0.0.1', enableSrtp : true }); - expect(typeof transport1.id).toBe('string'); - expect(typeof transport1.srtpParameters).toBe('object'); - expect(transport1.srtpParameters?.cryptoSuite).toBe('AES_CM_128_HMAC_SHA1_80'); - expect(transport1.srtpParameters?.keyBase64.length).toBe(40); + expect(typeof plainTransport.id).toBe('string'); + expect(typeof plainTransport.srtpParameters).toBe('object'); + expect(plainTransport.srtpParameters?.cryptoSuite).toBe('AES_CM_128_HMAC_SHA1_80'); + expect(plainTransport.srtpParameters?.keyBase64.length).toBe(40); // Missing srtpParameters. - await expect(transport1.connect( + await expect(plainTransport.connect( { ip : '127.0.0.2', port : 9999 @@ -209,7 +212,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => .toThrow(TypeError); // Invalid srtpParameters. - await expect(transport1.connect( + await expect(plainTransport.connect( { ip : '127.0.0.2', port : 9999, @@ -220,7 +223,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => .toThrow(TypeError); // Missing srtpParameters.cryptoSuite. - await expect(transport1.connect( + await expect(plainTransport.connect( { ip : '127.0.0.2', port : 9999, @@ -234,7 +237,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => .toThrow(TypeError); // Missing srtpParameters.keyBase64. - await expect(transport1.connect( + await expect(plainTransport.connect( { ip : '127.0.0.2', port : 9999, @@ -248,7 +251,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => .toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. - await expect(transport1.connect( + await expect(plainTransport.connect( { ip : '127.0.0.2', port : 9999, @@ -263,7 +266,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => .toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. - await expect(transport1.connect( + await expect(plainTransport.connect( { ip : '127.0.0.2', port : 9999, @@ -278,7 +281,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => .toThrow(TypeError); // Invalid srtpParameters.keyBase64. - await expect(transport1.connect( + await expect(plainTransport.connect( { ip : '127.0.0.2', port : 9999, @@ -293,7 +296,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => .toThrow(TypeError); // Valid srtpParameters. And let's update the crypto suite. - await expect(transport1.connect( + await expect(plainTransport.connect( { ip : '127.0.0.2', port : 9999, @@ -306,15 +309,13 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => .resolves .toBeUndefined(); - expect(transport1.srtpParameters?.cryptoSuite).toBe('AEAD_AES_256_GCM'); - expect(transport1.srtpParameters?.keyBase64.length).toBe(60); - - transport1.close(); + expect(plainTransport.srtpParameters?.cryptoSuite).toBe('AEAD_AES_256_GCM'); + expect(plainTransport.srtpParameters?.keyBase64.length).toBe(60); }, 2000); test('router.createPlainTransport() with non bindable IP rejects with Error', async () => { - await expect(router.createPlainTransport({ listenIp: '8.8.8.8' })) + await expect(ctx.router!.createPlainTransport({ listenIp: '8.8.8.8' })) .rejects .toThrow(Error); }, 2000); @@ -323,133 +324,135 @@ if (!IS_WINDOWS) { test('two transports binding to the same IP:port with udpReusePort flag succeed', async () => { - let transport1: mediasoup.types.PlainTransport | undefined; - let transport2: mediasoup.types.PlainTransport | undefined; + const multicastIp = '224.0.0.1'; + const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); - await expect(async () => - { - const multicastIp = '224.0.0.1'; - const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); - - transport1 = await router.createPlainTransport( + await expect(ctx.router!.createPlainTransport( + { + listenInfo : { - listenInfo : - { - protocol : 'udp', - ip : multicastIp, - port : port, - // NOTE: ipv6Only flag will be ignored since ip is IPv4. - flags : { udpReusePort: true, ipv6Only: true } - } - }); - - transport2 = await router.createPlainTransport( + protocol : 'udp', + ip : multicastIp, + port : port, + // NOTE: ipv6Only flag will be ignored since ip is IPv4. + flags : { udpReusePort: true, ipv6Only: true } + } + } + )).resolves.toBeDefined(); + + await expect(ctx.router!.createPlainTransport( + { + listenInfo : { - listenInfo : - { - protocol : 'udp', - ip : multicastIp, - port : port, - flags : { udpReusePort: true } - } - }); - }).not.toThrow(); - - transport1?.close(); - transport2?.close(); + protocol : 'udp', + ip : multicastIp, + port : port, + flags : { udpReusePort: true } + } + } + )).resolves.toBeDefined(); }, 2000); - test('two transports binding to the same IP:port without udpReusePort flag fails', async () => + test('two transports binding to the same IP:port without udpReusePort flag fail', async () => { - let transport1: mediasoup.types.PlainTransport | undefined; - let transport2: mediasoup.types.PlainTransport | undefined; - - await expect(async () => - { - const multicastIp = '224.0.0.1'; - const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); + const multicastIp = '224.0.0.1'; + const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); - transport1 = await router.createPlainTransport( + await expect(ctx.router!.createPlainTransport( + { + listenInfo : { - listenInfo : - { - protocol : 'udp', - ip : multicastIp, - port : port, - flags : { udpReusePort: false } - } - }); - - transport2 = await router.createPlainTransport( + protocol : 'udp', + ip : multicastIp, + port : port, + flags : { udpReusePort: false } + } + } + )).resolves.toBeDefined(); + + await expect(ctx.router!.createPlainTransport( + { + listenInfo : { - listenInfo : - { - protocol : 'udp', - ip : multicastIp, - port : port, - flags : { udpReusePort: false } - } - }); - }).rejects.toThrow(); - - transport1?.close(); - transport2?.close(); + protocol : 'udp', + ip : multicastIp, + port : port, + flags : { udpReusePort: false } + } + } + )).rejects.toThrow(); }, 2000); } test('plainTransport.getStats() succeeds', async () => { - const data = await transport.getStats(); - - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBe(1); - expect(data[0].type).toBe('plain-rtp-transport'); - expect(data[0].transportId).toBe(transport.id); - expect(typeof data[0].timestamp).toBe('number'); - expect(data[0].bytesReceived).toBe(0); - expect(data[0].recvBitrate).toBe(0); - expect(data[0].bytesSent).toBe(0); - expect(data[0].sendBitrate).toBe(0); - expect(data[0].rtpBytesReceived).toBe(0); - expect(data[0].rtpRecvBitrate).toBe(0); - expect(data[0].rtpBytesSent).toBe(0); - expect(data[0].rtpSendBitrate).toBe(0); - expect(data[0].rtxBytesReceived).toBe(0); - expect(data[0].rtxRecvBitrate).toBe(0); - expect(data[0].rtxBytesSent).toBe(0); - expect(data[0].rtxSendBitrate).toBe(0); - expect(data[0].probationBytesSent).toBe(0); - expect(data[0].probationSendBitrate).toBe(0); - expect(typeof data[0].tuple).toBe('object'); - expect(data[0].tuple.localIp).toBe('4.4.4.4'); - expect(typeof data[0].tuple.localPort).toBe('number'); - expect(data[0].tuple.protocol).toBe('udp'); - expect(data[0].rtcpTuple).toBeUndefined(); + const plainTransport = await ctx.router!.createPlainTransport( + { listenIp: '127.0.0.1' } + ); + + const stats = await plainTransport.getStats(); + + expect(Array.isArray(stats)).toBe(true); + expect(stats.length).toBe(1); + expect(stats[0].type).toBe('plain-rtp-transport'); + expect(stats[0].transportId).toBe(plainTransport.id); + expect(typeof stats[0].timestamp).toBe('number'); + expect(stats[0].bytesReceived).toBe(0); + expect(stats[0].recvBitrate).toBe(0); + expect(stats[0].bytesSent).toBe(0); + expect(stats[0].sendBitrate).toBe(0); + expect(stats[0].rtpBytesReceived).toBe(0); + expect(stats[0].rtpRecvBitrate).toBe(0); + expect(stats[0].rtpBytesSent).toBe(0); + expect(stats[0].rtpSendBitrate).toBe(0); + expect(stats[0].rtxBytesReceived).toBe(0); + expect(stats[0].rtxRecvBitrate).toBe(0); + expect(stats[0].rtxBytesSent).toBe(0); + expect(stats[0].rtxSendBitrate).toBe(0); + expect(stats[0].probationBytesSent).toBe(0); + expect(stats[0].probationSendBitrate).toBe(0); + expect(typeof stats[0].tuple).toBe('object'); + expect(stats[0].tuple.localIp).toBe('127.0.0.1'); + expect(typeof stats[0].tuple.localPort).toBe('number'); + expect(stats[0].tuple.protocol).toBe('udp'); + expect(stats[0].rtcpTuple).toBeUndefined(); }, 2000); test('plainTransport.connect() succeeds', async () => { - await expect(transport.connect({ ip: '1.2.3.4', port: 1234, rtcpPort: 1235 })) + const plainTransport = await ctx.router!.createPlainTransport( + { listenIp: '127.0.0.1', rtcpMux: false } + ); + + await expect(plainTransport.connect( + { ip: '1.2.3.4', port: 1234, rtcpPort: 1235 } + )) .resolves .toBeUndefined(); // Must fail if connected. - await expect(transport.connect({ ip: '1.2.3.4', port: 1234, rtcpPort: 1235 })) + await expect(plainTransport.connect( + { ip: '1.2.3.4', port: 1234, rtcpPort: 1235 } + )) .rejects .toThrow(Error); - expect(transport.tuple.remoteIp).toBe('1.2.3.4'); - expect(transport.tuple.remotePort).toBe(1234); - expect(transport.tuple.protocol).toBe('udp'); - expect(transport.rtcpTuple?.remoteIp).toBe('1.2.3.4'); - expect(transport.rtcpTuple?.remotePort).toBe(1235); - expect(transport.rtcpTuple?.protocol).toBe('udp'); + expect(plainTransport.tuple.remoteIp).toBe('1.2.3.4'); + expect(plainTransport.tuple.remotePort).toBe(1234); + expect(plainTransport.tuple.protocol).toBe('udp'); + expect(plainTransport.rtcpTuple?.remoteIp).toBe('1.2.3.4'); + expect(plainTransport.rtcpTuple?.remotePort).toBe(1235); + expect(plainTransport.rtcpTuple?.protocol).toBe('udp'); }, 2000); test('plainTransport.connect() with wrong arguments rejects with TypeError', async () => { + const plainTransport = await ctx.router!.createPlainTransport( + { listenIp: '127.0.0.1', rtcpMux: false } + ); + // No SRTP enabled so passing srtpParameters must fail. - await expect(transport.connect( + await expect(plainTransport.connect( { ip : '127.0.0.2', port : 9998, @@ -463,44 +466,61 @@ test('plainTransport.connect() with wrong arguments rejects with TypeError', asy .rejects .toThrow(TypeError); - await expect(transport.connect({})) + await expect(plainTransport.connect({})) .rejects .toThrow(TypeError); - await expect(transport.connect({ ip: '::::1234' })) + await expect(plainTransport.connect({ ip: '::::1234' })) .rejects .toThrow(TypeError); - // @ts-ignore - await expect(transport.connect({ ip: '127.0.0.1', port: 1234, __rtcpPort: 1235 })) + // Must fail because transport has rtcpMux: false so rtcpPort must be given + // in connect(). + await expect(plainTransport.connect( + { + ip : '127.0.0.1', + port : 1234, + // @ts-ignore + __rtcpPort : 1235 + } + )) .rejects .toThrow(TypeError); - // @ts-ignore - await expect(transport.connect({ ip: '127.0.0.1', __port: 'chicken', rtcpPort: 1235 })) + await expect(plainTransport.connect( + { + ip : '127.0.0.1', + // @ts-ignore + __port : 'chicken', + rtcpPort : 1235 + })) .rejects .toThrow(TypeError); }, 2000); test('PlainTransport methods reject if closed', async () => { + const plainTransport = await ctx.router!.createPlainTransport( + { listenIp: '127.0.0.1' } + ); + const onObserverClose = jest.fn(); - transport.observer.once('close', onObserverClose); - transport.close(); + plainTransport.observer.once('close', onObserverClose); + plainTransport.close(); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(transport.closed).toBe(true); + expect(plainTransport.closed).toBe(true); - await expect(transport.dump()) + await expect(plainTransport.dump()) .rejects .toThrow(Error); - await expect(transport.getStats()) + await expect(plainTransport.getStats()) .rejects .toThrow(Error); - await expect(transport.connect({})) + await expect(plainTransport.connect({})) .rejects .toThrow(Error); }, 2000); @@ -508,48 +528,52 @@ test('PlainTransport methods reject if closed', async () => test('router.createPlainTransport() with fixed port succeeds', async () => { const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const plainTransport = await router.createPlainTransport( + const plainTransport = await ctx.router!.createPlainTransport( { listenInfo : { protocol: 'udp', ip: '127.0.0.1', port } }); expect(plainTransport.tuple.localPort).toEqual(port); - - plainTransport.close(); }, 2000); test('PlainTransport emits "routerclose" if Router is closed', async () => { - // We need different Router and PlainTransport instances here. - const router2 = await worker.createRouter({ mediaCodecs }); - const transport2 = - await router2.createPlainTransport({ listenIp: '127.0.0.1' }); + const plainTransport = await ctx.router!.createPlainTransport( + { listenIp: '127.0.0.1' } + ); + const onObserverClose = jest.fn(); - transport2.observer.once('close', onObserverClose); + plainTransport.observer.once('close', onObserverClose); await new Promise((resolve) => { - transport2.on('routerclose', resolve); - router2.close(); + plainTransport.on('routerclose', resolve); + + ctx.router!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(transport2.closed).toBe(true); + expect(plainTransport.closed).toBe(true); }, 2000); test('PlainTransport emits "routerclose" if Worker is closed', async () => { + const plainTransport = await ctx.router!.createPlainTransport( + { listenIp: '127.0.0.1' } + ); + const onObserverClose = jest.fn(); - transport.observer.once('close', onObserverClose); + plainTransport.observer.once('close', onObserverClose); await new Promise((resolve) => { - transport.on('routerclose', resolve); - worker.close(); + plainTransport.on('routerclose', resolve); + + ctx.worker!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(transport.closed).toBe(true); + expect(plainTransport.closed).toBe(true); }, 2000); diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index 1861038370..c5e79a93cc 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -2,18 +2,22 @@ import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; -import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; +import { + Notification, + Body as NotificationBody, + Event +} from '../fbs/notification'; import * as FbsProducer from '../fbs/producer'; type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; - audioProducerParameters: mediasoup.types.ProducerOptions; - videoProducerParameters: mediasoup.types.ProducerOptions; + audioProducerOptions: mediasoup.types.ProducerOptions; + videoProducerOptions: mediasoup.types.ProducerOptions; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; - transport1?: mediasoup.types.WebRtcTransport; - transport2?: mediasoup.types.WebRtcTransport; + webRtcTransport1?: mediasoup.types.WebRtcTransport; + webRtcTransport2?: mediasoup.types.WebRtcTransport; }; const ctx: TestContext = @@ -50,7 +54,7 @@ const ctx: TestContext = } ] ), - audioProducerParameters : utils.deepFreeze( + audioProducerOptions : utils.deepFreeze( { kind : 'audio', rtpParameters : @@ -92,7 +96,7 @@ const ctx: TestContext = appData : { foo: 1, bar: '2' } } ), - videoProducerParameters : utils.deepFreeze( + videoProducerOptions : utils.deepFreeze( { kind : 'video', rtpParameters : @@ -155,11 +159,11 @@ beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); - ctx.transport1 = await ctx.router.createWebRtcTransport( + ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ] }); - ctx.transport2 = await ctx.router.createWebRtcTransport( + ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ] }); @@ -170,14 +174,14 @@ afterEach(() => ctx.worker?.close(); }); -test('transport1.produce() succeeds', async () => +test('webRtcTransport1.produce() succeeds', async () => { const onObserverNewProducer = jest.fn(); - ctx.transport1!.observer.once('newproducer', onObserverNewProducer); + ctx.webRtcTransport1!.observer.once('newproducer', onObserverNewProducer); const audioProducer = - await ctx.transport1!.produce(ctx.audioProducerParameters); + await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer); @@ -200,24 +204,24 @@ test('transport1.produce() succeeds', async () => mapConsumerIdProducerId : [] }); - await expect(ctx.transport1!.dump()) + await expect(ctx.webRtcTransport1!.dump()) .resolves .toMatchObject( { - id : ctx.transport1!.id, + id : ctx.webRtcTransport1!.id, producerIds : [ audioProducer.id ], consumerIds : [] }); }, 2000); -test('transport2.produce() succeeds', async () => +test('webRtcTransport2.produce() succeeds', async () => { const onObserverNewProducer = jest.fn(); - ctx.transport2!.observer.once('newproducer', onObserverNewProducer); + ctx.webRtcTransport2!.observer.once('newproducer', onObserverNewProducer); const videoProducer = - await ctx.transport2!.produce(ctx.videoProducerParameters); + await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); expect(onObserverNewProducer).toHaveBeenCalledWith(videoProducer); @@ -242,23 +246,23 @@ test('transport2.produce() succeeds', async () => expect(dump.mapConsumerIdProducerId.length).toBe(0); - await expect(ctx.transport2!.dump()) + await expect(ctx.webRtcTransport2!.dump()) .resolves .toMatchObject( { - id : ctx.transport2!.id, + id : ctx.webRtcTransport2!.id, producerIds : [ videoProducer.id ], consumerIds : [] }); }, 2000); -test('transport1.produce() without header extensions and rtcp succeeds', async () => +test('webRtcTransport1.produce() without header extensions and rtcp succeeds', async () => { const onObserverNewProducer = jest.fn(); - ctx.transport1!.observer.once('newproducer', onObserverNewProducer); + ctx.webRtcTransport1!.observer.once('newproducer', onObserverNewProducer); - const audioProducer = await ctx.transport1!.produce( + const audioProducer = await ctx.webRtcTransport1!.produce( { kind : 'audio', rtpParameters : @@ -300,9 +304,9 @@ test('transport1.produce() without header extensions and rtcp succeeds', async ( audioProducer.close(); }, 2000); -test('transport1.produce() with wrong arguments rejects with TypeError', async () => +test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', async () => { - await expect(ctx.transport1!.produce( + await expect(ctx.webRtcTransport1!.produce( { // @ts-ignore kind : 'chicken', @@ -312,7 +316,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( .rejects .toThrow(TypeError); - await expect(ctx.transport1!.produce( + await expect(ctx.webRtcTransport1!.produce( { kind : 'audio', // @ts-ignore @@ -322,7 +326,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( .toThrow(TypeError); // Invalid ssrc. - await expect(ctx.transport1!.produce( + await expect(ctx.webRtcTransport1!.produce( { kind : 'audio', rtpParameters : @@ -338,7 +342,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( .toThrow(TypeError); // Missing or empty rtpParameters.encodings. - await expect(ctx.transport1!.produce( + await expect(ctx.webRtcTransport1!.produce( { kind : 'video', rtpParameters : @@ -371,7 +375,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( .toThrow(TypeError); // Wrong apt in RTX codec. - await expect(ctx.transport1!.produce( + await expect(ctx.webRtcTransport1!.produce( { kind : 'audio', rtpParameters : @@ -410,9 +414,9 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( .toThrow(TypeError); }, 2000); -test('transport1.produce() with unsupported codecs rejects with UnsupportedError', async () => +test('webRtcTransport1.produce() with unsupported codecs rejects with UnsupportedError', async () => { - await expect(ctx.transport1!.produce( + await expect(ctx.webRtcTransport1!.produce( { kind : 'audio', rtpParameters : @@ -434,7 +438,7 @@ test('transport1.produce() with unsupported codecs rejects with UnsupportedError .toThrow(UnsupportedError); // Invalid H264 profile-level-id. - await expect(ctx.transport1!.produce( + await expect(ctx.webRtcTransport1!.produce( { kind : 'video', rtpParameters : @@ -527,22 +531,22 @@ test('transport.produce() with already used MID or SSRC rejects with Error', asy } }; - await ctx.transport1!.produce(audioProducerOptions); + await ctx.webRtcTransport1!.produce(audioProducerOptions); - await expect(ctx.transport1!.produce(audioProducerOptions)) + await expect(ctx.webRtcTransport1!.produce(audioProducerOptions)) .rejects .toThrow(Error); - await ctx.transport2!.produce(videoProducerOptions); + await ctx.webRtcTransport2!.produce(videoProducerOptions); - await expect(ctx.transport2!.produce(videoProducerOptions)) + await expect(ctx.webRtcTransport2!.produce(videoProducerOptions)) .rejects .toThrow(Error); }, 2000); test('transport.produce() with no MID and with single encoding without RID or SSRC rejects with Error', async () => { - await expect(ctx.transport1!.produce( + await expect(ctx.webRtcTransport1!.produce( { kind : 'audio', rtpParameters : @@ -566,7 +570,7 @@ test('transport.produce() with no MID and with single encoding without RID or SS test('producer.dump() succeeds', async () => { const audioProducer = - await ctx.transport1!.produce(ctx.audioProducerParameters); + await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); const dump1 = await audioProducer.dump(); @@ -616,7 +620,7 @@ test('producer.dump() succeeds', async () => expect(dump1.type).toBe('simple'); const videoProducer = - await ctx.transport2!.produce(ctx.videoProducerParameters); + await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); const dump2 = await videoProducer.dump(); @@ -685,10 +689,10 @@ test('producer.dump() succeeds', async () => test('producer.getStats() succeeds', async () => { const audioProducer = - await ctx.transport1!.produce(ctx.audioProducerParameters); + await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); const videoProducer = - await ctx.transport2!.produce(ctx.videoProducerParameters); + await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); await expect(audioProducer.getStats()) .resolves @@ -702,7 +706,7 @@ test('producer.getStats() succeeds', async () => test('producer.pause() and resume() succeed', async () => { const audioProducer = - await ctx.transport1!.produce(ctx.audioProducerParameters); + await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); const onObserverPause = jest.fn(); const onObserverResume = jest.fn(); @@ -740,7 +744,7 @@ test('producer.pause() and resume() succeed', async () => test('producer.pause() and resume() emit events', async () => { const audioProducer = - await ctx.transport1!.produce(ctx.audioProducerParameters); + await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); const promises = []; const events: string[] = []; @@ -767,7 +771,7 @@ test('producer.pause() and resume() emit events', async () => test('producer.enableTraceEvent() succeed', async () => { const audioProducer = - await ctx.transport1!.produce(ctx.audioProducerParameters); + await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); await audioProducer.enableTraceEvent([ 'rtp', 'pli' ]); @@ -802,7 +806,7 @@ test('producer.enableTraceEvent() succeed', async () => test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { const audioProducer = - await ctx.transport1!.produce(ctx.audioProducerParameters); + await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); // @ts-ignore await expect(audioProducer.enableTraceEvent(123)) @@ -823,7 +827,7 @@ test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', test('Producer emits "score"', async () => { const videoProducer = - await ctx.transport2!.produce(ctx.videoProducerParameters); + await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); // Private API. const channel = videoProducer.channelForTesting; @@ -877,7 +881,7 @@ test('Producer emits "score"', async () => test('producer.close() succeeds', async () => { const audioProducer = - await ctx.transport1!.produce(ctx.audioProducerParameters); + await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); const onObserverClose = jest.fn(); @@ -895,11 +899,11 @@ test('producer.close() succeeds', async () => mapConsumerIdProducerId : [] }); - await expect(ctx.transport1!.dump()) + await expect(ctx.webRtcTransport1!.dump()) .resolves .toMatchObject( { - id : ctx.transport1!.id, + id : ctx.webRtcTransport1!.id, producerIds : [], consumerIds : [] }); @@ -908,7 +912,7 @@ test('producer.close() succeeds', async () => test('Producer methods reject if closed', async () => { const audioProducer = - await ctx.transport1!.produce(ctx.audioProducerParameters); + await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); audioProducer.close(); @@ -932,7 +936,7 @@ test('Producer methods reject if closed', async () => test('Producer emits "transportclose" if Transport is closed', async () => { const videoProducer = - await ctx.transport2!.produce(ctx.videoProducerParameters); + await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); const onObserverClose = jest.fn(); @@ -941,7 +945,7 @@ test('Producer emits "transportclose" if Transport is closed', async () => await new Promise((resolve) => { videoProducer.on('transportclose', resolve); - ctx.transport2!.close(); + ctx.webRtcTransport2!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index 5aab850ac2..6c2b5db991 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -140,7 +140,10 @@ test('worker.createRouter() rejects with InvalidStateError if Worker is closed', test('router.close() succeeds', async () => { - const router = await ctx.worker!.createRouter({ mediaCodecs: ctx.mediaCodecs }); + const router = await ctx.worker!.createRouter( + { mediaCodecs: ctx.mediaCodecs } + ); + const onObserverClose = jest.fn(); router.observer.once('close', onObserverClose); @@ -152,7 +155,10 @@ test('router.close() succeeds', async () => test('Router emits "workerclose" if Worker is closed', async () => { - const router = await ctx.worker!.createRouter({ mediaCodecs: ctx.mediaCodecs }); + const router = await ctx.worker!.createRouter( + { mediaCodecs: ctx.mediaCodecs } + ); + const onObserverClose = jest.fn(); router.observer.once('close', onObserverClose); @@ -160,6 +166,7 @@ test('Router emits "workerclose" if Worker is closed', async () => await new Promise((resolve) => { router.on('workerclose', resolve); + ctx.worker!.close(); }); diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index b08b32c342..3cf16037eb 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -2,77 +2,78 @@ import * as pickPort from 'pick-port'; import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; -import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; +import * as utils from '../utils'; +import { serializeProtocol, TransportTuple } from '../Transport'; +import { + Notification, + Body as NotificationBody, + Event +} from '../fbs/notification'; import * as FbsTransport from '../fbs/transport'; import * as FbsWebRtcTransport from '../fbs/web-rtc-transport'; -import { serializeProtocol, TransportTuple } from '../Transport'; - -let worker: mediasoup.types.Worker; -let router: mediasoup.types.Router; -let transport: mediasoup.types.WebRtcTransport; -const mediaCodecs: mediasoup.types.RtpCodecCapability[] = -[ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } - }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 - }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - foo : 'bar' - } - } -]; - -beforeAll(async () => +type TestContext = { - worker = await mediasoup.createWorker(); - router = await worker.createRouter({ mediaCodecs }); -}); + mediaCodecs: mediasoup.types.RtpCodecCapability[]; + worker?: mediasoup.types.Worker; + router?: mediasoup.types.Router; +}; -afterAll(() => worker.close()); +const ctx: TestContext = +{ + mediaCodecs : utils.deepFreeze( + [ + { + kind : 'audio', + mimeType : 'audio/opus', + clockRate : 48000, + channels : 2, + parameters : + { + useinbandfec : 1, + foo : 'bar' + } + }, + { + kind : 'video', + mimeType : 'video/VP8', + clockRate : 90000 + }, + { + kind : 'video', + mimeType : 'video/H264', + clockRate : 90000, + parameters : + { + 'level-asymmetry-allowed' : 1, + 'packetization-mode' : 1, + 'profile-level-id' : '4d0032', + foo : 'bar' + } + } + ] + ) +}; beforeEach(async () => { - transport = await router.createWebRtcTransport( - { - listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } ] - }); + ctx.worker = await mediasoup.createWorker(); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => transport.close()); +afterEach(() => +{ + ctx.worker?.close(); +}); test('router.createWebRtcTransport() succeeds', async () => { - await expect(router.dump()) - .resolves - .toMatchObject({ transportIds: [ transport.id ] }); - const onObserverNewTransport = jest.fn(); - router.observer.once('newtransport', onObserverNewTransport); + ctx.router!.observer.once('newtransport', onObserverNewTransport); // Create a separate transport here. - const transport1 = await router.createWebRtcTransport( + const webRtcTransport = await ctx.router!.createWebRtcTransport( { listenInfos : [ @@ -91,27 +92,31 @@ test('router.createWebRtcTransport() succeeds', async () => appData : { foo: 'bar' } }); + await expect(ctx.router!.dump()) + .resolves + .toMatchObject({ transportIds: [ webRtcTransport.id ] }); + expect(onObserverNewTransport).toHaveBeenCalledTimes(1); - expect(onObserverNewTransport).toHaveBeenCalledWith(transport1); - expect(typeof transport1.id).toBe('string'); - expect(transport1.closed).toBe(false); - expect(transport1.appData).toEqual({ foo: 'bar' }); - expect(transport1.iceRole).toBe('controlled'); - expect(typeof transport1.iceParameters).toBe('object'); - expect(transport1.iceParameters.iceLite).toBe(true); - expect(typeof transport1.iceParameters.usernameFragment).toBe('string'); - expect(typeof transport1.iceParameters.password).toBe('string'); - expect(transport1.sctpParameters).toMatchObject( + expect(onObserverNewTransport).toHaveBeenCalledWith(webRtcTransport); + expect(typeof webRtcTransport.id).toBe('string'); + expect(webRtcTransport.closed).toBe(false); + expect(webRtcTransport.appData).toEqual({ foo: 'bar' }); + expect(webRtcTransport.iceRole).toBe('controlled'); + expect(typeof webRtcTransport.iceParameters).toBe('object'); + expect(webRtcTransport.iceParameters.iceLite).toBe(true); + expect(typeof webRtcTransport.iceParameters.usernameFragment).toBe('string'); + expect(typeof webRtcTransport.iceParameters.password).toBe('string'); + expect(webRtcTransport.sctpParameters).toMatchObject( { port : 5000, OS : 2048, MIS : 2048, maxMessageSize : 1000000 }); - expect(Array.isArray(transport1.iceCandidates)).toBe(true); - expect(transport1.iceCandidates.length).toBe(6); + expect(Array.isArray(webRtcTransport.iceCandidates)).toBe(true); + expect(webRtcTransport.iceCandidates.length).toBe(6); - const iceCandidates = transport1.iceCandidates; + const iceCandidates = webRtcTransport.iceCandidates; expect(iceCandidates[0].ip).toBe('9.9.9.1'); expect(iceCandidates[0].protocol).toBe('udp'); @@ -143,67 +148,61 @@ test('router.createWebRtcTransport() succeeds', async () => expect(iceCandidates[3].priority).toBeGreaterThan(iceCandidates[4].priority); expect(iceCandidates[4].priority).toBeGreaterThan(iceCandidates[5].priority); - expect(transport1.iceState).toBe('new'); - expect(transport1.iceSelectedTuple).toBeUndefined(); - expect(typeof transport1.dtlsParameters).toBe('object'); - expect(Array.isArray(transport1.dtlsParameters.fingerprints)).toBe(true); - expect(transport1.dtlsParameters.role).toBe('auto'); - expect(transport1.dtlsState).toBe('new'); - expect(transport1.dtlsRemoteCert).toBeUndefined(); - expect(transport1.sctpState).toBe('new'); - - const data1 = await transport1.dump(); - - expect(data1.id).toBe(transport1.id); - expect(data1.direct).toBe(false); - expect(data1.producerIds).toEqual([]); - expect(data1.consumerIds).toEqual([]); - expect(data1.iceRole).toBe(transport1.iceRole); - expect(data1.iceParameters).toEqual(transport1.iceParameters); - expect(data1.iceCandidates).toEqual(transport1.iceCandidates); - expect(data1.iceState).toBe(transport1.iceState); - expect(data1.iceSelectedTuple).toEqual(transport1.iceSelectedTuple); - expect(data1.dtlsParameters).toEqual(transport1.dtlsParameters); - expect(data1.dtlsState).toBe(transport1.dtlsState); - expect(data1.sctpParameters).toEqual(transport1.sctpParameters); - expect(data1.sctpState).toBe(transport1.sctpState); - expect(data1.recvRtpHeaderExtensions).toBeDefined(); - expect(typeof data1.rtpListener).toBe('object'); - - transport1.close(); - expect(transport1.closed).toBe(true); - - const anotherTransport = await router.createWebRtcTransport( - { - listenInfos : [ { protocol: 'udp', ip: '127.0.0.1' } ] - }); + expect(webRtcTransport.iceState).toBe('new'); + expect(webRtcTransport.iceSelectedTuple).toBeUndefined(); + expect(typeof webRtcTransport.dtlsParameters).toBe('object'); + expect(Array.isArray(webRtcTransport.dtlsParameters.fingerprints)).toBe(true); + expect(webRtcTransport.dtlsParameters.role).toBe('auto'); + expect(webRtcTransport.dtlsState).toBe('new'); + expect(webRtcTransport.dtlsRemoteCert).toBeUndefined(); + expect(webRtcTransport.sctpState).toBe('new'); + + const dump = await webRtcTransport.dump(); + + expect(dump.id).toBe(webRtcTransport.id); + expect(dump.direct).toBe(false); + expect(dump.producerIds).toEqual([]); + expect(dump.consumerIds).toEqual([]); + expect(dump.iceRole).toBe(webRtcTransport.iceRole); + expect(dump.iceParameters).toEqual(webRtcTransport.iceParameters); + expect(dump.iceCandidates).toEqual(webRtcTransport.iceCandidates); + expect(dump.iceState).toBe(webRtcTransport.iceState); + expect(dump.iceSelectedTuple).toEqual(webRtcTransport.iceSelectedTuple); + expect(dump.dtlsParameters).toEqual(webRtcTransport.dtlsParameters); + expect(dump.dtlsState).toBe(webRtcTransport.dtlsState); + expect(dump.sctpParameters).toEqual(webRtcTransport.sctpParameters); + expect(dump.sctpState).toBe(webRtcTransport.sctpState); + expect(dump.recvRtpHeaderExtensions).toBeDefined(); + expect(typeof dump.rtpListener).toBe('object'); + + webRtcTransport.close(); - expect(typeof anotherTransport).toBe('object'); + expect(webRtcTransport.closed).toBe(true); }, 2000); test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore - await expect(router.createWebRtcTransport({})) + await expect(ctx.router!.createWebRtcTransport({})) .rejects .toThrow(TypeError); // @ts-ignore - await expect(router.createWebRtcTransport({ listenIps: [ 123 ] })) + await expect(ctx.router!.createWebRtcTransport({ listenIps: [ 123 ] })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(router.createWebRtcTransport({ listenInfos: '127.0.0.1' })) + await expect(ctx.router!.createWebRtcTransport({ listenInfos: '127.0.0.1' })) .rejects .toThrow(TypeError); // @ts-ignore - await expect(router.createWebRtcTransport({ listenIps: '127.0.0.1' })) + await expect(ctx.router!.createWebRtcTransport({ listenIps: '127.0.0.1' })) .rejects .toThrow(TypeError); - await expect(router.createWebRtcTransport( + await expect(ctx.router!.createWebRtcTransport( { listenIps : [ '127.0.0.1' ], // @ts-ignore @@ -212,7 +211,7 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError .rejects .toThrow(TypeError); - await expect(router.createWebRtcTransport( + await expect(ctx.router!.createWebRtcTransport( { listenIps : [ '127.0.0.1' ], enableSctp : true, @@ -225,7 +224,7 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError test('router.createWebRtcTransport() with non bindable IP rejects with Error', async () => { - await expect(router.createWebRtcTransport( + await expect(ctx.router!.createWebRtcTransport( { listenInfos : [ { protocol: 'udp', ip: '8.8.8.8' } ] })) @@ -235,37 +234,53 @@ test('router.createWebRtcTransport() with non bindable IP rejects with Error', a test('webRtcTransport.getStats() succeeds', async () => { - const data = await transport.getStats(); - - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBe(1); - expect(data[0].type).toBe('webrtc-transport'); - expect(data[0].transportId).toBe(transport.id); - expect(typeof data[0].timestamp).toBe('number'); - expect(data[0].iceRole).toBe('controlled'); - expect(data[0].iceState).toBe('new'); - expect(data[0].dtlsState).toBe('new'); - expect(data[0].sctpState).toBeUndefined(); - expect(data[0].bytesReceived).toBe(0); - expect(data[0].recvBitrate).toBe(0); - expect(data[0].bytesSent).toBe(0); - expect(data[0].sendBitrate).toBe(0); - expect(data[0].rtpBytesReceived).toBe(0); - expect(data[0].rtpRecvBitrate).toBe(0); - expect(data[0].rtpBytesSent).toBe(0); - expect(data[0].rtpSendBitrate).toBe(0); - expect(data[0].rtxBytesReceived).toBe(0); - expect(data[0].rtxRecvBitrate).toBe(0); - expect(data[0].rtxBytesSent).toBe(0); - expect(data[0].rtxSendBitrate).toBe(0); - expect(data[0].probationBytesSent).toBe(0); - expect(data[0].probationSendBitrate).toBe(0); - expect(data[0].iceSelectedTuple).toBeUndefined(); - expect(data[0].maxIncomingBitrate).toBeUndefined(); + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { + listenInfos : + [ + { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } + ] + }); + + const stats = await webRtcTransport.getStats(); + + expect(Array.isArray(stats)).toBe(true); + expect(stats.length).toBe(1); + expect(stats[0].type).toBe('webrtc-transport'); + expect(stats[0].transportId).toBe(webRtcTransport.id); + expect(typeof stats[0].timestamp).toBe('number'); + expect(stats[0].iceRole).toBe('controlled'); + expect(stats[0].iceState).toBe('new'); + expect(stats[0].dtlsState).toBe('new'); + expect(stats[0].sctpState).toBeUndefined(); + expect(stats[0].bytesReceived).toBe(0); + expect(stats[0].recvBitrate).toBe(0); + expect(stats[0].bytesSent).toBe(0); + expect(stats[0].sendBitrate).toBe(0); + expect(stats[0].rtpBytesReceived).toBe(0); + expect(stats[0].rtpRecvBitrate).toBe(0); + expect(stats[0].rtpBytesSent).toBe(0); + expect(stats[0].rtpSendBitrate).toBe(0); + expect(stats[0].rtxBytesReceived).toBe(0); + expect(stats[0].rtxRecvBitrate).toBe(0); + expect(stats[0].rtxBytesSent).toBe(0); + expect(stats[0].rtxSendBitrate).toBe(0); + expect(stats[0].probationBytesSent).toBe(0); + expect(stats[0].probationSendBitrate).toBe(0); + expect(stats[0].iceSelectedTuple).toBeUndefined(); + expect(stats[0].maxIncomingBitrate).toBeUndefined(); }, 2000); test('webRtcTransport.connect() succeeds', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { + listenInfos : + [ + { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } + ] + }); + const dtlsRemoteParameters: mediasoup.types.DtlsParameters = { fingerprints : @@ -278,29 +293,32 @@ test('webRtcTransport.connect() succeeds', async () => role : 'client' }; - await expect(transport.connect({ dtlsParameters: dtlsRemoteParameters })) + await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) .resolves .toBeUndefined(); // Must fail if connected. - await expect(transport.connect({ dtlsParameters: dtlsRemoteParameters })) + await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) .rejects .toThrow(Error); - expect(transport.dtlsParameters.role).toBe('server'); + expect(webRtcTransport.dtlsParameters.role).toBe('server'); }, 2000); -/** - * When are we going to rely on the type system in the API? - * We are testing invalid type values which adds extra checks in the code that should be - * simply guarded by the type system. - */ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { + listenInfos : + [ + { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } + ] + }); + let dtlsRemoteParameters: mediasoup.types.DtlsParameters; // @ts-ignore - await expect(transport.connect({})) + await expect(webRtcTransport.connect({})) .rejects .toThrow(TypeError); @@ -317,7 +335,7 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as role : 'client' }; - await expect(transport.connect({ dtlsParameters: dtlsRemoteParameters })) + await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) .rejects .toThrow(TypeError); @@ -334,7 +352,7 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as role : 'chicken' }; - await expect(transport.connect({ dtlsParameters: dtlsRemoteParameters })) + await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) .rejects .toThrow(TypeError); @@ -344,91 +362,120 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as role : 'client' }; - await expect(transport.connect({ dtlsParameters: dtlsRemoteParameters })) + await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) .rejects .toThrow(TypeError); - await expect(transport.connect({ dtlsParameters: dtlsRemoteParameters })) + await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) .rejects .toThrow(TypeError); - expect(transport.dtlsParameters.role).toBe('auto'); + expect(webRtcTransport.dtlsParameters.role).toBe('auto'); }, 2000); test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => { - await expect(transport.setMaxIncomingBitrate(1000000)) + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { + listenInfos : + [ + { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } + ] + }); + + await expect(webRtcTransport.setMaxIncomingBitrate(1000000)) .resolves .toBeUndefined(); // Remove limit. - await expect(transport.setMaxIncomingBitrate(0)) + await expect(webRtcTransport.setMaxIncomingBitrate(0)) .resolves .toBeUndefined(); }, 2000); test('webRtcTransport.setMaxOutgoingBitrate() succeeds', async () => { - await expect(transport.setMaxOutgoingBitrate(2000000)) + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + + await expect(webRtcTransport.setMaxOutgoingBitrate(2000000)) .resolves .toBeUndefined(); // Remove limit. - await expect(transport.setMaxOutgoingBitrate(0)) + await expect(webRtcTransport.setMaxOutgoingBitrate(0)) .resolves .toBeUndefined(); }, 2000); test('webRtcTransport.setMinOutgoingBitrate() succeeds', async () => { - await expect(transport.setMinOutgoingBitrate(100000)) + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + + await expect(webRtcTransport.setMinOutgoingBitrate(100000)) .resolves .toBeUndefined(); // Remove limit. - await expect(transport.setMinOutgoingBitrate(0)) + await expect(webRtcTransport.setMinOutgoingBitrate(0)) .resolves .toBeUndefined(); }, 2000); test('webRtcTransport.setMaxOutgoingBitrate() fails if value is lower than current min limit', async () => { - await expect(transport.setMinOutgoingBitrate(3000000)) + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + + await expect(webRtcTransport.setMinOutgoingBitrate(3000000)) .resolves .toBeUndefined(); - await expect(transport.setMaxOutgoingBitrate(2000000)) + await expect(webRtcTransport.setMaxOutgoingBitrate(2000000)) .rejects .toThrow(Error); // Remove limit. - await expect(transport.setMinOutgoingBitrate(0)) + await expect(webRtcTransport.setMinOutgoingBitrate(0)) .resolves .toBeUndefined(); }, 2000); test('webRtcTransport.setMinOutgoingBitrate() fails if value is higher than current max limit', async () => { - await expect(transport.setMaxOutgoingBitrate(2000000)) + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + + await expect(webRtcTransport.setMaxOutgoingBitrate(2000000)) .resolves .toBeUndefined(); - await expect(transport.setMinOutgoingBitrate(3000000)) + await expect(webRtcTransport.setMinOutgoingBitrate(3000000)) .rejects .toThrow(Error); // Remove limit. - await expect(transport.setMaxOutgoingBitrate(0)) + await expect(webRtcTransport.setMaxOutgoingBitrate(0)) .resolves .toBeUndefined(); }, 2000); test('webRtcTransport.restartIce() succeeds', async () => { - const previousIceUsernameFragment = transport.iceParameters.usernameFragment; - const previousIcePassword = transport.iceParameters.password; + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + + const previousIceUsernameFragment = + webRtcTransport.iceParameters.usernameFragment; + const previousIcePassword = webRtcTransport.iceParameters.password; - await expect(transport.restartIce()) + await expect(webRtcTransport.restartIce()) .resolves .toMatchObject( { @@ -437,72 +484,85 @@ test('webRtcTransport.restartIce() succeeds', async () => iceLite : true }); - expect(typeof transport.iceParameters.usernameFragment).toBe('string'); - expect(typeof transport.iceParameters.password).toBe('string'); - expect(transport.iceParameters.usernameFragment) + expect(typeof webRtcTransport.iceParameters.usernameFragment).toBe('string'); + expect(typeof webRtcTransport.iceParameters.password).toBe('string'); + expect(webRtcTransport.iceParameters.usernameFragment) .not.toBe(previousIceUsernameFragment); - expect(transport.iceParameters.password).not.toBe(previousIcePassword); + expect(webRtcTransport.iceParameters.password).not.toBe(previousIcePassword); }, 2000); test('transport.enableTraceEvent() succeed', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + // @ts-ignore - await transport.enableTraceEvent([ 'foo', 'probation' ]); - await expect(transport.dump()) + await webRtcTransport.enableTraceEvent([ 'foo', 'probation' ]); + await expect(webRtcTransport.dump()) .resolves .toMatchObject({ traceEventTypes: [ 'probation' ] }); - await transport.enableTraceEvent([]); - await expect(transport.dump()) + await webRtcTransport.enableTraceEvent([]); + await expect(webRtcTransport.dump()) .resolves .toMatchObject({ traceEventTypes: [] }); // @ts-ignore - await transport.enableTraceEvent([ 'probation', 'FOO', 'bwe', 'BAR' ]); - await expect(transport.dump()) + await webRtcTransport.enableTraceEvent([ 'probation', 'FOO', 'bwe', 'BAR' ]); + await expect(webRtcTransport.dump()) .resolves .toMatchObject({ traceEventTypes: [ 'probation', 'bwe' ] }); - await transport.enableTraceEvent(); - await expect(transport.dump()) + await webRtcTransport.enableTraceEvent(); + await expect(webRtcTransport.dump()) .resolves .toMatchObject({ traceEventTypes: [] }); }, 2000); test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + // @ts-ignore - await expect(transport.enableTraceEvent(123)) + await expect(webRtcTransport.enableTraceEvent(123)) .rejects .toThrow(TypeError); // @ts-ignore - await expect(transport.enableTraceEvent('probation')) + await expect(webRtcTransport.enableTraceEvent('probation')) .rejects .toThrow(TypeError); // @ts-ignore - await expect(transport.enableTraceEvent([ 'probation', 123.123 ])) + await expect(webRtcTransport.enableTraceEvent([ 'probation', 123.123 ])) .rejects .toThrow(TypeError); }, 2000); test('WebRtcTransport events succeed', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + // Private API. - const channel = transport.channelForTesting; + const channel = webRtcTransport.channelForTesting; const onIceStateChange = jest.fn(); - transport.on('icestatechange', onIceStateChange); + webRtcTransport.on('icestatechange', onIceStateChange); - // Simulate a 'iceselectedtuplechange' notification coming through the channel. + // Simulate a 'iceselectedtuplechange' notification coming through the + // channel. const builder = new flatbuffers.Builder(); const iceStateChangeNotification = new FbsWebRtcTransport.IceStateChangeNotificationT( FbsWebRtcTransport.IceState.COMPLETED); let notificationOffset = Notification.createNotification( builder, - builder.createString(transport.id), + builder.createString(webRtcTransport.id), Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, NotificationBody.WebRtcTransport_IceStateChangeNotification, iceStateChangeNotification.pack(builder) @@ -511,13 +571,18 @@ test('WebRtcTransport events succeed', async () => builder.finish(notificationOffset); let notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array())); + new flatbuffers.ByteBuffer(builder.asUint8Array()) + ); - channel.emit(transport.id, Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, notification); + channel.emit( + webRtcTransport.id, + Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, + notification + ); expect(onIceStateChange).toHaveBeenCalledTimes(1); expect(onIceStateChange).toHaveBeenCalledWith('completed'); - expect(transport.iceState).toBe('completed'); + expect(webRtcTransport.iceState).toBe('completed'); builder.clear(); @@ -531,7 +596,7 @@ test('WebRtcTransport events succeed', async () => protocol : 'udp' }; - transport.on('iceselectedtuplechange', onIceSelectedTuple); + webRtcTransport.on('iceselectedtuplechange', onIceSelectedTuple); // Simulate a 'icestatechange' notification coming through the channel. const iceSelectedTupleChangeNotification = @@ -541,12 +606,13 @@ test('WebRtcTransport events succeed', async () => iceSelectedTuple.localPort, iceSelectedTuple.remoteIp, iceSelectedTuple.remotePort, - serializeProtocol(iceSelectedTuple.protocol)) + serializeProtocol(iceSelectedTuple.protocol) + ) ); notificationOffset = Notification.createNotification( builder, - builder.createString(transport.id), + builder.createString(webRtcTransport.id), Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, NotificationBody.WebRtcTransport_IceSelectedTupleChangeNotification, iceSelectedTupleChangeNotification.pack(builder) @@ -555,20 +621,24 @@ test('WebRtcTransport events succeed', async () => builder.finish(notificationOffset); notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array())); + new flatbuffers.ByteBuffer(builder.asUint8Array()) + ); channel.emit( - transport.id, Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, notification); + webRtcTransport.id, + Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, + notification + ); expect(onIceSelectedTuple).toHaveBeenCalledTimes(1); expect(onIceSelectedTuple).toHaveBeenCalledWith(iceSelectedTuple); - expect(transport.iceSelectedTuple).toEqual(iceSelectedTuple); + expect(webRtcTransport.iceSelectedTuple).toEqual(iceSelectedTuple); builder.clear(); const onDtlsStateChange = jest.fn(); - transport.on('dtlsstatechange', onDtlsStateChange); + webRtcTransport.on('dtlsstatechange', onDtlsStateChange); // Simulate a 'dtlsstatechange' notification coming through the channel. const dtlsStateChangeNotification = new FbsWebRtcTransport.DtlsStateChangeNotificationT( @@ -576,7 +646,7 @@ test('WebRtcTransport events succeed', async () => notificationOffset = Notification.createNotification( builder, - builder.createString(transport.id), + builder.createString(webRtcTransport.id), Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, NotificationBody.WebRtcTransport_DtlsStateChangeNotification, dtlsStateChangeNotification.pack(builder) @@ -587,62 +657,69 @@ test('WebRtcTransport events succeed', async () => notification = Notification.getRootAsNotification( new flatbuffers.ByteBuffer(builder.asUint8Array())); - channel.emit(transport.id, Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, notification); + channel.emit( + webRtcTransport.id, + Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + notification + ); expect(onDtlsStateChange).toHaveBeenCalledTimes(1); expect(onDtlsStateChange).toHaveBeenCalledWith('connecting'); - expect(transport.dtlsState).toBe('connecting'); + expect(webRtcTransport.dtlsState).toBe('connecting'); }, 2000); test('WebRtcTransport methods reject if closed', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + const onObserverClose = jest.fn(); - transport.observer.once('close', onObserverClose); - transport.close(); + webRtcTransport.observer.once('close', onObserverClose); + webRtcTransport.close(); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(transport.closed).toBe(true); - expect(transport.iceState).toBe('closed'); - expect(transport.iceSelectedTuple).toBeUndefined(); - expect(transport.dtlsState).toBe('closed'); - expect(transport.sctpState).toBeUndefined(); + expect(webRtcTransport.closed).toBe(true); + expect(webRtcTransport.iceState).toBe('closed'); + expect(webRtcTransport.iceSelectedTuple).toBeUndefined(); + expect(webRtcTransport.dtlsState).toBe('closed'); + expect(webRtcTransport.sctpState).toBeUndefined(); - await expect(transport.dump()) + await expect(webRtcTransport.dump()) .rejects .toThrow(Error); - await expect(transport.getStats()) + await expect(webRtcTransport.getStats()) .rejects .toThrow(Error); // @ts-ignore - await expect(transport.connect({})) + await expect(webRtcTransport.connect({})) .rejects .toThrow(Error); - await expect(transport.setMaxIncomingBitrate(200000)) + await expect(webRtcTransport.setMaxIncomingBitrate(200000)) .rejects .toThrow(Error); - await expect(transport.setMaxOutgoingBitrate(200000)) + await expect(webRtcTransport.setMaxOutgoingBitrate(200000)) .rejects .toThrow(Error); - await expect(transport.setMinOutgoingBitrate(100000)) + await expect(webRtcTransport.setMinOutgoingBitrate(100000)) .rejects .toThrow(Error); - await expect(transport.restartIce()) + await expect(webRtcTransport.restartIce()) .rejects .toThrow(Error); }, 2000); test('router.createWebRtcTransport() with fixed port succeeds', async () => { - const port = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcTransport = await router.createWebRtcTransport( + const webRtcTransport = await ctx.router!.createWebRtcTransport( { listenInfos : [ @@ -658,47 +735,50 @@ test('router.createWebRtcTransport() with fixed port succeeds', async () => test('WebRtcTransport emits "routerclose" if Router is closed', async () => { - // We need different Router and WebRtcTransport instances here. - const router2 = await worker.createRouter({ mediaCodecs }); - const transport2 = await router2.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ], - enableSctp : true - }); + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenIps: [ '127.0.0.1' ], enableSctp: true } + ); + const onObserverClose = jest.fn(); - transport2.observer.once('close', onObserverClose); + webRtcTransport.observer.once('close', onObserverClose); await new Promise((resolve) => { - transport2.on('routerclose', resolve); - router2.close(); + webRtcTransport.on('routerclose', resolve); + + ctx.router!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(transport2.closed).toBe(true); - expect(transport2.iceState).toBe('closed'); - expect(transport2.iceSelectedTuple).toBeUndefined(); - expect(transport2.dtlsState).toBe('closed'); - expect(transport2.sctpState).toBe('closed'); + expect(webRtcTransport.closed).toBe(true); + expect(webRtcTransport.iceState).toBe('closed'); + expect(webRtcTransport.iceSelectedTuple).toBeUndefined(); + expect(webRtcTransport.dtlsState).toBe('closed'); + expect(webRtcTransport.sctpState).toBe('closed'); }, 2000); test('WebRtcTransport emits "routerclose" if Worker is closed', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); + const onObserverClose = jest.fn(); - transport.observer.once('close', onObserverClose); + webRtcTransport.observer.once('close', onObserverClose); await new Promise((resolve) => { - transport.on('routerclose', resolve); - worker.close(); + webRtcTransport.on('routerclose', resolve); + + ctx.worker!.close(); }); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(transport.closed).toBe(true); - expect(transport.iceState).toBe('closed'); - expect(transport.iceSelectedTuple).toBeUndefined(); - expect(transport.dtlsState).toBe('closed'); - expect(transport.sctpState).toBeUndefined(); + expect(webRtcTransport.closed).toBe(true); + expect(webRtcTransport.iceState).toBe('closed'); + expect(webRtcTransport.iceSelectedTuple).toBeUndefined(); + expect(webRtcTransport.dtlsState).toBe('closed'); + expect(webRtcTransport.sctpState).toBeUndefined(); }, 2000); diff --git a/node/src/test/test-mediasoup.ts b/node/src/test/test-mediasoup.ts index 0032e49322..294506d960 100644 --- a/node/src/test/test-mediasoup.ts +++ b/node/src/test/test-mediasoup.ts @@ -3,8 +3,9 @@ import * as path from 'node:path'; import * as mediasoup from '../'; const PKG = JSON.parse(fs.readFileSync( - path.join(__dirname, '..', '..', '..', 'package.json'), { encoding: 'utf-8' }) -); + path.join(__dirname, '..', '..', '..', 'package.json'), + { encoding: 'utf-8' } +)); const { version, diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index 27715f6e76..1ebc848084 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -5,11 +5,11 @@ import * as utils from '../utils'; type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; - audioProducerParameters: mediasoup.types.ProducerOptions; + audioProducerOptions: mediasoup.types.ProducerOptions; consumerDeviceCapabilities: mediasoup.types.RtpCapabilities; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; - transport?: mediasoup.types.WebRtcTransport; + webRtcTransport?: mediasoup.types.WebRtcTransport; }; const ctx: TestContext = @@ -32,7 +32,7 @@ const ctx: TestContext = } ] ), - audioProducerParameters : utils.deepFreeze( + audioProducerOptions : utils.deepFreeze( { kind : 'audio', rtpParameters : @@ -114,11 +114,12 @@ const ctx: TestContext = beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); - ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); - ctx.transport = await ctx.router.createWebRtcTransport( - { - listenInfos : [ { protocol: 'udp', ip: '127.0.0.1' } ] - }); + ctx.router = await ctx.worker.createRouter( + { mediaCodecs: ctx.mediaCodecs } + ); + ctx.webRtcTransport = await ctx.router.createWebRtcTransport( + { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } + ); }); afterEach(() => @@ -128,7 +129,9 @@ afterEach(() => test('produce() and consume() succeed', async () => { - const audioProducer = await ctx.transport!.produce(ctx.audioProducerParameters); + const audioProducer = await ctx.webRtcTransport!.produce( + ctx.audioProducerOptions + ); expect(audioProducer.rtpParameters.codecs).toEqual([ { @@ -154,10 +157,11 @@ test('produce() and consume() succeed', async () => }) ).toBe(true); - const audioConsumer = await ctx.transport!.consume({ - producerId : audioProducer.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); + const audioConsumer = await ctx.webRtcTransport!.consume( + { + producerId : audioProducer.id, + rtpCapabilities : ctx.consumerDeviceCapabilities + }); expect(audioConsumer.rtpParameters.codecs).toEqual([ { @@ -179,60 +183,64 @@ test('produce() and consume() succeed', async () => test('fails to produce wrong parameters', async () => { - await expect(ctx.transport!.produce({ - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ - { - mimeType : 'audio/multiopus', - payloadType : 0, - clockRate : 48000, - channels : 6, - parameters : - { - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 2, - 'coupled_streams' : 2 - } - } - ] - } - })) + await expect(ctx.webRtcTransport!.produce( + { + kind : 'audio', + rtpParameters : + { + mid : 'AUDIO', + codecs : + [ + { + mimeType : 'audio/multiopus', + payloadType : 0, + clockRate : 48000, + channels : 6, + parameters : + { + 'channel_mapping' : '0,4,1,2,3,5', + 'num_streams' : 2, + 'coupled_streams' : 2 + } + } + ] + } + })) .rejects .toThrow(UnsupportedError); - await expect(ctx.transport!.produce({ - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ - { - mimeType : 'audio/multiopus', - payloadType : 0, - clockRate : 48000, - channels : 6, - parameters : - { - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 1 - } - } - ] - } - })) + await expect(ctx.webRtcTransport!.produce( + { + kind : 'audio', + rtpParameters : + { + mid : 'AUDIO', + codecs : + [ + { + mimeType : 'audio/multiopus', + payloadType : 0, + clockRate : 48000, + channels : 6, + parameters : + { + 'channel_mapping' : '0,4,1,2,3,5', + 'num_streams' : 4, + 'coupled_streams' : 1 + } + } + ] + } + })) .rejects .toThrow(UnsupportedError); }, 2000); test('fails to consume wrong channels', async () => { - const audioProducer = await ctx.transport!.produce(ctx.audioProducerParameters); + const audioProducer = await ctx.webRtcTransport!.produce( + ctx.audioProducerOptions + ); const localConsumerDeviceCapabilities: mediasoup.types.RtpCapabilities = { codecs : @@ -253,16 +261,18 @@ test('fails to consume wrong channels', async () => ] }; - expect(!ctx.router!.canConsume({ - producerId : audioProducer.id, - rtpCapabilities : localConsumerDeviceCapabilities - })) + expect(!ctx.router!.canConsume( + { + producerId : audioProducer.id, + rtpCapabilities : localConsumerDeviceCapabilities + })) .toBe(true); - await expect(ctx.transport!.consume({ - producerId : audioProducer.id, - rtpCapabilities : localConsumerDeviceCapabilities - })) + await expect(ctx.webRtcTransport!.consume( + { + producerId : audioProducer.id, + rtpCapabilities : localConsumerDeviceCapabilities + })) .rejects .toThrow(Error); }, 2000); diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index 12bef370f2..b9a3b0ff5d 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -7,7 +7,7 @@ type TestContext = { worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; - transport?: mediasoup.types.PlainTransport; + plainTransport?: mediasoup.types.PlainTransport; dataProducer?: mediasoup.types.DataProducer; dataConsumer?: mediasoup.types.DataConsumer; udpSocket?: dgram.Socket; @@ -25,10 +25,12 @@ beforeEach(async () => ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter(); - ctx.transport = await ctx.router.createPlainTransport( + ctx.plainTransport = await ctx.router.createPlainTransport( { - listenIp : '127.0.0.1', // https://github.com/nodejs/node/issues/14900 - comedia : true, // So we don't need to call transport.connect(). + // https://github.com/nodejs/node/issues/14900. + listenIp : '127.0.0.1', + // So we don't need to call plainTransport.connect(). + comedia : true, enableSctp : true, numSctpStreams : { OS: 256, MIS: 256 } }); @@ -41,9 +43,9 @@ beforeEach(async () => ctx.udpSocket!.bind(0, '127.0.0.1', resolve); }); - const remoteUdpIp = ctx.transport.tuple.localIp; - const remoteUdpPort = ctx.transport.tuple.localPort; - const { OS, MIS } = ctx.transport.sctpParameters!; + const remoteUdpIp = ctx.plainTransport.tuple.localIp; + const remoteUdpPort = ctx.plainTransport.tuple.localPort; + const { OS, MIS } = ctx.plainTransport.sctpParameters!; await new Promise((resolve, reject) => { @@ -85,7 +87,7 @@ beforeEach(async () => ctx.sctpSendStream = ctx.sctpSocket.createStream(ctx.sctpSendStreamId); // Create a DataProducer with the corresponding SCTP stream id. - ctx.dataProducer = await ctx.transport.produceData( + ctx.dataProducer = await ctx.plainTransport.produceData( { sctpStreamParameters : { @@ -97,8 +99,8 @@ beforeEach(async () => }); // Create a DataConsumer to receive messages from the DataProducer over the - // same transport. - ctx.dataConsumer = await ctx.transport.consumeData( + // same plainTransport. + ctx.dataConsumer = await ctx.plainTransport.consumeData( { dataProducerId: ctx.dataProducer.id } ); }); @@ -124,7 +126,7 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn let numSentMessages = 0; let numReceivedMessages = 0; - // It must be zero because it's the first DataConsumer on the transport. + // It must be zero because it's the first DataConsumer on the plainTransport. expect(ctx.dataConsumer!.sctpStreamParameters?.streamId).toBe(0); // eslint-disable-next-line no-async-promise-executor diff --git a/node/src/test/test-ortc.ts b/node/src/test/test-ortc.ts index 40801e3e9c..94bab10103 100644 --- a/node/src/test/test-ortc.ts +++ b/node/src/test/test-ortc.ts @@ -279,8 +279,9 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum } }; - const rtpMapping = - ortc.getProducerRtpParametersMapping(rtpParameters, routerRtpCapabilities); + const rtpMapping = ortc.getProducerRtpParametersMapping( + rtpParameters, routerRtpCapabilities + ); expect(rtpMapping.codecs).toEqual( [ @@ -299,7 +300,8 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(typeof rtpMapping.encodings[2].mappedSsrc).toBe('number'); const consumableRtpParameters = ortc.getConsumableRtpParameters( - 'video', rtpParameters, routerRtpCapabilities, rtpMapping); + 'video', rtpParameters, routerRtpCapabilities, rtpMapping + ); expect(consumableRtpParameters.codecs[0].mimeType).toBe('video/H264'); expect(consumableRtpParameters.codecs[0].payloadType).toBe(101); @@ -510,8 +512,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum { consumableRtpParameters, enableRtx : false - } - ); + }); expect(pipeConsumerRtpParameters.codecs.length).toEqual(1); expect(pipeConsumerRtpParameters.codecs[0]).toEqual( @@ -603,8 +604,7 @@ test('getProducerRtpParametersMapping() with incompatible params throws Unsuppor } }; - expect( - () => ortc.getProducerRtpParametersMapping( - rtpParameters, routerRtpCapabilities - )).toThrow(UnsupportedError); + expect(() => ortc.getProducerRtpParametersMapping( + rtpParameters, routerRtpCapabilities + )).toThrow(UnsupportedError); }); From 017303f390b07ba0b73433cd91bf3708ec42fe04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 6 Jan 2024 19:06:16 +0100 Subject: [PATCH 303/525] Update NPM eslint deps --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2916632477..279199fa28 100644 --- a/package.json +++ b/package.json @@ -110,8 +110,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.6", - "@typescript-eslint/eslint-plugin": "^6.17.0", - "@typescript-eslint/parser": "^6.17.0", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", "eslint": "^8.56.0", "eslint-plugin-jest": "^27.6.1", "jest": "^29.7.0", From bca9b0d7e8eda3654fab83861ff889920fc0968b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 7 Jan 2024 19:07:08 +0100 Subject: [PATCH 304/525] Use Prettier (#1302) --- node/.eslintignore => .eslintignore | 0 .eslintrc.js | 178 ++ .gitignore | 2 - .prettierignore | 18 + .prettierrc.json | 10 + doc/Building.md | 20 +- node/.eslintrc.js | 259 --- node/src/ActiveSpeakerObserver.ts | 86 +- node/src/AudioLevelObserver.ts | 124 +- node/src/Channel.ts | 327 ++-- node/src/Consumer.ts | 758 ++++----- node/src/DataConsumer.ts | 551 +++---- node/src/DataProducer.ts | 331 ++-- node/src/DirectTransport.ts | 172 +- node/src/EnhancedEventEmitter.ts | 78 +- node/src/Logger.ts | 22 +- node/src/PipeTransport.ts | 355 ++-- node/src/PlainTransport.ts | 350 ++-- node/src/Producer.ts | 447 +++-- node/src/Router.ts | 1355 +++++++-------- node/src/RtpObserver.ts | 131 +- node/src/RtpParameters.ts | 423 +++-- node/src/RtpStream.ts | 110 +- node/src/SctpParameters.ts | 90 +- node/src/SrtpParameters.ts | 66 +- node/src/Transport.ts | 1209 +++++++------- node/src/WebRtcServer.ts | 186 +-- node/src/WebRtcTransport.ts | 644 ++++---- node/src/Worker.ts | 527 +++--- node/src/errors.ts | 32 +- node/src/index.ts | 61 +- node/src/ortc.ts | 1072 +++++------- node/src/scalabilityModes.ts | 27 +- node/src/supportedRtpCapabilities.ts | 500 +++--- node/src/test/test-ActiveSpeakerObserver.ts | 107 +- node/src/test/test-AudioLevelObserver.ts | 125 +- node/src/test/test-Consumer.ts | 1649 +++++++++---------- node/src/test/test-DataConsumer.ts | 398 ++--- node/src/test/test-DataProducer.ts | 320 ++-- node/src/test/test-DirectTransport.ts | 315 ++-- node/src/test/test-PipeTransport.ts | 1464 ++++++++-------- node/src/test/test-PlainTransport.ts | 624 ++++--- node/src/test/test-Producer.ts | 1106 ++++++------- node/src/test/test-Router.ts | 174 +- node/src/test/test-WebRtcServer.ts | 606 +++---- node/src/test/test-WebRtcTransport.ts | 702 ++++---- node/src/test/test-Worker.ts | 243 ++- node/src/test/test-mediasoup.ts | 117 +- node/src/test/test-multiopus.ts | 411 +++-- node/src/test/test-node-sctp.ts | 190 +-- node/src/test/test-ortc.ts | 844 +++++----- node/src/types.ts | 9 +- node/src/utils.ts | 121 +- npm-scripts.mjs | 495 +++--- package-lock.json | 506 ++++-- package.json | 5 + worker/scripts/clang-format.mjs | 69 +- 57 files changed, 9636 insertions(+), 11485 deletions(-) rename node/.eslintignore => .eslintignore (100%) create mode 100644 .eslintrc.js create mode 100644 .prettierignore create mode 100644 .prettierrc.json delete mode 100644 node/.eslintrc.js diff --git a/node/.eslintignore b/.eslintignore similarity index 100% rename from node/.eslintignore rename to .eslintignore diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..e69646071b --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,178 @@ +const eslintConfig = { + env: { + es6: true, + node: true, + }, + plugins: ['prettier'], + settings: {}, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + ecmaFeatures: { + impliedStrict: true, + }, + lib: ['es2022'], + }, + globals: { + NodeJS: 'readonly', + }, + extends: ['eslint:recommended', 'plugin:prettier/recommended'], + rules: { + 'prettier/prettier': 2, + 'constructor-super': 2, + curly: [2, 'all'], + // Unfortunatelly `curly` does not apply to blocks in `switch` cases so + // this is needed. + 'no-restricted-syntax': [ + 2, + { + selector: 'SwitchCase > *.consequent[type!="BlockStatement"]', + message: 'Switch cases without blocks are disallowed', + }, + ], + 'guard-for-in': 2, + 'newline-after-var': 2, + 'newline-before-return': 2, + 'no-alert': 2, + 'no-caller': 2, + 'no-case-declarations': 2, + 'no-catch-shadow': 2, + 'no-class-assign': 2, + 'no-console': 2, + 'no-const-assign': 2, + 'no-debugger': 2, + 'no-dupe-args': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-div-regex': 2, + 'no-empty': [2, { allowEmptyCatch: true }], + 'no-empty-pattern': 2, + 'no-else-return': 0, + 'no-eval': 2, + 'no-extend-native': 2, + 'no-ex-assign': 2, + 'no-extra-bind': 2, + 'no-extra-boolean-cast': 2, + 'no-extra-label': 2, + 'no-fallthrough': 2, + 'no-func-assign': 2, + 'no-global-assign': 2, + 'no-implicit-coercion': 2, + 'no-implicit-globals': 2, + 'no-inner-declarations': 2, + 'no-invalid-regexp': 2, + 'no-invalid-this': 2, + 'no-irregular-whitespace': 2, + 'no-lonely-if': 2, + 'no-multi-str': 2, + 'no-native-reassign': 2, + 'no-negated-in-lhs': 2, + 'no-new': 2, + 'no-new-func': 2, + 'no-new-wrappers': 2, + 'no-obj-calls': 2, + 'no-proto': 2, + 'no-prototype-builtins': 0, + 'no-redeclare': 2, + 'no-regex-spaces': 2, + 'no-restricted-imports': 2, + 'no-return-assign': 2, + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow': 2, + 'no-shadow-restricted-names': 2, + 'no-sparse-arrays': 2, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-undef': 2, + 'no-unmodified-loop-condition': 2, + 'no-unreachable': 2, + 'no-unused-vars': [1, { vars: 'all', args: 'after-used' }], + 'no-use-before-define': 0, + 'no-useless-call': 2, + 'no-useless-computed-key': 2, + 'no-useless-concat': 2, + 'no-useless-rename': 2, + 'no-var': 2, + 'object-curly-newline': 0, + 'prefer-const': 2, + 'prefer-rest-params': 2, + 'prefer-spread': 2, + 'prefer-template': 2, + 'spaced-comment': [2, 'always'], + strict: 2, + 'valid-typeof': 2, + yoda: 2, + }, + overrides: [], +}; + +const tsRules = { + 'no-unused-vars': 0, + '@typescript-eslint/ban-types': 0, + '@typescript-eslint/ban-ts-comment': 0, + '@typescript-eslint/ban-ts-ignore': 0, + '@typescript-eslint/explicit-module-boundary-types': 0, + '@typescript-eslint/semi': 2, + '@typescript-eslint/member-delimiter-style': [ + 2, + { + multiline: { delimiter: 'semi', requireLast: true }, + singleline: { delimiter: 'semi', requireLast: false }, + }, + ], + '@typescript-eslint/no-explicit-any': 0, + '@typescript-eslint/no-unused-vars': [ + 2, + { + vars: 'all', + args: 'after-used', + ignoreRestSiblings: false, + }, + ], + '@typescript-eslint/no-use-before-define': [2, { functions: false }], + '@typescript-eslint/no-empty-function': 0, + '@typescript-eslint/no-non-null-assertion': 0, +}; + +eslintConfig.overrides.push({ + files: ['*.ts'], + parser: '@typescript-eslint/parser', + parserOptions: { + ...eslintConfig.parserOptions, + project: 'node/tsconfig.json', + }, + plugins: [...eslintConfig.plugins, '@typescript-eslint'], + extends: [ + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + ...eslintConfig.extends, + ], + rules: { ...eslintConfig.rules, ...tsRules }, +}); + +eslintConfig.overrides.push({ + files: ['node/src/test/*.ts'], + parserOptions: { + ...eslintConfig.parserOptions, + project: 'node/tsconfig.json', + }, + env: { + ...eslintConfig.env, + 'jest/globals': true, + }, + extends: [ + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + ...eslintConfig.extends, + ], + plugins: [...eslintConfig.plugins, '@typescript-eslint', 'jest'], + rules: { + ...eslintConfig.rules, + ...tsRules, + 'jest/no-disabled-tests': 2, + }, +}); + +module.exports = eslintConfig; diff --git a/.gitignore b/.gitignore index 027c5a99f3..e2f65fca29 100644 --- a/.gitignore +++ b/.gitignore @@ -30,8 +30,6 @@ # Ignore all fuzzer generated test inputs. /worker/fuzzer/new-corpus/* !/worker/fuzzer/new-corpus/.placeholder -# lcov is just for local usage. -/worker/lcov ## Others. /coverage diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..a9b8d7020d --- /dev/null +++ b/.prettierignore @@ -0,0 +1,18 @@ +/.cache +/art +/coverage +/doc +/node/lib +/node/src/fbs +/rust +/target +/worker/deps +/worker/fbs +/worker/fuzzer +/worker/include +/worker/prebuild +/worker/pip_invoke +/worker/src +/worker/subprojects +/worker/test +/worker/out diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000000..7cae653bfe --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "useTabs": true, + "tabWidth": 2, + "arrowParens": "avoid", + "bracketSpacing": true, + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "endOfLine": "auto" +} diff --git a/doc/Building.md b/doc/Building.md index 3ca30758e7..944b3e2502 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -34,6 +34,14 @@ Validates mediasoup JavaScript files using [ESLint](https://eslint.org). Validates mediasoup worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It invokes `invoke lint` below. +### `npm run format` + +Runs both `npm run format:node` and `npm run format:worker`. + +### `npm run format:node` + +Format TypeScript and JavaScript code using [Prettier](https://prettier.io). + ### `npm run format:worker` Rewrites mediasoup worker C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It invokes `invoke format` below. @@ -90,7 +98,7 @@ Tasks are defined in `worker/tasks.py`. For development purposes, developers or See all the tasks by running `invoke --list` within the `worker` folder. -*NOTE:* For some of these tasks to work, npm dependencies of `worker/scripts/package.json` must be installed: +_NOTE:_ For some of these tasks to work, npm dependencies of `worker/scripts/package.json` must be installed: ```bash npm ci --prefix worker/scripts @@ -189,8 +197,8 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy) and performs C++ code **Requirements:** -* `invoke clean` and `invoke mediasoup-worker` must have been called first. -* [PyYAML](https://pyyaml.org) is required. +- `invoke clean` and `invoke mediasoup-worker` must have been called first. +- [PyYAML](https://pyyaml.org) is required. - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. "MEDIASOUP_TIDY_CHECKS" environment variable with a comma separated list of checks overrides the checks defined in `.clang-tidy` file. @@ -201,9 +209,9 @@ Builds the `mediasoup-worker-fuzzer` binary (which uses [libFuzzer](http://llvm. **Requirements:** -* Linux with fuzzer capable clang++. -* `CC` environment variable must point to "clang". -* `CXX` environment variable must point to "clang++". +- Linux with fuzzer capable clang++. +- `CC` environment variable must point to "clang". +- `CXX` environment variable must point to "clang++". Read the [Fuzzer](Fuzzer.md) documentation for detailed information. diff --git a/node/.eslintrc.js b/node/.eslintrc.js deleted file mode 100644 index 687dcf1898..0000000000 --- a/node/.eslintrc.js +++ /dev/null @@ -1,259 +0,0 @@ -const os = require('os'); - -const isWindows = os.platform() === 'win32'; - -const eslintConfig = -{ - env : - { - es6 : true, - node : true - }, - plugins : [], - settings : {}, - parserOptions : - { - ecmaVersion : 2022, - sourceType : 'module', - ecmaFeatures : - { - impliedStrict : true - }, - lib : [ 'es2022' ], - project : 'node/tsconfig.json' - }, - globals : - { - NodeJS : 'readonly' - }, - rules : - { - 'array-bracket-spacing' : [ 2, 'always', - { - objectsInArrays : true, - arraysInArrays : true - } - ], - 'arrow-parens' : [ 2, 'always' ], - 'arrow-spacing' : 2, - 'block-spacing' : [ 2, 'always' ], - 'brace-style' : [ 2, 'allman', { allowSingleLine: true } ], - 'camelcase' : 2, - 'comma-dangle' : 2, - 'comma-spacing' : [ 2, { before: false, after: true } ], - 'comma-style' : 2, - 'computed-property-spacing' : 2, - 'constructor-super' : 2, - 'curly' : [ 2, 'all' ], - // Unfortunatelly `curly` does not apply to blocks in `switch` cases so - // this is needed. - 'no-restricted-syntax' : [ 2, - { - 'selector' : 'SwitchCase > *.consequent[type!="BlockStatement"]', - 'message' : 'Switch cases without blocks are disallowed' - } - ], - 'func-call-spacing' : 2, - 'generator-star-spacing' : 2, - 'guard-for-in' : 2, - 'indent' : [ 2, 'tab', { 'SwitchCase': 1 } ], - 'key-spacing' : [ 2, - { - singleLine : - { - beforeColon : false, - afterColon : true - }, - multiLine : - { - beforeColon : true, - afterColon : true, - mode : 'minimum', - align : 'colon' - } - } - ], - 'keyword-spacing' : 2, - 'linebreak-style' : [ 2, isWindows ? 'windows' : 'unix' ], - 'lines-around-comment' : [ 2, - { - allowBlockStart : true, - allowObjectStart : true, - beforeBlockComment : false, - beforeLineComment : false - } - ], - 'max-len' : [ 2, 100, - { - tabWidth : 2, - comments : 88, - ignoreUrls : true, - ignoreStrings : true, - ignoreTemplateLiterals : true, - ignoreRegExpLiterals : true - } - ], - 'newline-after-var' : 2, - 'newline-before-return' : 2, - 'newline-per-chained-call' : 2, - 'no-alert' : 2, - 'no-caller' : 2, - 'no-case-declarations' : 2, - 'no-catch-shadow' : 2, - 'no-class-assign' : 2, - 'no-confusing-arrow' : 2, - 'no-console' : 2, - 'no-const-assign' : 2, - 'no-debugger' : 2, - 'no-dupe-args' : 2, - 'no-dupe-keys' : 2, - 'no-duplicate-case' : 2, - 'no-div-regex' : 2, - 'no-empty' : [ 2, { allowEmptyCatch: true } ], - 'no-empty-pattern' : 2, - 'no-else-return' : 0, - 'no-eval' : 2, - 'no-extend-native' : 2, - 'no-ex-assign' : 2, - 'no-extra-bind' : 2, - 'no-extra-boolean-cast' : 2, - 'no-extra-label' : 2, - 'no-extra-semi' : 2, - 'no-fallthrough' : 2, - 'no-func-assign' : 2, - 'no-global-assign' : 2, - 'no-implicit-coercion' : 2, - 'no-implicit-globals' : 2, - 'no-inner-declarations' : 2, - 'no-invalid-regexp' : 2, - 'no-invalid-this' : 2, - 'no-irregular-whitespace' : 2, - 'no-lonely-if' : 2, - 'no-mixed-operators' : 2, - 'no-mixed-spaces-and-tabs' : 2, - 'no-multi-spaces' : 2, - 'no-multi-str' : 2, - 'no-multiple-empty-lines' : [ 1, { max: 1, maxEOF: 0, maxBOF: 0 } ], - 'no-native-reassign' : 2, - 'no-negated-in-lhs' : 2, - 'no-new' : 2, - 'no-new-func' : 2, - 'no-new-wrappers' : 2, - 'no-obj-calls' : 2, - 'no-proto' : 2, - 'no-prototype-builtins' : 0, - 'no-redeclare' : 2, - 'no-regex-spaces' : 2, - 'no-restricted-imports' : 2, - 'no-return-assign' : 2, - 'no-self-assign' : 2, - 'no-self-compare' : 2, - 'no-sequences' : 2, - 'no-shadow' : 2, - 'no-shadow-restricted-names' : 2, - 'no-spaced-func' : 2, - 'no-sparse-arrays' : 2, - 'no-this-before-super' : 2, - 'no-throw-literal' : 2, - 'no-undef' : 2, - 'no-unexpected-multiline' : 2, - 'no-unmodified-loop-condition' : 2, - 'no-unreachable' : 2, - 'no-unused-vars' : [ 1, { vars: 'all', args: 'after-used' } ], - 'no-use-before-define' : 0, - 'no-useless-call' : 2, - 'no-useless-computed-key' : 2, - 'no-useless-concat' : 2, - 'no-useless-rename' : 2, - 'no-var' : 2, - 'no-whitespace-before-property' : 2, - 'object-curly-newline' : 0, - 'object-curly-spacing' : [ 2, 'always' ], - 'object-property-newline' : [ 2, { allowMultiplePropertiesPerLine: true } ], - 'prefer-const' : 2, - 'prefer-rest-params' : 2, - 'prefer-spread' : 2, - 'prefer-template' : 2, - 'quotes' : [ 2, 'single', - { - avoidEscape : true, - allowTemplateLiterals : true - } - ], - 'semi' : [ 2, 'always' ], - 'semi-spacing' : 2, - 'space-before-blocks' : 2, - 'space-before-function-paren' : [ 2, - { - anonymous : 'never', - named : 'never', - asyncArrow : 'always' - } - ], - 'space-in-parens' : [ 2, 'never' ], - 'space-infix-ops' : [ 2, { 'int32Hint': false } ], - 'spaced-comment' : [ 2, 'always' ], - 'strict' : 2, - 'valid-typeof' : 2, - 'yoda' : 2 - }, - overrides : [] -}; - -eslintConfig.overrides.push( - { - files : [ '*.ts' ], - parser : '@typescript-eslint/parser', - plugins : [ - ...eslintConfig.plugins, - '@typescript-eslint' - ], - extends : [ - 'eslint:recommended', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended' - ], - rules : { - ...eslintConfig.rules, - 'no-unused-vars' : 0, - '@typescript-eslint/ban-types' : 0, - '@typescript-eslint/ban-ts-comment' : 0, - '@typescript-eslint/ban-ts-ignore' : 0, - '@typescript-eslint/explicit-module-boundary-types' : 0, - '@typescript-eslint/semi' : 2, - '@typescript-eslint/member-delimiter-style' : [ 2, - { - multiline : { delimiter: 'semi', requireLast: true }, - singleline : { delimiter: 'semi', requireLast: false } - } - ], - '@typescript-eslint/no-explicit-any' : 0, - '@typescript-eslint/no-unused-vars' : [ 2, - { - vars : 'all', - args : 'after-used', - ignoreRestSiblings : false - } - ], - '@typescript-eslint/no-use-before-define' : [ 2, { functions: false } ], - '@typescript-eslint/no-empty-function' : 0, - '@typescript-eslint/no-non-null-assertion' : 0 - } - }); - -eslintConfig.overrides.push( - { - files : [ '*.ts' ], - env : - { - ...eslintConfig.env, - 'jest/globals' : true - }, - plugins : - [ - ...eslintConfig.plugins, - 'jest' - ] - }); - -module.exports = eslintConfig; diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index 5a7aefbc66..6ac2825451 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -4,15 +4,16 @@ import { RtpObserver, RtpObserverEvents, RtpObserverObserverEvents, - RtpObserverConstructorOptions + RtpObserverConstructorOptions, } from './RtpObserver'; import { Producer } from './Producer'; import { AppData } from './types'; import { Event, Notification } from './fbs/notification'; import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; -export type ActiveSpeakerObserverOptions = -{ +export type ActiveSpeakerObserverOptions< + ActiveSpeakerObserverAppData extends AppData = AppData, +> = { interval?: number; /** @@ -21,21 +22,18 @@ export type ActiveSpeakerObserverOptions = const logger = new Logger('ActiveSpeakerObserver'); -export class ActiveSpeakerObserver - extends RtpObserver -{ +export class ActiveSpeakerObserver< + ActiveSpeakerObserverAppData extends AppData = AppData, +> extends RtpObserver< + ActiveSpeakerObserverAppData, + ActiveSpeakerObserverEvents +> { /** * @private */ - constructor(options: RtpObserverObserverConstructorOptions) - { + constructor( + options: RtpObserverObserverConstructorOptions, + ) { super(options); this.handleWorkerNotifications(); @@ -60,46 +62,42 @@ export class ActiveSpeakerObserver - { + get observer(): EnhancedEventEmitter { return super.observer; } - private handleWorkerNotifications(): void - { - this.channel.on(this.internal.rtpObserverId, (event: Event, data?: Notification) => - { - switch (event) - { - case Event.ACTIVESPEAKEROBSERVER_DOMINANT_SPEAKER: - { - const notification = new FbsActiveSpeakerObserver.DominantSpeakerNotification(); + private handleWorkerNotifications(): void { + this.channel.on( + this.internal.rtpObserverId, + (event: Event, data?: Notification) => { + switch (event) { + case Event.ACTIVESPEAKEROBSERVER_DOMINANT_SPEAKER: { + const notification = + new FbsActiveSpeakerObserver.DominantSpeakerNotification(); - data!.body(notification); + data!.body(notification); - const producer = this.getProducerById(notification.producerId()!); + const producer = this.getProducerById(notification.producerId()!); - if (!producer) - { - break; - } + if (!producer) { + break; + } - const dominantSpeaker: ActiveSpeakerObserverDominantSpeaker = - { - producer - }; + const dominantSpeaker: ActiveSpeakerObserverDominantSpeaker = { + producer, + }; - this.safeEmit('dominantspeaker', dominantSpeaker); - this.observer.safeEmit('dominantspeaker', dominantSpeaker); + this.safeEmit('dominantspeaker', dominantSpeaker); + this.observer.safeEmit('dominantspeaker', dominantSpeaker); - break; - } + break; + } - default: - { - logger.error('ignoring unknown event "%s"', event); + default: { + logger.error('ignoring unknown event "%s"', event); + } } - } - }); + }, + ); } } diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index 1dda1ca4b8..39a22472da 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -4,7 +4,7 @@ import { RtpObserver, RtpObserverEvents, RtpObserverObserverEvents, - RtpObserverConstructorOptions + RtpObserverConstructorOptions, } from './RtpObserver'; import { Producer } from './Producer'; import { AppData } from './types'; @@ -12,8 +12,9 @@ import * as utils from './utils'; import { Event, Notification } from './fbs/notification'; import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; -export type AudioLevelObserverOptions = -{ +export type AudioLevelObserverOptions< + AudioLevelObserverAppData extends AppData = AppData, +> = { /** * Maximum number of entries in the 'volumes”' event. Default 1. */ @@ -36,8 +37,7 @@ export type AudioLevelObserverOptions = const logger = new Logger('AudioLevelObserver'); -export class AudioLevelObserver - extends RtpObserver -{ +export class AudioLevelObserver< + AudioLevelObserverAppData extends AppData = AppData, +> extends RtpObserver { /** * @private */ - constructor(options: AudioLevelObserverConstructorOptions) - { + constructor( + options: AudioLevelObserverConstructorOptions, + ) { super(options); this.handleWorkerNotifications(); @@ -83,72 +82,73 @@ export class AudioLevelObserver - { + get observer(): EnhancedEventEmitter { return super.observer; } - private handleWorkerNotifications(): void - { - this.channel.on(this.internal.rtpObserverId, (event: Event, data?: Notification) => - { - switch (event) - { - case Event.AUDIOLEVELOBSERVER_VOLUMES: - { - const notification = new FbsAudioLevelObserver.VolumesNotification(); - - data!.body(notification); - - // Get the corresponding Producer instance and remove entries with - // no Producer (it may have been closed in the meanwhile). - const volumes: AudioLevelObserverVolume[] = - utils.parseVector(notification, 'volumes', parseVolume) - .map(({ producerId, volume }: { producerId: string; volume: number }) => ( - { - producer : this.getProducerById(producerId)!, - volume - } - )) + private handleWorkerNotifications(): void { + this.channel.on( + this.internal.rtpObserverId, + (event: Event, data?: Notification) => { + switch (event) { + case Event.AUDIOLEVELOBSERVER_VOLUMES: { + const notification = + new FbsAudioLevelObserver.VolumesNotification(); + + data!.body(notification); + + // Get the corresponding Producer instance and remove entries with + // no Producer (it may have been closed in the meanwhile). + const volumes: AudioLevelObserverVolume[] = utils + .parseVector(notification, 'volumes', parseVolume) + .map( + ({ + producerId, + volume, + }: { + producerId: string; + volume: number; + }) => ({ + producer: this.getProducerById(producerId)!, + volume, + }), + ) .filter(({ producer }: { producer: Producer }) => producer); - if (volumes.length > 0) - { - this.safeEmit('volumes', volumes); + if (volumes.length > 0) { + this.safeEmit('volumes', volumes); - // Emit observer event. - this.observer.safeEmit('volumes', volumes); - } + // Emit observer event. + this.observer.safeEmit('volumes', volumes); + } - break; - } + break; + } - case Event.AUDIOLEVELOBSERVER_SILENCE: - { - this.safeEmit('silence'); + case Event.AUDIOLEVELOBSERVER_SILENCE: { + this.safeEmit('silence'); - // Emit observer event. - this.observer.safeEmit('silence'); + // Emit observer event. + this.observer.safeEmit('silence'); - break; - } + break; + } - default: - { - logger.error('ignoring unknown event "%s"', event); + default: { + logger.error('ignoring unknown event "%s"', event); + } } - } - }); + }, + ); } } function parseVolume(binary: FbsAudioLevelObserver.Volume): { producerId: string; volume: number; -} -{ +} { return { - producerId : binary.producerId()!, - volume : binary.volume() + producerId: binary.producerId()!, + volume: binary.volume(), }; } diff --git a/node/src/Channel.ts b/node/src/Channel.ts index 00d0d25ce1..7e1c719612 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -10,7 +10,7 @@ import { Message, Body as MessageBody } from './fbs/message'; import { Notification, Body as NotificationBody, - Event + Event, } from './fbs/notification'; import { Log } from './fbs/log'; @@ -18,8 +18,7 @@ const IS_LITTLE_ENDIAN = os.endianness() === 'LE'; const logger = new Logger('Channel'); -type Sent = -{ +type Sent = { id: number; method: string; resolve: (data?: any) => void; @@ -31,8 +30,7 @@ type Sent = const MESSAGE_MAX_LEN = 4194308; const PAYLOAD_MAX_LEN = 4194304; -export class Channel extends EnhancedEventEmitter -{ +export class Channel extends EnhancedEventEmitter { // Closed flag. #closed = false; @@ -52,23 +50,20 @@ export class Channel extends EnhancedEventEmitter #recvBuffer = Buffer.alloc(0); // flatbuffers builder. - #bufferBuilder:flatbuffers.Builder = new flatbuffers.Builder(1024); + #bufferBuilder: flatbuffers.Builder = new flatbuffers.Builder(1024); /** * @private */ - constructor( - { - producerSocket, - consumerSocket, - pid - }: - { - producerSocket: any; - consumerSocket: any; - pid: number; - }) - { + constructor({ + producerSocket, + consumerSocket, + pid, + }: { + producerSocket: any; + consumerSocket: any; + pid: number; + }) { super(); logger.debug('constructor()'); @@ -77,22 +72,17 @@ export class Channel extends EnhancedEventEmitter this.#consumerSocket = consumerSocket as Duplex; // Read Channel responses/notifications from the worker. - this.#consumerSocket.on('data', (buffer: Buffer) => - { - if (!this.#recvBuffer.length) - { + this.#consumerSocket.on('data', (buffer: Buffer) => { + if (!this.#recvBuffer.length) { this.#recvBuffer = buffer; - } - else - { + } else { this.#recvBuffer = Buffer.concat( - [ this.#recvBuffer, buffer ], - this.#recvBuffer.length + buffer.length + [this.#recvBuffer, buffer], + this.#recvBuffer.length + buffer.length, ); } - if (this.#recvBuffer.length > PAYLOAD_MAX_LEN) - { + if (this.#recvBuffer.length > PAYLOAD_MAX_LEN) { logger.error('receiving buffer is full, discarding all data in it'); // Reset the buffer and exit. @@ -103,42 +93,39 @@ export class Channel extends EnhancedEventEmitter let msgStart = 0; - while (true) // eslint-disable-line no-constant-condition - { + // eslint-disable-next-line no-constant-condition + while (true) { const readLen = this.#recvBuffer.length - msgStart; - if (readLen < 4) - { + if (readLen < 4) { // Incomplete data. break; } const dataView = new DataView( this.#recvBuffer.buffer, - this.#recvBuffer.byteOffset + msgStart + this.#recvBuffer.byteOffset + msgStart, ); const msgLen = dataView.getUint32(0, IS_LITTLE_ENDIAN); - if (readLen < 4 + msgLen) - { + if (readLen < 4 + msgLen) { // Incomplete data. break; } - const payload = - this.#recvBuffer.subarray(msgStart + 4, msgStart + 4 + msgLen); + const payload = this.#recvBuffer.subarray( + msgStart + 4, + msgStart + 4 + msgLen, + ); msgStart += 4 + msgLen; const buf = new flatbuffers.ByteBuffer(new Uint8Array(payload)); const message = Message.getRootAsMessage(buf); - try - { - switch (message.dataType()) - { - case MessageBody.Response: - { + try { + switch (message.dataType()) { + case MessageBody.Response: { const response = new Response(); message.data(response); @@ -148,8 +135,7 @@ export class Channel extends EnhancedEventEmitter break; } - case MessageBody.Notification: - { + case MessageBody.Notification: { const notification = new Notification(); message.data(notification); @@ -159,8 +145,7 @@ export class Channel extends EnhancedEventEmitter break; } - case MessageBody.Log: - { + case MessageBody.Log: { const log = new Log(); message.data(log); @@ -170,61 +155,57 @@ export class Channel extends EnhancedEventEmitter break; } - default: - { + default: { // eslint-disable-next-line no-console console.warn( - `worker[pid:${pid}] unexpected data: ${payload.toString('utf8', 1)}` + `worker[pid:${pid}] unexpected data: ${payload.toString( + 'utf8', + 1, + )}`, ); } } - } - catch (error) - { + } catch (error) { logger.error( - `received invalid message from the worker process: ${error}` + `received invalid message from the worker process: ${error}`, ); } } - if (msgStart != 0) - { + if (msgStart != 0) { this.#recvBuffer = this.#recvBuffer.slice(msgStart); } }); - this.#consumerSocket.on('end', () => ( - logger.debug('Consumer Channel ended by the worker process') - )); + this.#consumerSocket.on('end', () => + logger.debug('Consumer Channel ended by the worker process'), + ); - this.#consumerSocket.on('error', (error) => ( - logger.error(`Consumer Channel error: ${error}`) - )); + this.#consumerSocket.on('error', error => + logger.error(`Consumer Channel error: ${error}`), + ); - this.#producerSocket.on('end', () => ( - logger.debug('Producer Channel ended by the worker process') - )); + this.#producerSocket.on('end', () => + logger.debug('Producer Channel ended by the worker process'), + ); - this.#producerSocket.on('error', (error) => ( - logger.error(`Producer Channel error: ${error}`) - )); + this.#producerSocket.on('error', error => + logger.error(`Producer Channel error: ${error}`), + ); } /** * flatbuffer builder. */ - get bufferBuilder(): flatbuffers.Builder - { + get bufferBuilder(): flatbuffers.Builder { return this.#bufferBuilder; } /** * @private */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -233,8 +214,7 @@ export class Channel extends EnhancedEventEmitter this.#closed = true; // Close every pending sent. - for (const sent of this.#sents.values()) - { + for (const sent of this.#sents.values()) { sent.close(); } @@ -249,12 +229,13 @@ export class Channel extends EnhancedEventEmitter this.#producerSocket.on('error', () => {}); // Destroy the socket after a while to allow pending incoming messages. - setTimeout(() => - { - try { this.#producerSocket.destroy(); } - catch (error) {} - try { this.#consumerSocket.destroy(); } - catch (error) {} + setTimeout(() => { + try { + this.#producerSocket.destroy(); + } catch (error) {} + try { + this.#consumerSocket.destroy(); + } catch (error) {} }, 200); } @@ -265,15 +246,13 @@ export class Channel extends EnhancedEventEmitter event: Event, bodyType?: NotificationBody, bodyOffset?: number, - handlerId?: string - ): void - { + handlerId?: string, + ): void { logger.debug(`notify() [event:${Event[event]}]`); - if (this.#closed) - { + if (this.#closed) { throw new InvalidStateError( - `Channel closed, cannot send notification [event:${Event[event]}]` + `Channel closed, cannot send notification [event:${Event[event]}]`, ); } @@ -281,21 +260,28 @@ export class Channel extends EnhancedEventEmitter let notificationOffset: number; - if (bodyType && bodyOffset) - { + if (bodyType && bodyOffset) { notificationOffset = Notification.createNotification( - this.#bufferBuilder, handlerIdOffset, event, bodyType, bodyOffset); - } - else - { + this.#bufferBuilder, + handlerIdOffset, + event, + bodyType, + bodyOffset, + ); + } else { notificationOffset = Notification.createNotification( - this.#bufferBuilder, handlerIdOffset, event, NotificationBody.NONE, 0); + this.#bufferBuilder, + handlerIdOffset, + event, + NotificationBody.NONE, + 0, + ); } const messageOffset = Message.createMessage( this.#bufferBuilder, MessageBody.Notification, - notificationOffset + notificationOffset, ); // Finalizes the buffer and adds a 4 byte prefix with the size of the buffer. @@ -308,18 +294,14 @@ export class Channel extends EnhancedEventEmitter // Clear the buffer builder so it's reused for the next request. this.#bufferBuilder.clear(); - if (buffer.byteLength > MESSAGE_MAX_LEN) - { + if (buffer.byteLength > MESSAGE_MAX_LEN) { throw new Error(`notification too big [event:${Event[event]}]`); } - try - { + try { // This may throw if closed or remote side ended. this.#producerSocket.write(buffer, 'binary'); - } - catch (error) - { + } catch (error) { logger.warn(`notify() | sending notification failed: ${error}`); return; @@ -330,14 +312,13 @@ export class Channel extends EnhancedEventEmitter method: Method, bodyType?: RequestBody, bodyOffset?: number, - handlerId?: string): Promise - { + handlerId?: string, + ): Promise { logger.debug(`request() [method:${Method[method]}]`); - if (this.#closed) - { + if (this.#closed) { throw new InvalidStateError( - `Channel closed, cannot send request [method:${Method[method]}]` + `Channel closed, cannot send request [method:${Method[method]}]`, ); } @@ -349,21 +330,30 @@ export class Channel extends EnhancedEventEmitter let requestOffset: number; - if (bodyType && bodyOffset) - { + if (bodyType && bodyOffset) { requestOffset = Request.createRequest( - this.#bufferBuilder, id, method, handlerIdOffset, bodyType, bodyOffset); - } - else - { + this.#bufferBuilder, + id, + method, + handlerIdOffset, + bodyType, + bodyOffset, + ); + } else { requestOffset = Request.createRequest( - this.#bufferBuilder, id, method, handlerIdOffset, RequestBody.NONE, 0); + this.#bufferBuilder, + id, + method, + handlerIdOffset, + RequestBody.NONE, + 0, + ); } const messageOffset = Message.createMessage( this.#bufferBuilder, MessageBody.Request, - requestOffset + requestOffset, ); // Finalizes the buffer and adds a 4 byte prefix with the size of the buffer. @@ -376,44 +366,38 @@ export class Channel extends EnhancedEventEmitter // Clear the buffer builder so it's reused for the next request. this.#bufferBuilder.clear(); - if (buffer.byteLength > MESSAGE_MAX_LEN) - { + if (buffer.byteLength > MESSAGE_MAX_LEN) { throw new Error(`request too big [method:${Method[method]}]`); } // This may throw if closed or remote side ended. this.#producerSocket.write(buffer, 'binary'); - return new Promise((pResolve, pReject) => - { - const sent: Sent = - { - id : id, - method : Method[method], - resolve : (data2) => - { - if (!this.#sents.delete(id)) - { + return new Promise((pResolve, pReject) => { + const sent: Sent = { + id: id, + method: Method[method], + resolve: data2 => { + if (!this.#sents.delete(id)) { return; } pResolve(data2); }, - reject : (error) => - { - if (!this.#sents.delete(id)) - { + reject: error => { + if (!this.#sents.delete(id)) { return; } pReject(error); }, - close : () => - { - pReject(new InvalidStateError( - `Channel closed, pending request aborted [method:${Method[method]}, id:${id}]` - )); - } + close: () => { + pReject( + new InvalidStateError( + `Channel closed, pending request aborted [method:${Method[method]}, id:${id}]`, + ), + ); + }, }; // Add sent stuff to the map. @@ -421,104 +405,85 @@ export class Channel extends EnhancedEventEmitter }); } - private processResponse(response: Response): void - { + private processResponse(response: Response): void { const sent = this.#sents.get(response.id()); - if (!sent) - { + if (!sent) { logger.error( - `received response does not match any sent request [id:${response.id}]` + `received response does not match any sent request [id:${response.id}]`, ); return; } - if (response.accepted()) - { - logger.debug( - `request succeeded [method:${sent.method}, id:${sent.id}]` - ); + if (response.accepted()) { + logger.debug(`request succeeded [method:${sent.method}, id:${sent.id}]`); sent.resolve(response); - } - else if (response.error()) - { + } else if (response.error()) { logger.warn( - `request failed [method:${sent.method}, id:${sent.id}]: ${response.reason()}` + `request failed [method:${sent.method}, id:${ + sent.id + }]: ${response.reason()}`, ); - switch (response.error()!) - { - case 'TypeError': - { + switch (response.error()!) { + case 'TypeError': { sent.reject(new TypeError(response.reason()!)); break; } - default: - { + default: { sent.reject(new Error(response.reason()!)); } } - } - else - { + } else { logger.error( - `received response is not accepted nor rejected [method:${sent.method}, id:${sent.id}]` + `received response is not accepted nor rejected [method:${sent.method}, id:${sent.id}]`, ); } } - private processNotification(notification: Notification): void - { + private processNotification(notification: Notification): void { // Due to how Promises work, it may happen that we receive a response // from the worker followed by a notification from the worker. If we // emit the notification immediately it may reach its target **before** // the response, destroying the ordered delivery. So we must wait a bit // here. // See https://github.com/versatica/mediasoup/issues/510 - setImmediate(() => this.emit( - notification.handlerId()!, - notification.event(), - notification) + setImmediate(() => + this.emit(notification.handlerId()!, notification.event(), notification), ); } - private processLog(pid: number, log: Log): void - { + private processLog(pid: number, log: Log): void { const logData = log.data()!; - switch (logData[0]) - { + switch (logData[0]) { // 'D' (a debug log). - case 'D': - { + case 'D': { logger.debug(`[pid:${pid}] ${logData.slice(1)}`); break; } // 'W' (a warn log). - case 'W': - { + case 'W': { logger.warn(`[pid:${pid}] ${logData.slice(1)}`); break; } // 'E' (a error log). - case 'E': - { + case 'E': { logger.error(`[pid:${pid}] ${logData.slice(1)}`); break; } // 'X' (a dump log). - case 'X': - { + case 'X': { // eslint-disable-next-line no-console console.log(logData.slice(1)); diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index e2ab1167e7..3ef48aee06 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -9,7 +9,7 @@ import { RtpEncodingParameters, RtpParameters, parseRtpEncodingParameters, - parseRtpParameters + parseRtpParameters, } from './RtpParameters'; import { parseRtpStreamStats, RtpStreamSendStats } from './RtpStream'; import { AppData } from './types'; @@ -25,8 +25,7 @@ import * as FbsRtxStream from './fbs/rtx-stream'; import { Type as FbsRtpParametersType } from './fbs/rtp-parameters'; import * as FbsRtpParameters from './fbs/rtp-parameters'; -export type ConsumerOptions = -{ +export type ConsumerOptions = { /** * The id of the Producer to consume. */ @@ -96,13 +95,17 @@ export type ConsumerOptions = /** * Valid types for 'trace' event. */ -export type ConsumerTraceEventType = 'rtp' | 'keyframe' | 'nack' | 'pli' | 'fir'; +export type ConsumerTraceEventType = + | 'rtp' + | 'keyframe' + | 'nack' + | 'pli' + | 'fir'; /** * 'trace' event data. */ -export type ConsumerTraceEventData = -{ +export type ConsumerTraceEventData = { /** * Trace type. */ @@ -124,8 +127,7 @@ export type ConsumerTraceEventData = info: any; }; -export type ConsumerScore = -{ +export type ConsumerScore = { /** * The score of the RTP stream of the consumer. */ @@ -143,8 +145,7 @@ export type ConsumerScore = producerScores: number[]; }; -export type ConsumerLayers = -{ +export type ConsumerLayers = { /** * The spatial layer index (from 0 to N). */ @@ -163,8 +164,7 @@ export type ConsumerStat = RtpStreamSendStats; */ export type ConsumerType = 'simple' | 'simulcast' | 'svc' | 'pipe'; -export type ConsumerEvents = -{ +export type ConsumerEvents = { transportclose: []; producerclose: []; producerpause: []; @@ -179,8 +179,7 @@ export type ConsumerEvents = '@producerclose': []; }; -export type ConsumerObserverEvents = -{ +export type ConsumerObserverEvents = { close: []; pause: []; resume: []; @@ -189,14 +188,12 @@ export type ConsumerObserverEvents = trace: [ConsumerTraceEventData]; }; -export type SimpleConsumerDump = BaseConsumerDump & -{ +export type SimpleConsumerDump = BaseConsumerDump & { type: string; rtpStream: RtpStreamDump; }; -export type SimulcastConsumerDump = BaseConsumerDump & -{ +export type SimulcastConsumerDump = BaseConsumerDump & { type: string; rtpStream: RtpStreamDump; preferredSpatialLayer: number; @@ -209,33 +206,29 @@ export type SimulcastConsumerDump = BaseConsumerDump & export type SvcConsumerDump = SimulcastConsumerDump; -export type PipeConsumerDump = BaseConsumerDump & -{ +export type PipeConsumerDump = BaseConsumerDump & { type: string; rtpStreams: RtpStreamDump[]; }; export type ConsumerDump = - SimpleConsumerDump | - SimulcastConsumerDump | - SvcConsumerDump | - PipeConsumerDump; + | SimpleConsumerDump + | SimulcastConsumerDump + | SvcConsumerDump + | PipeConsumerDump; -type ConsumerInternal = TransportInternal & -{ +type ConsumerInternal = TransportInternal & { consumerId: string; }; -type ConsumerData = -{ +type ConsumerData = { producerId: string; kind: MediaKind; rtpParameters: RtpParameters; type: ConsumerType; }; -type BaseConsumerDump = -{ +type BaseConsumerDump = { id: string; producerId: string; kind: MediaKind; @@ -248,8 +241,7 @@ type BaseConsumerDump = priority: number; }; -type RtpStreamParameters = -{ +type RtpStreamParameters = { encodingIdx: number; ssrc: number; payloadType: number; @@ -268,15 +260,13 @@ type RtpStreamParameters = temporalLayers: number; }; -type RtpStreamDump = -{ +type RtpStreamDump = { params: RtpStreamParameters; score: number; rtxStream?: RtxStreamDump; }; -type RtxStreamParameters = -{ +type RtxStreamParameters = { ssrc: number; payloadType: number; mimeType: string; @@ -285,16 +275,15 @@ type RtxStreamParameters = cname: string; }; -type RtxStreamDump = -{ +type RtxStreamDump = { params: RtxStreamParameters; }; const logger = new Logger('Consumer'); -export class Consumer - extends EnhancedEventEmitter -{ +export class Consumer< + ConsumerAppData extends AppData = AppData, +> extends EnhancedEventEmitter { // Internal data. readonly #internal: ConsumerInternal; @@ -334,28 +323,25 @@ export class Consumer /** * @private */ - constructor( - { - internal, - data, - channel, - appData, - paused, - producerPaused, - score = { score: 10, producerScore: 10, producerScores: [] }, - preferredLayers - }: - { - internal: ConsumerInternal; - data: ConsumerData; - channel: Channel; - appData?: ConsumerAppData; - paused: boolean; - producerPaused: boolean; - score?: ConsumerScore; - preferredLayers?: ConsumerLayers; - }) - { + constructor({ + internal, + data, + channel, + appData, + paused, + producerPaused, + score = { score: 10, producerScore: 10, producerScores: [] }, + preferredLayers, + }: { + internal: ConsumerInternal; + data: ConsumerData; + channel: Channel; + appData?: ConsumerAppData; + paused: boolean; + producerPaused: boolean; + score?: ConsumerScore; + preferredLayers?: ConsumerLayers; + }) { super(); logger.debug('constructor()'); @@ -367,7 +353,7 @@ export class Consumer this.#producerPaused = producerPaused; this.#score = score; this.#preferredLayers = preferredLayers; - this.#appData = appData || {} as ConsumerAppData; + this.#appData = appData || ({} as ConsumerAppData); this.handleWorkerNotifications(); } @@ -375,120 +361,105 @@ export class Consumer /** * Consumer id. */ - get id(): string - { + get id(): string { return this.#internal.consumerId; } /** * Associated Producer id. */ - get producerId(): string - { + get producerId(): string { return this.#data.producerId; } /** * Whether the Consumer is closed. */ - get closed(): boolean - { + get closed(): boolean { return this.#closed; } /** * Media kind. */ - get kind(): MediaKind - { + get kind(): MediaKind { return this.#data.kind; } /** * RTP parameters. */ - get rtpParameters(): RtpParameters - { + get rtpParameters(): RtpParameters { return this.#data.rtpParameters; } /** * Consumer type. */ - get type(): ConsumerType - { + get type(): ConsumerType { return this.#data.type; } /** * Whether the Consumer is paused. */ - get paused(): boolean - { + get paused(): boolean { return this.#paused; } /** * Whether the associate Producer is paused. */ - get producerPaused(): boolean - { + get producerPaused(): boolean { return this.#producerPaused; } /** * Current priority. */ - get priority(): number - { + get priority(): number { return this.#priority; } /** * Consumer score. */ - get score(): ConsumerScore - { + get score(): ConsumerScore { return this.#score; } /** * Preferred video layers. */ - get preferredLayers(): ConsumerLayers | undefined - { + get preferredLayers(): ConsumerLayers | undefined { return this.#preferredLayers; } /** * Current video layers. */ - get currentLayers(): ConsumerLayers | undefined - { + get currentLayers(): ConsumerLayers | undefined { return this.#currentLayers; } /** * App custom data. */ - get appData(): ConsumerAppData - { + get appData(): ConsumerAppData { return this.#appData; } /** * App custom data setter. */ - set appData(appData: ConsumerAppData) - { + set appData(appData: ConsumerAppData) { this.#appData = appData; } /** * Observer. */ - get observer(): EnhancedEventEmitter - { + get observer(): EnhancedEventEmitter { return this.#observer; } @@ -496,18 +467,15 @@ export class Consumer * @private * Just for testing purposes. */ - get channelForTesting(): Channel - { + get channelForTesting(): Channel { return this.#channel; } /** * Close the Consumer. */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -520,15 +488,17 @@ export class Consumer /* Build Request. */ const requestOffset = new FbsTransport.CloseConsumerRequestT( - this.#internal.consumerId + this.#internal.consumerId, ).pack(this.#channel.bufferBuilder); - this.#channel.request( - FbsRequest.Method.TRANSPORT_CLOSE_CONSUMER, - FbsRequest.Body.Transport_CloseConsumerRequest, - requestOffset, - this.#internal.transportId - ).catch(() => {}); + this.#channel + .request( + FbsRequest.Method.TRANSPORT_CLOSE_CONSUMER, + FbsRequest.Body.Transport_CloseConsumerRequest, + requestOffset, + this.#internal.transportId, + ) + .catch(() => {}); this.emit('@close'); @@ -541,10 +511,8 @@ export class Consumer * * @private */ - transportClosed(): void - { - if (this.#closed) - { + transportClosed(): void { + if (this.#closed) { return; } @@ -564,15 +532,14 @@ export class Consumer /** * Dump Consumer. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); const response = await this.#channel.request( FbsRequest.Method.CONSUMER_DUMP, undefined, undefined, - this.#internal.consumerId + this.#internal.consumerId, ); /* Decode Response. */ @@ -586,15 +553,14 @@ export class Consumer /** * Get Consumer stats. */ - async getStats(): Promise> - { + async getStats(): Promise> { logger.debug('getStats()'); const response = await this.#channel.request( FbsRequest.Method.CONSUMER_GET_STATS, undefined, undefined, - this.#internal.consumerId + this.#internal.consumerId, ); /* Decode Response. */ @@ -608,15 +574,14 @@ export class Consumer /** * Pause the Consumer. */ - async pause(): Promise - { + async pause(): Promise { logger.debug('pause()'); await this.#channel.request( FbsRequest.Method.CONSUMER_PAUSE, undefined, undefined, - this.#internal.consumerId + this.#internal.consumerId, ); const wasPaused = this.#paused; @@ -624,8 +589,7 @@ export class Consumer this.#paused = true; // Emit observer event. - if (!wasPaused && !this.#producerPaused) - { + if (!wasPaused && !this.#producerPaused) { this.#observer.safeEmit('pause'); } } @@ -633,15 +597,14 @@ export class Consumer /** * Resume the Consumer. */ - async resume(): Promise - { + async resume(): Promise { logger.debug('resume()'); await this.#channel.request( FbsRequest.Method.CONSUMER_RESUME, undefined, undefined, - this.#internal.consumerId + this.#internal.consumerId, ); const wasPaused = this.#paused; @@ -649,8 +612,7 @@ export class Consumer this.#paused = false; // Emit observer event. - if (wasPaused && !this.#producerPaused) - { + if (wasPaused && !this.#producerPaused) { this.#observer.safeEmit('resume'); } } @@ -658,39 +620,38 @@ export class Consumer /** * Set preferred video layers. */ - async setPreferredLayers( - { - spatialLayer, - temporalLayer - }: ConsumerLayers - ): Promise - { + async setPreferredLayers({ + spatialLayer, + temporalLayer, + }: ConsumerLayers): Promise { logger.debug('setPreferredLayers()'); - if (typeof spatialLayer !== 'number') - { + if (typeof spatialLayer !== 'number') { throw new TypeError('spatialLayer must be a number'); } - if (temporalLayer && typeof temporalLayer !== 'number') - { + if (temporalLayer && typeof temporalLayer !== 'number') { throw new TypeError('if given, temporalLayer must be a number'); } const builder = this.#channel.bufferBuilder; - const preferredLayersOffset = FbsConsumer.ConsumerLayers.createConsumerLayers( - builder, - spatialLayer, - temporalLayer !== undefined ? temporalLayer : null); + const preferredLayersOffset = + FbsConsumer.ConsumerLayers.createConsumerLayers( + builder, + spatialLayer, + temporalLayer !== undefined ? temporalLayer : null, + ); const requestOffset = FbsConsumer.SetPreferredLayersRequest.createSetPreferredLayersRequest( - builder, preferredLayersOffset); + builder, + preferredLayersOffset, + ); const response = await this.#channel.request( FbsRequest.Method.CONSUMER_SET_PREFERRED_LAYERS, FbsRequest.Body.Consumer_SetPreferredLayersRequest, requestOffset, - this.#internal.consumerId + this.#internal.consumerId, ); /* Decode Response. */ @@ -699,18 +660,16 @@ export class Consumer let preferredLayers: ConsumerLayers | undefined; // Response is empty for non Simulcast Consumers. - if (response.body(data)) - { + if (response.body(data)) { const status = data.unpack(); - if (status.preferredLayers) - { - preferredLayers = - { - spatialLayer : status.preferredLayers.spatialLayer, - temporalLayer : status.preferredLayers.temporalLayer !== null ? - status.preferredLayers.temporalLayer : - undefined + if (status.preferredLayers) { + preferredLayers = { + spatialLayer: status.preferredLayers.spatialLayer, + temporalLayer: + status.preferredLayers.temporalLayer !== null + ? status.preferredLayers.temporalLayer + : undefined, }; } } @@ -721,24 +680,24 @@ export class Consumer /** * Set priority. */ - async setPriority(priority: number): Promise - { + async setPriority(priority: number): Promise { logger.debug('setPriority()'); - if (typeof priority !== 'number' || priority < 0) - { + if (typeof priority !== 'number' || priority < 0) { throw new TypeError('priority must be a positive number'); } const requestOffset = FbsConsumer.SetPriorityRequest.createSetPriorityRequest( - this.#channel.bufferBuilder, priority); + this.#channel.bufferBuilder, + priority, + ); const response = await this.#channel.request( FbsRequest.Method.CONSUMER_SET_PRIORITY, FbsRequest.Body.Consumer_SetPriorityRequest, requestOffset, - this.#internal.consumerId + this.#internal.consumerId, ); const data = new FbsConsumer.SetPriorityResponse(); @@ -753,8 +712,7 @@ export class Consumer /** * Unset priority. */ - async unsetPriority(): Promise - { + async unsetPriority(): Promise { logger.debug('unsetPriority()'); await this.setPriority(1); @@ -763,221 +721,198 @@ export class Consumer /** * Request a key frame to the Producer. */ - async requestKeyFrame(): Promise - { + async requestKeyFrame(): Promise { logger.debug('requestKeyFrame()'); await this.#channel.request( FbsRequest.Method.CONSUMER_REQUEST_KEY_FRAME, undefined, undefined, - this.#internal.consumerId + this.#internal.consumerId, ); } /** * Enable 'trace' event. */ - async enableTraceEvent(types: ConsumerTraceEventType[] = []): Promise - { + async enableTraceEvent(types: ConsumerTraceEventType[] = []): Promise { logger.debug('enableTraceEvent()'); - if (!Array.isArray(types)) - { + if (!Array.isArray(types)) { throw new TypeError('types must be an array'); } - if (types.find((type) => typeof type !== 'string')) - { + if (types.find(type => typeof type !== 'string')) { throw new TypeError('every type must be a string'); } // Convert event types. const fbsEventTypes: FbsConsumer.TraceEventType[] = []; - for (const eventType of types) - { - try - { + for (const eventType of types) { + try { fbsEventTypes.push(consumerTraceEventTypeToFbs(eventType)); - } - catch (error) - { + } catch (error) { logger.warn('enableTraceEvent() | [error:${error}]'); } } /* Build Request. */ const requestOffset = new FbsConsumer.EnableTraceEventRequestT( - fbsEventTypes + fbsEventTypes, ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.CONSUMER_ENABLE_TRACE_EVENT, FbsRequest.Body.Consumer_EnableTraceEventRequest, requestOffset, - this.#internal.consumerId + this.#internal.consumerId, ); } - private handleWorkerNotifications(): void - { - this.#channel.on(this.#internal.consumerId, (event: Event, data?: Notification) => - { - switch (event) - { - case Event.CONSUMER_PRODUCER_CLOSE: - { - if (this.#closed) - { - break; - } - - this.#closed = true; + private handleWorkerNotifications(): void { + this.#channel.on( + this.#internal.consumerId, + (event: Event, data?: Notification) => { + switch (event) { + case Event.CONSUMER_PRODUCER_CLOSE: { + if (this.#closed) { + break; + } - // Remove notification subscriptions. - this.#channel.removeAllListeners(this.#internal.consumerId); + this.#closed = true; - this.emit('@producerclose'); - this.safeEmit('producerclose'); + // Remove notification subscriptions. + this.#channel.removeAllListeners(this.#internal.consumerId); - // Emit observer event. - this.#observer.safeEmit('close'); + this.emit('@producerclose'); + this.safeEmit('producerclose'); - break; - } + // Emit observer event. + this.#observer.safeEmit('close'); - case Event.CONSUMER_PRODUCER_PAUSE: - { - if (this.#producerPaused) - { break; } - this.#producerPaused = true; + case Event.CONSUMER_PRODUCER_PAUSE: { + if (this.#producerPaused) { + break; + } - this.safeEmit('producerpause'); + this.#producerPaused = true; - // Emit observer event. - if (!this.#paused) - { - this.#observer.safeEmit('pause'); - } + this.safeEmit('producerpause'); - break; - } + // Emit observer event. + if (!this.#paused) { + this.#observer.safeEmit('pause'); + } - case Event.CONSUMER_PRODUCER_RESUME: - { - if (!this.#producerPaused) - { break; } - this.#producerPaused = false; + case Event.CONSUMER_PRODUCER_RESUME: { + if (!this.#producerPaused) { + break; + } - this.safeEmit('producerresume'); + this.#producerPaused = false; - // Emit observer event. - if (!this.#paused) - { - this.#observer.safeEmit('resume'); - } + this.safeEmit('producerresume'); - break; - } + // Emit observer event. + if (!this.#paused) { + this.#observer.safeEmit('resume'); + } - case Event.CONSUMER_SCORE: - { - const notification = new FbsConsumer.ScoreNotification(); + break; + } - data!.body(notification); + case Event.CONSUMER_SCORE: { + const notification = new FbsConsumer.ScoreNotification(); - const score: ConsumerScore = notification!.score()!.unpack(); + data!.body(notification); - this.#score = score; + const score: ConsumerScore = notification!.score()!.unpack(); - this.safeEmit('score', score); + this.#score = score; - // Emit observer event. - this.#observer.safeEmit('score', score); + this.safeEmit('score', score); - break; - } + // Emit observer event. + this.#observer.safeEmit('score', score); - case Event.CONSUMER_LAYERS_CHANGE: - { - const notification = new FbsConsumer.LayersChangeNotification()!; + break; + } - data!.body(notification); + case Event.CONSUMER_LAYERS_CHANGE: { + const notification = new FbsConsumer.LayersChangeNotification()!; - const layers: ConsumerLayers | undefined = notification.layers() ? - parseConsumerLayers(notification.layers()!) : - undefined; + data!.body(notification); - this.#currentLayers = layers; + const layers: ConsumerLayers | undefined = notification.layers() + ? parseConsumerLayers(notification.layers()!) + : undefined; - this.safeEmit('layerschange', layers); + this.#currentLayers = layers; - // Emit observer event. - this.#observer.safeEmit('layerschange', layers); + this.safeEmit('layerschange', layers); - break; - } + // Emit observer event. + this.#observer.safeEmit('layerschange', layers); - case Event.CONSUMER_TRACE: - { - const notification = new FbsConsumer.TraceNotification(); + break; + } - data!.body(notification); + case Event.CONSUMER_TRACE: { + const notification = new FbsConsumer.TraceNotification(); - const trace: ConsumerTraceEventData = parseTraceEventData(notification); + data!.body(notification); - this.safeEmit('trace', trace); + const trace: ConsumerTraceEventData = + parseTraceEventData(notification); - // Emit observer event. - this.observer.safeEmit('trace', trace); + this.safeEmit('trace', trace); - this.safeEmit('trace', trace); + // Emit observer event. + this.observer.safeEmit('trace', trace); - // Emit observer event. - this.#observer.safeEmit('trace', trace); + this.safeEmit('trace', trace); - break; - } + // Emit observer event. + this.#observer.safeEmit('trace', trace); - case Event.CONSUMER_RTP: - { - if (this.#closed) - { break; } - const notification = new FbsConsumer.RtpNotification(); + case Event.CONSUMER_RTP: { + if (this.#closed) { + break; + } - data!.body(notification); + const notification = new FbsConsumer.RtpNotification(); - this.safeEmit('rtp', Buffer.from(notification.dataArray()!)); + data!.body(notification); - break; - } + this.safeEmit('rtp', Buffer.from(notification.dataArray()!)); + + break; + } - default: - { - logger.error('ignoring unknown event "%s"', event); + default: { + logger.error('ignoring unknown event "%s"', event); + } } - } - }); + }, + ); } } export function parseTraceEventData( - trace: FbsConsumer.TraceNotification -): ConsumerTraceEventData -{ + trace: FbsConsumer.TraceNotification, +): ConsumerTraceEventData { let info: any; - if (trace.infoType() !== FbsConsumer.TraceInfo.NONE) - { + if (trace.infoType() !== FbsConsumer.TraceInfo.NONE) { const accessor = trace.info.bind(trace); info = FbsConsumerTraceInfo.unionToTraceInfo(trace.infoType(), accessor); @@ -986,215 +921,210 @@ export function parseTraceEventData( } return { - type : consumerTraceEventTypeFromFbs(trace.type()), - timestamp : Number(trace.timestamp()), - direction : trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', - info : info ? info.unpack() : undefined + type: consumerTraceEventTypeFromFbs(trace.type()), + timestamp: Number(trace.timestamp()), + direction: + trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', + info: info ? info.unpack() : undefined, }; } -function consumerTraceEventTypeToFbs(eventType: ConsumerTraceEventType) - : FbsConsumer.TraceEventType -{ - switch (eventType) - { - case 'keyframe': - { +function consumerTraceEventTypeToFbs( + eventType: ConsumerTraceEventType, +): FbsConsumer.TraceEventType { + switch (eventType) { + case 'keyframe': { return FbsConsumer.TraceEventType.KEYFRAME; } - case 'fir': - { + case 'fir': { return FbsConsumer.TraceEventType.FIR; } - case 'nack': - { + case 'nack': { return FbsConsumer.TraceEventType.NACK; } - case 'pli': - { + case 'pli': { return FbsConsumer.TraceEventType.PLI; } - case 'rtp': - { + case 'rtp': { return FbsConsumer.TraceEventType.RTP; } - default: - { + default: { throw new TypeError(`invalid ConsumerTraceEventType: ${eventType}`); } } } -function consumerTraceEventTypeFromFbs(traceType: FbsConsumer.TraceEventType) - : ConsumerTraceEventType -{ - switch (traceType) - { - case FbsConsumer.TraceEventType.KEYFRAME: - { +function consumerTraceEventTypeFromFbs( + traceType: FbsConsumer.TraceEventType, +): ConsumerTraceEventType { + switch (traceType) { + case FbsConsumer.TraceEventType.KEYFRAME: { return 'keyframe'; } - case FbsConsumer.TraceEventType.FIR: - { + case FbsConsumer.TraceEventType.FIR: { return 'fir'; } - case FbsConsumer.TraceEventType.NACK: - { + case FbsConsumer.TraceEventType.NACK: { return 'nack'; } - case FbsConsumer.TraceEventType.PLI: - { + case FbsConsumer.TraceEventType.PLI: { return 'pli'; } - case FbsConsumer.TraceEventType.RTP: - { + case FbsConsumer.TraceEventType.RTP: { return 'rtp'; } - default: - { + default: { throw new TypeError(`invalid FbsConsumer.TraceEventType: ${traceType}`); } } } -function parseConsumerLayers(data: FbsConsumer.ConsumerLayers): ConsumerLayers -{ +function parseConsumerLayers(data: FbsConsumer.ConsumerLayers): ConsumerLayers { const spatialLayer = data.spatialLayer(); - const temporalLayer = data.temporalLayer() !== null ? data.temporalLayer()! : undefined; + const temporalLayer = + data.temporalLayer() !== null ? data.temporalLayer()! : undefined; return { spatialLayer, - temporalLayer + temporalLayer, }; } -function parseRtpStreamParameters(data: FbsRtpStream.Params): RtpStreamParameters -{ +function parseRtpStreamParameters( + data: FbsRtpStream.Params, +): RtpStreamParameters { return { - encodingIdx : data.encodingIdx(), - ssrc : data.ssrc(), - payloadType : data.payloadType(), - mimeType : data.mimeType()!, - clockRate : data.clockRate(), - rid : data.rid()!.length > 0 ? data.rid()! : undefined, - cname : data.cname()!, - rtxSsrc : data.rtxSsrc() !== null ? data.rtxSsrc()! : undefined, - rtxPayloadType : data.rtxPayloadType() !== null ? data.rtxPayloadType()! : undefined, - useNack : data.useNack(), - usePli : data.usePli(), - useFir : data.useFir(), - useInBandFec : data.useInBandFec(), - useDtx : data.useDtx(), - spatialLayers : data.spatialLayers(), - temporalLayers : data.temporalLayers() + encodingIdx: data.encodingIdx(), + ssrc: data.ssrc(), + payloadType: data.payloadType(), + mimeType: data.mimeType()!, + clockRate: data.clockRate(), + rid: data.rid()!.length > 0 ? data.rid()! : undefined, + cname: data.cname()!, + rtxSsrc: data.rtxSsrc() !== null ? data.rtxSsrc()! : undefined, + rtxPayloadType: + data.rtxPayloadType() !== null ? data.rtxPayloadType()! : undefined, + useNack: data.useNack(), + usePli: data.usePli(), + useFir: data.useFir(), + useInBandFec: data.useInBandFec(), + useDtx: data.useDtx(), + spatialLayers: data.spatialLayers(), + temporalLayers: data.temporalLayers(), }; } -function parseRtxStreamParameters(data: FbsRtxStream.Params): RtxStreamParameters -{ +function parseRtxStreamParameters( + data: FbsRtxStream.Params, +): RtxStreamParameters { return { - ssrc : data.ssrc(), - payloadType : data.payloadType(), - mimeType : data.mimeType()!, - clockRate : data.clockRate(), - rrid : data.rrid()!.length > 0 ? data.rrid()! : undefined, - cname : data.cname()! + ssrc: data.ssrc(), + payloadType: data.payloadType(), + mimeType: data.mimeType()!, + clockRate: data.clockRate(), + rrid: data.rrid()!.length > 0 ? data.rrid()! : undefined, + cname: data.cname()!, }; } -function parseRtxStream(data: FbsRtxStream.RtxDump): RtxStreamDump -{ +function parseRtxStream(data: FbsRtxStream.RtxDump): RtxStreamDump { const params = parseRtxStreamParameters(data.params()!); return { - params + params, }; } -function parseRtpStream(data: FbsRtpStream.Dump): RtpStreamDump -{ +function parseRtpStream(data: FbsRtpStream.Dump): RtpStreamDump { const params = parseRtpStreamParameters(data.params()!); let rtxStream: RtxStreamDump | undefined; - if (data.rtxStream()) - { + if (data.rtxStream()) { rtxStream = parseRtxStream(data.rtxStream()!); } return { params, - score : data.score(), - rtxStream + score: data.score(), + rtxStream, }; } -function parseBaseConsumerDump(data: FbsConsumer.BaseConsumerDump): BaseConsumerDump -{ +function parseBaseConsumerDump( + data: FbsConsumer.BaseConsumerDump, +): BaseConsumerDump { return { - id : data.id()!, - producerId : data.producerId()!, - kind : data.kind() === FbsRtpParameters.MediaKind.AUDIO ? - 'audio' : - 'video', - rtpParameters : parseRtpParameters(data.rtpParameters()!), - consumableRtpEncodings : data.consumableRtpEncodingsLength() > 0 ? - utils.parseVector(data, 'consumableRtpEncodings', parseRtpEncodingParameters) : - undefined, - traceEventTypes : utils.parseVector(data, 'traceEventTypes', consumerTraceEventTypeFromFbs), - supportedCodecPayloadTypes : utils.parseVector(data, 'supportedCodecPayloadTypes'), - paused : data.paused(), - producerPaused : data.producerPaused(), - priority : data.priority() + id: data.id()!, + producerId: data.producerId()!, + kind: data.kind() === FbsRtpParameters.MediaKind.AUDIO ? 'audio' : 'video', + rtpParameters: parseRtpParameters(data.rtpParameters()!), + consumableRtpEncodings: + data.consumableRtpEncodingsLength() > 0 + ? utils.parseVector( + data, + 'consumableRtpEncodings', + parseRtpEncodingParameters, + ) + : undefined, + traceEventTypes: utils.parseVector( + data, + 'traceEventTypes', + consumerTraceEventTypeFromFbs, + ), + supportedCodecPayloadTypes: utils.parseVector( + data, + 'supportedCodecPayloadTypes', + ), + paused: data.paused(), + producerPaused: data.producerPaused(), + priority: data.priority(), }; } -function parseSimpleConsumerDump(data: FbsConsumer.ConsumerDump): SimpleConsumerDump -{ +function parseSimpleConsumerDump( + data: FbsConsumer.ConsumerDump, +): SimpleConsumerDump { const base = parseBaseConsumerDump(data.base()!); const rtpStream = parseRtpStream(data.rtpStreams(0)!); return { ...base, - type : 'simple', - rtpStream + type: 'simple', + rtpStream, }; } function parseSimulcastConsumerDump( - data: FbsConsumer.ConsumerDump -) : SimulcastConsumerDump -{ + data: FbsConsumer.ConsumerDump, +): SimulcastConsumerDump { const base = parseBaseConsumerDump(data.base()!); const rtpStream = parseRtpStream(data.rtpStreams(0)!); return { ...base, - type : 'simulcast', + type: 'simulcast', rtpStream, - preferredSpatialLayer : data.preferredSpatialLayer()!, - targetSpatialLayer : data.targetSpatialLayer()!, - currentSpatialLayer : data.currentSpatialLayer()!, - preferredTemporalLayer : data.preferredTemporalLayer()!, - targetTemporalLayer : data.targetTemporalLayer()!, - currentTemporalLayer : data.currentTemporalLayer()! + preferredSpatialLayer: data.preferredSpatialLayer()!, + targetSpatialLayer: data.targetSpatialLayer()!, + currentSpatialLayer: data.currentSpatialLayer()!, + preferredTemporalLayer: data.preferredTemporalLayer()!, + targetTemporalLayer: data.targetTemporalLayer()!, + currentTemporalLayer: data.currentTemporalLayer()!, }; } -function parseSvcConsumerDump( - data: FbsConsumer.ConsumerDump -) : SvcConsumerDump -{ +function parseSvcConsumerDump(data: FbsConsumer.ConsumerDump): SvcConsumerDump { const dump = parseSimulcastConsumerDump(data); dump.type = 'svc'; @@ -1203,27 +1133,25 @@ function parseSvcConsumerDump( } function parsePipeConsumerDump( - data: FbsConsumer.ConsumerDump -) : PipeConsumerDump -{ + data: FbsConsumer.ConsumerDump, +): PipeConsumerDump { const base = parseBaseConsumerDump(data.base()!); const rtpStreams = utils.parseVector(data, 'rtpStreams', parseRtpStream); return { ...base, - type : 'pipe', - rtpStreams + type: 'pipe', + rtpStreams, }; } -function parseConsumerDumpResponse(data: FbsConsumer.DumpResponse): ConsumerDump -{ +function parseConsumerDumpResponse( + data: FbsConsumer.DumpResponse, +): ConsumerDump { const type = data.data()!.base()!.type(); - switch (type) - { - case FbsRtpParametersType.SIMPLE: - { + switch (type) { + case FbsRtpParametersType.SIMPLE: { const dump = new FbsConsumer.ConsumerDump(); data.data(dump); @@ -1231,8 +1159,7 @@ function parseConsumerDumpResponse(data: FbsConsumer.DumpResponse): ConsumerDump return parseSimpleConsumerDump(dump); } - case FbsRtpParametersType.SIMULCAST: - { + case FbsRtpParametersType.SIMULCAST: { const dump = new FbsConsumer.ConsumerDump(); data.data(dump); @@ -1240,8 +1167,7 @@ function parseConsumerDumpResponse(data: FbsConsumer.DumpResponse): ConsumerDump return parseSimulcastConsumerDump(dump); } - case FbsRtpParametersType.SVC: - { + case FbsRtpParametersType.SVC: { const dump = new FbsConsumer.ConsumerDump(); data.data(dump); @@ -1249,8 +1175,7 @@ function parseConsumerDumpResponse(data: FbsConsumer.DumpResponse): ConsumerDump return parseSvcConsumerDump(dump); } - case FbsRtpParametersType.PIPE: - { + case FbsRtpParametersType.PIPE: { const dump = new FbsConsumer.ConsumerDump(); data.data(dump); @@ -1258,15 +1183,14 @@ function parseConsumerDumpResponse(data: FbsConsumer.DumpResponse): ConsumerDump return parsePipeConsumerDump(dump); } - default: - { + default: { throw new TypeError(`invalid Consumer type: ${type}`); } } } -function parseConsumerStats(binary: FbsConsumer.GetStatsResponse) - : Array -{ +function parseConsumerStats( + binary: FbsConsumer.GetStatsResponse, +): Array { return utils.parseVector(binary, 'stats', parseRtpStreamStats); } diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 3a3ca78a6f..11ff7b14e5 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -4,7 +4,7 @@ import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { SctpStreamParameters, - parseSctpStreamParameters + parseSctpStreamParameters, } from './SctpParameters'; import { AppData } from './types'; import * as utils from './utils'; @@ -15,56 +15,55 @@ import * as FbsDataConsumer from './fbs/data-consumer'; import * as FbsDataProducer from './fbs/data-producer'; export type DataConsumerOptions = -{ - /** - * The id of the DataProducer to consume. - */ - dataProducerId: string; + { + /** + * The id of the DataProducer to consume. + */ + dataProducerId: string; - /** - * Just if consuming over SCTP. - * Whether data messages must be received in order. If true the messages will - * be sent reliably. Defaults to the value in the DataProducer if it has type - * 'sctp' or to true if it has type 'direct'. - */ - ordered?: boolean; + /** + * Just if consuming over SCTP. + * Whether data messages must be received in order. If true the messages will + * be sent reliably. Defaults to the value in the DataProducer if it has type + * 'sctp' or to true if it has type 'direct'. + */ + ordered?: boolean; - /** - * Just if consuming over SCTP. - * When ordered is false indicates the time (in milliseconds) after which a - * SCTP packet will stop being retransmitted. Defaults to the value in the - * DataProducer if it has type 'sctp' or unset if it has type 'direct'. - */ - maxPacketLifeTime?: number; + /** + * Just if consuming over SCTP. + * When ordered is false indicates the time (in milliseconds) after which a + * SCTP packet will stop being retransmitted. Defaults to the value in the + * DataProducer if it has type 'sctp' or unset if it has type 'direct'. + */ + maxPacketLifeTime?: number; - /** - * Just if consuming over SCTP. - * When ordered is false indicates the maximum number of times a packet will - * be retransmitted. Defaults to the value in the DataProducer if it has type - * 'sctp' or unset if it has type 'direct'. - */ - maxRetransmits?: number; + /** + * Just if consuming over SCTP. + * When ordered is false indicates the maximum number of times a packet will + * be retransmitted. Defaults to the value in the DataProducer if it has type + * 'sctp' or unset if it has type 'direct'. + */ + maxRetransmits?: number; - /** - * Whether the data consumer must start in paused mode. Default false. - */ - paused?: boolean; + /** + * Whether the data consumer must start in paused mode. Default false. + */ + paused?: boolean; - /** - * Subchannels this data consumer initially subscribes to. - * Only used in case this data consumer receives messages from a local data - * producer that specifies subchannel(s) when calling send(). - */ - subchannels?: number[]; + /** + * Subchannels this data consumer initially subscribes to. + * Only used in case this data consumer receives messages from a local data + * producer that specifies subchannel(s) when calling send(). + */ + subchannels?: number[]; - /** - * Custom application data. - */ - appData?: DataConsumerAppData; -}; + /** + * Custom application data. + */ + appData?: DataConsumerAppData; + }; -export type DataConsumerStat = -{ +export type DataConsumerStat = { type: string; timestamp: number; label: string; @@ -79,8 +78,7 @@ export type DataConsumerStat = */ export type DataConsumerType = 'sctp' | 'direct'; -export type DataConsumerEvents = -{ +export type DataConsumerEvents = { transportclose: []; dataproducerclose: []; dataproducerpause: []; @@ -94,28 +92,24 @@ export type DataConsumerEvents = '@dataproducerclose': []; }; -export type DataConsumerObserverEvents = -{ +export type DataConsumerObserverEvents = { close: []; pause: []; resume: []; }; -type DataConsumerDump = DataConsumerData & -{ +type DataConsumerDump = DataConsumerData & { id: string; paused: boolean; dataProducerPaused: boolean; subchannels: number[]; }; -type DataConsumerInternal = TransportInternal & -{ +type DataConsumerInternal = TransportInternal & { dataConsumerId: string; }; -type DataConsumerData = -{ +type DataConsumerData = { dataProducerId: string; type: DataConsumerType; sctpStreamParameters?: SctpStreamParameters; @@ -126,9 +120,9 @@ type DataConsumerData = const logger = new Logger('DataConsumer'); -export class DataConsumer - extends EnhancedEventEmitter -{ +export class DataConsumer< + DataConsumerAppData extends AppData = AppData, +> extends EnhancedEventEmitter { // Internal data. readonly #internal: DataConsumerInternal; @@ -159,27 +153,23 @@ export class DataConsumer /** * @private */ - constructor( - { - internal, - data, - channel, - paused, - dataProducerPaused, - subchannels, - appData - }: - { - internal: DataConsumerInternal; - data: DataConsumerData; - channel: Channel; - paused: boolean; - dataProducerPaused: boolean; - subchannels: number[]; - appData?: DataConsumerAppData; - } - ) - { + constructor({ + internal, + data, + channel, + paused, + dataProducerPaused, + subchannels, + appData, + }: { + internal: DataConsumerInternal; + data: DataConsumerData; + channel: Channel; + paused: boolean; + dataProducerPaused: boolean; + subchannels: number[]; + appData?: DataConsumerAppData; + }) { super(); logger.debug('constructor()'); @@ -190,7 +180,7 @@ export class DataConsumer this.#paused = paused; this.#dataProducerPaused = dataProducerPaused; this.#subchannels = subchannels; - this.#appData = appData || {} as DataConsumerAppData; + this.#appData = appData || ({} as DataConsumerAppData); this.handleWorkerNotifications(); } @@ -198,114 +188,99 @@ export class DataConsumer /** * DataConsumer id. */ - get id(): string - { + get id(): string { return this.#internal.dataConsumerId; } /** * Associated DataProducer id. */ - get dataProducerId(): string - { + get dataProducerId(): string { return this.#data.dataProducerId; } /** * Whether the DataConsumer is closed. */ - get closed(): boolean - { + get closed(): boolean { return this.#closed; } /** * DataConsumer type. */ - get type(): DataConsumerType - { + get type(): DataConsumerType { return this.#data.type; } /** * SCTP stream parameters. */ - get sctpStreamParameters(): SctpStreamParameters | undefined - { + get sctpStreamParameters(): SctpStreamParameters | undefined { return this.#data.sctpStreamParameters; } /** * DataChannel label. */ - get label(): string - { + get label(): string { return this.#data.label; } /** * DataChannel protocol. */ - get protocol(): string - { + get protocol(): string { return this.#data.protocol; } /** * Whether the DataConsumer is paused. */ - get paused(): boolean - { + get paused(): boolean { return this.#paused; } /** * Whether the associate DataProducer is paused. */ - get dataProducerPaused(): boolean - { + get dataProducerPaused(): boolean { return this.#dataProducerPaused; } /** * Get current subchannels this data consumer is subscribed to. */ - get subchannels(): number[] - { + get subchannels(): number[] { return Array.from(this.#subchannels); } /** * App custom data. */ - get appData(): DataConsumerAppData - { + get appData(): DataConsumerAppData { return this.#appData; } /** * App custom data setter. */ - set appData(appData: DataConsumerAppData) - { + set appData(appData: DataConsumerAppData) { this.#appData = appData; } /** * Observer. */ - get observer(): EnhancedEventEmitter - { + get observer(): EnhancedEventEmitter { return this.#observer; } /** * Close the DataConsumer. */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -318,15 +293,17 @@ export class DataConsumer /* Build Request. */ const requestOffset = new FbsTransport.CloseDataConsumerRequestT( - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ).pack(this.#channel.bufferBuilder); - this.#channel.request( - FbsRequest.Method.TRANSPORT_CLOSE_DATACONSUMER, - FbsRequest.Body.Transport_CloseDataConsumerRequest, - requestOffset, - this.#internal.transportId - ).catch(() => {}); + this.#channel + .request( + FbsRequest.Method.TRANSPORT_CLOSE_DATACONSUMER, + FbsRequest.Body.Transport_CloseDataConsumerRequest, + requestOffset, + this.#internal.transportId, + ) + .catch(() => {}); this.emit('@close'); @@ -339,10 +316,8 @@ export class DataConsumer * * @private */ - transportClosed(): void - { - if (this.#closed) - { + transportClosed(): void { + if (this.#closed) { return; } @@ -362,15 +337,14 @@ export class DataConsumer /** * Dump DataConsumer. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); const response = await this.#channel.request( FbsRequest.Method.DATACONSUMER_DUMP, undefined, undefined, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); /* Decode Response. */ @@ -384,15 +358,14 @@ export class DataConsumer /** * Get DataConsumer stats. */ - async getStats(): Promise - { + async getStats(): Promise { logger.debug('getStats()'); const response = await this.#channel.request( FbsRequest.Method.DATACONSUMER_GET_STATS, undefined, undefined, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); /* Decode Response. */ @@ -400,21 +373,20 @@ export class DataConsumer response.body(data); - return [ parseDataConsumerStats(data) ]; + return [parseDataConsumerStats(data)]; } /** * Pause the DataConsumer. */ - async pause(): Promise - { + async pause(): Promise { logger.debug('pause()'); await this.#channel.request( FbsRequest.Method.DATACONSUMER_PAUSE, undefined, undefined, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); const wasPaused = this.#paused; @@ -422,8 +394,7 @@ export class DataConsumer this.#paused = true; // Emit observer event. - if (!wasPaused && !this.#dataProducerPaused) - { + if (!wasPaused && !this.#dataProducerPaused) { this.#observer.safeEmit('pause'); } } @@ -431,15 +402,14 @@ export class DataConsumer /** * Resume the DataConsumer. */ - async resume(): Promise - { + async resume(): Promise { logger.debug('resume()'); await this.#channel.request( FbsRequest.Method.DATACONSUMER_RESUME, undefined, undefined, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); const wasPaused = this.#paused; @@ -447,8 +417,7 @@ export class DataConsumer this.#paused = false; // Emit observer event. - if (wasPaused && !this.#dataProducerPaused) - { + if (wasPaused && !this.#dataProducerPaused) { this.#observer.safeEmit('resume'); } } @@ -456,29 +425,29 @@ export class DataConsumer /** * Set buffered amount low threshold. */ - async setBufferedAmountLowThreshold(threshold: number): Promise - { + async setBufferedAmountLowThreshold(threshold: number): Promise { logger.debug('setBufferedAmountLowThreshold() [threshold:%s]', threshold); /* Build Request. */ - const requestOffset = FbsDataConsumer.SetBufferedAmountLowThresholdRequest. - createSetBufferedAmountLowThresholdRequest(this.#channel.bufferBuilder, threshold); + const requestOffset = + FbsDataConsumer.SetBufferedAmountLowThresholdRequest.createSetBufferedAmountLowThresholdRequest( + this.#channel.bufferBuilder, + threshold, + ); await this.#channel.request( FbsRequest.Method.DATACONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, FbsRequest.Body.DataConsumer_SetBufferedAmountLowThresholdRequest, requestOffset, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); } /** * Send data. */ - async send(message: string | Buffer, ppid?: number): Promise - { - if (typeof message !== 'string' && !Buffer.isBuffer(message)) - { + async send(message: string | Buffer, ppid?: number): Promise { + if (typeof message !== 'string' && !Buffer.isBuffer(message)) { throw new TypeError('message must be a string or a Buffer'); } @@ -498,20 +467,21 @@ export class DataConsumer * +-------------------------------+----------+ */ - if (typeof ppid !== 'number') - { - ppid = (typeof message === 'string') - ? message.length > 0 ? 51 : 56 - : message.length > 0 ? 53 : 57; + if (typeof ppid !== 'number') { + ppid = + typeof message === 'string' + ? message.length > 0 + ? 51 + : 56 + : message.length > 0 + ? 53 + : 57; } // Ensure we honor PPIDs. - if (ppid === 56) - { + if (ppid === 56) { message = ' '; - } - else if (ppid === 57) - { + } else if (ppid === 57) { message = Buffer.alloc(1); } @@ -519,8 +489,7 @@ export class DataConsumer let dataOffset = 0; - if (typeof message === 'string') - { + if (typeof message === 'string') { message = Buffer.from(message); } @@ -529,29 +498,28 @@ export class DataConsumer const requestOffset = FbsDataConsumer.SendRequest.createSendRequest( builder, ppid, - dataOffset + dataOffset, ); await this.#channel.request( FbsRequest.Method.DATACONSUMER_SEND, FbsRequest.Body.DataConsumer_SendRequest, requestOffset, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); } /** * Get buffered amount size. */ - async getBufferedAmount(): Promise - { + async getBufferedAmount(): Promise { logger.debug('getBufferedAmount()'); const response = await this.#channel.request( FbsRequest.Method.DATACONSUMER_GET_BUFFERED_AMOUNT, undefined, undefined, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); const data = new FbsDataConsumer.GetBufferedAmountResponse(); @@ -564,20 +532,19 @@ export class DataConsumer /** * Set subchannels. */ - async setSubchannels(subchannels: number[]): Promise - { + async setSubchannels(subchannels: number[]): Promise { logger.debug('setSubchannels()'); /* Build Request. */ const requestOffset = new FbsDataConsumer.SetSubchannelsRequestT( - subchannels + subchannels, ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( FbsRequest.Method.DATACONSUMER_SET_SUBCHANNELS, FbsRequest.Body.DataConsumer_SetSubchannelsRequest, requestOffset, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); /* Decode Response. */ @@ -592,20 +559,21 @@ export class DataConsumer /** * Add a subchannel. */ - async addSubchannel(subchannel: number): Promise - { + async addSubchannel(subchannel: number): Promise { logger.debug('addSubchannel()'); /* Build Request. */ const requestOffset = FbsDataConsumer.AddSubchannelRequest.createAddSubchannelRequest( - this.#channel.bufferBuilder, subchannel); + this.#channel.bufferBuilder, + subchannel, + ); const response = await this.#channel.request( FbsRequest.Method.DATACONSUMER_ADD_SUBCHANNEL, FbsRequest.Body.DataConsumer_AddSubchannelRequest, requestOffset, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); /* Decode Response. */ @@ -620,19 +588,21 @@ export class DataConsumer /** * Remove a subchannel. */ - async removeSubchannel(subchannel: number): Promise - { + async removeSubchannel(subchannel: number): Promise { logger.debug('removeSubchannel()'); /* Build Request. */ - const requestOffset = FbsDataConsumer.RemoveSubchannelRequest. - createRemoveSubchannelRequest(this.#channel.bufferBuilder, subchannel); + const requestOffset = + FbsDataConsumer.RemoveSubchannelRequest.createRemoveSubchannelRequest( + this.#channel.bufferBuilder, + subchannel, + ); const response = await this.#channel.request( FbsRequest.Method.DATACONSUMER_REMOVE_SUBCHANNEL, FbsRequest.Body.DataConsumer_RemoveSubchannelRequest, requestOffset, - this.#internal.dataConsumerId + this.#internal.dataConsumerId, ); /* Decode Response. */ @@ -644,190 +614,175 @@ export class DataConsumer this.#subchannels = utils.parseVector(data, 'subchannels'); } - private handleWorkerNotifications(): void - { - this.#channel.on(this.#internal.dataConsumerId, (event: Event, data?: Notification) => - { - switch (event) - { - case Event.DATACONSUMER_DATAPRODUCER_CLOSE: - { - if (this.#closed) - { - break; - } + private handleWorkerNotifications(): void { + this.#channel.on( + this.#internal.dataConsumerId, + (event: Event, data?: Notification) => { + switch (event) { + case Event.DATACONSUMER_DATAPRODUCER_CLOSE: { + if (this.#closed) { + break; + } - this.#closed = true; + this.#closed = true; - // Remove notification subscriptions. - this.#channel.removeAllListeners(this.#internal.dataConsumerId); + // Remove notification subscriptions. + this.#channel.removeAllListeners(this.#internal.dataConsumerId); - this.emit('@dataproducerclose'); - this.safeEmit('dataproducerclose'); + this.emit('@dataproducerclose'); + this.safeEmit('dataproducerclose'); - // Emit observer event. - this.#observer.safeEmit('close'); + // Emit observer event. + this.#observer.safeEmit('close'); - break; - } - - case Event.DATACONSUMER_DATAPRODUCER_PAUSE: - { - if (this.#dataProducerPaused) - { break; } - this.#dataProducerPaused = true; + case Event.DATACONSUMER_DATAPRODUCER_PAUSE: { + if (this.#dataProducerPaused) { + break; + } - this.safeEmit('dataproducerpause'); + this.#dataProducerPaused = true; - // Emit observer event. - if (!this.#paused) - { - this.#observer.safeEmit('pause'); - } + this.safeEmit('dataproducerpause'); - break; - } + // Emit observer event. + if (!this.#paused) { + this.#observer.safeEmit('pause'); + } - case Event.DATACONSUMER_DATAPRODUCER_RESUME: - { - if (!this.#dataProducerPaused) - { break; } - this.#dataProducerPaused = false; + case Event.DATACONSUMER_DATAPRODUCER_RESUME: { + if (!this.#dataProducerPaused) { + break; + } - this.safeEmit('dataproducerresume'); + this.#dataProducerPaused = false; - // Emit observer event. - if (!this.#paused) - { - this.#observer.safeEmit('resume'); - } + this.safeEmit('dataproducerresume'); - break; - } + // Emit observer event. + if (!this.#paused) { + this.#observer.safeEmit('resume'); + } - case Event.DATACONSUMER_SCTP_SENDBUFFER_FULL: - { - this.safeEmit('sctpsendbufferfull'); + break; + } - break; - } + case Event.DATACONSUMER_SCTP_SENDBUFFER_FULL: { + this.safeEmit('sctpsendbufferfull'); - case Event.DATACONSUMER_BUFFERED_AMOUNT_LOW: - { - const notification = new FbsDataConsumer.BufferedAmountLowNotification(); + break; + } - data!.body(notification); + case Event.DATACONSUMER_BUFFERED_AMOUNT_LOW: { + const notification = + new FbsDataConsumer.BufferedAmountLowNotification(); - const bufferedAmount = notification.bufferedAmount(); + data!.body(notification); - this.safeEmit('bufferedamountlow', bufferedAmount); + const bufferedAmount = notification.bufferedAmount(); - break; - } + this.safeEmit('bufferedamountlow', bufferedAmount); - case Event.DATACONSUMER_MESSAGE: - { - if (this.#closed) - { break; } - const notification = new FbsDataConsumer.MessageNotification(); + case Event.DATACONSUMER_MESSAGE: { + if (this.#closed) { + break; + } - data!.body(notification); + const notification = new FbsDataConsumer.MessageNotification(); - this.safeEmit( - 'message', - Buffer.from(notification.dataArray()!), - notification.ppid() - ); + data!.body(notification); - break; - } + this.safeEmit( + 'message', + Buffer.from(notification.dataArray()!), + notification.ppid(), + ); + + break; + } - default: - { - logger.error('ignoring unknown event "%s" in channel listener', event); + default: { + logger.error( + 'ignoring unknown event "%s" in channel listener', + event, + ); + } } - } - }); + }, + ); } } -export function dataConsumerTypeToFbs(type: DataConsumerType): FbsDataProducer.Type -{ - switch (type) - { - case 'sctp': - { +export function dataConsumerTypeToFbs( + type: DataConsumerType, +): FbsDataProducer.Type { + switch (type) { + case 'sctp': { return FbsDataProducer.Type.SCTP; } - case 'direct': - { + case 'direct': { return FbsDataProducer.Type.DIRECT; } - default: - { + default: { throw new TypeError('invalid DataConsumerType: ${type}'); } } } -export function dataConsumerTypeFromFbs(type: FbsDataProducer.Type): DataConsumerType -{ - switch (type) - { - case FbsDataProducer.Type.SCTP: - { +export function dataConsumerTypeFromFbs( + type: FbsDataProducer.Type, +): DataConsumerType { + switch (type) { + case FbsDataProducer.Type.SCTP: { return 'sctp'; } - case FbsDataProducer.Type.DIRECT: - { + case FbsDataProducer.Type.DIRECT: { return 'direct'; } } } export function parseDataConsumerDumpResponse( - data: FbsDataConsumer.DumpResponse -): DataConsumerDump -{ + data: FbsDataConsumer.DumpResponse, +): DataConsumerDump { return { - id : data.id()!, - dataProducerId : data.dataProducerId()!, - type : dataConsumerTypeFromFbs(data.type()), - sctpStreamParameters : data.sctpStreamParameters() !== null ? - parseSctpStreamParameters(data.sctpStreamParameters()!) : - undefined, - label : data.label()!, - protocol : data.protocol()!, - bufferedAmountLowThreshold : data.bufferedAmountLowThreshold(), - paused : data.paused(), - dataProducerPaused : data.dataProducerPaused(), - subchannels : utils.parseVector(data, 'subchannels') + id: data.id()!, + dataProducerId: data.dataProducerId()!, + type: dataConsumerTypeFromFbs(data.type()), + sctpStreamParameters: + data.sctpStreamParameters() !== null + ? parseSctpStreamParameters(data.sctpStreamParameters()!) + : undefined, + label: data.label()!, + protocol: data.protocol()!, + bufferedAmountLowThreshold: data.bufferedAmountLowThreshold(), + paused: data.paused(), + dataProducerPaused: data.dataProducerPaused(), + subchannels: utils.parseVector(data, 'subchannels'), }; } function parseDataConsumerStats( - binary: FbsDataConsumer.GetStatsResponse -): DataConsumerStat -{ + binary: FbsDataConsumer.GetStatsResponse, +): DataConsumerStat { return { - type : 'data-consumer', - timestamp : Number(binary.timestamp()), - label : binary.label()!, - protocol : binary.protocol()!, - messagesSent : Number(binary.messagesSent()), - bytesSent : Number(binary.bytesSent()), - bufferedAmount : binary.bufferedAmount() + type: 'data-consumer', + timestamp: Number(binary.timestamp()), + label: binary.label()!, + protocol: binary.protocol()!, + messagesSent: Number(binary.messagesSent()), + bytesSent: Number(binary.bytesSent()), + bufferedAmount: binary.bufferedAmount(), }; } diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index b6464e740e..c78818f0f7 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -4,7 +4,7 @@ import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { SctpStreamParameters, - parseSctpStreamParameters + parseSctpStreamParameters, } from './SctpParameters'; import { AppData } from './types'; import * as FbsTransport from './fbs/transport'; @@ -13,41 +13,40 @@ import * as FbsRequest from './fbs/request'; import * as FbsDataProducer from './fbs/data-producer'; export type DataProducerOptions = -{ - /** - * DataProducer id (just for Router.pipeToRouter() method). - */ - id?: string; + { + /** + * DataProducer id (just for Router.pipeToRouter() method). + */ + id?: string; - /** - * SCTP parameters defining how the endpoint is sending the data. - * Just if messages are sent over SCTP. - */ - sctpStreamParameters?: SctpStreamParameters; + /** + * SCTP parameters defining how the endpoint is sending the data. + * Just if messages are sent over SCTP. + */ + sctpStreamParameters?: SctpStreamParameters; - /** - * A label which can be used to distinguish this DataChannel from others. - */ - label?: string; + /** + * A label which can be used to distinguish this DataChannel from others. + */ + label?: string; - /** - * Name of the sub-protocol used by this DataChannel. - */ - protocol?: string; + /** + * Name of the sub-protocol used by this DataChannel. + */ + protocol?: string; - /** - * Whether the data producer must start in paused mode. Default false. - */ - paused?: boolean; + /** + * Whether the data producer must start in paused mode. Default false. + */ + paused?: boolean; - /** - * Custom application data. - */ - appData?: DataProducerAppData; -}; + /** + * Custom application data. + */ + appData?: DataProducerAppData; + }; -export type DataProducerStat = -{ +export type DataProducerStat = { type: string; timestamp: number; label: string; @@ -61,34 +60,29 @@ export type DataProducerStat = */ export type DataProducerType = 'sctp' | 'direct'; -export type DataProducerEvents = -{ +export type DataProducerEvents = { transportclose: []; listenererror: [string, Error]; // Private events. '@close': []; }; -export type DataProducerObserverEvents = -{ +export type DataProducerObserverEvents = { close: []; pause: []; resume: []; }; -type DataProducerDump = DataProducerData & -{ +type DataProducerDump = DataProducerData & { id: string; paused: boolean; }; -type DataProducerInternal = TransportInternal & -{ +type DataProducerInternal = TransportInternal & { dataProducerId: string; }; -type DataProducerData = -{ +type DataProducerData = { type: DataProducerType; sctpStreamParameters?: SctpStreamParameters; label: string; @@ -97,9 +91,9 @@ type DataProducerData = const logger = new Logger('DataProducer'); -export class DataProducer - extends EnhancedEventEmitter -{ +export class DataProducer< + DataProducerAppData extends AppData = AppData, +> extends EnhancedEventEmitter { // Internal data. readonly #internal: DataProducerInternal; @@ -124,23 +118,19 @@ export class DataProducer /** * @private */ - constructor( - { - internal, - data, - channel, - paused, - appData - }: - { - internal: DataProducerInternal; - data: DataProducerData; - channel: Channel; - paused: boolean; - appData?: DataProducerAppData; - } - ) - { + constructor({ + internal, + data, + channel, + paused, + appData, + }: { + internal: DataProducerInternal; + data: DataProducerData; + channel: Channel; + paused: boolean; + appData?: DataProducerAppData; + }) { super(); logger.debug('constructor()'); @@ -149,7 +139,7 @@ export class DataProducer this.#data = data; this.#channel = channel; this.#paused = paused; - this.#appData = appData || {} as DataProducerAppData; + this.#appData = appData || ({} as DataProducerAppData); this.handleWorkerNotifications(); } @@ -157,90 +147,78 @@ export class DataProducer /** * DataProducer id. */ - get id(): string - { + get id(): string { return this.#internal.dataProducerId; } /** * Whether the DataProducer is closed. */ - get closed(): boolean - { + get closed(): boolean { return this.#closed; } /** * DataProducer type. */ - get type(): DataProducerType - { + get type(): DataProducerType { return this.#data.type; } /** * SCTP stream parameters. */ - get sctpStreamParameters(): SctpStreamParameters | undefined - { + get sctpStreamParameters(): SctpStreamParameters | undefined { return this.#data.sctpStreamParameters; } /** * DataChannel label. */ - get label(): string - { + get label(): string { return this.#data.label; } /** * DataChannel protocol. */ - get protocol(): string - { + get protocol(): string { return this.#data.protocol; } /** * Whether the DataProducer is paused. */ - get paused(): boolean - { + get paused(): boolean { return this.#paused; } /** * App custom data. */ - get appData(): DataProducerAppData - { + get appData(): DataProducerAppData { return this.#appData; } /** * App custom data setter. */ - set appData(appData: DataProducerAppData) - { + set appData(appData: DataProducerAppData) { this.#appData = appData; } /** * Observer. */ - get observer(): EnhancedEventEmitter - { + get observer(): EnhancedEventEmitter { return this.#observer; } /** * Close the DataProducer. */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -253,15 +231,17 @@ export class DataProducer /* Build Request. */ const requestOffset = new FbsTransport.CloseDataProducerRequestT( - this.#internal.dataProducerId + this.#internal.dataProducerId, ).pack(this.#channel.bufferBuilder); - this.#channel.request( - FbsRequest.Method.TRANSPORT_CLOSE_DATAPRODUCER, - FbsRequest.Body.Transport_CloseDataProducerRequest, - requestOffset, - this.#internal.transportId - ).catch(() => {}); + this.#channel + .request( + FbsRequest.Method.TRANSPORT_CLOSE_DATAPRODUCER, + FbsRequest.Body.Transport_CloseDataProducerRequest, + requestOffset, + this.#internal.transportId, + ) + .catch(() => {}); this.emit('@close'); @@ -274,10 +254,8 @@ export class DataProducer * * @private */ - transportClosed(): void - { - if (this.#closed) - { + transportClosed(): void { + if (this.#closed) { return; } @@ -297,15 +275,14 @@ export class DataProducer /** * Dump DataProducer. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); const response = await this.#channel.request( FbsRequest.Method.DATAPRODUCER_DUMP, undefined, undefined, - this.#internal.dataProducerId + this.#internal.dataProducerId, ); /* Decode Response. */ @@ -319,15 +296,14 @@ export class DataProducer /** * Get DataProducer stats. */ - async getStats(): Promise - { + async getStats(): Promise { logger.debug('getStats()'); const response = await this.#channel.request( FbsRequest.Method.DATAPRODUCER_GET_STATS, undefined, undefined, - this.#internal.dataProducerId + this.#internal.dataProducerId, ); /* Decode Response. */ @@ -335,21 +311,20 @@ export class DataProducer response.body(data); - return [ parseDataProducerStats(data) ]; + return [parseDataProducerStats(data)]; } /** * Pause the DataProducer. */ - async pause(): Promise - { + async pause(): Promise { logger.debug('pause()'); await this.#channel.request( FbsRequest.Method.DATAPRODUCER_PAUSE, undefined, undefined, - this.#internal.dataProducerId + this.#internal.dataProducerId, ); const wasPaused = this.#paused; @@ -357,8 +332,7 @@ export class DataProducer this.#paused = true; // Emit observer event. - if (!wasPaused) - { + if (!wasPaused) { this.#observer.safeEmit('pause'); } } @@ -366,15 +340,14 @@ export class DataProducer /** * Resume the DataProducer. */ - async resume(): Promise - { + async resume(): Promise { logger.debug('resume()'); await this.#channel.request( FbsRequest.Method.DATAPRODUCER_RESUME, undefined, undefined, - this.#internal.dataProducerId + this.#internal.dataProducerId, ); const wasPaused = this.#paused; @@ -382,8 +355,7 @@ export class DataProducer this.#paused = false; // Emit observer event. - if (wasPaused) - { + if (wasPaused) { this.#observer.safeEmit('resume'); } } @@ -395,11 +367,9 @@ export class DataProducer message: string | Buffer, ppid?: number, subchannels?: number[], - requiredSubchannel?: number - ): void - { - if (typeof message !== 'string' && !Buffer.isBuffer(message)) - { + requiredSubchannel?: number, + ): void { + if (typeof message !== 'string' && !Buffer.isBuffer(message)) { throw new TypeError('message must be a string or a Buffer'); } @@ -419,20 +389,21 @@ export class DataProducer * +-------------------------------+----------+ */ - if (typeof ppid !== 'number') - { - ppid = (typeof message === 'string') - ? message.length > 0 ? 51 : 56 - : message.length > 0 ? 53 : 57; + if (typeof ppid !== 'number') { + ppid = + typeof message === 'string' + ? message.length > 0 + ? 51 + : 56 + : message.length > 0 + ? 53 + : 57; } // Ensure we honor PPIDs. - if (ppid === 56) - { + if (ppid === 56) { message = ' '; - } - else if (ppid === 57) - { + } else if (ppid === 57) { message = Buffer.alloc(1); } @@ -440,102 +411,100 @@ export class DataProducer let dataOffset = 0; - const subchannelsOffset = FbsDataProducer.SendNotification.createSubchannelsVector( - builder, subchannels ?? [] - ); + const subchannelsOffset = + FbsDataProducer.SendNotification.createSubchannelsVector( + builder, + subchannels ?? [], + ); - if (typeof message === 'string') - { + if (typeof message === 'string') { message = Buffer.from(message); } - dataOffset = FbsDataProducer.SendNotification.createDataVector(builder, message); - - const notificationOffset = FbsDataProducer.SendNotification.createSendNotification( + dataOffset = FbsDataProducer.SendNotification.createDataVector( builder, - ppid, - dataOffset, - subchannelsOffset, - requiredSubchannel ?? null + message, ); + const notificationOffset = + FbsDataProducer.SendNotification.createSendNotification( + builder, + ppid, + dataOffset, + subchannelsOffset, + requiredSubchannel ?? null, + ); + this.#channel.notify( FbsNotification.Event.DATAPRODUCER_SEND, FbsNotification.Body.DataProducer_SendNotification, notificationOffset, - this.#internal.dataProducerId + this.#internal.dataProducerId, ); } - private handleWorkerNotifications(): void - { + private handleWorkerNotifications(): void { // No need to subscribe to any event. } } -export function dataProducerTypeToFbs(type: DataProducerType): FbsDataProducer.Type -{ - switch (type) - { - case 'sctp': - { +export function dataProducerTypeToFbs( + type: DataProducerType, +): FbsDataProducer.Type { + switch (type) { + case 'sctp': { return FbsDataProducer.Type.SCTP; } - case 'direct': - { + case 'direct': { return FbsDataProducer.Type.DIRECT; } - default: - { + default: { throw new TypeError('invalid DataConsumerType: ${type}'); } } } -export function dataProducerTypeFromFbs(type: FbsDataProducer.Type): DataProducerType -{ - switch (type) - { - case FbsDataProducer.Type.SCTP: - { +export function dataProducerTypeFromFbs( + type: FbsDataProducer.Type, +): DataProducerType { + switch (type) { + case FbsDataProducer.Type.SCTP: { return 'sctp'; } - case FbsDataProducer.Type.DIRECT: - { + case FbsDataProducer.Type.DIRECT: { return 'direct'; } } } export function parseDataProducerDumpResponse( - data: FbsDataProducer.DumpResponse -): DataProducerDump -{ + data: FbsDataProducer.DumpResponse, +): DataProducerDump { return { - id : data.id()!, - type : dataProducerTypeFromFbs(data.type()), - sctpStreamParameters : data.sctpStreamParameters() !== null ? - parseSctpStreamParameters(data.sctpStreamParameters()!) : - undefined, - label : data.label()!, - protocol : data.protocol()!, - paused : data.paused() + id: data.id()!, + type: dataProducerTypeFromFbs(data.type()), + sctpStreamParameters: + data.sctpStreamParameters() !== null + ? parseSctpStreamParameters(data.sctpStreamParameters()!) + : undefined, + label: data.label()!, + protocol: data.protocol()!, + paused: data.paused(), }; } function parseDataProducerStats( - binary: FbsDataProducer.GetStatsResponse -): DataProducerStat -{ + binary: FbsDataProducer.GetStatsResponse, +): DataProducerStat { return { - type : 'data-producer', - timestamp : Number(binary.timestamp()), - label : binary.label()!, - protocol : binary.protocol()!, - messagesReceived : Number(binary.messagesReceived()), - bytesReceived : Number(binary.bytesReceived()) + type: 'data-producer', + timestamp: Number(binary.timestamp()), + label: binary.label()!, + protocol: binary.protocol()!, + messagesReceived: Number(binary.messagesReceived()), + bytesReceived: Number(binary.bytesReceived()), }; } diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 99da02ede9..1cea2c9bb3 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -9,7 +9,7 @@ import { Transport, TransportEvents, TransportObserverEvents, - TransportConstructorOptions + TransportConstructorOptions, } from './Transport'; import { SctpParameters } from './SctpParameters'; import { AppData } from './types'; @@ -19,8 +19,9 @@ import * as FbsTransport from './fbs/transport'; import * as FbsNotification from './fbs/notification'; import * as FbsRequest from './fbs/request'; -export type DirectTransportOptions = -{ +export type DirectTransportOptions< + DirectTransportAppData extends AppData = AppData, +> = { /** * Maximum allowed size for direct messages sent from DataProducers. * Default 262144. @@ -35,51 +36,50 @@ export type DirectTransportOptions = - TransportConstructorOptions & - { + TransportConstructorOptions & { data: DirectTransportData; }; -export type DirectTransportData = -{ +export type DirectTransportData = { sctpParameters?: SctpParameters; }; const logger = new Logger('DirectTransport'); -export class DirectTransport - extends Transport -{ +export class DirectTransport< + DirectTransportAppData extends AppData = AppData, +> extends Transport< + DirectTransportAppData, + DirectTransportEvents, + DirectTransportObserverEvents +> { // DirectTransport data. readonly #data: DirectTransportData; /** * @private */ - constructor(options: DirectTransportConstructorOptions) - { + constructor( + options: DirectTransportConstructorOptions, + ) { super(options); logger.debug('constructor()'); - this.#data = - { + this.#data = { // Nothing. }; @@ -91,10 +91,8 @@ export class DirectTransport * * @override */ - close(): void - { - if (this.closed) - { + close(): void { + if (this.closed) { return; } @@ -107,10 +105,8 @@ export class DirectTransport * @private * @override */ - routerClosed(): void - { - if (this.closed) - { + routerClosed(): void { + if (this.closed) { return; } @@ -120,15 +116,14 @@ export class DirectTransport /** * Dump Transport. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_DUMP, undefined, undefined, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -144,15 +139,14 @@ export class DirectTransport * * @override */ - async getStats(): Promise - { + async getStats(): Promise { logger.debug('getStats()'); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_GET_STATS, undefined, undefined, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -160,7 +154,7 @@ export class DirectTransport response.body(data); - return [ parseGetStatsResponse(data) ]; + return [parseGetStatsResponse(data)]; } /** @@ -168,8 +162,7 @@ export class DirectTransport * * @override */ - async connect(): Promise - { + async connect(): Promise { logger.debug('connect()'); } @@ -177,122 +170,115 @@ export class DirectTransport * @override */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - async setMaxIncomingBitrate(bitrate: number): Promise - { + async setMaxIncomingBitrate(bitrate: number): Promise { throw new UnsupportedError( - 'setMaxIncomingBitrate() not implemented in DirectTransport'); + 'setMaxIncomingBitrate() not implemented in DirectTransport', + ); } /** * @override */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - async setMaxOutgoingBitrate(bitrate: number): Promise - { + async setMaxOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( - 'setMaxOutgoingBitrate() not implemented in DirectTransport'); + 'setMaxOutgoingBitrate() not implemented in DirectTransport', + ); } /** * @override */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - async setMinOutgoingBitrate(bitrate: number): Promise - { + async setMinOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( - 'setMinOutgoingBitrate() not implemented in DirectTransport'); + 'setMinOutgoingBitrate() not implemented in DirectTransport', + ); } /** * Send RTCP packet. */ - sendRtcp(rtcpPacket: Buffer) - { - if (!Buffer.isBuffer(rtcpPacket)) - { + sendRtcp(rtcpPacket: Buffer) { + if (!Buffer.isBuffer(rtcpPacket)) { throw new TypeError('rtcpPacket must be a Buffer'); } const builder = this.channel.bufferBuilder; - const dataOffset = - FbsTransport.SendRtcpNotification.createDataVector(builder, rtcpPacket); + const dataOffset = FbsTransport.SendRtcpNotification.createDataVector( + builder, + rtcpPacket, + ); const notificationOffset = FbsTransport.SendRtcpNotification.createSendRtcpNotification( builder, - dataOffset + dataOffset, ); this.channel.notify( FbsNotification.Event.TRANSPORT_SEND_RTCP, FbsNotification.Body.Transport_SendRtcpNotification, notificationOffset, - this.internal.transportId + this.internal.transportId, ); - } - private handleWorkerNotifications(): void - { - this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => - { - switch (event) - { - case Event.TRANSPORT_TRACE: - { - const notification = new FbsTransport.TraceNotification(); - - data!.body(notification); + private handleWorkerNotifications(): void { + this.channel.on( + this.internal.transportId, + (event: Event, data?: Notification) => { + switch (event) { + case Event.TRANSPORT_TRACE: { + const notification = new FbsTransport.TraceNotification(); - const trace = parseTransportTraceEventData(notification); + data!.body(notification); - this.safeEmit('trace', trace); + const trace = parseTransportTraceEventData(notification); - // Emit observer event. - this.observer.safeEmit('trace', trace); + this.safeEmit('trace', trace); - break; - } + // Emit observer event. + this.observer.safeEmit('trace', trace); - case Event.DIRECTTRANSPORT_RTCP: - { - if (this.closed) - { break; } - const notification = new FbsDirectTransport.RtcpNotification(); + case Event.DIRECTTRANSPORT_RTCP: { + if (this.closed) { + break; + } - data!.body(notification); + const notification = new FbsDirectTransport.RtcpNotification(); - this.safeEmit('rtcp', Buffer.from(notification.dataArray()!)); + data!.body(notification); - break; - } + this.safeEmit('rtcp', Buffer.from(notification.dataArray()!)); + + break; + } - default: - { - logger.error('ignoring unknown event "%s"', event); + default: { + logger.error('ignoring unknown event "%s"', event); + } } - } - }); + }, + ); } } export function parseDirectTransportDumpResponse( - binary: FbsDirectTransport.DumpResponse -): BaseTransportDump -{ + binary: FbsDirectTransport.DumpResponse, +): BaseTransportDump { return parseBaseTransportDump(binary.base()!); } function parseGetStatsResponse( - binary: FbsDirectTransport.GetStatsResponse -):DirectTransportStat -{ + binary: FbsDirectTransport.GetStatsResponse, +): DirectTransportStat { const base = parseBaseTransportStats(binary.base()!); return { ...base, - type : 'direct-transport' + type: 'direct-transport', }; } diff --git a/node/src/EnhancedEventEmitter.ts b/node/src/EnhancedEventEmitter.ts index 3460f034ab..a0dce20193 100644 --- a/node/src/EnhancedEventEmitter.ts +++ b/node/src/EnhancedEventEmitter.ts @@ -5,41 +5,34 @@ const logger = new Logger('EnhancedEventEmitter'); type Events = Record; -export class EnhancedEventEmitter extends EventEmitter -{ - constructor() - { +export class EnhancedEventEmitter< + E extends Events = Events, +> extends EventEmitter { + constructor() { super(); this.setMaxListeners(Infinity); } - emit(eventName: K, ...args: E[K]): boolean - { + emit(eventName: K, ...args: E[K]): boolean { return super.emit(eventName, ...args); } /** * Special addition to the EventEmitter API. */ - safeEmit(eventName: K, ...args: E[K]): boolean - { - try - { + safeEmit(eventName: K, ...args: E[K]): boolean { + try { return super.emit(eventName, ...args); - } - catch (error) - { + } catch (error) { logger.error( 'safeEmit() | event listener threw an error [eventName:%s]:%o', - eventName, error + eventName, + error, ); - try - { + try { super.emit('listenererror', eventName, error); - } - catch (error2) - { + } catch (error2) { // Ignore it. } @@ -49,9 +42,8 @@ export class EnhancedEventEmitter extends EventEmitte on( eventName: K, - listener: (...args: E[K]) => void - ): this - { + listener: (...args: E[K]) => void, + ): this { super.on(eventName, listener as (...args: any[]) => void); return this; @@ -59,9 +51,8 @@ export class EnhancedEventEmitter extends EventEmitte off( eventName: K, - listener: (...args: E[K]) => void - ): this - { + listener: (...args: E[K]) => void, + ): this { super.off(eventName, listener as (...args: any[]) => void); return this; @@ -69,9 +60,8 @@ export class EnhancedEventEmitter extends EventEmitte addListener( eventName: K, - listener: (...args: E[K]) => void - ): this - { + listener: (...args: E[K]) => void, + ): this { super.on(eventName, listener as (...args: any[]) => void); return this; @@ -79,9 +69,8 @@ export class EnhancedEventEmitter extends EventEmitte prependListener( eventName: K, - listener: (...args: E[K]) => void - ): this - { + listener: (...args: E[K]) => void, + ): this { super.prependListener(eventName, listener as (...args: any[]) => void); return this; @@ -89,9 +78,8 @@ export class EnhancedEventEmitter extends EventEmitte once( eventName: K, - listener: (...args: E[K]) => void - ): this - { + listener: (...args: E[K]) => void, + ): this { super.once(eventName, listener as (...args: any[]) => void); return this; @@ -99,9 +87,8 @@ export class EnhancedEventEmitter extends EventEmitte prependOnceListener( eventName: K, - listener: (...args: E[K]) => void - ): this - { + listener: (...args: E[K]) => void, + ): this { super.prependOnceListener(eventName, listener as (...args: any[]) => void); return this; @@ -109,33 +96,28 @@ export class EnhancedEventEmitter extends EventEmitte removeListener( eventName: K, - listener: (...args: E[K]) => void - ): this - { + listener: (...args: E[K]) => void, + ): this { super.off(eventName, listener as (...args: any[]) => void); return this; } - removeAllListeners(eventName?: K): this - { + removeAllListeners(eventName?: K): this { super.removeAllListeners(eventName); return this; } - listenerCount(eventName: K): number - { + listenerCount(eventName: K): number { return super.listenerCount(eventName); } - listeners(eventName: K): Function[] - { + listeners(eventName: K): Function[] { return super.listeners(eventName); } - rawListeners(eventName: K): Function[] - { + rawListeners(eventName: K): Function[] { return super.rawListeners(eventName); } } diff --git a/node/src/Logger.ts b/node/src/Logger.ts index b5a199d989..96f5054b75 100644 --- a/node/src/Logger.ts +++ b/node/src/Logger.ts @@ -2,22 +2,17 @@ import debug from 'debug'; const APP_NAME = 'mediasoup'; -export class Logger -{ +export class Logger { readonly #debug: debug.Debugger; readonly #warn: debug.Debugger; readonly #error: debug.Debugger; - constructor(prefix?: string) - { - if (prefix) - { + constructor(prefix?: string) { + if (prefix) { this.#debug = debug(`${APP_NAME}:${prefix}`); this.#warn = debug(`${APP_NAME}:WARN:${prefix}`); this.#error = debug(`${APP_NAME}:ERROR:${prefix}`); - } - else - { + } else { this.#debug = debug(APP_NAME); this.#warn = debug(`${APP_NAME}:WARN`); this.#error = debug(`${APP_NAME}:ERROR`); @@ -30,18 +25,15 @@ export class Logger /* eslint-enable no-console */ } - get debug(): debug.Debugger - { + get debug(): debug.Debugger { return this.#debug; } - get warn(): debug.Debugger - { + get warn(): debug.Debugger { return this.#warn; } - get error(): debug.Debugger - { + get error(): debug.Debugger { return this.#error; } } diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index e3a10dc439..b801a83ed6 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -16,20 +16,20 @@ import { TransportEvents, TransportObserverEvents, TransportConstructorOptions, - SctpState + SctpState, } from './Transport'; import { Consumer, ConsumerType } from './Consumer'; import { Producer } from './Producer'; import { RtpParameters, serializeRtpEncodingParameters, - serializeRtpParameters + serializeRtpParameters, } from './RtpParameters'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; import { parseSrtpParameters, serializeSrtpParameters, - SrtpParameters + SrtpParameters, } from './SrtpParameters'; import { AppData, Either } from './types'; import { generateUUIDv4 } from './utils'; @@ -40,16 +40,14 @@ import * as FbsRequest from './fbs/request'; import * as FbsTransport from './fbs/transport'; import * as FbsPipeTransport from './fbs/pipe-transport'; -type PipeTransportListenInfo = -{ +type PipeTransportListenInfo = { /** * Listening info. */ listenInfo: TransportListenInfo; }; -type PipeTransportListenIp = -{ +type PipeTransportListenIp = { /** * Listening IP address. */ @@ -62,10 +60,14 @@ type PipeTransportListenIp = port?: number; }; -type PipeTransportListen = Either; +type PipeTransportListen = Either< + PipeTransportListenInfo, + PipeTransportListenIp +>; -export type PipeTransportOptions = -{ +export type PipeTransportOptions< + PipeTransportAppData extends AppData = AppData, +> = { /** * Create a SCTP association. Default false. */ @@ -108,14 +110,12 @@ export type PipeTransportOptions appData?: PipeTransportAppData; } & PipeTransportListen; -export type PipeTransportStat = BaseTransportStats & -{ +export type PipeTransportStat = BaseTransportStats & { type: string; tuple: TransportTuple; }; -export type PipeConsumerOptions = -{ +export type PipeConsumerOptions = { /** * The id of the Producer to consume. */ @@ -127,24 +127,20 @@ export type PipeConsumerOptions = appData?: ConsumerAppData; }; -export type PipeTransportEvents = TransportEvents & -{ +export type PipeTransportEvents = TransportEvents & { sctpstatechange: [SctpState]; }; -export type PipeTransportObserverEvents = TransportObserverEvents & -{ +export type PipeTransportObserverEvents = TransportObserverEvents & { sctpstatechange: [SctpState]; }; type PipeTransportConstructorOptions = - TransportConstructorOptions & - { + TransportConstructorOptions & { data: PipeTransportData; }; -export type PipeTransportData = -{ +export type PipeTransportData = { tuple: TransportTuple; sctpParameters?: SctpParameters; sctpState?: SctpState; @@ -152,8 +148,7 @@ export type PipeTransportData = srtpParameters?: SrtpParameters; }; -export type PipeTransportDump = BaseTransportDump & -{ +export type PipeTransportDump = BaseTransportDump & { tuple: TransportTuple; rtx: boolean; srtpParameters?: SrtpParameters; @@ -161,30 +156,32 @@ export type PipeTransportDump = BaseTransportDump & const logger = new Logger('PipeTransport'); -export class PipeTransport - extends Transport -{ +export class PipeTransport< + PipeTransportAppData extends AppData = AppData, +> extends Transport< + PipeTransportAppData, + PipeTransportEvents, + PipeTransportObserverEvents +> { // PipeTransport data. readonly #data: PipeTransportData; /** * @private */ - constructor(options: PipeTransportConstructorOptions) - { + constructor(options: PipeTransportConstructorOptions) { super(options); logger.debug('constructor()'); const { data } = options; - this.#data = - { - tuple : data.tuple, - sctpParameters : data.sctpParameters, - sctpState : data.sctpState, - rtx : data.rtx, - srtpParameters : data.srtpParameters + this.#data = { + tuple: data.tuple, + sctpParameters: data.sctpParameters, + sctpState: data.sctpState, + rtx: data.rtx, + srtpParameters: data.srtpParameters, }; this.handleWorkerNotifications(); @@ -193,32 +190,28 @@ export class PipeTransport /** * Transport tuple. */ - get tuple(): TransportTuple - { + get tuple(): TransportTuple { return this.#data.tuple; } /** * SCTP parameters. */ - get sctpParameters(): SctpParameters | undefined - { + get sctpParameters(): SctpParameters | undefined { return this.#data.sctpParameters; } /** * SCTP state. */ - get sctpState(): SctpState | undefined - { + get sctpState(): SctpState | undefined { return this.#data.sctpState; } /** * SRTP parameters. */ - get srtpParameters(): SrtpParameters | undefined - { + get srtpParameters(): SrtpParameters | undefined { return this.#data.srtpParameters; } @@ -227,15 +220,12 @@ export class PipeTransport * * @override */ - close(): void - { - if (this.closed) - { + close(): void { + if (this.closed) { return; } - if (this.#data.sctpState) - { + if (this.#data.sctpState) { this.#data.sctpState = 'closed'; } @@ -248,15 +238,12 @@ export class PipeTransport * @private * @override */ - routerClosed(): void - { - if (this.closed) - { + routerClosed(): void { + if (this.closed) { return; } - if (this.#data.sctpState) - { + if (this.#data.sctpState) { this.#data.sctpState = 'closed'; } @@ -268,15 +255,14 @@ export class PipeTransport * * @override */ - async getStats(): Promise - { + async getStats(): Promise { logger.debug('getStats()'); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_GET_STATS, undefined, undefined, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -284,7 +270,7 @@ export class PipeTransport response.body(data); - return [ parseGetStatsResponse(data) ]; + return [parseGetStatsResponse(data)]; } /** @@ -292,26 +278,22 @@ export class PipeTransport * * @override */ - async connect( - { - ip, - port, - srtpParameters - }: - { - ip: string; - port: number; - srtpParameters?: SrtpParameters; - } - ): Promise - { + async connect({ + ip, + port, + srtpParameters, + }: { + ip: string; + port: number; + srtpParameters?: SrtpParameters; + }): Promise { logger.debug('connect()'); const requestOffset = createConnectRequest({ - builder : this.channel.bufferBuilder, + builder: this.channel.bufferBuilder, ip, port, - srtpParameters + srtpParameters, }); // Wait for response. @@ -319,7 +301,7 @@ export class PipeTransport FbsRequest.Method.PIPETRANSPORT_CONNECT, FbsRequest.Body.PipeTransport_ConnectRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -328,8 +310,7 @@ export class PipeTransport response.body(data); // Update data. - if (data.tuple()) - { + if (data.tuple()) { this.#data.tuple = parseTuple(data.tuple()!); } } @@ -339,53 +320,44 @@ export class PipeTransport * * @override */ - async consume( - { - producerId, - appData - }: PipeConsumerOptions - ): Promise> - { + async consume({ + producerId, + appData, + }: PipeConsumerOptions): Promise> { logger.debug('consume()'); - if (!producerId || typeof producerId !== 'string') - { + if (!producerId || typeof producerId !== 'string') { throw new TypeError('missing producerId'); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } const producer = this.getProducerById(producerId); - if (!producer) - { + if (!producer) { throw Error(`Producer with id "${producerId}" not found`); } // This may throw. - const rtpParameters = ortc.getPipeConsumerRtpParameters( - { - consumableRtpParameters : producer.consumableRtpParameters, - enableRtx : this.#data.rtx - } - ); + const rtpParameters = ortc.getPipeConsumerRtpParameters({ + consumableRtpParameters: producer.consumableRtpParameters, + enableRtx: this.#data.rtx, + }); const consumerId = generateUUIDv4(); const consumeRequestOffset = createConsumeRequest({ - builder : this.channel.bufferBuilder, + builder: this.channel.bufferBuilder, consumerId, producer, - rtpParameters + rtpParameters, }); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_CONSUME, FbsRequest.Body.Transport_ConsumeRequest, consumeRequestOffset, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -395,27 +367,24 @@ export class PipeTransport const status = consumeResponse.unpack(); - const data = - { + const data = { producerId, - kind : producer.kind, + kind: producer.kind, rtpParameters, - type : 'pipe' as ConsumerType + type: 'pipe' as ConsumerType, }; - const consumer = new Consumer( - { - internal : - { - ...this.internal, - consumerId - }, - data, - channel : this.channel, - appData, - paused : status.paused, - producerPaused : status.producerPaused - }); + const consumer = new Consumer({ + internal: { + ...this.internal, + consumerId, + }, + data, + channel: this.channel, + appData, + paused: status.paused, + producerPaused: status.producerPaused, + }); this.consumers.set(consumer.id, consumer); consumer.on('@close', () => this.consumers.delete(consumer.id)); @@ -427,52 +396,49 @@ export class PipeTransport return consumer; } - private handleWorkerNotifications(): void - { - this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => - { - switch (event) - { - case Event.TRANSPORT_SCTP_STATE_CHANGE: - { - const notification = new FbsTransport.SctpStateChangeNotification(); + private handleWorkerNotifications(): void { + this.channel.on( + this.internal.transportId, + (event: Event, data?: Notification) => { + switch (event) { + case Event.TRANSPORT_SCTP_STATE_CHANGE: { + const notification = new FbsTransport.SctpStateChangeNotification(); - data!.body(notification); + data!.body(notification); - const sctpState = parseSctpState(notification.sctpState()); + const sctpState = parseSctpState(notification.sctpState()); - this.#data.sctpState = sctpState; + this.#data.sctpState = sctpState; - this.safeEmit('sctpstatechange', sctpState); + this.safeEmit('sctpstatechange', sctpState); - // Emit observer event. - this.observer.safeEmit('sctpstatechange', sctpState); + // Emit observer event. + this.observer.safeEmit('sctpstatechange', sctpState); - break; - } + break; + } - case Event.TRANSPORT_TRACE: - { - const notification = new FbsTransport.TraceNotification(); + case Event.TRANSPORT_TRACE: { + const notification = new FbsTransport.TraceNotification(); - data!.body(notification); + data!.body(notification); - const trace = parseTransportTraceEventData(notification); + const trace = parseTransportTraceEventData(notification); - this.safeEmit('trace', trace); + this.safeEmit('trace', trace); - // Emit observer event. - this.observer.safeEmit('trace', trace); + // Emit observer event. + this.observer.safeEmit('trace', trace); - break; - } + break; + } - default: - { - logger.error('ignoring unknown event "%s"', event); + default: { + logger.error('ignoring unknown event "%s"', event); + } } - } - }); + }, + ); } } @@ -481,9 +447,8 @@ export class PipeTransport */ export function parsePipeTransportDumpResponse( - binary: FbsPipeTransport.DumpResponse -): PipeTransportDump -{ + binary: FbsPipeTransport.DumpResponse, +): PipeTransportDump { // Retrieve BaseTransportDump. const baseTransportDump = parseBaseTransportDump(binary.base()!); // Retrieve RTP Tuple. @@ -492,29 +457,27 @@ export function parsePipeTransportDumpResponse( // Retrieve SRTP Parameters. let srtpParameters: SrtpParameters | undefined; - if (binary.srtpParameters()) - { + if (binary.srtpParameters()) { srtpParameters = parseSrtpParameters(binary.srtpParameters()!); } return { ...baseTransportDump, - tuple : tuple, - rtx : binary.rtx(), - srtpParameters : srtpParameters + tuple: tuple, + rtx: binary.rtx(), + srtpParameters: srtpParameters, }; } function parseGetStatsResponse( - binary: FbsPipeTransport.GetStatsResponse -):PipeTransportStat -{ + binary: FbsPipeTransport.GetStatsResponse, +): PipeTransportStat { const base = parseBaseTransportStats(binary.base()!); return { ...base, - type : 'pipe-transport', - tuple : parseTuple(binary.tuple()!) + type: 'pipe-transport', + tuple: parseTuple(binary.tuple()!), }; } @@ -522,24 +485,23 @@ function createConsumeRequest({ builder, consumerId, producer, - rtpParameters -} : { + rtpParameters, +}: { builder: flatbuffers.Builder; consumerId: string; producer: Producer; rtpParameters: RtpParameters; -}): number -{ +}): number { // Build the request. const producerIdOffset = builder.createString(producer.id); const consumerIdOffset = builder.createString(consumerId); const rtpParametersOffset = serializeRtpParameters(builder, rtpParameters); let consumableRtpEncodingsOffset: number | undefined; - if (producer.consumableRtpParameters.encodings) - { + if (producer.consumableRtpParameters.encodings) { consumableRtpEncodingsOffset = serializeRtpEncodingParameters( - builder, producer.consumableRtpParameters.encodings + builder, + producer.consumableRtpParameters.encodings, ); } @@ -550,44 +512,42 @@ function createConsumeRequest({ ConsumeRequest.addConsumerId(builder, consumerIdOffset); ConsumeRequest.addProducerId(builder, producerIdOffset); ConsumeRequest.addKind( - builder, producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO); + builder, + producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO, + ); ConsumeRequest.addRtpParameters(builder, rtpParametersOffset); ConsumeRequest.addType(builder, FbsRtpParameters.Type.PIPE); - if (consumableRtpEncodingsOffset) - { - ConsumeRequest.addConsumableRtpEncodings(builder, consumableRtpEncodingsOffset); + if (consumableRtpEncodingsOffset) { + ConsumeRequest.addConsumableRtpEncodings( + builder, + consumableRtpEncodingsOffset, + ); } return ConsumeRequest.endConsumeRequest(builder); } -function createConnectRequest( - { - builder, - ip, - port, - srtpParameters - }: - { - builder: flatbuffers.Builder; - ip?: string; - port?: number; - srtpParameters?: SrtpParameters; - } -): number -{ +function createConnectRequest({ + builder, + ip, + port, + srtpParameters, +}: { + builder: flatbuffers.Builder; + ip?: string; + port?: number; + srtpParameters?: SrtpParameters; +}): number { let ipOffset = 0; let srtpParametersOffset = 0; - if (ip) - { + if (ip) { ipOffset = builder.createString(ip); } // Serialize SrtpParameters. - if (srtpParameters) - { + if (srtpParameters) { srtpParametersOffset = serializeSrtpParameters(builder, srtpParameters); } @@ -595,14 +555,13 @@ function createConnectRequest( FbsPipeTransport.ConnectRequest.startConnectRequest(builder); FbsPipeTransport.ConnectRequest.addIp(builder, ipOffset); - if (typeof port === 'number') - { + if (typeof port === 'number') { FbsPipeTransport.ConnectRequest.addPort(builder, port); } - if (srtpParameters) - { + if (srtpParameters) { FbsPipeTransport.ConnectRequest.addSrtpParameters( - builder, srtpParametersOffset + builder, + srtpParametersOffset, ); } diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index 2852b30485..3f6f4382b4 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -15,14 +15,14 @@ import { TransportEvents, TransportObserverEvents, TransportConstructorOptions, - SctpState + SctpState, } from './Transport'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; import { parseSrtpParameters, serializeSrtpParameters, SrtpParameters, - SrtpCryptoSuite + SrtpCryptoSuite, } from './SrtpParameters'; import { AppData, Either } from './types'; import { Event, Notification } from './fbs/notification'; @@ -30,8 +30,7 @@ import * as FbsRequest from './fbs/request'; import * as FbsTransport from './fbs/transport'; import * as FbsPlainTransport from './fbs/plain-transport'; -type PlainTransportListenInfo = -{ +type PlainTransportListenInfo = { /** * Listening info. */ @@ -43,8 +42,7 @@ type PlainTransportListenInfo = rtcpListenInfo?: TransportListenInfo; }; -type PlainTransportListenIp = -{ +type PlainTransportListenIp = { /** * Listening IP address. */ @@ -57,10 +55,14 @@ type PlainTransportListenIp = port?: number; }; -type PlainTransportListen = Either; +type PlainTransportListen = Either< + PlainTransportListenInfo, + PlainTransportListenIp +>; -export type PlainTransportOptions = -{ +export type PlainTransportOptions< + PlainTransportAppData extends AppData = AppData, +> = { /** * Use RTCP-mux (RTP and RTCP in the same port). Default true. */ @@ -114,8 +116,7 @@ export type PlainTransportOptions = - TransportConstructorOptions & - { + TransportConstructorOptions & { data: PlainTransportData; }; -export type PlainTransportData = -{ +export type PlainTransportData = { rtcpMux?: boolean; comedia?: boolean; tuple: TransportTuple; @@ -154,8 +151,7 @@ export type PlainTransportData = srtpParameters?: SrtpParameters; }; -type PlainTransportDump = BaseTransportDump & -{ +type PlainTransportDump = BaseTransportDump & { rtcpMux: boolean; comedia: boolean; tuple: TransportTuple; @@ -165,32 +161,36 @@ type PlainTransportDump = BaseTransportDump & const logger = new Logger('PlainTransport'); -export class PlainTransport - extends Transport -{ +export class PlainTransport< + PlainTransportAppData extends AppData = AppData, +> extends Transport< + PlainTransportAppData, + PlainTransportEvents, + PlainTransportObserverEvents +> { // PlainTransport data. readonly #data: PlainTransportData; /** * @private */ - constructor(options: PlainTransportConstructorOptions) - { + constructor( + options: PlainTransportConstructorOptions, + ) { super(options); logger.debug('constructor()'); const { data } = options; - this.#data = - { - rtcpMux : data.rtcpMux, - comedia : data.comedia, - tuple : data.tuple, - rtcpTuple : data.rtcpTuple, - sctpParameters : data.sctpParameters, - sctpState : data.sctpState, - srtpParameters : data.srtpParameters + this.#data = { + rtcpMux: data.rtcpMux, + comedia: data.comedia, + tuple: data.tuple, + rtcpTuple: data.rtcpTuple, + sctpParameters: data.sctpParameters, + sctpState: data.sctpState, + srtpParameters: data.srtpParameters, }; this.handleWorkerNotifications(); @@ -199,40 +199,35 @@ export class PlainTransport /** * Transport tuple. */ - get tuple(): TransportTuple - { + get tuple(): TransportTuple { return this.#data.tuple; } /** * Transport RTCP tuple. */ - get rtcpTuple(): TransportTuple | undefined - { + get rtcpTuple(): TransportTuple | undefined { return this.#data.rtcpTuple; } /** * SCTP parameters. */ - get sctpParameters(): SctpParameters | undefined - { + get sctpParameters(): SctpParameters | undefined { return this.#data.sctpParameters; } /** * SCTP state. */ - get sctpState(): SctpState | undefined - { + get sctpState(): SctpState | undefined { return this.#data.sctpState; } /** * SRTP parameters. */ - get srtpParameters(): SrtpParameters | undefined - { + get srtpParameters(): SrtpParameters | undefined { return this.#data.srtpParameters; } @@ -241,15 +236,12 @@ export class PlainTransport * * @override */ - close(): void - { - if (this.closed) - { + close(): void { + if (this.closed) { return; } - if (this.#data.sctpState) - { + if (this.#data.sctpState) { this.#data.sctpState = 'closed'; } @@ -262,15 +254,12 @@ export class PlainTransport * @private * @override */ - routerClosed(): void - { - if (this.closed) - { + routerClosed(): void { + if (this.closed) { return; } - if (this.#data.sctpState) - { + if (this.#data.sctpState) { this.#data.sctpState = 'closed'; } @@ -280,15 +269,14 @@ export class PlainTransport /** * Dump Transport. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_DUMP, undefined, undefined, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -304,15 +292,14 @@ export class PlainTransport * * @override */ - async getStats(): Promise - { + async getStats(): Promise { logger.debug('getStats()'); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_GET_STATS, undefined, undefined, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -320,7 +307,7 @@ export class PlainTransport response.body(data); - return [ parseGetStatsResponse(data) ]; + return [parseGetStatsResponse(data)]; } /** @@ -328,29 +315,25 @@ export class PlainTransport * * @override */ - async connect( - { - ip, - port, - rtcpPort, - srtpParameters - }: - { - ip?: string; - port?: number; - rtcpPort?: number; - srtpParameters?: SrtpParameters; - } - ): Promise - { + async connect({ + ip, + port, + rtcpPort, + srtpParameters, + }: { + ip?: string; + port?: number; + rtcpPort?: number; + srtpParameters?: SrtpParameters; + }): Promise { logger.debug('connect()'); const requestOffset = createConnectRequest({ - builder : this.channel.bufferBuilder, + builder: this.channel.bufferBuilder, ip, port, rtcpPort, - srtpParameters + srtpParameters, }); // Wait for response. @@ -358,7 +341,7 @@ export class PlainTransport FbsRequest.Method.PLAINTRANSPORT_CONNECT, FbsRequest.Body.PlainTransport_ConnectRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -367,112 +350,102 @@ export class PlainTransport response.body(data); // Update data. - if (data.tuple()) - { + if (data.tuple()) { this.#data.tuple = parseTuple(data.tuple()!); } - if (data.rtcpTuple()) - { + if (data.rtcpTuple()) { this.#data.rtcpTuple = parseTuple(data.rtcpTuple()!); } - if (data.srtpParameters()) - { - this.#data.srtpParameters = parseSrtpParameters( - data.srtpParameters()!); + if (data.srtpParameters()) { + this.#data.srtpParameters = parseSrtpParameters(data.srtpParameters()!); } } - private handleWorkerNotifications(): void - { - this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => - { - switch (event) - { - case Event.PLAINTRANSPORT_TUPLE: - { - const notification = new FbsPlainTransport.TupleNotification(); + private handleWorkerNotifications(): void { + this.channel.on( + this.internal.transportId, + (event: Event, data?: Notification) => { + switch (event) { + case Event.PLAINTRANSPORT_TUPLE: { + const notification = new FbsPlainTransport.TupleNotification(); - data!.body(notification); + data!.body(notification); - const tuple = parseTuple(notification.tuple()!); + const tuple = parseTuple(notification.tuple()!); - this.#data.tuple = tuple; + this.#data.tuple = tuple; - this.safeEmit('tuple', tuple); + this.safeEmit('tuple', tuple); - // Emit observer event. - this.observer.safeEmit('tuple', tuple); + // Emit observer event. + this.observer.safeEmit('tuple', tuple); - break; - } + break; + } - case Event.PLAINTRANSPORT_RTCP_TUPLE: - { - const notification = new FbsPlainTransport.RtcpTupleNotification(); + case Event.PLAINTRANSPORT_RTCP_TUPLE: { + const notification = new FbsPlainTransport.RtcpTupleNotification(); - data!.body(notification); + data!.body(notification); - const rtcpTuple = parseTuple(notification.tuple()!); + const rtcpTuple = parseTuple(notification.tuple()!); - this.#data.rtcpTuple = rtcpTuple; + this.#data.rtcpTuple = rtcpTuple; - this.safeEmit('rtcptuple', rtcpTuple); + this.safeEmit('rtcptuple', rtcpTuple); - // Emit observer event. - this.observer.safeEmit('rtcptuple', rtcpTuple); + // Emit observer event. + this.observer.safeEmit('rtcptuple', rtcpTuple); - break; - } + break; + } - case Event.TRANSPORT_SCTP_STATE_CHANGE: - { - const notification = new FbsTransport.SctpStateChangeNotification(); + case Event.TRANSPORT_SCTP_STATE_CHANGE: { + const notification = new FbsTransport.SctpStateChangeNotification(); - data!.body(notification); + data!.body(notification); - const sctpState = parseSctpState(notification.sctpState()); + const sctpState = parseSctpState(notification.sctpState()); - this.#data.sctpState = sctpState; + this.#data.sctpState = sctpState; - this.safeEmit('sctpstatechange', sctpState); + this.safeEmit('sctpstatechange', sctpState); - // Emit observer event. - this.observer.safeEmit('sctpstatechange', sctpState); + // Emit observer event. + this.observer.safeEmit('sctpstatechange', sctpState); - break; - } + break; + } - case Event.TRANSPORT_TRACE: - { - const notification = new FbsTransport.TraceNotification(); + case Event.TRANSPORT_TRACE: { + const notification = new FbsTransport.TraceNotification(); - data!.body(notification); + data!.body(notification); - const trace = parseTransportTraceEventData(notification); + const trace = parseTransportTraceEventData(notification); - this.safeEmit('trace', trace); + this.safeEmit('trace', trace); - // Emit observer event. - this.observer.safeEmit('trace', trace); + // Emit observer event. + this.observer.safeEmit('trace', trace); - break; - } + break; + } - default: - { - logger.error('ignoring unknown event "%s"', event); + default: { + logger.error('ignoring unknown event "%s"', event); + } } - } - }); + }, + ); } } export function parsePlainTransportDumpResponse( - binary: FbsPlainTransport.DumpResponse -): PlainTransportDump -{ + binary: FbsPlainTransport.DumpResponse, +): PlainTransportDump { // Retrieve BaseTransportDump. const baseTransportDump = parseBaseTransportDump(binary.base()!); // Retrieve RTP Tuple. @@ -481,75 +454,64 @@ export function parsePlainTransportDumpResponse( // Retrieve RTCP Tuple. let rtcpTuple: TransportTuple | undefined; - if (binary.rtcpTuple()) - { + if (binary.rtcpTuple()) { rtcpTuple = parseTuple(binary.rtcpTuple()!); } // Retrieve SRTP Parameters. let srtpParameters: SrtpParameters | undefined; - if (binary.srtpParameters()) - { + if (binary.srtpParameters()) { srtpParameters = parseSrtpParameters(binary.srtpParameters()!); } return { ...baseTransportDump, - rtcpMux : binary.rtcpMux(), - comedia : binary.comedia(), - tuple : tuple, - rtcpTuple : rtcpTuple, - srtpParameters : srtpParameters + rtcpMux: binary.rtcpMux(), + comedia: binary.comedia(), + tuple: tuple, + rtcpTuple: rtcpTuple, + srtpParameters: srtpParameters, }; } function parseGetStatsResponse( - binary: FbsPlainTransport.GetStatsResponse -):PlainTransportStat -{ + binary: FbsPlainTransport.GetStatsResponse, +): PlainTransportStat { const base = parseBaseTransportStats(binary.base()!); return { ...base, - type : 'plain-rtp-transport', - rtcpMux : binary.rtcpMux(), - comedia : binary.comedia(), - tuple : parseTuple(binary.tuple()!), - rtcpTuple : binary.rtcpTuple() ? - parseTuple(binary.rtcpTuple()!) : - undefined + type: 'plain-rtp-transport', + rtcpMux: binary.rtcpMux(), + comedia: binary.comedia(), + tuple: parseTuple(binary.tuple()!), + rtcpTuple: binary.rtcpTuple() ? parseTuple(binary.rtcpTuple()!) : undefined, }; } -function createConnectRequest( - { - builder, - ip, - port, - rtcpPort, - srtpParameters - }: - { - builder : flatbuffers.Builder; - ip?: string; - port?: number; - rtcpPort?: number; - srtpParameters?: SrtpParameters; - } -): number -{ +function createConnectRequest({ + builder, + ip, + port, + rtcpPort, + srtpParameters, +}: { + builder: flatbuffers.Builder; + ip?: string; + port?: number; + rtcpPort?: number; + srtpParameters?: SrtpParameters; +}): number { let ipOffset = 0; let srtpParametersOffset = 0; - if (ip) - { + if (ip) { ipOffset = builder.createString(ip); } // Serialize SrtpParameters. - if (srtpParameters) - { + if (srtpParameters) { srtpParametersOffset = serializeSrtpParameters(builder, srtpParameters); } @@ -557,18 +519,16 @@ function createConnectRequest( FbsPlainTransport.ConnectRequest.startConnectRequest(builder); FbsPlainTransport.ConnectRequest.addIp(builder, ipOffset); - if (typeof port === 'number') - { + if (typeof port === 'number') { FbsPlainTransport.ConnectRequest.addPort(builder, port); } - if (typeof rtcpPort === 'number') - { + if (typeof rtcpPort === 'number') { FbsPlainTransport.ConnectRequest.addRtcpPort(builder, rtcpPort); } - if (srtpParameters) - { + if (srtpParameters) { FbsPlainTransport.ConnectRequest.addSrtpParameters( - builder, srtpParametersOffset + builder, + srtpParametersOffset, ); } diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 9deb4a931c..7c08d427d2 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -15,8 +15,7 @@ import * as FbsProducer from './fbs/producer'; import * as FbsProducerTraceInfo from './fbs/producer/trace-info'; import * as FbsRtpParameters from './fbs/rtp-parameters'; -export type ProducerOptions = -{ +export type ProducerOptions = { /** * Producer id (just for Router.pipeToRouter() method). */ @@ -52,13 +51,18 @@ export type ProducerOptions = /** * Valid types for 'trace' event. */ -export type ProducerTraceEventType = 'rtp' | 'keyframe' | 'nack' | 'pli' | 'fir' | 'sr'; +export type ProducerTraceEventType = + | 'rtp' + | 'keyframe' + | 'nack' + | 'pli' + | 'fir' + | 'sr'; /** * 'trace' event data. */ -export type ProducerTraceEventData = -{ +export type ProducerTraceEventData = { /** * Trace type. */ @@ -80,8 +84,7 @@ export type ProducerTraceEventData = info: any; }; -export type ProducerScore = -{ +export type ProducerScore = { /** * Index of the RTP stream in the rtpParameters.encodings array. */ @@ -103,8 +106,7 @@ export type ProducerScore = score: number; }; -export type ProducerVideoOrientation = -{ +export type ProducerVideoOrientation = { /** * Whether the source is a video camera. */ @@ -128,8 +130,7 @@ export type ProducerStat = RtpStreamRecvStats; */ export type ProducerType = 'simple' | 'simulcast' | 'svc'; -export type ProducerEvents = -{ +export type ProducerEvents = { transportclose: []; score: [ProducerScore[]]; videoorientationchange: [ProducerVideoOrientation]; @@ -139,8 +140,7 @@ export type ProducerEvents = '@close': []; }; -export type ProducerObserverEvents = -{ +export type ProducerObserverEvents = { close: []; pause: []; resume: []; @@ -149,8 +149,7 @@ export type ProducerObserverEvents = trace: [ProducerTraceEventData]; }; -type ProducerDump = -{ +type ProducerDump = { id: string; kind: string; type: ProducerType; @@ -161,13 +160,11 @@ type ProducerDump = paused: boolean; }; -type ProducerInternal = TransportInternal & -{ +type ProducerInternal = TransportInternal & { producerId: string; }; -type ProducerData = -{ +type ProducerData = { kind: MediaKind; rtpParameters: RtpParameters; type: ProducerType; @@ -176,9 +173,9 @@ type ProducerData = const logger = new Logger('Producer'); -export class Producer - extends EnhancedEventEmitter -{ +export class Producer< + ProducerAppData extends AppData = AppData, +> extends EnhancedEventEmitter { // Internal data. readonly #internal: ProducerInternal; @@ -206,23 +203,19 @@ export class Producer /** * @private */ - constructor( - { - internal, - data, - channel, - appData, - paused - }: - { - internal: ProducerInternal; - data: ProducerData; - channel: Channel; - appData?: ProducerAppData; - paused: boolean; - } - ) - { + constructor({ + internal, + data, + channel, + appData, + paused, + }: { + internal: ProducerInternal; + data: ProducerData; + channel: Channel; + appData?: ProducerAppData; + paused: boolean; + }) { super(); logger.debug('constructor()'); @@ -231,7 +224,7 @@ export class Producer this.#data = data; this.#channel = channel; this.#paused = paused; - this.#appData = appData || {} as ProducerAppData; + this.#appData = appData || ({} as ProducerAppData); this.handleWorkerNotifications(); } @@ -239,40 +232,35 @@ export class Producer /** * Producer id. */ - get id(): string - { + get id(): string { return this.#internal.producerId; } /** * Whether the Producer is closed. */ - get closed(): boolean - { + get closed(): boolean { return this.#closed; } /** * Media kind. */ - get kind(): MediaKind - { + get kind(): MediaKind { return this.#data.kind; } /** * RTP parameters. */ - get rtpParameters(): RtpParameters - { + get rtpParameters(): RtpParameters { return this.#data.rtpParameters; } /** * Producer type. */ - get type(): ProducerType - { + get type(): ProducerType { return this.#data.type; } @@ -281,48 +269,42 @@ export class Producer * * @private */ - get consumableRtpParameters(): RtpParameters - { + get consumableRtpParameters(): RtpParameters { return this.#data.consumableRtpParameters; } /** * Whether the Producer is paused. */ - get paused(): boolean - { + get paused(): boolean { return this.#paused; } /** * Producer score list. */ - get score(): ProducerScore[] - { + get score(): ProducerScore[] { return this.#score; } /** * App custom data. */ - get appData(): ProducerAppData - { + get appData(): ProducerAppData { return this.#appData; } /** * App custom data setter. */ - set appData(appData: ProducerAppData) - { + set appData(appData: ProducerAppData) { this.#appData = appData; } /** * Observer. */ - get observer(): EnhancedEventEmitter - { + get observer(): EnhancedEventEmitter { return this.#observer; } @@ -330,18 +312,15 @@ export class Producer * @private * Just for testing purposes. */ - get channelForTesting(): Channel - { + get channelForTesting(): Channel { return this.#channel; } /** * Close the Producer. */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -354,15 +333,17 @@ export class Producer /* Build Request. */ const requestOffset = new FbsTransport.CloseProducerRequestT( - this.#internal.producerId + this.#internal.producerId, ).pack(this.#channel.bufferBuilder); - this.#channel.request( - FbsRequest.Method.TRANSPORT_CLOSE_PRODUCER, - FbsRequest.Body.Transport_CloseProducerRequest, - requestOffset, - this.#internal.transportId - ).catch(() => {}); + this.#channel + .request( + FbsRequest.Method.TRANSPORT_CLOSE_PRODUCER, + FbsRequest.Body.Transport_CloseProducerRequest, + requestOffset, + this.#internal.transportId, + ) + .catch(() => {}); this.emit('@close'); @@ -375,10 +356,8 @@ export class Producer * * @private */ - transportClosed(): void - { - if (this.#closed) - { + transportClosed(): void { + if (this.#closed) { return; } @@ -398,15 +377,14 @@ export class Producer /** * Dump Producer. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); const response = await this.#channel.request( FbsRequest.Method.PRODUCER_DUMP, undefined, undefined, - this.#internal.producerId + this.#internal.producerId, ); /* Decode Response. */ @@ -420,15 +398,14 @@ export class Producer /** * Get Producer stats. */ - async getStats(): Promise - { + async getStats(): Promise { logger.debug('getStats()'); const response = await this.#channel.request( FbsRequest.Method.PRODUCER_GET_STATS, undefined, undefined, - this.#internal.producerId + this.#internal.producerId, ); /* Decode Response. */ @@ -442,15 +419,14 @@ export class Producer /** * Pause the Producer. */ - async pause(): Promise - { + async pause(): Promise { logger.debug('pause()'); await this.#channel.request( FbsRequest.Method.PRODUCER_PAUSE, undefined, undefined, - this.#internal.producerId + this.#internal.producerId, ); const wasPaused = this.#paused; @@ -458,8 +434,7 @@ export class Producer this.#paused = true; // Emit observer event. - if (!wasPaused) - { + if (!wasPaused) { this.#observer.safeEmit('pause'); } } @@ -467,15 +442,14 @@ export class Producer /** * Resume the Producer. */ - async resume(): Promise - { + async resume(): Promise { logger.debug('resume()'); await this.#channel.request( FbsRequest.Method.PRODUCER_RESUME, undefined, undefined, - this.#internal.producerId + this.#internal.producerId, ); const wasPaused = this.#paused; @@ -483,8 +457,7 @@ export class Producer this.#paused = false; // Emit observer event. - if (wasPaused) - { + if (wasPaused) { this.#observer.safeEmit('resume'); } } @@ -492,312 +465,281 @@ export class Producer /** * Enable 'trace' event. */ - async enableTraceEvent(types: ProducerTraceEventType[] = []): Promise - { + async enableTraceEvent(types: ProducerTraceEventType[] = []): Promise { logger.debug('enableTraceEvent()'); - if (!Array.isArray(types)) - { + if (!Array.isArray(types)) { throw new TypeError('types must be an array'); } - if (types.find((type) => typeof type !== 'string')) - { + if (types.find(type => typeof type !== 'string')) { throw new TypeError('every type must be a string'); } // Convert event types. const fbsEventTypes: FbsProducer.TraceEventType[] = []; - for (const eventType of types) - { - try - { + for (const eventType of types) { + try { fbsEventTypes.push(producerTraceEventTypeToFbs(eventType)); - } - catch (error) - { + } catch (error) { logger.warn('enableTraceEvent() | [error:${error}]'); } } /* Build Request. */ const requestOffset = new FbsProducer.EnableTraceEventRequestT( - fbsEventTypes + fbsEventTypes, ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.PRODUCER_ENABLE_TRACE_EVENT, FbsRequest.Body.Producer_EnableTraceEventRequest, requestOffset, - this.#internal.producerId + this.#internal.producerId, ); } /** * Send RTP packet (just valid for Producers created on a DirectTransport). */ - send(rtpPacket: Buffer) - { - if (!Buffer.isBuffer(rtpPacket)) - { + send(rtpPacket: Buffer) { + if (!Buffer.isBuffer(rtpPacket)) { throw new TypeError('rtpPacket must be a Buffer'); } const builder = this.#channel.bufferBuilder; - const dataOffset = FbsProducer.SendNotification.createDataVector(builder, rtpPacket); - const notificationOffset = FbsProducer.SendNotification.createSendNotification( + const dataOffset = FbsProducer.SendNotification.createDataVector( builder, - dataOffset + rtpPacket, ); + const notificationOffset = + FbsProducer.SendNotification.createSendNotification(builder, dataOffset); this.#channel.notify( FbsNotification.Event.PRODUCER_SEND, FbsNotification.Body.Producer_SendNotification, notificationOffset, - this.#internal.producerId + this.#internal.producerId, ); } - private handleWorkerNotifications(): void - { - this.#channel.on(this.#internal.producerId, (event: Event, data?: Notification) => - { - switch (event) - { - case Event.PRODUCER_SCORE: - { - const notification = new FbsProducer.ScoreNotification(); + private handleWorkerNotifications(): void { + this.#channel.on( + this.#internal.producerId, + (event: Event, data?: Notification) => { + switch (event) { + case Event.PRODUCER_SCORE: { + const notification = new FbsProducer.ScoreNotification(); - data!.body(notification); + data!.body(notification); - const score: ProducerScore[] = utils.parseVector( - notification, 'scores', parseProducerScore - ); + const score: ProducerScore[] = utils.parseVector( + notification, + 'scores', + parseProducerScore, + ); - this.#score = score; + this.#score = score; - this.safeEmit('score', score); + this.safeEmit('score', score); - // Emit observer event. - this.#observer.safeEmit('score', score); + // Emit observer event. + this.#observer.safeEmit('score', score); - break; - } + break; + } - case Event.PRODUCER_VIDEO_ORIENTATION_CHANGE: - { - const notification = new FbsProducer.VideoOrientationChangeNotification(); + case Event.PRODUCER_VIDEO_ORIENTATION_CHANGE: { + const notification = + new FbsProducer.VideoOrientationChangeNotification(); - data!.body(notification); + data!.body(notification); - const videoOrientation: ProducerVideoOrientation = notification.unpack(); + const videoOrientation: ProducerVideoOrientation = + notification.unpack(); - this.safeEmit('videoorientationchange', videoOrientation); + this.safeEmit('videoorientationchange', videoOrientation); - // Emit observer event. - this.#observer.safeEmit('videoorientationchange', videoOrientation); + // Emit observer event. + this.#observer.safeEmit('videoorientationchange', videoOrientation); - break; - } + break; + } - case Event.PRODUCER_TRACE: - { - const notification = new FbsProducer.TraceNotification(); + case Event.PRODUCER_TRACE: { + const notification = new FbsProducer.TraceNotification(); - data!.body(notification); + data!.body(notification); - const trace: ProducerTraceEventData = parseTraceEventData(notification); + const trace: ProducerTraceEventData = + parseTraceEventData(notification); - this.safeEmit('trace', trace); + this.safeEmit('trace', trace); - // Emit observer event. - this.#observer.safeEmit('trace', trace); + // Emit observer event. + this.#observer.safeEmit('trace', trace); - break; - } + break; + } - default: - { - logger.error('ignoring unknown event "%s"', event); + default: { + logger.error('ignoring unknown event "%s"', event); + } } - } - }); + }, + ); } } -export function producerTypeFromFbs(type: FbsRtpParameters.Type): ProducerType -{ - switch (type) - { - case FbsRtpParameters.Type.SIMPLE: - { +export function producerTypeFromFbs(type: FbsRtpParameters.Type): ProducerType { + switch (type) { + case FbsRtpParameters.Type.SIMPLE: { return 'simple'; } - case FbsRtpParameters.Type.SIMULCAST: - { + case FbsRtpParameters.Type.SIMULCAST: { return 'simulcast'; } - case FbsRtpParameters.Type.SVC: - { + case FbsRtpParameters.Type.SVC: { return 'svc'; } - default: - { + default: { throw new TypeError(`invalid FbsRtpParameters.Type: ${type}`); } } } -export function producerTypeToFbs(type: ProducerType): FbsRtpParameters.Type -{ - switch (type) - { - case 'simple': - { +export function producerTypeToFbs(type: ProducerType): FbsRtpParameters.Type { + switch (type) { + case 'simple': { return FbsRtpParameters.Type.SIMPLE; } - case 'simulcast': - { + case 'simulcast': { return FbsRtpParameters.Type.SIMULCAST; } - case 'svc': - { + case 'svc': { return FbsRtpParameters.Type.SVC; } } } -function producerTraceEventTypeToFbs(eventType: ProducerTraceEventType) - : FbsProducer.TraceEventType -{ - switch (eventType) - { - case 'keyframe': - { +function producerTraceEventTypeToFbs( + eventType: ProducerTraceEventType, +): FbsProducer.TraceEventType { + switch (eventType) { + case 'keyframe': { return FbsProducer.TraceEventType.KEYFRAME; } - case 'fir': - { + case 'fir': { return FbsProducer.TraceEventType.FIR; } - case 'nack': - { + case 'nack': { return FbsProducer.TraceEventType.NACK; } - case 'pli': - { + case 'pli': { return FbsProducer.TraceEventType.PLI; } - case 'rtp': - { + case 'rtp': { return FbsProducer.TraceEventType.RTP; } - case 'sr': - { + case 'sr': { return FbsProducer.TraceEventType.SR; } - default: - { + default: { throw new TypeError(`invalid ProducerTraceEventType: ${eventType}`); } } } -function producerTraceEventTypeFromFbs(eventType: FbsProducer.TraceEventType) - : ProducerTraceEventType -{ - switch (eventType) - { - case FbsProducer.TraceEventType.KEYFRAME: - { +function producerTraceEventTypeFromFbs( + eventType: FbsProducer.TraceEventType, +): ProducerTraceEventType { + switch (eventType) { + case FbsProducer.TraceEventType.KEYFRAME: { return 'keyframe'; } - case FbsProducer.TraceEventType.FIR: - { + case FbsProducer.TraceEventType.FIR: { return 'fir'; } - case FbsProducer.TraceEventType.NACK: - { + case FbsProducer.TraceEventType.NACK: { return 'nack'; } - case FbsProducer.TraceEventType.PLI: - { + case FbsProducer.TraceEventType.PLI: { return 'pli'; } - case FbsProducer.TraceEventType.RTP: - { + case FbsProducer.TraceEventType.RTP: { return 'rtp'; } - case FbsProducer.TraceEventType.SR: - { + case FbsProducer.TraceEventType.SR: { return 'sr'; } } } export function parseProducerDump( - data: FbsProducer.DumpResponse -): ProducerDump -{ + data: FbsProducer.DumpResponse, +): ProducerDump { return { - id : data.id()!, - kind : data.kind() === FbsRtpParameters.MediaKind.AUDIO ? 'audio' : 'video', - type : producerTypeFromFbs(data.type()), - rtpParameters : parseRtpParameters(data.rtpParameters()!), + id: data.id()!, + kind: data.kind() === FbsRtpParameters.MediaKind.AUDIO ? 'audio' : 'video', + type: producerTypeFromFbs(data.type()), + rtpParameters: parseRtpParameters(data.rtpParameters()!), // NOTE: optional values are represented with null instead of undefined. // TODO: Make flatbuffers TS return undefined instead of null. - rtpMapping : data.rtpMapping() ? data.rtpMapping()!.unpack() : undefined, + rtpMapping: data.rtpMapping() ? data.rtpMapping()!.unpack() : undefined, // NOTE: optional values are represented with null instead of undefined. // TODO: Make flatbuffers TS return undefined instead of null. - rtpStreams : data.rtpStreamsLength() > 0 ? - utils.parseVector(data, 'rtpStreams', (rtpStream: any) => rtpStream.unpack()) : - undefined, - traceEventTypes : utils.parseVector(data, 'traceEventTypes', producerTraceEventTypeFromFbs), - paused : data.paused() + rtpStreams: + data.rtpStreamsLength() > 0 + ? utils.parseVector(data, 'rtpStreams', (rtpStream: any) => + rtpStream.unpack(), + ) + : undefined, + traceEventTypes: utils.parseVector( + data, + 'traceEventTypes', + producerTraceEventTypeFromFbs, + ), + paused: data.paused(), }; } -function parseProducerStats(binary: FbsProducer.GetStatsResponse): ProducerStat[] -{ +function parseProducerStats( + binary: FbsProducer.GetStatsResponse, +): ProducerStat[] { return utils.parseVector(binary, 'stats', parseRtpStreamRecvStats); } -function parseProducerScore( - binary: FbsProducer.Score -): ProducerScore -{ +function parseProducerScore(binary: FbsProducer.Score): ProducerScore { return { - encodingIdx : binary.encodingIdx(), - ssrc : binary.ssrc(), - rid : binary.rid() ?? undefined, - score : binary.score() + encodingIdx: binary.encodingIdx(), + ssrc: binary.ssrc(), + rid: binary.rid() ?? undefined, + score: binary.score(), }; } function parseTraceEventData( - trace: FbsProducer.TraceNotification -): ProducerTraceEventData -{ + trace: FbsProducer.TraceNotification, +): ProducerTraceEventData { let info: any; - if (trace.infoType() !== FbsProducer.TraceInfo.NONE) - { + if (trace.infoType() !== FbsProducer.TraceInfo.NONE) { const accessor = trace.info.bind(trace); info = FbsProducerTraceInfo.unionToTraceInfo(trace.infoType(), accessor); @@ -806,9 +748,10 @@ function parseTraceEventData( } return { - type : producerTraceEventTypeFromFbs(trace.type()), - timestamp : Number(trace.timestamp()), - direction : trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', - info : info ? info.unpack() : undefined + type: producerTraceEventTypeFromFbs(trace.type()), + timestamp: Number(trace.timestamp()), + direction: + trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', + info: info ? info.unpack() : undefined, }; } diff --git a/node/src/Router.ts b/node/src/Router.ts index d42004d7bb..6afa5a3e41 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -8,27 +8,27 @@ import { TransportListenInfo, TransportListenIp, TransportProtocol, - TransportSocketFlags + TransportSocketFlags, } from './Transport'; import { WebRtcTransport, WebRtcTransportOptions, - parseWebRtcTransportDumpResponse + parseWebRtcTransportDumpResponse, } from './WebRtcTransport'; import { PlainTransport, PlainTransportOptions, - parsePlainTransportDumpResponse + parsePlainTransportDumpResponse, } from './PlainTransport'; import { PipeTransport, PipeTransportOptions, - parsePipeTransportDumpResponse + parsePipeTransportDumpResponse, } from './PipeTransport'; import { DirectTransport, DirectTransportOptions, - parseDirectTransportDumpResponse + parseDirectTransportDumpResponse, } from './DirectTransport'; import { Producer } from './Producer'; import { Consumer } from './Consumer'; @@ -37,11 +37,11 @@ import { DataConsumer } from './DataConsumer'; import { RtpObserver } from './RtpObserver'; import { ActiveSpeakerObserver, - ActiveSpeakerObserverOptions + ActiveSpeakerObserverOptions, } from './ActiveSpeakerObserver'; import { AudioLevelObserver, - AudioLevelObserverOptions + AudioLevelObserverOptions, } from './AudioLevelObserver'; import { RtpCapabilities, RtpCodecCapability } from './RtpParameters'; import { cryptoSuiteToFbs } from './SrtpParameters'; @@ -52,7 +52,7 @@ import { generateUUIDv4, parseVector, parseStringStringVector, - parseStringStringArrayVector + parseStringStringArrayVector, } from './utils'; import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; @@ -67,8 +67,7 @@ import * as FbsPipeTransport from './fbs/pipe-transport'; import * as FbsDirectTransport from './fbs/direct-transport'; import * as FbsSctpParameters from './fbs/sctp-parameters'; -export type RouterOptions = -{ +export type RouterOptions = { /** * Router media codecs. */ @@ -80,24 +79,20 @@ export type RouterOptions = appData?: RouterAppData; }; -type PipeToRouterListenInfo = -{ +type PipeToRouterListenInfo = { listenInfo: TransportListenInfo; }; -type PipeToRouterListenIp = -{ +type PipeToRouterListenIp = { /** * IP used in the PipeTransport pair. Default '127.0.0.1'. */ listenIp?: TransportListenIp | string; }; -type PipeToRouterListen = - Either; +type PipeToRouterListen = Either; -export type PipeToRouterOptions = -{ +export type PipeToRouterOptions = { /** * The id of the Producer to consume. */ @@ -134,8 +129,7 @@ export type PipeToRouterOptions = enableSrtp?: boolean; } & PipeToRouterListen; -export type PipeToRouterResult = -{ +export type PipeToRouterResult = { /** * The Consumer created in the current Router. */ @@ -157,8 +151,7 @@ export type PipeToRouterResult = pipeDataProducer?: DataProducer; }; -export type RouterDump = -{ +export type RouterDump = { /** * The Router id. */ @@ -178,56 +171,51 @@ export type RouterDump = /** * Array of Consumer id and its Producer id. */ - mapConsumerIdProducerId: {key: string; value: string}[]; + mapConsumerIdProducerId: { key: string; value: string }[]; /** * Array of Producer id and its respective Observer ids. */ - mapProducerIdObserverIds: {key: string; values: string[]}[]; + mapProducerIdObserverIds: { key: string; values: string[] }[]; /** * Array of Producer id and its respective DataConsumer ids. */ - mapDataProducerIdDataConsumerIds: {key: string; values: string[]}[]; + mapDataProducerIdDataConsumerIds: { key: string; values: string[] }[]; /** * Array of DataConsumer id and its DataProducer id. */ - mapDataConsumerIdDataProducerId: {key: string; value: string}[]; + mapDataConsumerIdDataProducerId: { key: string; value: string }[]; }; -type PipeTransportPair = -{ +type PipeTransportPair = { [key: string]: PipeTransport; }; -export type RouterEvents = -{ +export type RouterEvents = { workerclose: []; listenererror: [string, Error]; // Private events. '@close': []; }; -export type RouterObserverEvents = -{ +export type RouterObserverEvents = { close: []; newtransport: [Transport]; newrtpobserver: [RtpObserver]; }; -export type RouterInternal = -{ +export type RouterInternal = { routerId: string; }; -type RouterData = -{ +type RouterData = { rtpCapabilities: RtpCapabilities; }; const logger = new Logger('Router'); -export class Router - extends EnhancedEventEmitter -{ +export class Router< + RouterAppData extends AppData = AppData, +> extends EnhancedEventEmitter { // Internal data. readonly #internal: RouterInternal; @@ -257,8 +245,10 @@ export class Router // Map of PipeTransport pair Promises indexed by the id of the Router in // which pipeToRouter() was called. - readonly #mapRouterPairPipeTransportPairPromise: - Map> = new Map(); + readonly #mapRouterPairPipeTransportPairPromise: Map< + string, + Promise + > = new Map(); // Observer instance. readonly #observer = new EnhancedEventEmitter(); @@ -266,21 +256,17 @@ export class Router /** * @private */ - constructor( - { - internal, - data, - channel, - appData - }: - { - internal: RouterInternal; - data: RouterData; - channel: Channel; - appData?: RouterAppData; - } - ) - { + constructor({ + internal, + data, + channel, + appData, + }: { + internal: RouterInternal; + data: RouterData; + channel: Channel; + appData?: RouterAppData; + }) { super(); logger.debug('constructor()'); @@ -288,54 +274,48 @@ export class Router this.#internal = internal; this.#data = data; this.#channel = channel; - this.#appData = appData || {} as RouterAppData; + this.#appData = appData || ({} as RouterAppData); } /** * Router id. */ - get id(): string - { + get id(): string { return this.#internal.routerId; } /** * Whether the Router is closed. */ - get closed(): boolean - { + get closed(): boolean { return this.#closed; } /** * RTP capabilities of the Router. */ - get rtpCapabilities(): RtpCapabilities - { + get rtpCapabilities(): RtpCapabilities { return this.#data.rtpCapabilities; } /** * App custom data. */ - get appData(): RouterAppData - { + get appData(): RouterAppData { return this.#appData; } /** * App custom data setter. */ - set appData(appData: RouterAppData) - { + set appData(appData: RouterAppData) { this.#appData = appData; } /** * Observer. */ - get observer(): EnhancedEventEmitter - { + get observer(): EnhancedEventEmitter { return this.#observer; } @@ -343,18 +323,15 @@ export class Router * @private * Just for testing purposes. */ - get transportsForTesting(): Map - { + get transportsForTesting(): Map { return this.#transports; } /** * Close the Router. */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -363,17 +340,19 @@ export class Router this.#closed = true; const requestOffset = new FbsWorker.CloseRouterRequestT( - this.#internal.routerId).pack(this.#channel.bufferBuilder); + this.#internal.routerId, + ).pack(this.#channel.bufferBuilder); - this.#channel.request( - FbsRequest.Method.WORKER_CLOSE_ROUTER, - FbsRequest.Body.Worker_CloseRouterRequest, - requestOffset) + this.#channel + .request( + FbsRequest.Method.WORKER_CLOSE_ROUTER, + FbsRequest.Body.Worker_CloseRouterRequest, + requestOffset, + ) .catch(() => {}); // Close every Transport. - for (const transport of this.#transports.values()) - { + for (const transport of this.#transports.values()) { transport.routerClosed(); } this.#transports.clear(); @@ -382,8 +361,7 @@ export class Router this.#producers.clear(); // Close every RtpObserver. - for (const rtpObserver of this.#rtpObservers.values()) - { + for (const rtpObserver of this.#rtpObservers.values()) { rtpObserver.routerClosed(); } this.#rtpObservers.clear(); @@ -402,10 +380,8 @@ export class Router * * @private */ - workerClosed(): void - { - if (this.#closed) - { + workerClosed(): void { + if (this.#closed) { return; } @@ -414,8 +390,7 @@ export class Router this.#closed = true; // Close every Transport. - for (const transport of this.#transports.values()) - { + for (const transport of this.#transports.values()) { transport.routerClosed(); } this.#transports.clear(); @@ -424,8 +399,7 @@ export class Router this.#producers.clear(); // Close every RtpObserver. - for (const rtpObserver of this.#rtpObservers.values()) - { + for (const rtpObserver of this.#rtpObservers.values()) { rtpObserver.routerClosed(); } this.#rtpObservers.clear(); @@ -442,8 +416,7 @@ export class Router /** * Dump Router. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); // Send the request and wait for the response. @@ -451,7 +424,7 @@ export class Router FbsRequest.Method.ROUTER_DUMP, undefined, undefined, - this.#internal.routerId + this.#internal.routerId, ); /* Decode Response. */ @@ -465,72 +438,67 @@ export class Router /** * Create a WebRtcTransport. */ - async createWebRtcTransport( - { - webRtcServer, - listenInfos, - listenIps, - port, - enableUdp, - enableTcp, - preferUdp = false, - preferTcp = false, - initialAvailableOutgoingBitrate = 600000, - enableSctp = false, - numSctpStreams = { OS: 1024, MIS: 1024 }, - maxSctpMessageSize = 262144, - sctpSendBufferSize = 262144, - appData - }: WebRtcTransportOptions - ): Promise> - { + async createWebRtcTransport< + WebRtcTransportAppData extends AppData = AppData, + >({ + webRtcServer, + listenInfos, + listenIps, + port, + enableUdp, + enableTcp, + preferUdp = false, + preferTcp = false, + initialAvailableOutgoingBitrate = 600000, + enableSctp = false, + numSctpStreams = { OS: 1024, MIS: 1024 }, + maxSctpMessageSize = 262144, + sctpSendBufferSize = 262144, + appData, + }: WebRtcTransportOptions): Promise< + WebRtcTransport + > { logger.debug('createWebRtcTransport()'); - if (!webRtcServer && !Array.isArray(listenInfos) && !Array.isArray(listenIps)) - { - throw new TypeError('missing webRtcServer, listenInfos and listenIps (one of them is mandatory)'); - } - else if (webRtcServer && listenInfos && listenIps) - { - throw new TypeError('only one of webRtcServer, listenInfos and listenIps must be given'); - } - else if ( + if ( + !webRtcServer && + !Array.isArray(listenInfos) && + !Array.isArray(listenIps) + ) { + throw new TypeError( + 'missing webRtcServer, listenInfos and listenIps (one of them is mandatory)', + ); + } else if (webRtcServer && listenInfos && listenIps) { + throw new TypeError( + 'only one of webRtcServer, listenInfos and listenIps must be given', + ); + } else if ( numSctpStreams && - (typeof numSctpStreams.OS !== 'number' || typeof numSctpStreams.MIS !== 'number') - ) - { + (typeof numSctpStreams.OS !== 'number' || + typeof numSctpStreams.MIS !== 'number') + ) { throw new TypeError('if given, numSctpStreams must contain OS and MIS'); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } // If webRtcServer is given, then do not force default values for enableUdp // and enableTcp. Otherwise set them if unset. - if (webRtcServer) - { + if (webRtcServer) { enableUdp ??= true; enableTcp ??= true; - } - else - { + } else { enableUdp ??= true; enableTcp ??= false; } // Convert deprecated TransportListenIps to TransportListenInfos. - if (listenIps) - { + if (listenIps) { // Normalize IP strings to TransportListenIp objects. - listenIps = listenIps.map((listenIp) => - { - if (typeof listenIp === 'string') - { + listenIps = listenIps.map(listenIp => { + if (typeof listenIp === 'string') { return { ip: listenIp }; - } - else - { + } else { return listenIp; } }); @@ -539,36 +507,28 @@ export class Router const orderedProtocols: TransportProtocol[] = []; - if (enableUdp && (!enableTcp || preferUdp)) - { + if (enableUdp && (!enableTcp || preferUdp)) { orderedProtocols.push('udp'); - if (enableTcp) - { + if (enableTcp) { orderedProtocols.push('tcp'); } - } - else if (enableTcp && (!enableUdp || (preferTcp && !preferUdp))) - { + } else if (enableTcp && (!enableUdp || (preferTcp && !preferUdp))) { orderedProtocols.push('tcp'); - if (enableUdp) - { + if (enableUdp) { orderedProtocols.push('udp'); } } - for (const listenIp of listenIps as TransportListenIp[]) - { - for (const protocol of orderedProtocols) - { - listenInfos.push( - { - protocol : protocol, - ip : listenIp.ip, - announcedIp : listenIp.announcedIp, - port : port - }); + for (const listenIp of listenIps as TransportListenIp[]) { + for (const protocol of orderedProtocols) { + listenInfos.push({ + protocol: protocol, + ip: listenIp.ip, + announcedIp: listenIp.announcedIp, + port: port, + }); } } } @@ -577,32 +537,33 @@ export class Router /* Build Request. */ let webRtcTransportListenServer: - FbsWebRtcTransport.ListenServerT | undefined; + | FbsWebRtcTransport.ListenServerT + | undefined; let webRtcTransportListenIndividual: - FbsWebRtcTransport.ListenIndividualT | undefined; + | FbsWebRtcTransport.ListenIndividualT + | undefined; - if (webRtcServer) - { - webRtcTransportListenServer = - new FbsWebRtcTransport.ListenServerT(webRtcServer.id); - } - else - { + if (webRtcServer) { + webRtcTransportListenServer = new FbsWebRtcTransport.ListenServerT( + webRtcServer.id, + ); + } else { const fbsListenInfos: FbsTransport.ListenInfoT[] = []; - for (const listenInfo of listenInfos!) - { - fbsListenInfos.push(new FbsTransport.ListenInfoT( - listenInfo.protocol === 'udp' - ? FbsTransportProtocol.UDP - : FbsTransportProtocol.TCP, - listenInfo.ip, - listenInfo.announcedIp, - listenInfo.port, - socketFlagsToFbs(listenInfo.flags), - listenInfo.sendBufferSize, - listenInfo.recvBufferSize - )); + for (const listenInfo of listenInfos!) { + fbsListenInfos.push( + new FbsTransport.ListenInfoT( + listenInfo.protocol === 'udp' + ? FbsTransportProtocol.UDP + : FbsTransportProtocol.TCP, + listenInfo.ip, + listenInfo.announcedIp, + listenInfo.port, + socketFlagsToFbs(listenInfo.flags), + listenInfo.sendBufferSize, + listenInfo.recvBufferSize, + ), + ); } webRtcTransportListenIndividual = @@ -614,26 +575,33 @@ export class Router undefined /* maxMessageSize */, initialAvailableOutgoingBitrate, enableSctp, - new FbsSctpParameters.NumSctpStreamsT(numSctpStreams.OS, numSctpStreams.MIS), + new FbsSctpParameters.NumSctpStreamsT( + numSctpStreams.OS, + numSctpStreams.MIS, + ), maxSctpMessageSize, sctpSendBufferSize, - true /* isDataChannel */ + true /* isDataChannel */, ); - const webRtcTransportOptions = new FbsWebRtcTransport.WebRtcTransportOptionsT( - baseTransportOptions, - webRtcServer ? - FbsWebRtcTransport.Listen.ListenServer : - FbsWebRtcTransport.Listen.ListenIndividual, - webRtcServer ? webRtcTransportListenServer : webRtcTransportListenIndividual, - enableUdp, - enableTcp, - preferUdp, - preferTcp - ); + const webRtcTransportOptions = + new FbsWebRtcTransport.WebRtcTransportOptionsT( + baseTransportOptions, + webRtcServer + ? FbsWebRtcTransport.Listen.ListenServer + : FbsWebRtcTransport.Listen.ListenIndividual, + webRtcServer + ? webRtcTransportListenServer + : webRtcTransportListenIndividual, + enableUdp, + enableTcp, + preferUdp, + preferTcp, + ); const requestOffset = new FbsRouter.CreateWebRtcTransportRequestT( - transportId, webRtcTransportOptions + transportId, + webRtcTransportOptions, ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( @@ -642,7 +610,7 @@ export class Router : FbsRequest.Method.ROUTER_CREATE_WEBRTCTRANSPORT, FbsRequest.Body.Router_CreateWebRtcTransportRequest, requestOffset, - this.#internal.routerId + this.#internal.routerId, ); /* Decode Response. */ @@ -652,42 +620,44 @@ export class Router const webRtcTransportData = parseWebRtcTransportDumpResponse(data); - const transport = new WebRtcTransport( - { - internal : - { - ...this.#internal, - transportId : transportId - }, - data : webRtcTransportData, - channel : this.#channel, - appData, - getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, - getProducerById : (producerId: string): Producer | undefined => ( - this.#producers.get(producerId) - ), - getDataProducerById : (dataProducerId: string): DataProducer | undefined => ( - this.#dataProducers.get(dataProducerId) - ) - }); + const transport = new WebRtcTransport({ + internal: { + ...this.#internal, + transportId: transportId, + }, + data: webRtcTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: (dataProducerId: string): DataProducer | undefined => + this.#dataProducers.get(dataProducerId), + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); - transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); - transport.on('@newproducer', (producer: Producer) => this.#producers.set(producer.id, producer)); - transport.on('@producerclose', (producer: Producer) => this.#producers.delete(producer.id)); - transport.on('@newdataproducer', (dataProducer: DataProducer) => ( - this.#dataProducers.set(dataProducer.id, dataProducer) - )); - transport.on('@dataproducerclose', (dataProducer: DataProducer) => ( - this.#dataProducers.delete(dataProducer.id) - )); + transport.on('@listenserverclose', () => + this.#transports.delete(transport.id), + ); + transport.on('@newproducer', (producer: Producer) => + this.#producers.set(producer.id, producer), + ); + transport.on('@producerclose', (producer: Producer) => + this.#producers.delete(producer.id), + ); + transport.on('@newdataproducer', (dataProducer: DataProducer) => + this.#dataProducers.set(dataProducer.id, dataProducer), + ); + transport.on('@dataproducerclose', (dataProducer: DataProducer) => + this.#dataProducers.delete(dataProducer.id), + ); // Emit observer event. this.#observer.safeEmit('newtransport', transport); - if (webRtcServer) - { + if (webRtcServer) { webRtcServer.handleWebRtcTransport(transport); } @@ -697,62 +667,56 @@ export class Router /** * Create a PlainTransport. */ - async createPlainTransport( - { - listenInfo, - rtcpListenInfo, - listenIp, - port, - rtcpMux = true, - comedia = false, - enableSctp = false, - numSctpStreams = { OS: 1024, MIS: 1024 }, - maxSctpMessageSize = 262144, - sctpSendBufferSize = 262144, - enableSrtp = false, - srtpCryptoSuite = 'AES_CM_128_HMAC_SHA1_80', - appData - }: PlainTransportOptions - ): Promise> - { + async createPlainTransport({ + listenInfo, + rtcpListenInfo, + listenIp, + port, + rtcpMux = true, + comedia = false, + enableSctp = false, + numSctpStreams = { OS: 1024, MIS: 1024 }, + maxSctpMessageSize = 262144, + sctpSendBufferSize = 262144, + enableSrtp = false, + srtpCryptoSuite = 'AES_CM_128_HMAC_SHA1_80', + appData, + }: PlainTransportOptions): Promise< + PlainTransport + > { logger.debug('createPlainTransport()'); - if (!listenInfo && !listenIp) - { - throw new TypeError('missing listenInfo and listenIp (one of them is mandatory)'); - } - else if (listenInfo && listenIp) - { + if (!listenInfo && !listenIp) { + throw new TypeError( + 'missing listenInfo and listenIp (one of them is mandatory)', + ); + } else if (listenInfo && listenIp) { throw new TypeError('only one of listenInfo and listenIp must be given'); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } // If rtcpMux is enabled, ignore rtcpListenInfo. - if (rtcpMux && rtcpListenInfo) - { - logger.warn('createPlainTransport() | ignoring rtcpMux since rtcpListenInfo is given'); + if (rtcpMux && rtcpListenInfo) { + logger.warn( + 'createPlainTransport() | ignoring rtcpMux since rtcpListenInfo is given', + ); rtcpMux = false; } // Convert deprecated TransportListenIps to TransportListenInfos. - if (listenIp) - { + if (listenIp) { // Normalize IP string to TransportListenIp object. - if (typeof listenIp === 'string') - { + if (typeof listenIp === 'string') { listenIp = { ip: listenIp }; } - listenInfo = - { - protocol : 'udp', - ip : listenIp.ip, - announcedIp : listenIp.announcedIp, - port : port + listenInfo = { + protocol: 'udp', + ip: listenIp.ip, + announcedIp: listenIp.announcedIp, + port: port, }; } @@ -764,10 +728,13 @@ export class Router undefined /* maxMessageSize */, undefined /* initialAvailableOutgoingBitrate */, enableSctp, - new FbsSctpParameters.NumSctpStreamsT(numSctpStreams.OS, numSctpStreams.MIS), + new FbsSctpParameters.NumSctpStreamsT( + numSctpStreams.OS, + numSctpStreams.MIS, + ), maxSctpMessageSize, sctpSendBufferSize, - false /* isDataChannel */ + false /* isDataChannel */, ); const plainTransportOptions = new FbsPlainTransport.PlainTransportOptionsT( @@ -781,34 +748,37 @@ export class Router listenInfo!.port, socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, - listenInfo!.recvBufferSize + listenInfo!.recvBufferSize, ), - rtcpListenInfo ? new FbsTransport.ListenInfoT( - rtcpListenInfo.protocol === 'udp' - ? FbsTransportProtocol.UDP - : FbsTransportProtocol.TCP, - rtcpListenInfo.ip, - rtcpListenInfo.announcedIp, - rtcpListenInfo.port, - socketFlagsToFbs(rtcpListenInfo.flags), - rtcpListenInfo.sendBufferSize, - rtcpListenInfo.recvBufferSize - ) : undefined, + rtcpListenInfo + ? new FbsTransport.ListenInfoT( + rtcpListenInfo.protocol === 'udp' + ? FbsTransportProtocol.UDP + : FbsTransportProtocol.TCP, + rtcpListenInfo.ip, + rtcpListenInfo.announcedIp, + rtcpListenInfo.port, + socketFlagsToFbs(rtcpListenInfo.flags), + rtcpListenInfo.sendBufferSize, + rtcpListenInfo.recvBufferSize, + ) + : undefined, rtcpMux, comedia, enableSrtp, - cryptoSuiteToFbs(srtpCryptoSuite) + cryptoSuiteToFbs(srtpCryptoSuite), ); const requestOffset = new FbsRouter.CreatePlainTransportRequestT( - transportId, plainTransportOptions + transportId, + plainTransportOptions, ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_PLAINTRANSPORT, FbsRequest.Body.Router_CreatePlainTransportRequest, requestOffset, - this.#internal.routerId + this.#internal.routerId, ); /* Decode Response. */ @@ -818,36 +788,39 @@ export class Router const plainTransportData = parsePlainTransportDumpResponse(data); - const transport = new PlainTransport( - { - internal : - { - ...this.#internal, - transportId : transportId - }, - data : plainTransportData, - channel : this.#channel, - appData, - getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, - getProducerById : (producerId: string): Producer | undefined => ( - this.#producers.get(producerId) - ), - getDataProducerById : (dataProducerId: string): DataProducer | undefined => ( - this.#dataProducers.get(dataProducerId) - ) - }); + const transport = new PlainTransport({ + internal: { + ...this.#internal, + transportId: transportId, + }, + data: plainTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: (dataProducerId: string): DataProducer | undefined => + this.#dataProducers.get(dataProducerId), + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); - transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); - transport.on('@newproducer', (producer: Producer) => this.#producers.set(producer.id, producer)); - transport.on('@producerclose', (producer: Producer) => this.#producers.delete(producer.id)); - transport.on('@newdataproducer', (dataProducer: DataProducer) => ( - this.#dataProducers.set(dataProducer.id, dataProducer) - )); - transport.on('@dataproducerclose', (dataProducer: DataProducer) => ( - this.#dataProducers.delete(dataProducer.id) - )); + transport.on('@listenserverclose', () => + this.#transports.delete(transport.id), + ); + transport.on('@newproducer', (producer: Producer) => + this.#producers.set(producer.id, producer), + ); + transport.on('@producerclose', (producer: Producer) => + this.#producers.delete(producer.id), + ); + transport.on('@newdataproducer', (dataProducer: DataProducer) => + this.#dataProducers.set(dataProducer.id, dataProducer), + ); + transport.on('@dataproducerclose', (dataProducer: DataProducer) => + this.#dataProducers.delete(dataProducer.id), + ); // Emit observer event. this.#observer.safeEmit('newtransport', transport); @@ -858,51 +831,44 @@ export class Router /** * Create a PipeTransport. */ - async createPipeTransport( - { - listenInfo, - listenIp, - port, - enableSctp = false, - numSctpStreams = { OS: 1024, MIS: 1024 }, - maxSctpMessageSize = 268435456, - sctpSendBufferSize = 268435456, - enableRtx = false, - enableSrtp = false, - appData - }: PipeTransportOptions - ): Promise> - { + async createPipeTransport({ + listenInfo, + listenIp, + port, + enableSctp = false, + numSctpStreams = { OS: 1024, MIS: 1024 }, + maxSctpMessageSize = 268435456, + sctpSendBufferSize = 268435456, + enableRtx = false, + enableSrtp = false, + appData, + }: PipeTransportOptions): Promise< + PipeTransport + > { logger.debug('createPipeTransport()'); - if (!listenInfo && !listenIp) - { - throw new TypeError('missing listenInfo and listenIp (one of them is mandatory)'); - } - else if (listenInfo && listenIp) - { + if (!listenInfo && !listenIp) { + throw new TypeError( + 'missing listenInfo and listenIp (one of them is mandatory)', + ); + } else if (listenInfo && listenIp) { throw new TypeError('only one of listenInfo and listenIp must be given'); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } // Convert deprecated TransportListenIps to TransportListenInfos. - if (listenIp) - { + if (listenIp) { // Normalize IP string to TransportListenIp object. - if (typeof listenIp === 'string') - { + if (typeof listenIp === 'string') { listenIp = { ip: listenIp }; } - listenInfo = - { - protocol : 'udp', - ip : listenIp.ip, - announcedIp : listenIp.announcedIp, - port : port + listenInfo = { + protocol: 'udp', + ip: listenIp.ip, + announcedIp: listenIp.announcedIp, + port: port, }; } @@ -914,10 +880,13 @@ export class Router undefined /* maxMessageSize */, undefined /* initialAvailableOutgoingBitrate */, enableSctp, - new FbsSctpParameters.NumSctpStreamsT(numSctpStreams.OS, numSctpStreams.MIS), + new FbsSctpParameters.NumSctpStreamsT( + numSctpStreams.OS, + numSctpStreams.MIS, + ), maxSctpMessageSize, sctpSendBufferSize, - false /* isDataChannel */ + false /* isDataChannel */, ); const pipeTransportOptions = new FbsPipeTransport.PipeTransportOptionsT( @@ -931,21 +900,22 @@ export class Router listenInfo!.port, socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, - listenInfo!.recvBufferSize + listenInfo!.recvBufferSize, ), enableRtx, - enableSrtp + enableSrtp, ); const requestOffset = new FbsRouter.CreatePipeTransportRequestT( - transportId, pipeTransportOptions + transportId, + pipeTransportOptions, ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_PIPETRANSPORT, FbsRequest.Body.Router_CreatePipeTransportRequest, requestOffset, - this.#internal.routerId + this.#internal.routerId, ); /* Decode Response. */ @@ -955,36 +925,39 @@ export class Router const plainTransportData = parsePipeTransportDumpResponse(data); - const transport = new PipeTransport( - { - internal : - { - ...this.#internal, - transportId - }, - data : plainTransportData, - channel : this.#channel, - appData, - getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, - getProducerById : (producerId: string): Producer | undefined => ( - this.#producers.get(producerId) - ), - getDataProducerById : (dataProducerId: string): DataProducer | undefined => ( - this.#dataProducers.get(dataProducerId) - ) - }); + const transport = new PipeTransport({ + internal: { + ...this.#internal, + transportId, + }, + data: plainTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: (dataProducerId: string): DataProducer | undefined => + this.#dataProducers.get(dataProducerId), + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); - transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); - transport.on('@newproducer', (producer: Producer) => this.#producers.set(producer.id, producer)); - transport.on('@producerclose', (producer: Producer) => this.#producers.delete(producer.id)); - transport.on('@newdataproducer', (dataProducer: DataProducer) => ( - this.#dataProducers.set(dataProducer.id, dataProducer) - )); - transport.on('@dataproducerclose', (dataProducer: DataProducer) => ( - this.#dataProducers.delete(dataProducer.id) - )); + transport.on('@listenserverclose', () => + this.#transports.delete(transport.id), + ); + transport.on('@newproducer', (producer: Producer) => + this.#producers.set(producer.id, producer), + ); + transport.on('@producerclose', (producer: Producer) => + this.#producers.delete(producer.id), + ); + transport.on('@newdataproducer', (dataProducer: DataProducer) => + this.#dataProducers.set(dataProducer.id, dataProducer), + ); + transport.on('@dataproducerclose', (dataProducer: DataProducer) => + this.#dataProducers.delete(dataProducer.id), + ); // Emit observer event. this.#observer.safeEmit('newtransport', transport); @@ -998,21 +971,16 @@ export class Router async createDirectTransport( { maxMessageSize = 262144, - appData - }: DirectTransportOptions = - { - maxMessageSize : 262144 - } - ): Promise> - { + appData, + }: DirectTransportOptions = { + maxMessageSize: 262144, + }, + ): Promise> { logger.debug('createDirectTransport()'); - if (typeof maxMessageSize !== 'number' || maxMessageSize < 0) - { + if (typeof maxMessageSize !== 'number' || maxMessageSize < 0) { throw new TypeError('if given, maxMessageSize must be a positive number'); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } @@ -1027,22 +995,22 @@ export class Router undefined /* numSctpStreams */, undefined /* maxSctpMessageSize */, undefined /* sctpSendBufferSize */, - undefined /* isDataChannel */ + undefined /* isDataChannel */, ); - const directTransportOptions = new FbsDirectTransport.DirectTransportOptionsT( - baseTransportOptions - ); + const directTransportOptions = + new FbsDirectTransport.DirectTransportOptionsT(baseTransportOptions); const requestOffset = new FbsRouter.CreateDirectTransportRequestT( - transportId, directTransportOptions + transportId, + directTransportOptions, ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_DIRECTTRANSPORT, FbsRequest.Body.Router_CreateDirectTransportRequest, requestOffset, - this.#internal.routerId + this.#internal.routerId, ); /* Decode Response. */ @@ -1052,36 +1020,39 @@ export class Router const directTransportData = parseDirectTransportDumpResponse(data); - const transport = new DirectTransport( - { - internal : - { - ...this.#internal, - transportId : transportId - }, - data : directTransportData, - channel : this.#channel, - appData, - getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, - getProducerById : (producerId: string): Producer | undefined => ( - this.#producers.get(producerId) - ), - getDataProducerById : (dataProducerId: string): DataProducer | undefined => ( - this.#dataProducers.get(dataProducerId) - ) - }); + const transport = new DirectTransport({ + internal: { + ...this.#internal, + transportId: transportId, + }, + data: directTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: (dataProducerId: string): DataProducer | undefined => + this.#dataProducers.get(dataProducerId), + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); - transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); - transport.on('@newproducer', (producer: Producer) => this.#producers.set(producer.id, producer)); - transport.on('@producerclose', (producer: Producer) => this.#producers.delete(producer.id)); - transport.on('@newdataproducer', (dataProducer: DataProducer) => ( - this.#dataProducers.set(dataProducer.id, dataProducer) - )); - transport.on('@dataproducerclose', (dataProducer: DataProducer) => ( - this.#dataProducers.delete(dataProducer.id) - )); + transport.on('@listenserverclose', () => + this.#transports.delete(transport.id), + ); + transport.on('@newproducer', (producer: Producer) => + this.#producers.set(producer.id, producer), + ); + transport.on('@producerclose', (producer: Producer) => + this.#producers.delete(producer.id), + ); + transport.on('@newdataproducer', (dataProducer: DataProducer) => + this.#dataProducers.set(dataProducer.id, dataProducer), + ); + transport.on('@dataproducerclose', (dataProducer: DataProducer) => + this.#dataProducers.delete(dataProducer.id), + ); // Emit observer event. this.#observer.safeEmit('newtransport', transport); @@ -1092,87 +1063,65 @@ export class Router /** * Pipes the given Producer or DataProducer into another Router in same host. */ - async pipeToRouter( - { - producerId, - dataProducerId, - router, - listenInfo, - listenIp, - enableSctp = true, - numSctpStreams = { OS: 1024, MIS: 1024 }, - enableRtx = false, - enableSrtp = false - }: PipeToRouterOptions - ): Promise - { + async pipeToRouter({ + producerId, + dataProducerId, + router, + listenInfo, + listenIp, + enableSctp = true, + numSctpStreams = { OS: 1024, MIS: 1024 }, + enableRtx = false, + enableSrtp = false, + }: PipeToRouterOptions): Promise { logger.debug('pipeToRouter()'); - if (!listenInfo && !listenIp) - { - listenInfo = - { - protocol : 'udp', - ip : '127.0.0.1' + if (!listenInfo && !listenIp) { + listenInfo = { + protocol: 'udp', + ip: '127.0.0.1', }; } - if (listenInfo && listenIp) - { + if (listenInfo && listenIp) { throw new TypeError('only one of listenInfo and listenIp must be given'); - } - else if (!producerId && !dataProducerId) - { + } else if (!producerId && !dataProducerId) { throw new TypeError('missing producerId or dataProducerId'); - } - else if (producerId && dataProducerId) - { + } else if (producerId && dataProducerId) { throw new TypeError('just producerId or dataProducerId can be given'); - } - else if (!router) - { + } else if (!router) { throw new TypeError('Router not found'); - } - else if (router === this) - { + } else if (router === this) { throw new TypeError('cannot use this Router as destination'); } // Convert deprecated TransportListenIps to TransportListenInfos. - if (listenIp) - { + if (listenIp) { // Normalize IP string to TransportListenIp object. - if (typeof listenIp === 'string') - { + if (typeof listenIp === 'string') { listenIp = { ip: listenIp }; } - listenInfo = - { - protocol : 'udp', - ip : listenIp.ip, - announcedIp : listenIp.announcedIp + listenInfo = { + protocol: 'udp', + ip: listenIp.ip, + announcedIp: listenIp.announcedIp, }; } let producer: Producer | undefined; let dataProducer: DataProducer | undefined; - if (producerId) - { + if (producerId) { producer = this.#producers.get(producerId); - if (!producer) - { + if (!producer) { throw new TypeError('Producer not found'); } - } - else if (dataProducerId) - { + } else if (dataProducerId) { dataProducer = this.#dataProducers.get(dataProducerId); - if (!dataProducer) - { + if (!dataProducer) { throw new TypeError('DataProducer not found'); } } @@ -1184,93 +1133,77 @@ export class Router let localPipeTransport: PipeTransport; let remotePipeTransport: PipeTransport; - if (pipeTransportPairPromise) - { + if (pipeTransportPairPromise) { pipeTransportPair = await pipeTransportPairPromise; localPipeTransport = pipeTransportPair[this.id]; remotePipeTransport = pipeTransportPair[router.id]; - } - else - { - pipeTransportPairPromise = new Promise((resolve, reject) => - { - Promise.all( - [ - this.createPipeTransport( - { - listenInfo : listenInfo!, - enableSctp, - numSctpStreams, - enableRtx, - enableSrtp - }), - router.createPipeTransport( - { - listenInfo : listenInfo!, - enableSctp, - numSctpStreams, - enableRtx, - enableSrtp - }) - ]) - .then((pipeTransports) => - { + } else { + pipeTransportPairPromise = new Promise((resolve, reject) => { + Promise.all([ + this.createPipeTransport({ + listenInfo: listenInfo!, + enableSctp, + numSctpStreams, + enableRtx, + enableSrtp, + }), + router.createPipeTransport({ + listenInfo: listenInfo!, + enableSctp, + numSctpStreams, + enableRtx, + enableSrtp, + }), + ]) + .then(pipeTransports => { localPipeTransport = pipeTransports[0]; remotePipeTransport = pipeTransports[1]; }) - .then(() => - { - return Promise.all( - [ - localPipeTransport.connect( - { - ip : remotePipeTransport.tuple.localIp, - port : remotePipeTransport.tuple.localPort, - srtpParameters : remotePipeTransport.srtpParameters - }), - remotePipeTransport.connect( - { - ip : localPipeTransport.tuple.localIp, - port : localPipeTransport.tuple.localPort, - srtpParameters : localPipeTransport.srtpParameters - }) - ]); + .then(() => { + return Promise.all([ + localPipeTransport.connect({ + ip: remotePipeTransport.tuple.localIp, + port: remotePipeTransport.tuple.localPort, + srtpParameters: remotePipeTransport.srtpParameters, + }), + remotePipeTransport.connect({ + ip: localPipeTransport.tuple.localIp, + port: localPipeTransport.tuple.localPort, + srtpParameters: localPipeTransport.srtpParameters, + }), + ]); }) - .then(() => - { - localPipeTransport.observer.on('close', () => - { + .then(() => { + localPipeTransport.observer.on('close', () => { remotePipeTransport.close(); this.#mapRouterPairPipeTransportPairPromise.delete( - pipeTransportPairKey); + pipeTransportPairKey, + ); }); - remotePipeTransport.observer.on('close', () => - { + remotePipeTransport.observer.on('close', () => { localPipeTransport.close(); this.#mapRouterPairPipeTransportPairPromise.delete( - pipeTransportPairKey); + pipeTransportPairKey, + ); }); - resolve( - { - [this.id] : localPipeTransport, - [router.id] : remotePipeTransport - }); + resolve({ + [this.id]: localPipeTransport, + [router.id]: remotePipeTransport, + }); }) - .catch((error) => - { + .catch(error => { logger.error( 'pipeToRouter() | error creating PipeTransport pair:%o', - error); + error, + ); - if (localPipeTransport) - { + if (localPipeTransport) { localPipeTransport.close(); } - if (remotePipeTransport) - { + if (remotePipeTransport) { remotePipeTransport.close(); } @@ -1279,50 +1212,43 @@ export class Router }); this.#mapRouterPairPipeTransportPairPromise.set( - pipeTransportPairKey, pipeTransportPairPromise); + pipeTransportPairKey, + pipeTransportPairPromise, + ); router.addPipeTransportPair(this.id, pipeTransportPairPromise); await pipeTransportPairPromise; } - if (producer) - { + if (producer) { let pipeConsumer: Consumer | undefined; let pipeProducer: Producer | undefined; - try - { - pipeConsumer = await localPipeTransport!.consume( - { - producerId : producerId! - }); + try { + pipeConsumer = await localPipeTransport!.consume({ + producerId: producerId!, + }); - pipeProducer = await remotePipeTransport!.produce( - { - id : producer.id, - kind : pipeConsumer!.kind, - rtpParameters : pipeConsumer!.rtpParameters, - paused : pipeConsumer!.producerPaused, - appData : producer.appData - }); + pipeProducer = await remotePipeTransport!.produce({ + id: producer.id, + kind: pipeConsumer!.kind, + rtpParameters: pipeConsumer!.rtpParameters, + paused: pipeConsumer!.producerPaused, + appData: producer.appData, + }); // Ensure that the producer has not been closed in the meanwhile. - if (producer.closed) - { + if (producer.closed) { throw new InvalidStateError('original Producer closed'); } // Ensure that producer.paused has not changed in the meanwhile and, if // so, sync the pipeProducer. - if (pipeProducer.paused !== producer.paused) - { - if (producer.paused) - { + if (pipeProducer.paused !== producer.paused) { + if (producer.paused) { await pipeProducer.pause(); - } - else - { + } else { await pipeProducer.resume(); } } @@ -1336,50 +1262,41 @@ export class Router pipeProducer.observer.on('close', () => pipeConsumer!.close()); return { pipeConsumer, pipeProducer }; - } - catch (error) - { + } catch (error) { logger.error( 'pipeToRouter() | error creating pipe Consumer/Producer pair:%o', - error); + error, + ); - if (pipeConsumer) - { + if (pipeConsumer) { pipeConsumer.close(); } - if (pipeProducer) - { + if (pipeProducer) { pipeProducer.close(); } throw error; } - } - else if (dataProducer) - { + } else if (dataProducer) { let pipeDataConsumer: DataConsumer | undefined; let pipeDataProducer: DataProducer | undefined; - try - { - pipeDataConsumer = await localPipeTransport!.consumeData( - { - dataProducerId : dataProducerId! - }); + try { + pipeDataConsumer = await localPipeTransport!.consumeData({ + dataProducerId: dataProducerId!, + }); - pipeDataProducer = await remotePipeTransport!.produceData( - { - id : dataProducer.id, - sctpStreamParameters : pipeDataConsumer!.sctpStreamParameters, - label : pipeDataConsumer!.label, - protocol : pipeDataConsumer!.protocol, - appData : dataProducer.appData - }); + pipeDataProducer = await remotePipeTransport!.produceData({ + id: dataProducer.id, + sctpStreamParameters: pipeDataConsumer!.sctpStreamParameters, + label: pipeDataConsumer!.label, + protocol: pipeDataConsumer!.protocol, + appData: dataProducer.appData, + }); // Ensure that the dataProducer has not been closed in the meanwhile. - if (dataProducer.closed) - { + if (dataProducer.closed) { throw new InvalidStateError('original DataProducer closed'); } @@ -1390,28 +1307,23 @@ export class Router pipeDataProducer.observer.on('close', () => pipeDataConsumer!.close()); return { pipeDataConsumer, pipeDataProducer }; - } - catch (error) - { + } catch (error) { logger.error( 'pipeToRouter() | error creating pipe DataConsumer/DataProducer pair:%o', - error); + error, + ); - if (pipeDataConsumer) - { + if (pipeDataConsumer) { pipeDataConsumer.close(); } - if (pipeDataProducer) - { + if (pipeDataProducer) { pipeDataProducer.close(); } throw error; } - } - else - { + } else { throw new Error('internal error'); } } @@ -1421,56 +1333,54 @@ export class Router */ addPipeTransportPair( pipeTransportPairKey: string, - pipeTransportPairPromise: Promise - ): void - { - if (this.#mapRouterPairPipeTransportPairPromise.has(pipeTransportPairKey)) - { + pipeTransportPairPromise: Promise, + ): void { + if (this.#mapRouterPairPipeTransportPairPromise.has(pipeTransportPairKey)) { throw new Error( - 'given pipeTransportPairKey already exists in this Router'); + 'given pipeTransportPairKey already exists in this Router', + ); } this.#mapRouterPairPipeTransportPairPromise.set( - pipeTransportPairKey, pipeTransportPairPromise); + pipeTransportPairKey, + pipeTransportPairPromise, + ); pipeTransportPairPromise - .then((pipeTransportPair) => - { + .then(pipeTransportPair => { const localPipeTransport = pipeTransportPair[this.id]; // NOTE: No need to do any other cleanup here since that is done by the // Router calling this method on us. - localPipeTransport.observer.on('close', () => - { + localPipeTransport.observer.on('close', () => { this.#mapRouterPairPipeTransportPairPromise.delete( - pipeTransportPairKey); + pipeTransportPairKey, + ); }); }) - .catch(() => - { + .catch(() => { this.#mapRouterPairPipeTransportPairPromise.delete( - pipeTransportPairKey); + pipeTransportPairKey, + ); }); } /** * Create an ActiveSpeakerObserver */ - async createActiveSpeakerObserver( - { - interval = 300, - appData - }: ActiveSpeakerObserverOptions = {} - ): Promise> - { + async createActiveSpeakerObserver< + ActiveSpeakerObserverAppData extends AppData = AppData, + >({ + interval = 300, + appData, + }: ActiveSpeakerObserverOptions = {}): Promise< + ActiveSpeakerObserver + > { logger.debug('createActiveSpeakerObserver()'); - if (typeof interval !== 'number') - { + if (typeof interval !== 'number') { throw new TypeError('if given, interval must be an number'); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } @@ -1478,40 +1388,34 @@ export class Router /* Build Request. */ const activeRtpObserverOptions = - new FbsActiveSpeakerObserver.ActiveSpeakerObserverOptionsT( - interval - ); + new FbsActiveSpeakerObserver.ActiveSpeakerObserverOptionsT(interval); - const requestOffset = - new FbsRouter.CreateActiveSpeakerObserverRequestT( - rtpObserverId, - activeRtpObserverOptions - ).pack(this.#channel.bufferBuilder); + const requestOffset = new FbsRouter.CreateActiveSpeakerObserverRequestT( + rtpObserverId, + activeRtpObserverOptions, + ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_ACTIVESPEAKEROBSERVER, FbsRequest.Body.Router_CreateActiveSpeakerObserverRequest, requestOffset, - this.#internal.routerId + this.#internal.routerId, ); - const activeSpeakerObserver = new ActiveSpeakerObserver( - { - internal : - { + const activeSpeakerObserver = + new ActiveSpeakerObserver({ + internal: { ...this.#internal, - rtpObserverId : rtpObserverId + rtpObserverId: rtpObserverId, }, - channel : this.#channel, + channel: this.#channel, appData, - getProducerById : (producerId: string): Producer | undefined => ( - this.#producers.get(producerId) - ) + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), }); this.#rtpObservers.set(activeSpeakerObserver.id, activeSpeakerObserver); - activeSpeakerObserver.on('@close', () => - { + activeSpeakerObserver.on('@close', () => { this.#rtpObservers.delete(activeSpeakerObserver.id); }); @@ -1524,31 +1428,31 @@ export class Router /** * Create an AudioLevelObserver. */ - async createAudioLevelObserver( - { - maxEntries = 1, - threshold = -80, - interval = 1000, - appData - }: AudioLevelObserverOptions = {} - ): Promise> - { + async createAudioLevelObserver< + AudioLevelObserverAppData extends AppData = AppData, + >({ + maxEntries = 1, + threshold = -80, + interval = 1000, + appData, + }: AudioLevelObserverOptions = {}): Promise< + AudioLevelObserver + > { logger.debug('createAudioLevelObserver()'); - if (typeof maxEntries !== 'number' || maxEntries <= 0) - { + if (typeof maxEntries !== 'number' || maxEntries <= 0) { throw new TypeError('if given, maxEntries must be a positive number'); - } - else if (typeof threshold !== 'number' || threshold < -127 || threshold > 0) - { - throw new TypeError('if given, threshole must be a negative number greater than -127'); - } - else if (typeof interval !== 'number') - { + } else if ( + typeof threshold !== 'number' || + threshold < -127 || + threshold > 0 + ) { + throw new TypeError( + 'if given, threshole must be a negative number greater than -127', + ); + } else if (typeof interval !== 'number') { throw new TypeError('if given, interval must be an number'); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } @@ -1559,38 +1463,35 @@ export class Router new FbsAudioLevelObserver.AudioLevelObserverOptionsT( maxEntries, threshold, - interval + interval, ); const requestOffset = new FbsRouter.CreateAudioLevelObserverRequestT( rtpObserverId, - audioLevelObserverOptions + audioLevelObserverOptions, ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_AUDIOLEVELOBSERVER, FbsRequest.Body.Router_CreateAudioLevelObserverRequest, requestOffset, - this.#internal.routerId + this.#internal.routerId, ); - const audioLevelObserver = new AudioLevelObserver( - { - internal : - { + const audioLevelObserver = + new AudioLevelObserver({ + internal: { ...this.#internal, - rtpObserverId : rtpObserverId + rtpObserverId: rtpObserverId, }, - channel : this.#channel, + channel: this.#channel, appData, - getProducerById : (producerId: string): Producer | undefined => ( - this.#producers.get(producerId) - ) + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), }); this.#rtpObservers.set(audioLevelObserver.id, audioLevelObserver); - audioLevelObserver.on('@close', () => - { + audioLevelObserver.on('@close', () => { this.#rtpObservers.delete(audioLevelObserver.id); }); @@ -1603,23 +1504,20 @@ export class Router /** * Check whether the given RTP capabilities can consume the given Producer. */ - canConsume( - { - producerId, - rtpCapabilities - }: - { - producerId: string; - rtpCapabilities: RtpCapabilities; - } - ): boolean - { + canConsume({ + producerId, + rtpCapabilities, + }: { + producerId: string; + rtpCapabilities: RtpCapabilities; + }): boolean { const producer = this.#producers.get(producerId); - if (!producer) - { + if (!producer) { logger.error( - 'canConsume() | Producer with id "%s" not found', producerId); + 'canConsume() | Producer with id "%s" not found', + producerId, + ); return false; } @@ -1627,14 +1525,12 @@ export class Router // Clone given RTP capabilities to not modify input data. const clonedRtpCapabilities = clone(rtpCapabilities); - try - { + try { return ortc.canConsume( - producer.consumableRtpParameters, clonedRtpCapabilities + producer.consumableRtpParameters, + clonedRtpCapabilities, ); - } - catch (error) - { + } catch (error) { logger.error('canConsume() | unexpected error: %s', String(error)); return false; @@ -1643,27 +1539,40 @@ export class Router } export function parseRouterDumpResponse( - binary: FbsRouter.DumpResponse -): RouterDump -{ + binary: FbsRouter.DumpResponse, +): RouterDump { return { - id : binary.id()!, - transportIds : parseVector(binary, 'transportIds'), - rtpObserverIds : parseVector(binary, 'rtpObserverIds'), - mapProducerIdConsumerIds : parseStringStringArrayVector(binary, 'mapProducerIdConsumerIds'), - mapConsumerIdProducerId : parseStringStringVector(binary, 'mapConsumerIdProducerId'), - mapProducerIdObserverIds : parseStringStringArrayVector(binary, 'mapProducerIdObserverIds'), - mapDataProducerIdDataConsumerIds : parseStringStringArrayVector(binary, 'mapDataProducerIdDataConsumerIds'), - mapDataConsumerIdDataProducerId : parseStringStringVector(binary, 'mapDataConsumerIdDataProducerId') + id: binary.id()!, + transportIds: parseVector(binary, 'transportIds'), + rtpObserverIds: parseVector(binary, 'rtpObserverIds'), + mapProducerIdConsumerIds: parseStringStringArrayVector( + binary, + 'mapProducerIdConsumerIds', + ), + mapConsumerIdProducerId: parseStringStringVector( + binary, + 'mapConsumerIdProducerId', + ), + mapProducerIdObserverIds: parseStringStringArrayVector( + binary, + 'mapProducerIdObserverIds', + ), + mapDataProducerIdDataConsumerIds: parseStringStringArrayVector( + binary, + 'mapDataProducerIdDataConsumerIds', + ), + mapDataConsumerIdDataProducerId: parseStringStringVector( + binary, + 'mapDataConsumerIdDataProducerId', + ), }; } export function socketFlagsToFbs( - flags: TransportSocketFlags = {} -): FbsTransport.SocketFlagsT -{ + flags: TransportSocketFlags = {}, +): FbsTransport.SocketFlagsT { return new FbsTransport.SocketFlagsT( Boolean(flags.ipv6Only), - Boolean(flags.udpReusePort) + Boolean(flags.udpReusePort), ); } diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 42ee9f099c..3243ef3727 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -8,16 +8,14 @@ import * as FbsRequest from './fbs/request'; import * as FbsRouter from './fbs/router'; import * as FbsRtpObserver from './fbs/rtp-observer'; -export type RtpObserverEvents = -{ +export type RtpObserverEvents = { routerclose: []; listenererror: [string, Error]; // Private events. '@close': []; }; -export type RtpObserverObserverEvents = -{ +export type RtpObserverObserverEvents = { close: []; pause: []; resume: []; @@ -25,34 +23,30 @@ export type RtpObserverObserverEvents = removeproducer: [Producer]; }; -export type RtpObserverConstructorOptions = -{ +export type RtpObserverConstructorOptions = { internal: RtpObserverObserverInternal; channel: Channel; appData?: RtpObserverAppData; getProducerById: (producerId: string) => Producer | undefined; }; -export type RtpObserverObserverInternal = RouterInternal & -{ +export type RtpObserverObserverInternal = RouterInternal & { rtpObserverId: string; }; const logger = new Logger('RtpObserver'); -export type RtpObserverAddRemoveProducerOptions = -{ +export type RtpObserverAddRemoveProducerOptions = { /** * The id of the Producer to be added or removed. */ producerId: string; }; -export class RtpObserver - - extends EnhancedEventEmitter -{ +export class RtpObserver< + RtpObserverAppData extends AppData = AppData, + Events extends RtpObserverEvents = RtpObserverEvents, +> extends EnhancedEventEmitter { // Internal data. protected readonly internal: RtpObserverObserverInternal; @@ -69,7 +63,9 @@ export class RtpObserver #appData: RtpObserverAppData; // Method to retrieve a Producer. - protected readonly getProducerById: (producerId: string) => Producer | undefined; + protected readonly getProducerById: ( + producerId: string, + ) => Producer | undefined; // Observer instance. readonly #observer = new EnhancedEventEmitter(); @@ -78,80 +74,69 @@ export class RtpObserver * @private * @interface */ - constructor( - { - internal, - channel, - appData, - getProducerById - }: RtpObserverConstructorOptions - ) - { + constructor({ + internal, + channel, + appData, + getProducerById, + }: RtpObserverConstructorOptions) { super(); logger.debug('constructor()'); this.internal = internal; this.channel = channel; - this.#appData = appData || {} as RtpObserverAppData; + this.#appData = appData || ({} as RtpObserverAppData); this.getProducerById = getProducerById; } /** * RtpObserver id. */ - get id(): string - { + get id(): string { return this.internal.rtpObserverId; } /** * Whether the RtpObserver is closed. */ - get closed(): boolean - { + get closed(): boolean { return this.#closed; } /** * Whether the RtpObserver is paused. */ - get paused(): boolean - { + get paused(): boolean { return this.#paused; } /** * App custom data. */ - get appData(): RtpObserverAppData - { + get appData(): RtpObserverAppData { return this.#appData; } /** * App custom data setter. */ - set appData(appData: RtpObserverAppData) - { + set appData(appData: RtpObserverAppData) { this.#appData = appData; } /** * Observer. */ - get observer(): EnhancedEventEmitter - { + get observer(): EnhancedEventEmitter { return this.#observer; } /** * Close the RtpObserver. */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -164,15 +149,17 @@ export class RtpObserver /* Build Request. */ const requestOffset = new FbsRouter.CloseRtpObserverRequestT( - this.internal.rtpObserverId + this.internal.rtpObserverId, ).pack(this.channel.bufferBuilder); - this.channel.request( - FbsRequest.Method.ROUTER_CLOSE_RTPOBSERVER, - FbsRequest.Body.Router_CloseRtpObserverRequest, - requestOffset, - this.internal.routerId - ).catch(() => {}); + this.channel + .request( + FbsRequest.Method.ROUTER_CLOSE_RTPOBSERVER, + FbsRequest.Body.Router_CloseRtpObserverRequest, + requestOffset, + this.internal.routerId, + ) + .catch(() => {}); this.emit('@close'); @@ -185,10 +172,8 @@ export class RtpObserver * * @private */ - routerClosed(): void - { - if (this.#closed) - { + routerClosed(): void { + if (this.#closed) { return; } @@ -208,8 +193,7 @@ export class RtpObserver /** * Pause the RtpObserver. */ - async pause(): Promise - { + async pause(): Promise { logger.debug('pause()'); const wasPaused = this.#paused; @@ -218,14 +202,13 @@ export class RtpObserver FbsRequest.Method.RTPOBSERVER_PAUSE, undefined, undefined, - this.internal.rtpObserverId + this.internal.rtpObserverId, ); this.#paused = true; // Emit observer event. - if (!wasPaused) - { + if (!wasPaused) { this.#observer.safeEmit('pause'); } } @@ -233,8 +216,7 @@ export class RtpObserver /** * Resume the RtpObserver. */ - async resume(): Promise - { + async resume(): Promise { logger.debug('resume()'); const wasPaused = this.#paused; @@ -243,14 +225,13 @@ export class RtpObserver FbsRequest.Method.RTPOBSERVER_RESUME, undefined, undefined, - this.internal.rtpObserverId + this.internal.rtpObserverId, ); this.#paused = false; // Emit observer event. - if (wasPaused) - { + if (wasPaused) { this.#observer.safeEmit('resume'); } } @@ -258,26 +239,26 @@ export class RtpObserver /** * Add a Producer to the RtpObserver. */ - async addProducer({ producerId }: RtpObserverAddRemoveProducerOptions): Promise - { + async addProducer({ + producerId, + }: RtpObserverAddRemoveProducerOptions): Promise { logger.debug('addProducer()'); const producer = this.getProducerById(producerId); - if (!producer) - { + if (!producer) { throw Error(`Producer with id "${producerId}" not found`); } const requestOffset = new FbsRtpObserver.AddProducerRequestT( - producerId + producerId, ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.RTPOBSERVER_ADD_PRODUCER, FbsRequest.Body.RtpObserver_AddProducerRequest, requestOffset, - this.internal.rtpObserverId + this.internal.rtpObserverId, ); // Emit observer event. @@ -287,26 +268,26 @@ export class RtpObserver /** * Remove a Producer from the RtpObserver. */ - async removeProducer({ producerId }: RtpObserverAddRemoveProducerOptions): Promise - { + async removeProducer({ + producerId, + }: RtpObserverAddRemoveProducerOptions): Promise { logger.debug('removeProducer()'); const producer = this.getProducerById(producerId); - if (!producer) - { + if (!producer) { throw Error(`Producer with id "${producerId}" not found`); } const requestOffset = new FbsRtpObserver.RemoveProducerRequestT( - producerId + producerId, ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.RTPOBSERVER_REMOVE_PRODUCER, FbsRequest.Body.RtpObserver_RemoveProducerRequest, requestOffset, - this.internal.rtpObserverId + this.internal.rtpObserverId, ); // Emit observer event. diff --git a/node/src/RtpParameters.ts b/node/src/RtpParameters.ts index 99e9f528ed..8978aea24d 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/RtpParameters.ts @@ -14,7 +14,7 @@ import { RtpHeaderExtensionUri as FbsRtpHeaderExtensionUri, RtpParameters as FbsRtpParameters, Rtx as FbsRtx, - Value as FbsValue + Value as FbsValue, } from './fbs/rtp-parameters'; import * as utils from './utils'; @@ -22,8 +22,7 @@ import * as utils from './utils'; * The RTP capabilities define what mediasoup or an endpoint can receive at * media level. */ -export type RtpCapabilities = -{ +export type RtpCapabilities = { /** * Supported media and RTX codecs. */ @@ -57,8 +56,7 @@ export type MediaKind = 'audio' | 'video'; * require preferredPayloadType field (if unset, mediasoup will choose a random * one). If given, make sure it's in the 96-127 range. */ -export type RtpCodecCapability = -{ +export type RtpCodecCapability = { /** * Media kind. */ @@ -101,7 +99,11 @@ export type RtpCodecCapability = /** * Direction of RTP header extension. */ -export type RtpHeaderExtensionDirection = 'sendrecv' | 'sendonly' | 'recvonly' | 'inactive'; +export type RtpHeaderExtensionDirection = + | 'sendrecv' + | 'sendonly' + | 'recvonly' + | 'inactive'; /** * Provides information relating to supported header extensions. The list of @@ -113,8 +115,7 @@ export type RtpHeaderExtensionDirection = 'sendrecv' | 'sendonly' | 'recvonly' | * router.rtpCapabilities or mediasoup.getSupportedRtpCapabilities()). It's * ignored if present in endpoints' RTP capabilities. */ -export type RtpHeaderExtension = -{ +export type RtpHeaderExtension = { /** * Media kind. */ @@ -176,8 +177,7 @@ export type RtpHeaderExtension = * the associated producer. This applies even if the producer's encodings have * rid set. */ -export type RtpParameters = -{ +export type RtpParameters = { /** * The MID RTP extension value as defined in the BUNDLE specification. */ @@ -209,8 +209,7 @@ export type RtpParameters = * of media codecs supported by mediasoup and their settings is defined in the * supportedRtpCapabilities.ts file. */ -export type RtpCodecParameters = -{ +export type RtpCodecParameters = { /** * The codec MIME media type/subtype (e.g. 'audio/opus', 'video/VP8'). */ @@ -251,8 +250,7 @@ export type RtpCodecParameters = * messages. The list of RTCP feedbacks supported by mediasoup is defined in the * supportedRtpCapabilities.ts file. */ -export type RtcpFeedback = -{ +export type RtcpFeedback = { /** * RTCP feedback type. */ @@ -268,8 +266,7 @@ export type RtcpFeedback = * Provides information relating to an encoding, which represents a media RTP * stream and its associated RTX stream (if any). */ -export type RtpEncodingParameters = -{ +export type RtpEncodingParameters = { /** * The media SSRC. */ @@ -314,17 +311,17 @@ export type RtpEncodingParameters = }; export type RtpHeaderExtensionUri = - 'urn:ietf:params:rtp-hdrext:sdes:mid' | - 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id' | - 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id' | - 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07' | - 'urn:ietf:params:rtp-hdrext:framemarking' | - 'urn:ietf:params:rtp-hdrext:ssrc-audio-level' | - 'urn:3gpp:video-orientation' | - 'urn:ietf:params:rtp-hdrext:toffset' | - 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' | - 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' | - 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time'; + | 'urn:ietf:params:rtp-hdrext:sdes:mid' + | 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id' + | 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id' + | 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07' + | 'urn:ietf:params:rtp-hdrext:framemarking' + | 'urn:ietf:params:rtp-hdrext:ssrc-audio-level' + | 'urn:3gpp:video-orientation' + | 'urn:ietf:params:rtp-hdrext:toffset' + | 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' + | 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' + | 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time'; /** * Defines a RTP header extension within the RTP parameters. The list of RTP @@ -334,8 +331,7 @@ export type RtpHeaderExtensionUri = * mediasoup does not currently support encrypted RTP header extensions and no * parameters are currently considered. */ -export type RtpHeaderExtensionParameters = -{ +export type RtpHeaderExtensionParameters = { /** * The URI of the RTP header extension, as defined in RFC 5285. */ @@ -366,8 +362,7 @@ export type RtpHeaderExtensionParameters = * * mediasoup assumes reducedSize to always be true. */ -export type RtcpParameters = -{ +export type RtcpParameters = { /** * The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages). */ @@ -381,31 +376,38 @@ export type RtcpParameters = }; export function serializeRtpParameters( - builder: flatbuffers.Builder, rtpParameters: RtpParameters -): number -{ + builder: flatbuffers.Builder, + rtpParameters: RtpParameters, +): number { const codecs: number[] = []; const headerExtensions: number[] = []; - for (const codec of rtpParameters.codecs) - { + for (const codec of rtpParameters.codecs) { const mimeTypeOffset = builder.createString(codec.mimeType); const parameters = serializeParameters(builder, codec.parameters); - const parametersOffset = - FbsRtpCodecParameters.createParametersVector(builder, parameters); + const parametersOffset = FbsRtpCodecParameters.createParametersVector( + builder, + parameters, + ); const rtcpFeedback: number[] = []; - for (const rtcp of codec.rtcpFeedback ?? []) - { + for (const rtcp of codec.rtcpFeedback ?? []) { const typeOffset = builder.createString(rtcp.type); const rtcpParametersOffset = builder.createString(rtcp.parameter); rtcpFeedback.push( - FbsRtcpFeedback.createRtcpFeedback(builder, typeOffset, rtcpParametersOffset)); + FbsRtcpFeedback.createRtcpFeedback( + builder, + typeOffset, + rtcpParametersOffset, + ), + ); } - const rtcpFeedbackOffset = - FbsRtpCodecParameters.createRtcpFeedbackVector(builder, rtcpFeedback); + const rtcpFeedbackOffset = FbsRtpCodecParameters.createRtcpFeedbackVector( + builder, + rtcpFeedback, + ); codecs.push( FbsRtpCodecParameters.createRtpCodecParameters( @@ -415,18 +417,20 @@ export function serializeRtpParameters( codec.clockRate, Number(codec.channels), parametersOffset, - rtcpFeedbackOffset - )); + rtcpFeedbackOffset, + ), + ); } const codecsOffset = FbsRtpParameters.createCodecsVector(builder, codecs); // RtpHeaderExtensionParameters. - for (const headerExtension of rtpParameters.headerExtensions ?? []) - { + for (const headerExtension of rtpParameters.headerExtensions ?? []) { const uri = rtpHeaderExtensionUriToFbs(headerExtension.uri); const parameters = serializeParameters(builder, headerExtension.parameters); - const parametersOffset = - FbsRtpCodecParameters.createParametersVector(builder, parameters); + const parametersOffset = FbsRtpCodecParameters.createParametersVector( + builder, + parameters, + ); headerExtensions.push( FbsRtpHeaderExtensionParameters.createRtpHeaderExtensionParameters( @@ -434,20 +438,29 @@ export function serializeRtpParameters( uri, headerExtension.id, Boolean(headerExtension.encrypt), - parametersOffset)); + parametersOffset, + ), + ); } - const headerExtensionsOffset = - FbsRtpParameters.createHeaderExtensionsVector(builder, headerExtensions); + const headerExtensionsOffset = FbsRtpParameters.createHeaderExtensionsVector( + builder, + headerExtensions, + ); // RtpEncodingParameters. - const encodingsOffset = serializeRtpEncodingParameters(builder, rtpParameters.encodings ?? []); + const encodingsOffset = serializeRtpEncodingParameters( + builder, + rtpParameters.encodings ?? [], + ); // RtcpParameters. const { cname, reducedSize } = rtpParameters.rtcp ?? { reducedSize: true }; const cnameOffset = builder.createString(cname); const rtcpOffset = FbsRtcpParameters.createRtcpParameters( - builder, cnameOffset, Boolean(reducedSize) + builder, + cnameOffset, + Boolean(reducedSize), ); const midOffset = builder.createString(rtpParameters.mid); @@ -464,29 +477,26 @@ export function serializeRtpParameters( } export function serializeRtpEncodingParameters( - builder: flatbuffers.Builder, rtpEncodingParameters: RtpEncodingParameters[] = [] -): number -{ + builder: flatbuffers.Builder, + rtpEncodingParameters: RtpEncodingParameters[] = [], +): number { const encodings: number[] = []; - for (const encoding of rtpEncodingParameters) - { + for (const encoding of rtpEncodingParameters) { // Prepare Rid. const ridOffset = builder.createString(encoding.rid); // Prepare Rtx. let rtxOffset: number | undefined; - if (encoding.rtx) - { + if (encoding.rtx) { rtxOffset = FbsRtx.createRtx(builder, encoding.rtx.ssrc); } // Prepare scalability mode. let scalabilityModeOffset: number | undefined; - if (encoding.scalabilityMode) - { + if (encoding.scalabilityMode) { scalabilityModeOffset = builder.createString(encoding.scalabilityMode); } @@ -494,8 +504,7 @@ export function serializeRtpEncodingParameters( FbsRtpEncodingParameters.startRtpEncodingParameters(builder); // Add SSRC. - if (encoding.ssrc) - { + if (encoding.ssrc) { FbsRtpEncodingParameters.addSsrc(builder, encoding.ssrc); } @@ -503,32 +512,33 @@ export function serializeRtpEncodingParameters( FbsRtpEncodingParameters.addRid(builder, ridOffset); // Add payload type. - if (encoding.codecPayloadType) - { - FbsRtpEncodingParameters.addCodecPayloadType(builder, encoding.codecPayloadType); + if (encoding.codecPayloadType) { + FbsRtpEncodingParameters.addCodecPayloadType( + builder, + encoding.codecPayloadType, + ); } // Add RTX. - if (rtxOffset) - { + if (rtxOffset) { FbsRtpEncodingParameters.addRtx(builder, rtxOffset); } // Add DTX. - if (encoding.dtx !== undefined) - { + if (encoding.dtx !== undefined) { FbsRtpEncodingParameters.addDtx(builder, encoding.dtx); } // Add scalability ode. - if (scalabilityModeOffset) - { - FbsRtpEncodingParameters.addScalabilityMode(builder, scalabilityModeOffset); + if (scalabilityModeOffset) { + FbsRtpEncodingParameters.addScalabilityMode( + builder, + scalabilityModeOffset, + ); } // Add max bitrate. - if (encoding.maxBitrate !== undefined) - { + if (encoding.maxBitrate !== undefined) { FbsRtpEncodingParameters.addMaxBitrate(builder, encoding.maxBitrate); } @@ -540,62 +550,68 @@ export function serializeRtpEncodingParameters( } export function serializeParameters( - builder: flatbuffers.Builder, parameters: any -):number[] -{ + builder: flatbuffers.Builder, + parameters: any, +): number[] { const fbsParameters: number[] = []; - for (const key of Object.keys(parameters)) - { + for (const key of Object.keys(parameters)) { const value = parameters[key]; const keyOffset = builder.createString(key); let parameterOffset: number; - if (typeof value === 'boolean') - { + if (typeof value === 'boolean') { parameterOffset = FbsParameter.createParameter( - builder, keyOffset, FbsValue.Boolean, value === true ? 1 : 0 + builder, + keyOffset, + FbsValue.Boolean, + value === true ? 1 : 0, ); - } - else if (typeof value === 'number') - { + } else if (typeof value === 'number') { // Integer. - if (value % 1 === 0) - { + if (value % 1 === 0) { const valueOffset = FbsInteger32.createInteger32(builder, value); parameterOffset = FbsParameter.createParameter( - builder, keyOffset, FbsValue.Integer32, valueOffset + builder, + keyOffset, + FbsValue.Integer32, + valueOffset, ); } // Float. - else - { + else { const valueOffset = FbsDouble.createDouble(builder, value); parameterOffset = FbsParameter.createParameter( - builder, keyOffset, FbsValue.Double, valueOffset + builder, + keyOffset, + FbsValue.Double, + valueOffset, ); } - } - else if (typeof value === 'string') - { - const valueOffset = FbsString.createString(builder, builder.createString(value)); + } else if (typeof value === 'string') { + const valueOffset = FbsString.createString( + builder, + builder.createString(value), + ); parameterOffset = FbsParameter.createParameter( - builder, keyOffset, FbsValue.String, valueOffset + builder, + keyOffset, + FbsValue.String, + valueOffset, ); - } - else if (Array.isArray(value)) - { + } else if (Array.isArray(value)) { const valueOffset = FbsInteger32Array.createValueVector(builder, value); parameterOffset = FbsParameter.createParameter( - builder, keyOffset, FbsValue.Integer32Array, valueOffset + builder, + keyOffset, + FbsValue.Integer32Array, + valueOffset, ); - } - else - { + } else { throw new Error(`invalid parameter type [key:'${key}', value:${value}]`); } @@ -605,26 +621,21 @@ export function serializeParameters( return fbsParameters; } -export function parseRtcpFeedback(data: FbsRtcpFeedback): RtcpFeedback -{ +export function parseRtcpFeedback(data: FbsRtcpFeedback): RtcpFeedback { return { - type : data.type()!, - parameter : data.parameter() ?? undefined + type: data.type()!, + parameter: data.parameter() ?? undefined, }; } -export function parseParameters(data: any): any -{ +export function parseParameters(data: any): any { const parameters: any = {}; - for (let i = 0; i < data.parametersLength(); i++) - { + for (let i = 0; i < data.parametersLength(); i++) { const fbsParameter = data.parameters(i)!; - switch (fbsParameter.valueType()) - { - case FbsValue.Boolean: - { + switch (fbsParameter.valueType()) { + case FbsValue.Boolean: { const value = new FbsBoolean(); fbsParameter.value(value); @@ -634,8 +645,7 @@ export function parseParameters(data: any): any break; } - case FbsValue.Integer32: - { + case FbsValue.Integer32: { const value = new FbsInteger32(); fbsParameter.value(value); @@ -645,8 +655,7 @@ export function parseParameters(data: any): any break; } - case FbsValue.Double: - { + case FbsValue.Double: { const value = new FbsDouble(); fbsParameter.value(value); @@ -656,8 +665,7 @@ export function parseParameters(data: any): any break; } - case FbsValue.String: - { + case FbsValue.String: { const value = new FbsString(); fbsParameter.value(value); @@ -667,8 +675,7 @@ export function parseParameters(data: any): any break; } - case FbsValue.Integer32Array: - { + case FbsValue.Integer32Array: { const value = new FbsInteger32Array(); fbsParameter.value(value); @@ -683,224 +690,196 @@ export function parseParameters(data: any): any return parameters; } -export function parseRtpCodecParameters(data: FbsRtpCodecParameters): RtpCodecParameters -{ +export function parseRtpCodecParameters( + data: FbsRtpCodecParameters, +): RtpCodecParameters { const parameters = parseParameters(data); let rtcpFeedback: RtcpFeedback[] = []; - if (data.rtcpFeedbackLength() > 0) - { + if (data.rtcpFeedbackLength() > 0) { rtcpFeedback = utils.parseVector(data, 'rtcpFeedback', parseRtcpFeedback); } return { - mimeType : data.mimeType()!, - payloadType : data.payloadType(), - clockRate : data.clockRate(), - channels : data.channels() ?? undefined, + mimeType: data.mimeType()!, + payloadType: data.payloadType(), + clockRate: data.clockRate(), + channels: data.channels() ?? undefined, parameters, - rtcpFeedback + rtcpFeedback, }; } -export function rtpHeaderExtensionUriFromFbs(uri: FbsRtpHeaderExtensionUri): RtpHeaderExtensionUri -{ - switch (uri) - { - case FbsRtpHeaderExtensionUri.Mid: - { +export function rtpHeaderExtensionUriFromFbs( + uri: FbsRtpHeaderExtensionUri, +): RtpHeaderExtensionUri { + switch (uri) { + case FbsRtpHeaderExtensionUri.Mid: { return 'urn:ietf:params:rtp-hdrext:sdes:mid'; } - case FbsRtpHeaderExtensionUri.RtpStreamId: - { + case FbsRtpHeaderExtensionUri.RtpStreamId: { return 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id'; } - case FbsRtpHeaderExtensionUri.RepairRtpStreamId: - { + case FbsRtpHeaderExtensionUri.RepairRtpStreamId: { return 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id'; } - case FbsRtpHeaderExtensionUri.FrameMarkingDraft07: - { + case FbsRtpHeaderExtensionUri.FrameMarkingDraft07: { return 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07'; } - case FbsRtpHeaderExtensionUri.FrameMarking: - { + case FbsRtpHeaderExtensionUri.FrameMarking: { return 'urn:ietf:params:rtp-hdrext:framemarking'; } - case FbsRtpHeaderExtensionUri.AudioLevel: - { + case FbsRtpHeaderExtensionUri.AudioLevel: { return 'urn:ietf:params:rtp-hdrext:ssrc-audio-level'; } - case FbsRtpHeaderExtensionUri.VideoOrientation: - { + case FbsRtpHeaderExtensionUri.VideoOrientation: { return 'urn:3gpp:video-orientation'; } - case FbsRtpHeaderExtensionUri.TimeOffset: - { + case FbsRtpHeaderExtensionUri.TimeOffset: { return 'urn:ietf:params:rtp-hdrext:toffset'; } - case FbsRtpHeaderExtensionUri.TransportWideCcDraft01: - { + case FbsRtpHeaderExtensionUri.TransportWideCcDraft01: { return 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01'; } - case FbsRtpHeaderExtensionUri.AbsSendTime: - { + case FbsRtpHeaderExtensionUri.AbsSendTime: { return 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time'; } - case FbsRtpHeaderExtensionUri.AbsCaptureTime: - { + case FbsRtpHeaderExtensionUri.AbsCaptureTime: { return 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time'; } } } -export function rtpHeaderExtensionUriToFbs(uri: RtpHeaderExtensionUri): FbsRtpHeaderExtensionUri -{ - switch (uri) - { - case 'urn:ietf:params:rtp-hdrext:sdes:mid': - { +export function rtpHeaderExtensionUriToFbs( + uri: RtpHeaderExtensionUri, +): FbsRtpHeaderExtensionUri { + switch (uri) { + case 'urn:ietf:params:rtp-hdrext:sdes:mid': { return FbsRtpHeaderExtensionUri.Mid; } - case 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id': - { + case 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id': { return FbsRtpHeaderExtensionUri.RtpStreamId; } - case 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id': - { + case 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id': { return FbsRtpHeaderExtensionUri.RepairRtpStreamId; } - case 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07': - { + case 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07': { return FbsRtpHeaderExtensionUri.FrameMarkingDraft07; } - case 'urn:ietf:params:rtp-hdrext:framemarking': - { + case 'urn:ietf:params:rtp-hdrext:framemarking': { return FbsRtpHeaderExtensionUri.FrameMarking; } - case 'urn:ietf:params:rtp-hdrext:ssrc-audio-level': - { + case 'urn:ietf:params:rtp-hdrext:ssrc-audio-level': { return FbsRtpHeaderExtensionUri.AudioLevel; } - case 'urn:3gpp:video-orientation': - { + case 'urn:3gpp:video-orientation': { return FbsRtpHeaderExtensionUri.VideoOrientation; } - case 'urn:ietf:params:rtp-hdrext:toffset': - { + case 'urn:ietf:params:rtp-hdrext:toffset': { return FbsRtpHeaderExtensionUri.TimeOffset; } - case 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01': - { + case 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01': { return FbsRtpHeaderExtensionUri.TransportWideCcDraft01; } - case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time': - { + case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time': { return FbsRtpHeaderExtensionUri.AbsSendTime; } - case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time': - { + case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time': { return FbsRtpHeaderExtensionUri.AbsCaptureTime; } - default: - { + default: { throw new TypeError(`invalid RtpHeaderExtensionUri: ${uri}`); } } } export function parseRtpHeaderExtensionParameters( - data: FbsRtpHeaderExtensionParameters): RtpHeaderExtensionParameters -{ + data: FbsRtpHeaderExtensionParameters, +): RtpHeaderExtensionParameters { return { - uri : rtpHeaderExtensionUriFromFbs(data.uri()), - id : data.id(), - encrypt : data.encrypt(), - parameters : parseParameters(data) + uri: rtpHeaderExtensionUriFromFbs(data.uri()), + id: data.id(), + encrypt: data.encrypt(), + parameters: parseParameters(data), }; } export function parseRtpEncodingParameters( - data: FbsRtpEncodingParameters): RtpEncodingParameters -{ + data: FbsRtpEncodingParameters, +): RtpEncodingParameters { return { - ssrc : data.ssrc() ?? undefined, - rid : data.rid() ?? undefined, - codecPayloadType : data.codecPayloadType() !== null ? - data.codecPayloadType()! : - undefined, - rtx : data.rtx() ? - { ssrc: data.rtx()!.ssrc()! } : - undefined, - dtx : data.dtx(), - scalabilityMode : data.scalabilityMode() ?? undefined, - maxBitrate : data.maxBitrate() !== null ? data.maxBitrate()! : undefined + ssrc: data.ssrc() ?? undefined, + rid: data.rid() ?? undefined, + codecPayloadType: + data.codecPayloadType() !== null ? data.codecPayloadType()! : undefined, + rtx: data.rtx() ? { ssrc: data.rtx()!.ssrc()! } : undefined, + dtx: data.dtx(), + scalabilityMode: data.scalabilityMode() ?? undefined, + maxBitrate: data.maxBitrate() !== null ? data.maxBitrate()! : undefined, }; } -export function parseRtpParameters(data: FbsRtpParameters): RtpParameters -{ +export function parseRtpParameters(data: FbsRtpParameters): RtpParameters { const codecs = utils.parseVector(data, 'codecs', parseRtpCodecParameters); let headerExtensions: RtpHeaderExtensionParameters[] = []; - if (data.headerExtensionsLength() > 0) - { + if (data.headerExtensionsLength() > 0) { headerExtensions = utils.parseVector( data, 'headerExtensions', - parseRtpHeaderExtensionParameters); + parseRtpHeaderExtensionParameters, + ); } let encodings: RtpEncodingParameters[] = []; - if (data.encodingsLength() > 0) - { + if (data.encodingsLength() > 0) { encodings = utils.parseVector( data, 'encodings', - parseRtpEncodingParameters); + parseRtpEncodingParameters, + ); } let rtcp: RtcpParameters | undefined; - if (data.rtcp()) - { + if (data.rtcp()) { const fbsRtcp = data.rtcp()!; rtcp = { - cname : fbsRtcp.cname() ?? undefined, - reducedSize : fbsRtcp.reducedSize() + cname: fbsRtcp.cname() ?? undefined, + reducedSize: fbsRtcp.reducedSize(), }; } return { - mid : data.mid() ?? undefined, + mid: data.mid() ?? undefined, codecs, headerExtensions, encodings, - rtcp + rtcp, }; } diff --git a/node/src/RtpStream.ts b/node/src/RtpStream.ts index 434cfaf947..f42cb23c36 100644 --- a/node/src/RtpStream.ts +++ b/node/src/RtpStream.ts @@ -1,8 +1,7 @@ import * as FbsRtpStream from './fbs/rtp-stream'; import * as FbsRtpParameters from './fbs/rtp-parameters'; -export type RtpStreamRecvStats = BaseRtpStreamStats & -{ +export type RtpStreamRecvStats = BaseRtpStreamStats & { type: string; jitter: number; packetCount: number; @@ -11,16 +10,14 @@ export type RtpStreamRecvStats = BaseRtpStreamStats & bitrateByLayer?: any; }; -export type RtpStreamSendStats = BaseRtpStreamStats & -{ +export type RtpStreamSendStats = BaseRtpStreamStats & { type: string; packetCount: number; byteCount: number; bitrate: number; }; -type BaseRtpStreamStats = -{ +type BaseRtpStreamStats = { timestamp: number; ssrc: number; rtxSsrc?: number; @@ -42,21 +39,18 @@ type BaseRtpStreamStats = }; export function parseRtpStreamStats( - binary: FbsRtpStream.Stats -) : RtpStreamRecvStats | RtpStreamSendStats -{ - if (binary.dataType() === FbsRtpStream.StatsData.RecvStats) - { + binary: FbsRtpStream.Stats, +): RtpStreamRecvStats | RtpStreamSendStats { + if (binary.dataType() === FbsRtpStream.StatsData.RecvStats) { return parseRtpStreamRecvStats(binary); - } - else - { + } else { return parseSendStreamStats(binary); } } -export function parseRtpStreamRecvStats(binary: FbsRtpStream.Stats): RtpStreamRecvStats -{ +export function parseRtpStreamRecvStats( + binary: FbsRtpStream.Stats, +): RtpStreamRecvStats { const recvStats = new FbsRtpStream.RecvStats(); const baseStats = new FbsRtpStream.BaseStats(); @@ -67,17 +61,18 @@ export function parseRtpStreamRecvStats(binary: FbsRtpStream.Stats): RtpStreamRe return { ...base, - type : 'inbound-rtp', - jitter : recvStats.jitter(), - byteCount : Number(recvStats.byteCount()), - packetCount : Number(recvStats.packetCount()), - bitrate : Number(recvStats.bitrate()), - bitrateByLayer : parseBitrateByLayer(recvStats) + type: 'inbound-rtp', + jitter: recvStats.jitter(), + byteCount: Number(recvStats.byteCount()), + packetCount: Number(recvStats.packetCount()), + bitrate: Number(recvStats.bitrate()), + bitrateByLayer: parseBitrateByLayer(recvStats), }; } -export function parseSendStreamStats(binary: FbsRtpStream.Stats): RtpStreamSendStats -{ +export function parseSendStreamStats( + binary: FbsRtpStream.Stats, +): RtpStreamSendStats { const sendStats = new FbsRtpStream.SendStats(); const baseStats = new FbsRtpStream.BaseStats(); @@ -88,52 +83,49 @@ export function parseSendStreamStats(binary: FbsRtpStream.Stats): RtpStreamSendS return { ...base, - type : 'outbound-rtp', - byteCount : Number(sendStats.byteCount()), - packetCount : Number(sendStats.packetCount()), - bitrate : Number(sendStats.bitrate()) + type: 'outbound-rtp', + byteCount: Number(sendStats.byteCount()), + packetCount: Number(sendStats.packetCount()), + bitrate: Number(sendStats.bitrate()), }; } -function parseBaseStreamStats(binary: FbsRtpStream.BaseStats): BaseRtpStreamStats -{ +function parseBaseStreamStats( + binary: FbsRtpStream.BaseStats, +): BaseRtpStreamStats { return { - timestamp : Number(binary.timestamp()), - ssrc : binary.ssrc(), - rtxSsrc : binary.rtxSsrc() ?? undefined, - rid : binary.rid() ?? undefined, - kind : binary.kind() === FbsRtpParameters.MediaKind.AUDIO ? - 'audio' : - 'video', - mimeType : binary.mimeType()!, - packetsLost : Number(binary.packetsLost()), - fractionLost : Number(binary.fractionLost()), - packetsDiscarded : Number(binary.packetsDiscarded()), - packetsRetransmitted : Number(binary.packetsRetransmitted()), - packetsRepaired : Number(binary.packetsRepaired()), - nackCount : Number(binary.nackCount()), - nackPacketCount : Number(binary.nackPacketCount()), - pliCount : Number(binary.pliCount()), - firCount : Number(binary.firCount()), - score : binary.score(), - roundTripTime : binary.roundTripTime(), - rtxPacketsDiscarded : binary.rtxPacketsDiscarded() ? - Number(binary.rtxPacketsDiscarded()) : - undefined + timestamp: Number(binary.timestamp()), + ssrc: binary.ssrc(), + rtxSsrc: binary.rtxSsrc() ?? undefined, + rid: binary.rid() ?? undefined, + kind: + binary.kind() === FbsRtpParameters.MediaKind.AUDIO ? 'audio' : 'video', + mimeType: binary.mimeType()!, + packetsLost: Number(binary.packetsLost()), + fractionLost: Number(binary.fractionLost()), + packetsDiscarded: Number(binary.packetsDiscarded()), + packetsRetransmitted: Number(binary.packetsRetransmitted()), + packetsRepaired: Number(binary.packetsRepaired()), + nackCount: Number(binary.nackCount()), + nackPacketCount: Number(binary.nackPacketCount()), + pliCount: Number(binary.pliCount()), + firCount: Number(binary.firCount()), + score: binary.score(), + roundTripTime: binary.roundTripTime(), + rtxPacketsDiscarded: binary.rtxPacketsDiscarded() + ? Number(binary.rtxPacketsDiscarded()) + : undefined, }; } -function parseBitrateByLayer(binary: FbsRtpStream.RecvStats): any -{ - if (binary.bitrateByLayerLength() === 0) - { +function parseBitrateByLayer(binary: FbsRtpStream.RecvStats): any { + if (binary.bitrateByLayerLength() === 0) { return {}; } - const bitRateByLayer: {[key: string]: number} = {}; + const bitRateByLayer: { [key: string]: number } = {}; - for (let i = 0; i < binary.bitrateByLayerLength(); ++i) - { + for (let i = 0; i < binary.bitrateByLayerLength(); ++i) { const layer: string = binary.bitrateByLayer(i)!.layer()!; const bitrate = binary.bitrateByLayer(i)!.bitrate(); diff --git a/node/src/SctpParameters.ts b/node/src/SctpParameters.ts index 54a878fb6a..ab6daec1d4 100644 --- a/node/src/SctpParameters.ts +++ b/node/src/SctpParameters.ts @@ -1,9 +1,8 @@ import * as flatbuffers from 'flatbuffers'; import * as FbsSctpParameters from './fbs/sctp-parameters'; -export type SctpCapabilities = -{ - numStreams: NumSctpStreams; +export type SctpCapabilities = { + numStreams: NumSctpStreams; }; /** @@ -28,8 +27,7 @@ export type SctpCapabilities = * mediasoup-client provides specific per browser/version OS and MIS values via * the device.sctpCapabilities getter. */ -export type NumSctpStreams = -{ +export type NumSctpStreams = { /** * Initially requested number of outgoing SCTP streams. */ @@ -41,8 +39,7 @@ export type NumSctpStreams = MIS: number; }; -export type SctpParameters = -{ +export type SctpParameters = { /** * Must always equal 5000. */ @@ -71,8 +68,7 @@ export type SctpParameters = * If ordered if false, only one of maxPacketLifeTime or maxRetransmits * can be true. */ -export type SctpStreamParameters = -{ +export type SctpStreamParameters = { /** * SCTP stream id. */ @@ -97,62 +93,60 @@ export type SctpStreamParameters = maxRetransmits?: number; }; -export type SctpParametersDump = -{ - port : number; - OS : number; - MIS : number; - maxMessageSize : number; - sendBufferSize : number; - sctpBufferedAmount : number; - isDataChannel : boolean; +export type SctpParametersDump = { + port: number; + OS: number; + MIS: number; + maxMessageSize: number; + sendBufferSize: number; + sctpBufferedAmount: number; + isDataChannel: boolean; }; export function parseSctpParametersDump( - binary: FbsSctpParameters.SctpParameters -): SctpParametersDump -{ + binary: FbsSctpParameters.SctpParameters, +): SctpParametersDump { return { - port : binary.port(), - OS : binary.os(), - MIS : binary.mis(), - maxMessageSize : binary.maxMessageSize(), - sendBufferSize : binary.sendBufferSize(), - sctpBufferedAmount : binary.sctpBufferedAmount(), - isDataChannel : binary.isDataChannel() + port: binary.port(), + OS: binary.os(), + MIS: binary.mis(), + maxMessageSize: binary.maxMessageSize(), + sendBufferSize: binary.sendBufferSize(), + sctpBufferedAmount: binary.sctpBufferedAmount(), + isDataChannel: binary.isDataChannel(), }; } export function serializeSctpStreamParameters( builder: flatbuffers.Builder, - parameters: SctpStreamParameters -): number -{ + parameters: SctpStreamParameters, +): number { return FbsSctpParameters.SctpStreamParameters.createSctpStreamParameters( builder, parameters.streamId, parameters.ordered!, - typeof parameters.maxPacketLifeTime === 'number' ? - parameters.maxPacketLifeTime : - null, - typeof parameters.maxRetransmits === 'number' ? - parameters.maxRetransmits : - null + typeof parameters.maxPacketLifeTime === 'number' + ? parameters.maxPacketLifeTime + : null, + typeof parameters.maxRetransmits === 'number' + ? parameters.maxRetransmits + : null, ); } export function parseSctpStreamParameters( - parameters: FbsSctpParameters.SctpStreamParameters -): SctpStreamParameters -{ + parameters: FbsSctpParameters.SctpStreamParameters, +): SctpStreamParameters { return { - streamId : parameters.streamId(), - ordered : parameters.ordered()!, - maxPacketLifeTime : parameters.maxPacketLifeTime() !== null ? - parameters.maxPacketLifeTime()! : - undefined, - maxRetransmits : parameters.maxRetransmits() !== null ? - parameters.maxRetransmits()! : - undefined + streamId: parameters.streamId(), + ordered: parameters.ordered()!, + maxPacketLifeTime: + parameters.maxPacketLifeTime() !== null + ? parameters.maxPacketLifeTime()! + : undefined, + maxRetransmits: + parameters.maxRetransmits() !== null + ? parameters.maxRetransmits()! + : undefined, }; } diff --git a/node/src/SrtpParameters.ts b/node/src/SrtpParameters.ts index 87470bb5a4..d76baccb1a 100644 --- a/node/src/SrtpParameters.ts +++ b/node/src/SrtpParameters.ts @@ -4,8 +4,7 @@ import * as FbsSrtpParameters from './fbs/srtp-parameters'; /** * SRTP parameters. */ -export type SrtpParameters = -{ +export type SrtpParameters = { /** * Encryption and authentication transforms to be used. */ @@ -26,79 +25,72 @@ export type SrtpCryptoSuite = | 'AES_CM_128_HMAC_SHA1_80' | 'AES_CM_128_HMAC_SHA1_32'; -export function cryptoSuiteFromFbs(binary: FbsSrtpParameters.SrtpCryptoSuite): SrtpCryptoSuite -{ - switch (binary) - { - case FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_256_GCM: - { +export function cryptoSuiteFromFbs( + binary: FbsSrtpParameters.SrtpCryptoSuite, +): SrtpCryptoSuite { + switch (binary) { + case FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_256_GCM: { return 'AEAD_AES_256_GCM'; } - case FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_128_GCM: - { + case FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_128_GCM: { return 'AEAD_AES_128_GCM'; } - case FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80: - { + case FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80: { return 'AES_CM_128_HMAC_SHA1_80'; } - case FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32: - { + case FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32: { return 'AES_CM_128_HMAC_SHA1_32'; } } } -export function cryptoSuiteToFbs(cryptoSuite: SrtpCryptoSuite) - : FbsSrtpParameters.SrtpCryptoSuite -{ - switch (cryptoSuite) - { - case 'AEAD_AES_256_GCM': - { +export function cryptoSuiteToFbs( + cryptoSuite: SrtpCryptoSuite, +): FbsSrtpParameters.SrtpCryptoSuite { + switch (cryptoSuite) { + case 'AEAD_AES_256_GCM': { return FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_256_GCM; } - case 'AEAD_AES_128_GCM': - { + case 'AEAD_AES_128_GCM': { return FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_128_GCM; } - case 'AES_CM_128_HMAC_SHA1_80': - { + case 'AES_CM_128_HMAC_SHA1_80': { return FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80; } - case 'AES_CM_128_HMAC_SHA1_32': - { + case 'AES_CM_128_HMAC_SHA1_32': { return FbsSrtpParameters.SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32; } - default: - { + default: { throw new TypeError(`invalid SrtpCryptoSuite: ${cryptoSuite}`); } } } -export function parseSrtpParameters(binary: FbsSrtpParameters.SrtpParameters): SrtpParameters -{ +export function parseSrtpParameters( + binary: FbsSrtpParameters.SrtpParameters, +): SrtpParameters { return { - cryptoSuite : cryptoSuiteFromFbs(binary.cryptoSuite()), - keyBase64 : binary.keyBase64()! + cryptoSuite: cryptoSuiteFromFbs(binary.cryptoSuite()), + keyBase64: binary.keyBase64()!, }; } export function serializeSrtpParameters( - builder:flatbuffers.Builder, srtpParameters:SrtpParameters -): number -{ + builder: flatbuffers.Builder, + srtpParameters: SrtpParameters, +): number { const keyBase64Offset = builder.createString(srtpParameters.keyBase64); return FbsSrtpParameters.SrtpParameters.createSrtpParameters( - builder, cryptoSuiteToFbs(srtpParameters.cryptoSuite), keyBase64Offset + builder, + cryptoSuiteToFbs(srtpParameters.cryptoSuite), + keyBase64Offset, ); } diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 5fd110ba14..3da3b248bf 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -12,40 +12,40 @@ import { Producer, ProducerOptions, producerTypeFromFbs, - producerTypeToFbs + producerTypeToFbs, } from './Producer'; import { Consumer, ConsumerOptions, ConsumerType, - ConsumerLayers + ConsumerLayers, } from './Consumer'; import { DataProducer, DataProducerOptions, DataProducerType, dataProducerTypeToFbs, - parseDataProducerDumpResponse + parseDataProducerDumpResponse, } from './DataProducer'; import { DataConsumer, DataConsumerOptions, DataConsumerType, dataConsumerTypeToFbs, - parseDataConsumerDumpResponse + parseDataConsumerDumpResponse, } from './DataConsumer'; import { MediaKind, RtpCapabilities, RtpParameters, serializeRtpEncodingParameters, - serializeRtpParameters + serializeRtpParameters, } from './RtpParameters'; import { parseSctpParametersDump, serializeSctpStreamParameters, SctpParameters, - SctpStreamParameters + SctpStreamParameters, } from './SctpParameters'; import { AppData } from './types'; import * as utils from './utils'; @@ -60,8 +60,7 @@ import * as FbsRouter from './fbs/router'; import * as FbsRtpParameters from './fbs/rtp-parameters'; import { SctpState as FbsSctpState } from './fbs/sctp-association/sctp-state'; -export type TransportListenInfo = -{ +export type TransportListenInfo = { /** * Network protocol. */ @@ -103,8 +102,7 @@ export type TransportListenInfo = * Use TransportListenInfo instead. * @deprecated */ -export type TransportListenIp = -{ +export type TransportListenIp = { /** * Listening IPv4 or IPv6. */ @@ -125,8 +123,7 @@ export type TransportProtocol = 'udp' | 'tcp'; /** * UDP/TCP socket flags. */ -export type TransportSocketFlags = -{ +export type TransportSocketFlags = { /** * Disable dual-stack support so only IPv6 is used (only if ip is IPv6). */ @@ -138,8 +135,7 @@ export type TransportSocketFlags = udpReusePort?: boolean; }; -export type TransportTuple = -{ +export type TransportTuple = { localIp: string; localPort: number; remoteIp?: string; @@ -155,8 +151,7 @@ export type TransportTraceEventType = 'probation' | 'bwe'; /** * 'trace' event data. */ -export type TransportTraceEventData = -{ +export type TransportTraceEventData = { /** * Trace type. */ @@ -178,10 +173,14 @@ export type TransportTraceEventData = info: any; }; -export type SctpState = 'new' | 'connecting' | 'connected' | 'failed' | 'closed'; +export type SctpState = + | 'new' + | 'connecting' + | 'connected' + | 'failed' + | 'closed'; -export type TransportEvents = -{ +export type TransportEvents = { routerclose: []; listenserverclose: []; trace: [TransportTraceEventData]; @@ -195,8 +194,7 @@ export type TransportEvents = '@listenserverclose': []; }; -export type TransportObserverEvents = -{ +export type TransportObserverEvents = { close: []; newproducer: [Producer]; newconsumer: [Consumer]; @@ -205,8 +203,7 @@ export type TransportObserverEvents = trace: [TransportTraceEventData]; }; -export type TransportConstructorOptions = -{ +export type TransportConstructorOptions = { internal: TransportInternal; data: TransportData; channel: Channel; @@ -216,32 +213,29 @@ export type TransportConstructorOptions = getDataProducerById: (dataProducerId: string) => DataProducer | undefined; }; -export type TransportInternal = RouterInternal & -{ +export type TransportInternal = RouterInternal & { transportId: string; }; -export type BaseTransportDump = -{ - id : string; - direct : boolean; - producerIds : string[]; - consumerIds : string[]; - mapSsrcConsumerId : { key: number; value: string }[]; - mapRtxSsrcConsumerId : { key: number; value: string }[]; - recvRtpHeaderExtensions : RecvRtpHeaderExtensions; +export type BaseTransportDump = { + id: string; + direct: boolean; + producerIds: string[]; + consumerIds: string[]; + mapSsrcConsumerId: { key: number; value: string }[]; + mapRtxSsrcConsumerId: { key: number; value: string }[]; + recvRtpHeaderExtensions: RecvRtpHeaderExtensions; rtpListener: RtpListenerDump; maxMessageSize: number; - dataProducerIds : string[]; - dataConsumerIds : string[]; - sctpParameters? : SctpParameters; - sctpState? : SctpState; + dataProducerIds: string[]; + dataConsumerIds: string[]; + sctpParameters?: SctpParameters; + sctpState?: SctpState; sctpListener?: SctpListenerDump; - traceEventTypes? : string[]; + traceEventTypes?: string[]; }; -export type BaseTransportStats = -{ +export type BaseTransportStats = { transportId: string; timestamp: number; sctpState?: SctpState; @@ -265,40 +259,36 @@ export type BaseTransportStats = }; type TransportData = - | WebRtcTransportData - | PlainTransportData - | PipeTransportData - | DirectTransportData; - -type RtpListenerDump = -{ - ssrcTable : {key: number; value: string}[]; - midTable : {key: number; value: string}[]; - ridTable : {key: number; value: string}[]; + | WebRtcTransportData + | PlainTransportData + | PipeTransportData + | DirectTransportData; + +type RtpListenerDump = { + ssrcTable: { key: number; value: string }[]; + midTable: { key: number; value: string }[]; + ridTable: { key: number; value: string }[]; }; -type SctpListenerDump = -{ - streamIdTable : {key: number; value: string}[]; +type SctpListenerDump = { + streamIdTable: { key: number; value: string }[]; }; -type RecvRtpHeaderExtensions = -{ - mid?: number; - rid?: number; - rrid?: number; - absSendTime?: number; - transportWideCc01?: number; +type RecvRtpHeaderExtensions = { + mid?: number; + rid?: number; + rrid?: number; + absSendTime?: number; + transportWideCc01?: number; }; const logger = new Logger('Transport'); -export class Transport - - extends EnhancedEventEmitter -{ + ObserverEvents extends TransportObserverEvents = TransportObserverEvents, +> extends EnhancedEventEmitter { // Internal data. protected readonly internal: TransportInternal; @@ -318,11 +308,14 @@ export class Transport readonly #getRouterRtpCapabilities: () => RtpCapabilities; // Method to retrieve a Producer. - protected readonly getProducerById: (producerId: string) => Producer | undefined; + protected readonly getProducerById: ( + producerId: string, + ) => Producer | undefined; // Method to retrieve a DataProducer. - protected readonly getDataProducerById: - (dataProducerId: string) => DataProducer | undefined; + protected readonly getDataProducerById: ( + dataProducerId: string, + ) => DataProducer | undefined; // Producers map. readonly #producers: Map = new Map(); @@ -355,18 +348,15 @@ export class Transport * @private * @interface */ - constructor( - { - internal, - data, - channel, - appData, - getRouterRtpCapabilities, - getProducerById, - getDataProducerById - }: TransportConstructorOptions - ) - { + constructor({ + internal, + data, + channel, + appData, + getRouterRtpCapabilities, + getProducerById, + getDataProducerById, + }: TransportConstructorOptions) { super(); logger.debug('constructor()'); @@ -374,7 +364,7 @@ export class Transport this.internal = internal; this.#data = data; this.channel = channel; - this.#appData = appData || {} as TransportAppData; + this.#appData = appData || ({} as TransportAppData); this.#getRouterRtpCapabilities = getRouterRtpCapabilities; this.getProducerById = getProducerById; this.getDataProducerById = getDataProducerById; @@ -383,40 +373,35 @@ export class Transport /** * Transport id. */ - get id(): string - { + get id(): string { return this.internal.transportId; } /** * Whether the Transport is closed. */ - get closed(): boolean - { + get closed(): boolean { return this.#closed; } /** * App custom data. */ - get appData(): TransportAppData - { + get appData(): TransportAppData { return this.#appData; } /** * App custom data setter. */ - set appData(appData: TransportAppData) - { + set appData(appData: TransportAppData) { this.#appData = appData; } /** * Observer. */ - get observer(): EnhancedEventEmitter - { + get observer(): EnhancedEventEmitter { return this.#observer; } @@ -424,18 +409,15 @@ export class Transport * @private * Just for testing purposes. */ - get channelForTesting(): Channel - { + get channelForTesting(): Channel { return this.channel; } /** * Close the Transport. */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -448,19 +430,20 @@ export class Transport /* Build Request. */ const requestOffset = new FbsRouter.CloseTransportRequestT( - this.internal.transportId + this.internal.transportId, ).pack(this.channel.bufferBuilder); - this.channel.request( - FbsRequest.Method.ROUTER_CLOSE_TRANSPORT, - FbsRequest.Body.Router_CloseTransportRequest, - requestOffset, - this.internal.routerId - ).catch(() => {}); + this.channel + .request( + FbsRequest.Method.ROUTER_CLOSE_TRANSPORT, + FbsRequest.Body.Router_CloseTransportRequest, + requestOffset, + this.internal.routerId, + ) + .catch(() => {}); // Close every Producer. - for (const producer of this.#producers.values()) - { + for (const producer of this.#producers.values()) { producer.transportClosed(); // Must tell the Router. @@ -469,15 +452,13 @@ export class Transport this.#producers.clear(); // Close every Consumer. - for (const consumer of this.consumers.values()) - { + for (const consumer of this.consumers.values()) { consumer.transportClosed(); } this.consumers.clear(); // Close every DataProducer. - for (const dataProducer of this.dataProducers.values()) - { + for (const dataProducer of this.dataProducers.values()) { dataProducer.transportClosed(); // Must tell the Router. @@ -486,8 +467,7 @@ export class Transport this.dataProducers.clear(); // Close every DataConsumer. - for (const dataConsumer of this.dataConsumers.values()) - { + for (const dataConsumer of this.dataConsumers.values()) { dataConsumer.transportClosed(); } this.dataConsumers.clear(); @@ -504,10 +484,8 @@ export class Transport * @private * @virtual */ - routerClosed(): void - { - if (this.#closed) - { + routerClosed(): void { + if (this.#closed) { return; } @@ -519,8 +497,7 @@ export class Transport this.channel.removeAllListeners(this.internal.transportId); // Close every Producer. - for (const producer of this.#producers.values()) - { + for (const producer of this.#producers.values()) { producer.transportClosed(); // NOTE: No need to tell the Router since it already knows (it has @@ -529,15 +506,13 @@ export class Transport this.#producers.clear(); // Close every Consumer. - for (const consumer of this.consumers.values()) - { + for (const consumer of this.consumers.values()) { consumer.transportClosed(); } this.consumers.clear(); // Close every DataProducer. - for (const dataProducer of this.dataProducers.values()) - { + for (const dataProducer of this.dataProducers.values()) { dataProducer.transportClosed(); // NOTE: No need to tell the Router since it already knows (it has @@ -546,8 +521,7 @@ export class Transport this.dataProducers.clear(); // Close every DataConsumer. - for (const dataConsumer of this.dataConsumers.values()) - { + for (const dataConsumer of this.dataConsumers.values()) { dataConsumer.transportClosed(); } this.dataConsumers.clear(); @@ -564,10 +538,8 @@ export class Transport * * @private */ - listenServerClosed(): void - { - if (this.#closed) - { + listenServerClosed(): void { + if (this.#closed) { return; } @@ -579,8 +551,7 @@ export class Transport this.channel.removeAllListeners(this.internal.transportId); // Close every Producer. - for (const producer of this.#producers.values()) - { + for (const producer of this.#producers.values()) { producer.transportClosed(); // NOTE: No need to tell the Router since it already knows (it has @@ -589,15 +560,13 @@ export class Transport this.#producers.clear(); // Close every Consumer. - for (const consumer of this.consumers.values()) - { + for (const consumer of this.consumers.values()) { consumer.transportClosed(); } this.consumers.clear(); // Close every DataProducer. - for (const dataProducer of this.dataProducers.values()) - { + for (const dataProducer of this.dataProducers.values()) { dataProducer.transportClosed(); // NOTE: No need to tell the Router since it already knows (it has @@ -606,8 +575,7 @@ export class Transport this.dataProducers.clear(); // Close every DataConsumer. - for (const dataConsumer of this.dataConsumers.values()) - { + for (const dataConsumer of this.dataConsumers.values()) { dataConsumer.transportClosed(); } this.dataConsumers.clear(); @@ -628,8 +596,7 @@ export class Transport * * @abstract */ - async dump(): Promise - { + async dump(): Promise { // Should not happen. throw new Error('method implemented in the subclass'); } @@ -639,8 +606,7 @@ export class Transport * * @abstract */ - async getStats(): Promise - { + async getStats(): Promise { // Should not happen. throw new Error('method implemented in the subclass'); } @@ -651,8 +617,7 @@ export class Transport * @abstract */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - async connect(params: any): Promise - { + async connect(params: any): Promise { // Should not happen. throw new Error('method implemented in the subclass'); } @@ -660,88 +625,80 @@ export class Transport /** * Set maximum incoming bitrate for receiving media. */ - async setMaxIncomingBitrate(bitrate: number): Promise - { + async setMaxIncomingBitrate(bitrate: number): Promise { logger.debug('setMaxIncomingBitrate() [bitrate:%s]', bitrate); /* Build Request. */ - const requestOffset = FbsTransport.SetMaxIncomingBitrateRequest - .createSetMaxIncomingBitrateRequest(this.channel.bufferBuilder, bitrate); + const requestOffset = + FbsTransport.SetMaxIncomingBitrateRequest.createSetMaxIncomingBitrateRequest( + this.channel.bufferBuilder, + bitrate, + ); await this.channel.request( FbsRequest.Method.TRANSPORT_SET_MAX_INCOMING_BITRATE, FbsRequest.Body.Transport_SetMaxIncomingBitrateRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); } /** * Set maximum outgoing bitrate for sending media. */ - async setMaxOutgoingBitrate(bitrate: number): Promise - { + async setMaxOutgoingBitrate(bitrate: number): Promise { logger.debug('setMaxOutgoingBitrate() [bitrate:%s]', bitrate); /* Build Request. */ const requestOffset = new FbsTransport.SetMaxOutgoingBitrateRequestT( - bitrate + bitrate, ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.TRANSPORT_SET_MAX_OUTGOING_BITRATE, FbsRequest.Body.Transport_SetMaxOutgoingBitrateRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); } /** * Set minimum outgoing bitrate for sending media. */ - async setMinOutgoingBitrate(bitrate: number): Promise - { + async setMinOutgoingBitrate(bitrate: number): Promise { logger.debug('setMinOutgoingBitrate() [bitrate:%s]', bitrate); /* Build Request. */ const requestOffset = new FbsTransport.SetMinOutgoingBitrateRequestT( - bitrate + bitrate, ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.TRANSPORT_SET_MIN_OUTGOING_BITRATE, FbsRequest.Body.Transport_SetMinOutgoingBitrateRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); } /** * Create a Producer. */ - async produce( - { - id = undefined, - kind, - rtpParameters, - paused = false, - keyFrameRequestDelay, - appData - }: ProducerOptions - ): Promise> - { + async produce({ + id = undefined, + kind, + rtpParameters, + paused = false, + keyFrameRequestDelay, + appData, + }: ProducerOptions): Promise> { logger.debug('produce()'); - if (id && this.#producers.has(id)) - { + if (id && this.#producers.has(id)) { throw new TypeError(`a Producer with same id "${id}" already exists`); - } - else if (![ 'audio', 'video' ].includes(kind)) - { + } else if (!['audio', 'video'].includes(kind)) { throw new TypeError(`invalid kind "${kind}"`); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } @@ -756,29 +713,25 @@ export class Transport !clonedRtpParameters.encodings || !Array.isArray(clonedRtpParameters.encodings) || clonedRtpParameters.encodings.length === 0 - ) - { - clonedRtpParameters.encodings = [ {} ]; + ) { + clonedRtpParameters.encodings = [{}]; } // Don't do this in PipeTransports since there we must keep CNAME value in // each Producer. - if (this.constructor.name !== 'PipeTransport') - { + if (this.constructor.name !== 'PipeTransport') { // If CNAME is given and we don't have yet a CNAME for Producers in this // Transport, take it. if ( !this.#cnameForProducers && clonedRtpParameters.rtcp && clonedRtpParameters.rtcp.cname - ) - { + ) { this.#cnameForProducers = clonedRtpParameters.rtcp.cname; } // Otherwise if we don't have yet a CNAME for Producers and the RTP // parameters do not include CNAME, create a random one. - else if (!this.#cnameForProducers) - { + else if (!this.#cnameForProducers) { this.#cnameForProducers = utils.generateUUIDv4().substr(0, 8); } @@ -791,28 +744,34 @@ export class Transport // This may throw. const rtpMapping = ortc.getProducerRtpParametersMapping( - clonedRtpParameters, routerRtpCapabilities); + clonedRtpParameters, + routerRtpCapabilities, + ); // This may throw. const consumableRtpParameters = ortc.getConsumableRtpParameters( - kind, clonedRtpParameters, routerRtpCapabilities, rtpMapping); + kind, + clonedRtpParameters, + routerRtpCapabilities, + rtpMapping, + ); const producerId = id || utils.generateUUIDv4(); const requestOffset = createProduceRequest({ - builder : this.channel.bufferBuilder, + builder: this.channel.bufferBuilder, producerId, kind, - rtpParameters : clonedRtpParameters, + rtpParameters: clonedRtpParameters, rtpMapping, keyFrameRequestDelay, - paused + paused, }); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_PRODUCE, FbsRequest.Body.Transport_ProduceRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -822,30 +781,26 @@ export class Transport const status = produceResponse.unpack(); - const data = - { + const data = { kind, - rtpParameters : clonedRtpParameters, - type : producerTypeFromFbs(status.type), - consumableRtpParameters + rtpParameters: clonedRtpParameters, + type: producerTypeFromFbs(status.type), + consumableRtpParameters, }; - const producer = new Producer( - { - internal : - { - ...this.internal, - producerId - }, - data, - channel : this.channel, - appData, - paused - }); + const producer = new Producer({ + internal: { + ...this.internal, + producerId, + }, + data, + channel: this.channel, + appData, + paused, + }); this.#producers.set(producer.id, producer); - producer.on('@close', () => - { + producer.on('@close', () => { this.#producers.delete(producer.id); this.emit('@producerclose', producer); }); @@ -863,32 +818,24 @@ export class Transport * * @virtual */ - async consume( - { - producerId, - rtpCapabilities, - paused = false, - mid, - preferredLayers, - ignoreDtx = false, - enableRtx, - pipe = false, - appData - }: ConsumerOptions - ): Promise> - { + async consume({ + producerId, + rtpCapabilities, + paused = false, + mid, + preferredLayers, + ignoreDtx = false, + enableRtx, + pipe = false, + appData, + }: ConsumerOptions): Promise> { logger.debug('consume()'); - if (!producerId || typeof producerId !== 'string') - { + if (!producerId || typeof producerId !== 'string') { throw new TypeError('missing producerId'); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); - } - else if (mid && (typeof mid !== 'string' || mid.length === 0)) - { + } else if (mid && (typeof mid !== 'string' || mid.length === 0)) { throw new TypeError('if given, mid must be non empty string'); } @@ -900,43 +847,35 @@ export class Transport const producer = this.getProducerById(producerId); - if (!producer) - { + if (!producer) { throw Error(`Producer with id "${producerId}" not found`); } // If enableRtx is not given, set it to true if video and false if audio. - if (enableRtx === undefined) - { + if (enableRtx === undefined) { enableRtx = producer.kind === 'video'; } // This may throw. - const rtpParameters = ortc.getConsumerRtpParameters( - { - consumableRtpParameters : producer.consumableRtpParameters, - remoteRtpCapabilities : clonedRtpCapabilities, - pipe, - enableRtx - } - ); + const rtpParameters = ortc.getConsumerRtpParameters({ + consumableRtpParameters: producer.consumableRtpParameters, + remoteRtpCapabilities: clonedRtpCapabilities, + pipe, + enableRtx, + }); // Set MID. - if (!pipe) - { - if (mid) - { + if (!pipe) { + if (mid) { rtpParameters.mid = mid; - } - else - { + } else { rtpParameters.mid = `${this.#nextMidForConsumers++}`; // We use up to 8 bytes for MID (string). - if (this.#nextMidForConsumers === 100000000) - { + if (this.#nextMidForConsumers === 100000000) { logger.error( - `consume() | reaching max MID value "${this.#nextMidForConsumers}"`); + `consume() | reaching max MID value "${this.#nextMidForConsumers}"`, + ); this.#nextMidForConsumers = 0; } @@ -945,21 +884,21 @@ export class Transport const consumerId = utils.generateUUIDv4(); const requestOffset = createConsumeRequest({ - builder : this.channel.bufferBuilder, + builder: this.channel.bufferBuilder, producer, consumerId, rtpParameters, paused, preferredLayers, ignoreDtx, - pipe + pipe, }); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_CONSUME, FbsRequest.Body.Transport_ConsumeRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -969,36 +908,34 @@ export class Transport const status = consumeResponse.unpack(); - const data = - { + const data = { producerId, - kind : producer.kind, + kind: producer.kind, rtpParameters, - type : pipe ? 'pipe' : producer.type as ConsumerType + type: pipe ? 'pipe' : (producer.type as ConsumerType), }; - const consumer = new Consumer( - { - internal : - { - ...this.internal, - consumerId - }, - data, - channel : this.channel, - appData, - paused : status.paused, - producerPaused : status.producerPaused, - score : status.score ?? undefined, - preferredLayers : status.preferredLayers ? - { - spatialLayer : status.preferredLayers.spatialLayer, - temporalLayer : status.preferredLayers.temporalLayer !== null ? - status.preferredLayers.temporalLayer : - undefined - } : - undefined - }); + const consumer = new Consumer({ + internal: { + ...this.internal, + consumerId, + }, + data, + channel: this.channel, + appData, + paused: status.paused, + producerPaused: status.producerPaused, + score: status.score ?? undefined, + preferredLayers: status.preferredLayers + ? { + spatialLayer: status.preferredLayers.spatialLayer, + temporalLayer: + status.preferredLayers.temporalLayer !== null + ? status.preferredLayers.temporalLayer + : undefined, + } + : undefined, + }); this.consumers.set(consumer.id, consumer); consumer.on('@close', () => this.consumers.delete(consumer.id)); @@ -1013,51 +950,46 @@ export class Transport /** * Create a DataProducer. */ - async produceData( - { - id = undefined, - sctpStreamParameters, - label = '', - protocol = '', - paused = false, - appData - }: DataProducerOptions = {} - ): Promise> - { + async produceData({ + id = undefined, + sctpStreamParameters, + label = '', + protocol = '', + paused = false, + appData, + }: DataProducerOptions = {}): Promise< + DataProducer + > { logger.debug('produceData()'); - if (id && this.dataProducers.has(id)) - { + if (id && this.dataProducers.has(id)) { throw new TypeError(`a DataProducer with same id "${id}" already exists`); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } let type: DataProducerType; // Clone given SCTP stream parameters to not modify input data. - let clonedSctpStreamParameters - = utils.clone(sctpStreamParameters); + let clonedSctpStreamParameters = utils.clone< + SctpStreamParameters | undefined + >(sctpStreamParameters); // If this is not a DirectTransport, sctpStreamParameters are required. - if (this.constructor.name !== 'DirectTransport') - { + if (this.constructor.name !== 'DirectTransport') { type = 'sctp'; // This may throw. ortc.validateSctpStreamParameters(clonedSctpStreamParameters!); } // If this is a DirectTransport, sctpStreamParameters must not be given. - else - { + else { type = 'direct'; - if (sctpStreamParameters) - { + if (sctpStreamParameters) { logger.warn( - 'produceData() | sctpStreamParameters are ignored when producing data on a DirectTransport'); + 'produceData() | sctpStreamParameters are ignored when producing data on a DirectTransport', + ); clonedSctpStreamParameters = undefined; } @@ -1065,20 +997,20 @@ export class Transport const dataProducerId = id || utils.generateUUIDv4(); const requestOffset = createProduceDataRequest({ - builder : this.channel.bufferBuilder, + builder: this.channel.bufferBuilder, dataProducerId, type, - sctpStreamParameters : clonedSctpStreamParameters, + sctpStreamParameters: clonedSctpStreamParameters, label, protocol, - paused + paused, }); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_PRODUCE_DATA, FbsRequest.Body.Transport_ProduceDataRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -1088,28 +1020,24 @@ export class Transport const dump = parseDataProducerDumpResponse(produceDataResponse); - const dataProducer = new DataProducer( - { - internal : - { - ...this.internal, - dataProducerId - }, - data : - { - type : dump.type, - sctpStreamParameters : dump.sctpStreamParameters, - label : dump.label, - protocol : dump.protocol - }, - channel : this.channel, - paused, - appData - }); + const dataProducer = new DataProducer({ + internal: { + ...this.internal, + dataProducerId, + }, + data: { + type: dump.type, + sctpStreamParameters: dump.sctpStreamParameters, + label: dump.label, + protocol: dump.protocol, + }, + channel: this.channel, + paused, + appData, + }); this.dataProducers.set(dataProducer.id, dataProducer); - dataProducer.on('@close', () => - { + dataProducer.on('@close', () => { this.dataProducers.delete(dataProducer.id); this.emit('@dataproducerclose', dataProducer); }); @@ -1125,33 +1053,28 @@ export class Transport /** * Create a DataConsumer. */ - async consumeData( - { - dataProducerId, - ordered, - maxPacketLifeTime, - maxRetransmits, - paused = false, - subchannels, - appData - }: DataConsumerOptions - ): Promise> - { + async consumeData({ + dataProducerId, + ordered, + maxPacketLifeTime, + maxRetransmits, + paused = false, + subchannels, + appData, + }: DataConsumerOptions): Promise< + DataConsumer + > { logger.debug('consumeData()'); - if (!dataProducerId || typeof dataProducerId !== 'string') - { + if (!dataProducerId || typeof dataProducerId !== 'string') { throw new TypeError('missing dataProducerId'); - } - else if (appData && typeof appData !== 'object') - { + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } const dataProducer = this.getDataProducerById(dataProducerId); - if (!dataProducer) - { + if (!dataProducer) { throw Error(`DataProducer with id "${dataProducerId}" not found`); } @@ -1161,27 +1084,24 @@ export class Transport // If this is not a DirectTransport, use sctpStreamParameters from the // DataProducer (if type 'sctp') unless they are given in method parameters. - if (this.constructor.name !== 'DirectTransport') - { + if (this.constructor.name !== 'DirectTransport') { type = 'sctp'; - sctpStreamParameters = utils.clone( - dataProducer.sctpStreamParameters - ) ?? {} as SctpStreamParameters; + sctpStreamParameters = + utils.clone( + dataProducer.sctpStreamParameters, + ) ?? ({} as SctpStreamParameters); // Override if given. - if (ordered !== undefined) - { + if (ordered !== undefined) { sctpStreamParameters.ordered = ordered; } - if (maxPacketLifeTime !== undefined) - { + if (maxPacketLifeTime !== undefined) { sctpStreamParameters.maxPacketLifeTime = maxPacketLifeTime; } - if (maxRetransmits !== undefined) - { + if (maxRetransmits !== undefined) { sctpStreamParameters.maxRetransmits = maxRetransmits; } @@ -1192,18 +1112,17 @@ export class Transport sctpStreamParameters.streamId = sctpStreamId; } // If this is a DirectTransport, sctpStreamParameters must not be used. - else - { + else { type = 'direct'; if ( ordered !== undefined || maxPacketLifeTime !== undefined || maxRetransmits !== undefined - ) - { + ) { logger.warn( - 'consumeData() | ordered, maxPacketLifeTime and maxRetransmits are ignored when consuming data on a DirectTransport'); + 'consumeData() | ordered, maxPacketLifeTime and maxRetransmits are ignored when consuming data on a DirectTransport', + ); } } @@ -1211,7 +1130,7 @@ export class Transport const dataConsumerId = utils.generateUUIDv4(); const requestOffset = createConsumeDataRequest({ - builder : this.channel.bufferBuilder, + builder: this.channel.bufferBuilder, dataConsumerId, dataProducerId, type, @@ -1219,14 +1138,14 @@ export class Transport label, protocol, paused, - subchannels + subchannels, }); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_CONSUME_DATA, FbsRequest.Body.Transport_ConsumeDataRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -1236,45 +1155,38 @@ export class Transport const dump = parseDataConsumerDumpResponse(consumeDataResponse); - const dataConsumer = new DataConsumer( - { - internal : - { - ...this.internal, - dataConsumerId - }, - data : - { - dataProducerId : dump.dataProducerId, - type : dump.type, - sctpStreamParameters : dump.sctpStreamParameters, - label : dump.label, - protocol : dump.protocol, - bufferedAmountLowThreshold : dump.bufferedAmountLowThreshold - }, - channel : this.channel, - paused : dump.paused, - subchannels : dump.subchannels, - dataProducerPaused : dump.dataProducerPaused, - appData - }); + const dataConsumer = new DataConsumer({ + internal: { + ...this.internal, + dataConsumerId, + }, + data: { + dataProducerId: dump.dataProducerId, + type: dump.type, + sctpStreamParameters: dump.sctpStreamParameters, + label: dump.label, + protocol: dump.protocol, + bufferedAmountLowThreshold: dump.bufferedAmountLowThreshold, + }, + channel: this.channel, + paused: dump.paused, + subchannels: dump.subchannels, + dataProducerPaused: dump.dataProducerPaused, + appData, + }); this.dataConsumers.set(dataConsumer.id, dataConsumer); - dataConsumer.on('@close', () => - { + dataConsumer.on('@close', () => { this.dataConsumers.delete(dataConsumer.id); - if (this.#sctpStreamIds) - { + if (this.#sctpStreamIds) { this.#sctpStreamIds[sctpStreamId] = 0; } }); - dataConsumer.on('@dataproducerclose', () => - { + dataConsumer.on('@dataproducerclose', () => { this.dataConsumers.delete(dataConsumer.id); - if (this.#sctpStreamIds) - { + if (this.#sctpStreamIds) { this.#sctpStreamIds[sctpStreamId] = 0; } }); @@ -1288,72 +1200,60 @@ export class Transport /** * Enable 'trace' event. */ - async enableTraceEvent(types: TransportTraceEventType[] = []): Promise - { + async enableTraceEvent(types: TransportTraceEventType[] = []): Promise { logger.debug('enableTraceEvent()'); - if (!Array.isArray(types)) - { + if (!Array.isArray(types)) { throw new TypeError('types must be an array'); - } - else if (types.find((type) => typeof type !== 'string')) - { + } else if (types.find(type => typeof type !== 'string')) { throw new TypeError('every type must be a string'); } // Convert event types. const fbsEventTypes: FbsTransport.TraceEventType[] = []; - for (const eventType of types) - { - try - { + for (const eventType of types) { + try { fbsEventTypes.push(transportTraceEventTypeToFbs(eventType)); - } - catch (error) - { + } catch (error) { // Ignore invalid event types. } } /* Build Request. */ const requestOffset = new FbsTransport.EnableTraceEventRequestT( - fbsEventTypes + fbsEventTypes, ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.TRANSPORT_ENABLE_TRACE_EVENT, FbsRequest.Body.Transport_EnableTraceEventRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); } - private getNextSctpStreamId(): number - { + private getNextSctpStreamId(): number { if ( !this.#data.sctpParameters || typeof this.#data.sctpParameters.MIS !== 'number' - ) - { + ) { throw new TypeError('missing sctpParameters.MIS'); } const numStreams = this.#data.sctpParameters.MIS; - if (!this.#sctpStreamIds) - { + if (!this.#sctpStreamIds) { this.#sctpStreamIds = Buffer.alloc(numStreams, 0); } let sctpStreamId; - for (let idx = 0; idx < this.#sctpStreamIds.length; ++idx) - { - sctpStreamId = (this.#nextSctpStreamId + idx) % this.#sctpStreamIds.length; + for (let idx = 0; idx < this.#sctpStreamIds.length; ++idx) { + sctpStreamId = + (this.#nextSctpStreamId + idx) % this.#sctpStreamIds.length; - if (!this.#sctpStreamIds[sctpStreamId]) - { + if (!this.#sctpStreamIds[sctpStreamId]) { this.#nextSctpStreamId = sctpStreamId + 1; return sctpStreamId; @@ -1364,143 +1264,129 @@ export class Transport } } -function transportTraceEventTypeToFbs(eventType: TransportTraceEventType) - : FbsTransport.TraceEventType -{ - switch (eventType) - { - case 'probation': - { +function transportTraceEventTypeToFbs( + eventType: TransportTraceEventType, +): FbsTransport.TraceEventType { + switch (eventType) { + case 'probation': { return FbsTransport.TraceEventType.PROBATION; } - case 'bwe': - { + case 'bwe': { return FbsTransport.TraceEventType.BWE; } - default: - { + default: { throw new TypeError(`invalid TransportTraceEventType: ${eventType}`); } } } -function transportTraceEventTypeFromFbs(eventType: FbsTransport.TraceEventType) - : TransportTraceEventType -{ - switch (eventType) - { - case FbsTransport.TraceEventType.PROBATION: - { +function transportTraceEventTypeFromFbs( + eventType: FbsTransport.TraceEventType, +): TransportTraceEventType { + switch (eventType) { + case FbsTransport.TraceEventType.PROBATION: { return 'probation'; } - case FbsTransport.TraceEventType.BWE: - { + case FbsTransport.TraceEventType.BWE: { return 'bwe'; } - } } -export function parseSctpState(fbsSctpState: FbsSctpState): SctpState -{ - switch (fbsSctpState) - { - case FbsSctpState.NEW: - { +export function parseSctpState(fbsSctpState: FbsSctpState): SctpState { + switch (fbsSctpState) { + case FbsSctpState.NEW: { return 'new'; } - case FbsSctpState.CONNECTING: - { + case FbsSctpState.CONNECTING: { return 'connecting'; } - case FbsSctpState.CONNECTED: - { + case FbsSctpState.CONNECTED: { return 'connected'; } - case FbsSctpState.FAILED: - { + case FbsSctpState.FAILED: { return 'failed'; } - case FbsSctpState.CLOSED: - { + case FbsSctpState.CLOSED: { return 'closed'; } - default: - { + default: { throw new TypeError(`invalid SctpState: ${fbsSctpState}`); } } } -export function parseProtocol(protocol: FbsTransport.Protocol): TransportProtocol -{ - switch (protocol) - { - case FbsTransport.Protocol.UDP: - { +export function parseProtocol( + protocol: FbsTransport.Protocol, +): TransportProtocol { + switch (protocol) { + case FbsTransport.Protocol.UDP: { return 'udp'; } - case FbsTransport.Protocol.TCP: - { + case FbsTransport.Protocol.TCP: { return 'tcp'; } } } -export function serializeProtocol(protocol: TransportProtocol): FbsTransport.Protocol -{ - switch (protocol) - { - case 'udp': - { +export function serializeProtocol( + protocol: TransportProtocol, +): FbsTransport.Protocol { + switch (protocol) { + case 'udp': { return FbsTransport.Protocol.UDP; } - case 'tcp': - { + case 'tcp': { return FbsTransport.Protocol.TCP; } } } -export function parseTuple(binary: FbsTransport.Tuple): TransportTuple -{ +export function parseTuple(binary: FbsTransport.Tuple): TransportTuple { return { - localIp : binary.localIp()!, - localPort : binary.localPort(), - remoteIp : binary.remoteIp() ?? undefined, - remotePort : binary.remotePort(), - protocol : parseProtocol(binary.protocol()) + localIp: binary.localIp()!, + localPort: binary.localPort(), + remoteIp: binary.remoteIp() ?? undefined, + remotePort: binary.remotePort(), + protocol: parseProtocol(binary.protocol()), }; } export function parseBaseTransportDump( - binary: FbsTransport.Dump -): BaseTransportDump -{ + binary: FbsTransport.Dump, +): BaseTransportDump { // Retrieve producerIds. const producerIds = utils.parseVector(binary, 'producerIds'); // Retrieve consumerIds. const consumerIds = utils.parseVector(binary, 'consumerIds'); // Retrieve map SSRC consumerId. - const mapSsrcConsumerId = utils.parseUint32StringVector(binary, 'mapSsrcConsumerId'); + const mapSsrcConsumerId = utils.parseUint32StringVector( + binary, + 'mapSsrcConsumerId', + ); // Retrieve map RTX SSRC consumerId. - const mapRtxSsrcConsumerId = utils.parseUint32StringVector(binary, 'mapRtxSsrcConsumerId'); + const mapRtxSsrcConsumerId = utils.parseUint32StringVector( + binary, + 'mapRtxSsrcConsumerId', + ); // Retrieve dataProducerIds. const dataProducerIds = utils.parseVector(binary, 'dataProducerIds'); // Retrieve dataConsumerIds. const dataConsumerIds = utils.parseVector(binary, 'dataConsumerIds'); // Retrieve recvRtpHeaderExtesions. - const recvRtpHeaderExtensions = parseRecvRtpHeaderExtensions(binary.recvRtpHeaderExtensions()!); + const recvRtpHeaderExtensions = parseRecvRtpHeaderExtensions( + binary.recvRtpHeaderExtensions()!, + ); // Retrieve RtpListener. const rtpListener = parseRtpListenerDump(binary.rtpListener()!); @@ -1508,142 +1394,149 @@ export function parseBaseTransportDump( const fbsSctpParameters = binary.sctpParameters(); let sctpParameters: SctpParameters | undefined; - if (fbsSctpParameters) - { + if (fbsSctpParameters) { sctpParameters = parseSctpParametersDump(fbsSctpParameters); } // Retrieve sctpState. - const sctpState = binary.sctpState() === null ? undefined : parseSctpState(binary.sctpState()!); + const sctpState = + binary.sctpState() === null + ? undefined + : parseSctpState(binary.sctpState()!); // Retrive sctpListener. - const sctpListener = binary.sctpListener() ? - parseSctpListenerDump(binary.sctpListener()!) : - undefined; + const sctpListener = binary.sctpListener() + ? parseSctpListenerDump(binary.sctpListener()!) + : undefined; // Retrieve traceEventTypes. - const traceEventTypes = utils.parseVector(binary, 'traceEventTypes', transportTraceEventTypeFromFbs); + const traceEventTypes = utils.parseVector( + binary, + 'traceEventTypes', + transportTraceEventTypeFromFbs, + ); return { - id : binary.id()!, - direct : binary.direct(), - producerIds : producerIds, - consumerIds : consumerIds, - mapSsrcConsumerId : mapSsrcConsumerId, - mapRtxSsrcConsumerId : mapRtxSsrcConsumerId, - dataProducerIds : dataProducerIds, - dataConsumerIds : dataConsumerIds, - recvRtpHeaderExtensions : recvRtpHeaderExtensions, - rtpListener : rtpListener, - maxMessageSize : binary.maxMessageSize(), - sctpParameters : sctpParameters, - sctpState : sctpState, - sctpListener : sctpListener, - traceEventTypes : traceEventTypes + id: binary.id()!, + direct: binary.direct(), + producerIds: producerIds, + consumerIds: consumerIds, + mapSsrcConsumerId: mapSsrcConsumerId, + mapRtxSsrcConsumerId: mapRtxSsrcConsumerId, + dataProducerIds: dataProducerIds, + dataConsumerIds: dataConsumerIds, + recvRtpHeaderExtensions: recvRtpHeaderExtensions, + rtpListener: rtpListener, + maxMessageSize: binary.maxMessageSize(), + sctpParameters: sctpParameters, + sctpState: sctpState, + sctpListener: sctpListener, + traceEventTypes: traceEventTypes, }; } export function parseBaseTransportStats( - binary: FbsTransport.Stats -): BaseTransportStats -{ - const sctpState = binary.sctpState() === null ? undefined : parseSctpState(binary.sctpState()!); + binary: FbsTransport.Stats, +): BaseTransportStats { + const sctpState = + binary.sctpState() === null + ? undefined + : parseSctpState(binary.sctpState()!); return { - transportId : binary.transportId()!, - timestamp : Number(binary.timestamp()), + transportId: binary.transportId()!, + timestamp: Number(binary.timestamp()), sctpState, - bytesReceived : Number(binary.bytesReceived()), - recvBitrate : Number(binary.recvBitrate()), - bytesSent : Number(binary.bytesSent()), - sendBitrate : Number(binary.sendBitrate()), - rtpBytesReceived : Number(binary.rtpBytesReceived()), - rtpRecvBitrate : Number(binary.rtpRecvBitrate()), - rtpBytesSent : Number(binary.rtpBytesSent()), - rtpSendBitrate : Number(binary.rtpSendBitrate()), - rtxBytesReceived : Number(binary.rtxBytesReceived()), - rtxRecvBitrate : Number(binary.rtxRecvBitrate()), - rtxBytesSent : Number(binary.rtxBytesSent()), - rtxSendBitrate : Number(binary.rtxSendBitrate()), - probationBytesSent : Number(binary.probationBytesSent()), - probationSendBitrate : Number(binary.probationSendBitrate()), - availableOutgoingBitrate : Number(binary.availableOutgoingBitrate()), - availableIncomingBitrate : Number(binary.availableIncomingBitrate()), - maxIncomingBitrate : binary.maxIncomingBitrate() ? - Number(binary.maxIncomingBitrate()) : - undefined + bytesReceived: Number(binary.bytesReceived()), + recvBitrate: Number(binary.recvBitrate()), + bytesSent: Number(binary.bytesSent()), + sendBitrate: Number(binary.sendBitrate()), + rtpBytesReceived: Number(binary.rtpBytesReceived()), + rtpRecvBitrate: Number(binary.rtpRecvBitrate()), + rtpBytesSent: Number(binary.rtpBytesSent()), + rtpSendBitrate: Number(binary.rtpSendBitrate()), + rtxBytesReceived: Number(binary.rtxBytesReceived()), + rtxRecvBitrate: Number(binary.rtxRecvBitrate()), + rtxBytesSent: Number(binary.rtxBytesSent()), + rtxSendBitrate: Number(binary.rtxSendBitrate()), + probationBytesSent: Number(binary.probationBytesSent()), + probationSendBitrate: Number(binary.probationSendBitrate()), + availableOutgoingBitrate: Number(binary.availableOutgoingBitrate()), + availableIncomingBitrate: Number(binary.availableIncomingBitrate()), + maxIncomingBitrate: binary.maxIncomingBitrate() + ? Number(binary.maxIncomingBitrate()) + : undefined, }; } export function parseTransportTraceEventData( - trace: FbsTransport.TraceNotification -): TransportTraceEventData -{ - switch (trace.type()) - { - case FbsTransport.TraceEventType.BWE: - { + trace: FbsTransport.TraceNotification, +): TransportTraceEventData { + switch (trace.type()) { + case FbsTransport.TraceEventType.BWE: { const info = new FbsTransport.BweTraceInfo(); trace.info(info); return { - type : 'bwe', - timestamp : Number(trace.timestamp()), - direction : trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', - info : parseBweTraceInfo(info!) + type: 'bwe', + timestamp: Number(trace.timestamp()), + direction: + trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', + info: parseBweTraceInfo(info!), }; } - case FbsTransport.TraceEventType.PROBATION: - { + case FbsTransport.TraceEventType.PROBATION: { return { - type : 'probation', - timestamp : Number(trace.timestamp()), - direction : trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', - info : {} + type: 'probation', + timestamp: Number(trace.timestamp()), + direction: + trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', + info: {}, }; } } } -function parseRecvRtpHeaderExtensions(binary: FbsTransport.RecvRtpHeaderExtensions) - : RecvRtpHeaderExtensions -{ +function parseRecvRtpHeaderExtensions( + binary: FbsTransport.RecvRtpHeaderExtensions, +): RecvRtpHeaderExtensions { return { - mid : binary.mid() !== null ? binary.mid()! : undefined, - rid : binary.rid() !== null ? binary.rid()! : undefined, - rrid : binary.rrid() !== null ? binary.rrid()! : undefined, - absSendTime : binary.absSendTime() !== null ? binary.absSendTime()! : undefined, - transportWideCc01 : binary.transportWideCc01() !== null ? - binary.transportWideCc01()! : - undefined + mid: binary.mid() !== null ? binary.mid()! : undefined, + rid: binary.rid() !== null ? binary.rid()! : undefined, + rrid: binary.rrid() !== null ? binary.rrid()! : undefined, + absSendTime: + binary.absSendTime() !== null ? binary.absSendTime()! : undefined, + transportWideCc01: + binary.transportWideCc01() !== null + ? binary.transportWideCc01()! + : undefined, }; } -function parseBweTraceInfo(binary: FbsTransport.BweTraceInfo): -{ - desiredBitrate:number; - effectiveDesiredBitrate:number; - minBitrate:number; - maxBitrate:number; - startBitrate:number; - maxPaddingBitrate:number; - availableBitrate:number; - bweType:'transport-cc' | 'remb'; -} -{ +function parseBweTraceInfo(binary: FbsTransport.BweTraceInfo): { + desiredBitrate: number; + effectiveDesiredBitrate: number; + minBitrate: number; + maxBitrate: number; + startBitrate: number; + maxPaddingBitrate: number; + availableBitrate: number; + bweType: 'transport-cc' | 'remb'; +} { return { - desiredBitrate : binary.desiredBitrate(), - effectiveDesiredBitrate : binary.effectiveDesiredBitrate(), - minBitrate : binary.minBitrate(), - maxBitrate : binary.maxBitrate(), - startBitrate : binary.startBitrate(), - maxPaddingBitrate : binary.maxPaddingBitrate(), - availableBitrate : binary.availableBitrate(), - bweType : binary.bweType() === FbsTransport.BweType.TRANSPORT_CC ? - 'transport-cc' : - 'remb' + desiredBitrate: binary.desiredBitrate(), + effectiveDesiredBitrate: binary.effectiveDesiredBitrate(), + minBitrate: binary.minBitrate(), + maxBitrate: binary.maxBitrate(), + startBitrate: binary.startBitrate(), + maxPaddingBitrate: binary.maxPaddingBitrate(), + availableBitrate: binary.availableBitrate(), + bweType: + binary.bweType() === FbsTransport.BweType.TRANSPORT_CC + ? 'transport-cc' + : 'remb', }; } @@ -1655,8 +1548,8 @@ function createConsumeRequest({ paused, preferredLayers, ignoreDtx, - pipe -} : { + pipe, +}: { builder: flatbuffers.Builder; producer: Producer; consumerId: string; @@ -1665,34 +1558,36 @@ function createConsumeRequest({ preferredLayers?: ConsumerLayers; ignoreDtx?: boolean; pipe: boolean; -}): number -{ +}): number { const rtpParametersOffset = serializeRtpParameters(builder, rtpParameters); const consumerIdOffset = builder.createString(consumerId); const producerIdOffset = builder.createString(producer.id); let consumableRtpEncodingsOffset: number | undefined; let preferredLayersOffset: number | undefined; - if (producer.consumableRtpParameters.encodings) - { + if (producer.consumableRtpParameters.encodings) { consumableRtpEncodingsOffset = serializeRtpEncodingParameters( - builder, producer.consumableRtpParameters.encodings + builder, + producer.consumableRtpParameters.encodings, ); } - if (preferredLayers) - { + if (preferredLayers) { FbsConsumer.ConsumerLayers.startConsumerLayers(builder); - FbsConsumer.ConsumerLayers.addSpatialLayer(builder, preferredLayers.spatialLayer); + FbsConsumer.ConsumerLayers.addSpatialLayer( + builder, + preferredLayers.spatialLayer, + ); - if (preferredLayers.temporalLayer !== undefined) - { + if (preferredLayers.temporalLayer !== undefined) { FbsConsumer.ConsumerLayers.addTemporalLayer( - builder, preferredLayers.temporalLayer + builder, + preferredLayers.temporalLayer, ); } - preferredLayersOffset = FbsConsumer.ConsumerLayers.endConsumerLayers(builder); + preferredLayersOffset = + FbsConsumer.ConsumerLayers.endConsumerLayers(builder); } const ConsumeRequest = FbsTransport.ConsumeRequest; @@ -1702,22 +1597,25 @@ function createConsumeRequest({ ConsumeRequest.addConsumerId(builder, consumerIdOffset); ConsumeRequest.addProducerId(builder, producerIdOffset); ConsumeRequest.addKind( - builder, producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO); + builder, + producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO, + ); ConsumeRequest.addRtpParameters(builder, rtpParametersOffset); ConsumeRequest.addType( builder, - pipe ? FbsRtpParameters.Type.PIPE : producerTypeToFbs(producer.type) + pipe ? FbsRtpParameters.Type.PIPE : producerTypeToFbs(producer.type), ); - if (consumableRtpEncodingsOffset) - { - ConsumeRequest.addConsumableRtpEncodings(builder, consumableRtpEncodingsOffset); + if (consumableRtpEncodingsOffset) { + ConsumeRequest.addConsumableRtpEncodings( + builder, + consumableRtpEncodingsOffset, + ); } ConsumeRequest.addPaused(builder, paused); - if (preferredLayersOffset) - { + if (preferredLayersOffset) { ConsumeRequest.addPreferredLayers(builder, preferredLayersOffset); } @@ -1733,17 +1631,16 @@ function createProduceRequest({ rtpParameters, rtpMapping, keyFrameRequestDelay, - paused -} : { - builder : flatbuffers.Builder; + paused, +}: { + builder: flatbuffers.Builder; producerId: string; kind: MediaKind; rtpParameters: RtpParameters; rtpMapping: ortc.RtpMapping; keyFrameRequestDelay?: number; paused: boolean; -}): number -{ +}): number { const producerIdOffset = builder.createString(producerId); const rtpParametersOffset = serializeRtpParameters(builder, rtpParameters); const rtpMappingOffset = ortc.serializeRtpMapping(builder, rtpMapping); @@ -1751,10 +1648,15 @@ function createProduceRequest({ FbsTransport.ProduceRequest.startProduceRequest(builder); FbsTransport.ProduceRequest.addProducerId(builder, producerIdOffset); FbsTransport.ProduceRequest.addKind( - builder, kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO); + builder, + kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO, + ); FbsTransport.ProduceRequest.addRtpParameters(builder, rtpParametersOffset); FbsTransport.ProduceRequest.addRtpMapping(builder, rtpMappingOffset); - FbsTransport.ProduceRequest.addKeyFrameRequestDelay(builder, keyFrameRequestDelay ?? 0); + FbsTransport.ProduceRequest.addKeyFrameRequestDelay( + builder, + keyFrameRequestDelay ?? 0, + ); FbsTransport.ProduceRequest.addPaused(builder, paused); return FbsTransport.ProduceRequest.endProduceRequest(builder); @@ -1767,38 +1669,40 @@ function createProduceDataRequest({ sctpStreamParameters, label, protocol, - paused -} : { - builder : flatbuffers.Builder; + paused, +}: { + builder: flatbuffers.Builder; dataProducerId: string; type: DataProducerType; sctpStreamParameters?: SctpStreamParameters; label: string; protocol: string; paused: boolean; -}): number -{ +}): number { const dataProducerIdOffset = builder.createString(dataProducerId); const labelOffset = builder.createString(label); const protocolOffset = builder.createString(protocol); let sctpStreamParametersOffset = 0; - if (sctpStreamParameters) - { + if (sctpStreamParameters) { sctpStreamParametersOffset = serializeSctpStreamParameters( - builder, sctpStreamParameters + builder, + sctpStreamParameters, ); } FbsTransport.ProduceDataRequest.startProduceDataRequest(builder); - FbsTransport.ProduceDataRequest.addDataProducerId(builder, dataProducerIdOffset); + FbsTransport.ProduceDataRequest.addDataProducerId( + builder, + dataProducerIdOffset, + ); FbsTransport.ProduceDataRequest.addType(builder, dataProducerTypeToFbs(type)); - if (sctpStreamParametersOffset) - { + if (sctpStreamParametersOffset) { FbsTransport.ProduceDataRequest.addSctpStreamParameters( - builder, sctpStreamParametersOffset + builder, + sctpStreamParametersOffset, ); } @@ -1818,8 +1722,8 @@ function createConsumeDataRequest({ label, protocol, paused, - subchannels = [] -} : { + subchannels = [], +}: { builder: flatbuffers.Builder; dataConsumerId: string; dataProducerId: string; @@ -1829,8 +1733,7 @@ function createConsumeDataRequest({ protocol: string; paused: boolean; subchannels?: number[]; -}): number -{ +}): number { const dataConsumerIdOffset = builder.createString(dataConsumerId); const dataProducerIdOffset = builder.createString(dataProducerId); const labelOffset = builder.createString(label); @@ -1838,26 +1741,34 @@ function createConsumeDataRequest({ let sctpStreamParametersOffset = 0; - if (sctpStreamParameters) - { + if (sctpStreamParameters) { sctpStreamParametersOffset = serializeSctpStreamParameters( - builder, sctpStreamParameters + builder, + sctpStreamParameters, ); } - const subchannelsOffset = FbsTransport.ConsumeDataRequest.createSubchannelsVector( - builder, subchannels - ); + const subchannelsOffset = + FbsTransport.ConsumeDataRequest.createSubchannelsVector( + builder, + subchannels, + ); FbsTransport.ConsumeDataRequest.startConsumeDataRequest(builder); - FbsTransport.ConsumeDataRequest.addDataConsumerId(builder, dataConsumerIdOffset); - FbsTransport.ConsumeDataRequest.addDataProducerId(builder, dataProducerIdOffset); + FbsTransport.ConsumeDataRequest.addDataConsumerId( + builder, + dataConsumerIdOffset, + ); + FbsTransport.ConsumeDataRequest.addDataProducerId( + builder, + dataProducerIdOffset, + ); FbsTransport.ConsumeDataRequest.addType(builder, dataConsumerTypeToFbs(type)); - if (sctpStreamParametersOffset) - { + if (sctpStreamParametersOffset) { FbsTransport.ConsumeDataRequest.addSctpStreamParameters( - builder, sctpStreamParametersOffset + builder, + sctpStreamParametersOffset, ); } @@ -1869,8 +1780,9 @@ function createConsumeDataRequest({ return FbsTransport.ConsumeDataRequest.endConsumeDataRequest(builder); } -function parseRtpListenerDump(binary: FbsTransport.RtpListener): RtpListenerDump -{ +function parseRtpListenerDump( + binary: FbsTransport.RtpListener, +): RtpListenerDump { // Retrieve ssrcTable. const ssrcTable = utils.parseUint32StringVector(binary, 'ssrcTable'); // Retrieve midTable. @@ -1881,12 +1793,13 @@ function parseRtpListenerDump(binary: FbsTransport.RtpListener): RtpListenerDump return { ssrcTable, midTable, - ridTable + ridTable, }; } -function parseSctpListenerDump(binary: FbsTransport.SctpListener): SctpListenerDump -{ +function parseSctpListenerDump( + binary: FbsTransport.SctpListener, +): SctpListenerDump { // Retrieve streamIdTable. const streamIdTable = utils.parseUint32StringVector(binary, 'streamIdTable'); diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index abfd064c0f..c0984a47f0 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -10,17 +10,17 @@ import * as FbsWorker from './fbs/worker'; import * as FbsWebRtcServer from './fbs/web-rtc-server'; export type WebRtcServerOptions = -{ - /** - * Listen infos. - */ - listenInfos: TransportListenInfo[]; - - /** - * Custom application data. - */ - appData?: WebRtcServerAppData; -}; + { + /** + * Listen infos. + */ + listenInfos: TransportListenInfo[]; + + /** + * Custom application data. + */ + appData?: WebRtcServerAppData; + }; /** * @deprecated @@ -28,23 +28,20 @@ export type WebRtcServerOptions = */ export type WebRtcServerListenInfo = TransportListenInfo; -export type WebRtcServerEvents = -{ +export type WebRtcServerEvents = { workerclose: []; listenererror: [string, Error]; // Private events. '@close': []; }; -export type WebRtcServerObserverEvents = -{ +export type WebRtcServerObserverEvents = { close: []; webrtctransporthandled: [WebRtcTransport]; webrtctransportunhandled: [WebRtcTransport]; }; -export type WebRtcServerDump = -{ +export type WebRtcServerDump = { id: string; udpSockets: IpPort[]; tcpServers: IpPort[]; @@ -53,34 +50,30 @@ export type WebRtcServerDump = tupleHashes: TupleHash[]; }; -type IpPort = -{ +type IpPort = { ip: string; port: number; }; -type IceUserNameFragment = -{ +type IceUserNameFragment = { localIceUsernameFragment: string; webRtcTransportId: string; }; -type TupleHash = -{ +type TupleHash = { tupleHash: number; webRtcTransportId: string; }; -type WebRtcServerInternal = -{ +type WebRtcServerInternal = { webRtcServerId: string; }; const logger = new Logger('WebRtcServer'); -export class WebRtcServer - extends EnhancedEventEmitter -{ +export class WebRtcServer< + WebRtcServerAppData extends AppData = AppData, +> extends EnhancedEventEmitter { // Internal data. readonly #internal: WebRtcServerInternal; @@ -102,65 +95,56 @@ export class WebRtcServer /** * @private */ - constructor( - { - internal, - channel, - appData - }: - { - internal: WebRtcServerInternal; - channel: Channel; - appData?: WebRtcServerAppData; - } - ) - { + constructor({ + internal, + channel, + appData, + }: { + internal: WebRtcServerInternal; + channel: Channel; + appData?: WebRtcServerAppData; + }) { super(); logger.debug('constructor()'); this.#internal = internal; this.#channel = channel; - this.#appData = appData || {} as WebRtcServerAppData; + this.#appData = appData || ({} as WebRtcServerAppData); } /** * WebRtcServer id. */ - get id(): string - { + get id(): string { return this.#internal.webRtcServerId; } /** * Whether the WebRtcServer is closed. */ - get closed(): boolean - { + get closed(): boolean { return this.#closed; } /** * App custom data. */ - get appData(): WebRtcServerAppData - { + get appData(): WebRtcServerAppData { return this.#appData; } /** * App custom data setter. */ - set appData(appData: WebRtcServerAppData) - { + set appData(appData: WebRtcServerAppData) { this.#appData = appData; } /** * Observer. */ - get observer(): EnhancedEventEmitter - { + get observer(): EnhancedEventEmitter { return this.#observer; } @@ -168,18 +152,15 @@ export class WebRtcServer * @private * Just for testing purposes. */ - get webRtcTransportsForTesting(): Map - { + get webRtcTransportsForTesting(): Map { return this.#webRtcTransports; } /** * Close the WebRtcServer. */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -189,17 +170,19 @@ export class WebRtcServer // Build the request. const requestOffset = new FbsWorker.CloseWebRtcServerRequestT( - this.#internal.webRtcServerId).pack(this.#channel.bufferBuilder); - - this.#channel.request( - Method.WORKER_WEBRTCSERVER_CLOSE, - RequestBody.Worker_CloseWebRtcServerRequest, - requestOffset) + this.#internal.webRtcServerId, + ).pack(this.#channel.bufferBuilder); + + this.#channel + .request( + Method.WORKER_WEBRTCSERVER_CLOSE, + RequestBody.Worker_CloseWebRtcServerRequest, + requestOffset, + ) .catch(() => {}); // Close every WebRtcTransport. - for (const webRtcTransport of this.#webRtcTransports.values()) - { + for (const webRtcTransport of this.#webRtcTransports.values()) { webRtcTransport.listenServerClosed(); // Emit observer event. @@ -218,10 +201,8 @@ export class WebRtcServer * * @private */ - workerClosed(): void - { - if (this.#closed) - { + workerClosed(): void { + if (this.#closed) { return; } @@ -242,12 +223,15 @@ export class WebRtcServer /** * Dump WebRtcServer. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); const response = await this.#channel.request( - Method.WEBRTCSERVER_DUMP, undefined, undefined, this.#internal.webRtcServerId); + Method.WEBRTCSERVER_DUMP, + undefined, + undefined, + this.#internal.webRtcServerId, + ); /* Decode Response. */ const dump = new FbsWebRtcServer.DumpResponse(); @@ -260,15 +244,13 @@ export class WebRtcServer /** * @private */ - handleWebRtcTransport(webRtcTransport: WebRtcTransport): void - { + handleWebRtcTransport(webRtcTransport: WebRtcTransport): void { this.#webRtcTransports.set(webRtcTransport.id, webRtcTransport); // Emit observer event. this.#observer.safeEmit('webrtctransporthandled', webRtcTransport); - webRtcTransport.on('@close', () => - { + webRtcTransport.on('@close', () => { this.#webRtcTransports.delete(webRtcTransport.id); // Emit observer event. @@ -277,48 +259,42 @@ export class WebRtcServer } } -function parseIpPort(binary: FbsWebRtcServer.IpPort): IpPort -{ +function parseIpPort(binary: FbsWebRtcServer.IpPort): IpPort { return { - ip : binary.ip()!, - port : binary.port() + ip: binary.ip()!, + port: binary.port(), }; } -function parseIceUserNameFragment(binary: FbsWebRtcServer.IceUserNameFragment): IceUserNameFragment -{ +function parseIceUserNameFragment( + binary: FbsWebRtcServer.IceUserNameFragment, +): IceUserNameFragment { return { - localIceUsernameFragment : binary.localIceUsernameFragment()!, - webRtcTransportId : binary.webRtcTransportId()! + localIceUsernameFragment: binary.localIceUsernameFragment()!, + webRtcTransportId: binary.webRtcTransportId()!, }; } -function parseTupleHash(binary: FbsWebRtcServer.TupleHash): TupleHash -{ +function parseTupleHash(binary: FbsWebRtcServer.TupleHash): TupleHash { return { - tupleHash : Number(binary.tupleHash()!), - webRtcTransportId : binary.webRtcTransportId()! + tupleHash: Number(binary.tupleHash()!), + webRtcTransportId: binary.webRtcTransportId()!, }; } function parseWebRtcServerDump( - data: FbsWebRtcServer.DumpResponse -): WebRtcServerDump -{ + data: FbsWebRtcServer.DumpResponse, +): WebRtcServerDump { return { - id : data.id()!, - udpSockets : utils.parseVector( - data, 'udpSockets', parseIpPort - ), - tcpServers : utils.parseVector( - data, 'tcpServers', parseIpPort - ), - webRtcTransportIds : utils.parseVector(data, 'webRtcTransportIds'), - localIceUsernameFragments : utils.parseVector( - data, 'localIceUsernameFragments', parseIceUserNameFragment + id: data.id()!, + udpSockets: utils.parseVector(data, 'udpSockets', parseIpPort), + tcpServers: utils.parseVector(data, 'tcpServers', parseIpPort), + webRtcTransportIds: utils.parseVector(data, 'webRtcTransportIds'), + localIceUsernameFragments: utils.parseVector( + data, + 'localIceUsernameFragments', + parseIceUserNameFragment, ), - tupleHashes : utils.parseVector( - data, 'tupleHashes', parseTupleHash - ) + tupleHashes: utils.parseVector(data, 'tupleHashes', parseTupleHash), }; } diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index e822f5c5d0..2625e5e4b7 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -17,7 +17,7 @@ import { TransportEvents, TransportObserverEvents, TransportConstructorOptions, - SctpState + SctpState, } from './Transport'; import { WebRtcServer } from './WebRtcServer'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; @@ -35,19 +35,18 @@ import { IceRole as FbsIceRole } from './fbs/web-rtc-transport/ice-role'; import { IceCandidateType as FbsIceCandidateType } from './fbs/web-rtc-transport/ice-candidate-type'; import { IceCandidateTcpType as FbsIceCandidateTcpType } from './fbs/web-rtc-transport/ice-candidate-tcp-type'; -export type WebRtcTransportOptions = - WebRtcTransportOptionsBase & WebRtcTransportListen; +export type WebRtcTransportOptions< + WebRtcTransportAppData extends AppData = AppData, +> = WebRtcTransportOptionsBase & WebRtcTransportListen; -type WebRtcTransportListenIndividualListenInfo = -{ +type WebRtcTransportListenIndividualListenInfo = { /** * Listening info. */ listenInfos: TransportListenInfo[]; }; -type WebRtcTransportListenIndividualListenIp = -{ +type WebRtcTransportListenIndividualListenIp = { /** * Listening IP address or addresses in order of preference (first one is the * preferred one). @@ -61,8 +60,7 @@ type WebRtcTransportListenIndividualListenIp = port?: number; }; -type WebRtcTransportListenServer = -{ +type WebRtcTransportListenServer = { /** * Instance of WebRtcServer. */ @@ -70,12 +68,14 @@ type WebRtcTransportListenServer = }; type WebRtcTransportListen = Either< - Either, + Either< + WebRtcTransportListenIndividualListenInfo, + WebRtcTransportListenIndividualListenIp + >, WebRtcTransportListenServer >; -export type WebRtcTransportOptionsBase = -{ +export type WebRtcTransportOptionsBase = { /** * Listen in UDP. Default true. */ @@ -129,15 +129,13 @@ export type WebRtcTransportOptionsBase = appData?: WebRtcTransportAppData; }; -export type IceParameters = -{ +export type IceParameters = { usernameFragment: string; password: string; iceLite?: boolean; }; -export type IceCandidate = -{ +export type IceCandidate = { foundation: string; priority: number; ip: string; @@ -147,8 +145,7 @@ export type IceCandidate = tcpType?: IceCandidateTcpType; }; -export type DtlsParameters = -{ +export type DtlsParameters = { role?: DtlsRole; fingerprints: DtlsFingerprint[]; }; @@ -157,22 +154,31 @@ export type DtlsParameters = * The hash function algorithm (as defined in the "Hash function Textual Names" * registry initially specified in RFC 4572 Section 8). */ -export type FingerprintAlgorithm = 'sha-1'| 'sha-224'| 'sha-256'| 'sha-384'| 'sha-512'; +export type FingerprintAlgorithm = + | 'sha-1' + | 'sha-224' + | 'sha-256' + | 'sha-384' + | 'sha-512'; /** * The hash function algorithm and its corresponding certificate fingerprint * value (in lowercase hex string as expressed utilizing the syntax of * "fingerprint" in RFC 4572 Section 5). */ -export type DtlsFingerprint = -{ +export type DtlsFingerprint = { algorithm: FingerprintAlgorithm; value: string; }; export type IceRole = 'controlled' | 'controlling'; -export type IceState = 'new' | 'connected' | 'completed' | 'disconnected' | 'closed'; +export type IceState = + | 'new' + | 'connected' + | 'completed' + | 'disconnected' + | 'closed'; export type IceCandidateType = 'host'; @@ -180,10 +186,14 @@ export type IceCandidateTcpType = 'passive'; export type DtlsRole = 'auto' | 'client' | 'server'; -export type DtlsState = 'new' | 'connecting' | 'connected' | 'failed' | 'closed'; +export type DtlsState = + | 'new' + | 'connecting' + | 'connected' + | 'failed' + | 'closed'; -export type WebRtcTransportStat = BaseTransportStats & -{ +export type WebRtcTransportStat = BaseTransportStats & { type: string; iceRole: string; iceState: IceState; @@ -191,16 +201,14 @@ export type WebRtcTransportStat = BaseTransportStats & dtlsState: DtlsState; }; -export type WebRtcTransportEvents = TransportEvents & -{ +export type WebRtcTransportEvents = TransportEvents & { icestatechange: [IceState]; iceselectedtuplechange: [TransportTuple]; dtlsstatechange: [DtlsState]; sctpstatechange: [SctpState]; }; -export type WebRtcTransportObserverEvents = TransportObserverEvents & -{ +export type WebRtcTransportObserverEvents = TransportObserverEvents & { icestatechange: [IceState]; iceselectedtuplechange: [TransportTuple]; dtlsstatechange: [DtlsState]; @@ -208,13 +216,11 @@ export type WebRtcTransportObserverEvents = TransportObserverEvents & }; type WebRtcTransportConstructorOptions = - TransportConstructorOptions & - { + TransportConstructorOptions & { data: WebRtcTransportData; }; -export type WebRtcTransportData = -{ +export type WebRtcTransportData = { iceRole: 'controlled'; iceParameters: IceParameters; iceCandidates: IceCandidate[]; @@ -227,8 +233,7 @@ export type WebRtcTransportData = sctpState?: SctpState; }; -type WebRtcTransportDump = BaseTransportDump & -{ +type WebRtcTransportDump = BaseTransportDump & { iceRole: 'controlled'; iceParameters: IceParameters; iceCandidates: IceCandidate[]; @@ -241,35 +246,39 @@ type WebRtcTransportDump = BaseTransportDump & const logger = new Logger('WebRtcTransport'); -export class WebRtcTransport - extends Transport -{ +export class WebRtcTransport< + WebRtcTransportAppData extends AppData = AppData, +> extends Transport< + WebRtcTransportAppData, + WebRtcTransportEvents, + WebRtcTransportObserverEvents +> { // WebRtcTransport data. readonly #data: WebRtcTransportData; /** * @private */ - constructor(options: WebRtcTransportConstructorOptions) - { + constructor( + options: WebRtcTransportConstructorOptions, + ) { super(options); logger.debug('constructor()'); const { data } = options; - this.#data = - { - iceRole : data.iceRole, - iceParameters : data.iceParameters, - iceCandidates : data.iceCandidates, - iceState : data.iceState, - iceSelectedTuple : data.iceSelectedTuple, - dtlsParameters : data.dtlsParameters, - dtlsState : data.dtlsState, - dtlsRemoteCert : data.dtlsRemoteCert, - sctpParameters : data.sctpParameters, - sctpState : data.sctpState + this.#data = { + iceRole: data.iceRole, + iceParameters: data.iceParameters, + iceCandidates: data.iceCandidates, + iceState: data.iceState, + iceSelectedTuple: data.iceSelectedTuple, + dtlsParameters: data.dtlsParameters, + dtlsState: data.dtlsState, + dtlsRemoteCert: data.dtlsRemoteCert, + sctpParameters: data.sctpParameters, + sctpState: data.sctpState, }; this.handleWorkerNotifications(); @@ -278,80 +287,70 @@ export class WebRtcTransport /** * ICE role. */ - get iceRole(): 'controlled' - { + get iceRole(): 'controlled' { return this.#data.iceRole; } /** * ICE parameters. */ - get iceParameters(): IceParameters - { + get iceParameters(): IceParameters { return this.#data.iceParameters; } /** * ICE candidates. */ - get iceCandidates(): IceCandidate[] - { + get iceCandidates(): IceCandidate[] { return this.#data.iceCandidates; } /** * ICE state. */ - get iceState(): IceState - { + get iceState(): IceState { return this.#data.iceState; } /** * ICE selected tuple. */ - get iceSelectedTuple(): TransportTuple | undefined - { + get iceSelectedTuple(): TransportTuple | undefined { return this.#data.iceSelectedTuple; } /** * DTLS parameters. */ - get dtlsParameters(): DtlsParameters - { + get dtlsParameters(): DtlsParameters { return this.#data.dtlsParameters; } /** * DTLS state. */ - get dtlsState(): DtlsState - { + get dtlsState(): DtlsState { return this.#data.dtlsState; } /** * Remote certificate in PEM format. */ - get dtlsRemoteCert(): string | undefined - { + get dtlsRemoteCert(): string | undefined { return this.#data.dtlsRemoteCert; } /** * SCTP parameters. */ - get sctpParameters(): SctpParameters | undefined - { + get sctpParameters(): SctpParameters | undefined { return this.#data.sctpParameters; } /** * SCTP state. */ - get sctpState(): SctpState | undefined - { + get sctpState(): SctpState | undefined { return this.#data.sctpState; } @@ -360,10 +359,8 @@ export class WebRtcTransport * * @override */ - close(): void - { - if (this.closed) - { + close(): void { + if (this.closed) { return; } @@ -371,8 +368,7 @@ export class WebRtcTransport this.#data.iceSelectedTuple = undefined; this.#data.dtlsState = 'closed'; - if (this.#data.sctpState) - { + if (this.#data.sctpState) { this.#data.sctpState = 'closed'; } @@ -385,10 +381,8 @@ export class WebRtcTransport * @private * @override */ - routerClosed(): void - { - if (this.closed) - { + routerClosed(): void { + if (this.closed) { return; } @@ -396,8 +390,7 @@ export class WebRtcTransport this.#data.iceSelectedTuple = undefined; this.#data.dtlsState = 'closed'; - if (this.#data.sctpState) - { + if (this.#data.sctpState) { this.#data.sctpState = 'closed'; } @@ -409,10 +402,8 @@ export class WebRtcTransport * * @private */ - listenServerClosed(): void - { - if (this.closed) - { + listenServerClosed(): void { + if (this.closed) { return; } @@ -420,8 +411,7 @@ export class WebRtcTransport this.#data.iceSelectedTuple = undefined; this.#data.dtlsState = 'closed'; - if (this.#data.sctpState) - { + if (this.#data.sctpState) { this.#data.sctpState = 'closed'; } @@ -431,15 +421,14 @@ export class WebRtcTransport /** * Dump Transport. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_DUMP, undefined, undefined, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -455,15 +444,14 @@ export class WebRtcTransport * * @override */ - async getStats(): Promise - { + async getStats(): Promise { logger.debug('getStats()'); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_GET_STATS, undefined, undefined, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -471,7 +459,7 @@ export class WebRtcTransport response.body(data); - return [ parseGetStatsResponse(data) ]; + return [parseGetStatsResponse(data)]; } /** @@ -479,13 +467,16 @@ export class WebRtcTransport * * @override */ - async connect({ dtlsParameters }: { dtlsParameters: DtlsParameters }): Promise - { + async connect({ + dtlsParameters, + }: { + dtlsParameters: DtlsParameters; + }): Promise { logger.debug('connect()'); const requestOffset = createConnectRequest({ - builder : this.channel.bufferBuilder, - dtlsParameters + builder: this.channel.bufferBuilder, + dtlsParameters, }); // Wait for response. @@ -493,7 +484,7 @@ export class WebRtcTransport FbsRequest.Method.WEBRTCTRANSPORT_CONNECT, FbsRequest.Body.WebRtcTransport_ConnectRequest, requestOffset, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -508,15 +499,14 @@ export class WebRtcTransport /** * Restart ICE. */ - async restartIce(): Promise - { + async restartIce(): Promise { logger.debug('restartIce()'); const response = await this.channel.request( FbsRequest.Method.TRANSPORT_RESTART_ICE, undefined, undefined, - this.internal.transportId + this.internal.transportId, ); /* Decode Response. */ @@ -524,11 +514,10 @@ export class WebRtcTransport response.body(restartIceResponse); - const iceParameters = - { - usernameFragment : restartIceResponse.usernameFragment()!, - password : restartIceResponse.password()!, - iceLite : restartIceResponse.iceLite() + const iceParameters = { + usernameFragment: restartIceResponse.usernameFragment()!, + password: restartIceResponse.password()!, + iceLite: restartIceResponse.iceLite(), }; this.#data.iceParameters = iceParameters; @@ -536,334 +525,287 @@ export class WebRtcTransport return iceParameters; } - private handleWorkerNotifications(): void - { - this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => - { - switch (event) - { - case Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE: - { - const notification = new FbsWebRtcTransport.IceStateChangeNotification(); + private handleWorkerNotifications(): void { + this.channel.on( + this.internal.transportId, + (event: Event, data?: Notification) => { + switch (event) { + case Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE: { + const notification = + new FbsWebRtcTransport.IceStateChangeNotification(); - data!.body(notification); + data!.body(notification); - const iceState = iceStateFromFbs(notification.iceState()); + const iceState = iceStateFromFbs(notification.iceState()); - this.#data.iceState = iceState; + this.#data.iceState = iceState; - this.safeEmit('icestatechange', iceState); + this.safeEmit('icestatechange', iceState); - // Emit observer event. - this.observer.safeEmit('icestatechange', iceState); + // Emit observer event. + this.observer.safeEmit('icestatechange', iceState); - break; - } + break; + } - case Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE: - { - const notification = - new FbsWebRtcTransport.IceSelectedTupleChangeNotification(); + case Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE: { + const notification = + new FbsWebRtcTransport.IceSelectedTupleChangeNotification(); - data!.body(notification); + data!.body(notification); - const iceSelectedTuple = parseTuple(notification.tuple()!); + const iceSelectedTuple = parseTuple(notification.tuple()!); - this.#data.iceSelectedTuple = iceSelectedTuple; + this.#data.iceSelectedTuple = iceSelectedTuple; - this.safeEmit('iceselectedtuplechange', iceSelectedTuple); + this.safeEmit('iceselectedtuplechange', iceSelectedTuple); - // Emit observer event. - this.observer.safeEmit('iceselectedtuplechange', iceSelectedTuple); + // Emit observer event. + this.observer.safeEmit('iceselectedtuplechange', iceSelectedTuple); - break; - } + break; + } - case Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE: - { - const notification = new FbsWebRtcTransport.DtlsStateChangeNotification(); + case Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE: { + const notification = + new FbsWebRtcTransport.DtlsStateChangeNotification(); - data!.body(notification); + data!.body(notification); - const dtlsState = dtlsStateFromFbs(notification.dtlsState()); + const dtlsState = dtlsStateFromFbs(notification.dtlsState()); - this.#data.dtlsState = dtlsState; + this.#data.dtlsState = dtlsState; - if (dtlsState === 'connected') - { - this.#data.dtlsRemoteCert = notification.remoteCert()!; - } + if (dtlsState === 'connected') { + this.#data.dtlsRemoteCert = notification.remoteCert()!; + } - this.safeEmit('dtlsstatechange', dtlsState); + this.safeEmit('dtlsstatechange', dtlsState); - // Emit observer event. - this.observer.safeEmit('dtlsstatechange', dtlsState); + // Emit observer event. + this.observer.safeEmit('dtlsstatechange', dtlsState); - break; - } + break; + } - case Event.TRANSPORT_SCTP_STATE_CHANGE: - { - const notification = new FbsTransport.SctpStateChangeNotification(); + case Event.TRANSPORT_SCTP_STATE_CHANGE: { + const notification = new FbsTransport.SctpStateChangeNotification(); - data!.body(notification); + data!.body(notification); - const sctpState = parseSctpState(notification.sctpState()); + const sctpState = parseSctpState(notification.sctpState()); - this.#data.sctpState = sctpState; + this.#data.sctpState = sctpState; - this.safeEmit('sctpstatechange', sctpState); + this.safeEmit('sctpstatechange', sctpState); - // Emit observer event. - this.observer.safeEmit('sctpstatechange', sctpState); + // Emit observer event. + this.observer.safeEmit('sctpstatechange', sctpState); - break; - } + break; + } - case Event.TRANSPORT_TRACE: - { - const notification = new FbsTransport.TraceNotification(); + case Event.TRANSPORT_TRACE: { + const notification = new FbsTransport.TraceNotification(); - data!.body(notification); + data!.body(notification); - const trace = parseTransportTraceEventData(notification); + const trace = parseTransportTraceEventData(notification); - this.safeEmit('trace', trace); + this.safeEmit('trace', trace); - // Emit observer event. - this.observer.safeEmit('trace', trace); + // Emit observer event. + this.observer.safeEmit('trace', trace); - break; - } + break; + } - default: - { - logger.error('ignoring unknown event "%s"', event); + default: { + logger.error('ignoring unknown event "%s"', event); + } } - } - }); + }, + ); } } -function iceStateFromFbs(fbsIceState: FbsIceState): IceState -{ - switch (fbsIceState) - { - case FbsIceState.NEW: - { +function iceStateFromFbs(fbsIceState: FbsIceState): IceState { + switch (fbsIceState) { + case FbsIceState.NEW: { return 'new'; } - case FbsIceState.CONNECTED: - { + case FbsIceState.CONNECTED: { return 'connected'; } - case FbsIceState.COMPLETED: - { + case FbsIceState.COMPLETED: { return 'completed'; } - case FbsIceState.DISCONNECTED: - { + case FbsIceState.DISCONNECTED: { return 'disconnected'; } } } -function iceRoleFromFbs(role: FbsIceRole): IceRole -{ - switch (role) - { - case FbsIceRole.CONTROLLED: - { +function iceRoleFromFbs(role: FbsIceRole): IceRole { + switch (role) { + case FbsIceRole.CONTROLLED: { return 'controlled'; } - case FbsIceRole.CONTROLLING: - { + case FbsIceRole.CONTROLLING: { return 'controlling'; } } } -function iceCandidateTypeFromFbs(type: FbsIceCandidateType): IceCandidateType -{ - switch (type) - { - case FbsIceCandidateType.HOST: - { +function iceCandidateTypeFromFbs(type: FbsIceCandidateType): IceCandidateType { + switch (type) { + case FbsIceCandidateType.HOST: { return 'host'; } } } -function iceCandidateTcpTypeFromFbs(type: FbsIceCandidateTcpType): IceCandidateTcpType -{ - switch (type) - { - case FbsIceCandidateTcpType.PASSIVE: - { +function iceCandidateTcpTypeFromFbs( + type: FbsIceCandidateTcpType, +): IceCandidateTcpType { + switch (type) { + case FbsIceCandidateTcpType.PASSIVE: { return 'passive'; } } } -function dtlsStateFromFbs(fbsDtlsState: FbsDtlsState): DtlsState -{ - switch (fbsDtlsState) - { - case FbsDtlsState.NEW: - { +function dtlsStateFromFbs(fbsDtlsState: FbsDtlsState): DtlsState { + switch (fbsDtlsState) { + case FbsDtlsState.NEW: { return 'new'; } - case FbsDtlsState.CONNECTING: - { + case FbsDtlsState.CONNECTING: { return 'connecting'; } - case FbsDtlsState.CONNECTED: - { + case FbsDtlsState.CONNECTED: { return 'connected'; } - case FbsDtlsState.FAILED: - { + case FbsDtlsState.FAILED: { return 'failed'; } - case FbsDtlsState.CLOSED: - { + case FbsDtlsState.CLOSED: { return 'closed'; } } } -function dtlsRoleFromFbs(role: FbsDtlsRole): DtlsRole -{ - switch (role) - { - case FbsDtlsRole.AUTO: - { +function dtlsRoleFromFbs(role: FbsDtlsRole): DtlsRole { + switch (role) { + case FbsDtlsRole.AUTO: { return 'auto'; } - case FbsDtlsRole.CLIENT: - { + case FbsDtlsRole.CLIENT: { return 'client'; } - case FbsDtlsRole.SERVER: - { + case FbsDtlsRole.SERVER: { return 'server'; } } } -function fingerprintAlgorithmsFromFbs(algorithm: FbsFingerprintAlgorithm) - : FingerprintAlgorithm -{ - switch (algorithm) - { - case FbsFingerprintAlgorithm.SHA1: - { +function fingerprintAlgorithmsFromFbs( + algorithm: FbsFingerprintAlgorithm, +): FingerprintAlgorithm { + switch (algorithm) { + case FbsFingerprintAlgorithm.SHA1: { return 'sha-1'; } - case FbsFingerprintAlgorithm.SHA224: - { + case FbsFingerprintAlgorithm.SHA224: { return 'sha-224'; } - case FbsFingerprintAlgorithm.SHA256: - { + case FbsFingerprintAlgorithm.SHA256: { return 'sha-256'; } - case FbsFingerprintAlgorithm.SHA384: - { + case FbsFingerprintAlgorithm.SHA384: { return 'sha-384'; } - case FbsFingerprintAlgorithm.SHA512: - { + case FbsFingerprintAlgorithm.SHA512: { return 'sha-512'; } } } -function fingerprintAlgorithmToFbs(algorithm: FingerprintAlgorithm) - : FbsFingerprintAlgorithm -{ - switch (algorithm) - { - case 'sha-1': - { +function fingerprintAlgorithmToFbs( + algorithm: FingerprintAlgorithm, +): FbsFingerprintAlgorithm { + switch (algorithm) { + case 'sha-1': { return FbsFingerprintAlgorithm.SHA1; } - case 'sha-224': - { + case 'sha-224': { return FbsFingerprintAlgorithm.SHA224; } - case 'sha-256': - { + case 'sha-256': { return FbsFingerprintAlgorithm.SHA256; } - case 'sha-384': - { + case 'sha-384': { return FbsFingerprintAlgorithm.SHA384; } - case 'sha-512': - { + case 'sha-512': { return FbsFingerprintAlgorithm.SHA512; } - default: - { + default: { throw new TypeError(`invalid FingerprintAlgorithm: ${algorithm}`); } } } -function dtlsRoleToFbs(role: DtlsRole): FbsDtlsRole -{ - switch (role) - { - case 'auto': - { +function dtlsRoleToFbs(role: DtlsRole): FbsDtlsRole { + switch (role) { + case 'auto': { return FbsDtlsRole.AUTO; } - case 'client': - { + case 'client': { return FbsDtlsRole.CLIENT; } - case 'server': - { + case 'server': { return FbsDtlsRole.SERVER; } - default: - { + default: { throw new TypeError(`invalid DtlsRole: ${role}`); } } } export function parseWebRtcTransportDumpResponse( - binary: FbsWebRtcTransport.DumpResponse -): WebRtcTransportDump -{ + binary: FbsWebRtcTransport.DumpResponse, +): WebRtcTransportDump { // Retrieve BaseTransportDump. const baseTransportDump = parseBaseTransportDump(binary.base()!); // Retrieve ICE candidates. - const iceCandidates = parseVector(binary, 'iceCandidates', parseIceCandidate); + const iceCandidates = parseVector( + binary, + 'iceCandidates', + parseIceCandidate, + ); // Retrieve ICE parameters. const iceParameters = parseIceParameters(binary.iceParameters()!); // Retrieve DTLS parameters. @@ -871,114 +813,112 @@ export function parseWebRtcTransportDumpResponse( return { ...baseTransportDump, - sctpParameters : baseTransportDump.sctpParameters, - sctpState : baseTransportDump.sctpState, - iceRole : 'controlled', - iceParameters : iceParameters, - iceCandidates : iceCandidates, - iceState : iceStateFromFbs(binary.iceState()), - dtlsParameters : dtlsParameters, - dtlsState : dtlsStateFromFbs(binary.dtlsState()) + sctpParameters: baseTransportDump.sctpParameters, + sctpState: baseTransportDump.sctpState, + iceRole: 'controlled', + iceParameters: iceParameters, + iceCandidates: iceCandidates, + iceState: iceStateFromFbs(binary.iceState()), + dtlsParameters: dtlsParameters, + dtlsState: dtlsStateFromFbs(binary.dtlsState()), }; } -function createConnectRequest( - { - builder, - dtlsParameters - }: - { - builder : flatbuffers.Builder; - dtlsParameters: DtlsParameters; - } -): number -{ +function createConnectRequest({ + builder, + dtlsParameters, +}: { + builder: flatbuffers.Builder; + dtlsParameters: DtlsParameters; +}): number { // Serialize DtlsParameters. This can throw. const dtlsParametersOffset = serializeDtlsParameters(builder, dtlsParameters); // Create request. return FbsWebRtcTransport.ConnectRequest.createConnectRequest( builder, - dtlsParametersOffset + dtlsParametersOffset, ); } function parseGetStatsResponse( - binary: FbsWebRtcTransport.GetStatsResponse -):WebRtcTransportStat -{ + binary: FbsWebRtcTransport.GetStatsResponse, +): WebRtcTransportStat { const base = parseBaseTransportStats(binary.base()!); return { ...base, - type : 'webrtc-transport', - iceRole : iceRoleFromFbs(binary.iceRole()), - iceState : iceStateFromFbs(binary.iceState()), - iceSelectedTuple : binary.iceSelectedTuple() ? - parseTuple(binary.iceSelectedTuple()!) : - undefined, - dtlsState : dtlsStateFromFbs(binary.dtlsState()) + type: 'webrtc-transport', + iceRole: iceRoleFromFbs(binary.iceRole()), + iceState: iceStateFromFbs(binary.iceState()), + iceSelectedTuple: binary.iceSelectedTuple() + ? parseTuple(binary.iceSelectedTuple()!) + : undefined, + dtlsState: dtlsStateFromFbs(binary.dtlsState()), }; } -function parseIceCandidate(binary: FbsWebRtcTransport.IceCandidate): IceCandidate -{ +function parseIceCandidate( + binary: FbsWebRtcTransport.IceCandidate, +): IceCandidate { return { - foundation : binary.foundation()!, - priority : binary.priority(), - ip : binary.ip()!, - protocol : parseProtocol(binary.protocol()), - port : binary.port(), - type : iceCandidateTypeFromFbs(binary.type()), - tcpType : binary.tcpType() === null ? - undefined : - iceCandidateTcpTypeFromFbs(binary.tcpType()!) + foundation: binary.foundation()!, + priority: binary.priority(), + ip: binary.ip()!, + protocol: parseProtocol(binary.protocol()), + port: binary.port(), + type: iceCandidateTypeFromFbs(binary.type()), + tcpType: + binary.tcpType() === null + ? undefined + : iceCandidateTcpTypeFromFbs(binary.tcpType()!), }; } -function parseIceParameters(binary: FbsWebRtcTransport.IceParameters): IceParameters -{ +function parseIceParameters( + binary: FbsWebRtcTransport.IceParameters, +): IceParameters { return { - usernameFragment : binary.usernameFragment()!, - password : binary.password()!, - iceLite : binary.iceLite() + usernameFragment: binary.usernameFragment()!, + password: binary.password()!, + iceLite: binary.iceLite(), }; } -function parseDtlsParameters(binary: FbsWebRtcTransport.DtlsParameters): DtlsParameters -{ +function parseDtlsParameters( + binary: FbsWebRtcTransport.DtlsParameters, +): DtlsParameters { const fingerprints: DtlsFingerprint[] = []; - for (let i = 0; i < binary.fingerprintsLength(); ++i) - { + for (let i = 0; i < binary.fingerprintsLength(); ++i) { const fbsFingerprint = binary.fingerprints(i)!; - const fingerPrint : DtlsFingerprint = - { - algorithm : fingerprintAlgorithmsFromFbs(fbsFingerprint.algorithm()), - value : fbsFingerprint.value()! + const fingerPrint: DtlsFingerprint = { + algorithm: fingerprintAlgorithmsFromFbs(fbsFingerprint.algorithm()), + value: fbsFingerprint.value()!, }; fingerprints.push(fingerPrint); } return { - fingerprints : fingerprints, - role : binary.role() === null ? undefined : dtlsRoleFromFbs(binary.role()!) + fingerprints: fingerprints, + role: binary.role() === null ? undefined : dtlsRoleFromFbs(binary.role()!), }; } function serializeDtlsParameters( - builder: flatbuffers.Builder, dtlsParameters: DtlsParameters -): number -{ + builder: flatbuffers.Builder, + dtlsParameters: DtlsParameters, +): number { const fingerprints: number[] = []; - for (const fingerprint of dtlsParameters.fingerprints) - { + for (const fingerprint of dtlsParameters.fingerprints) { const algorithm = fingerprintAlgorithmToFbs(fingerprint.algorithm); const valueOffset = builder.createString(fingerprint.value); const fingerprintOffset = FbsWebRtcTransport.Fingerprint.createFingerprint( - builder, algorithm, valueOffset + builder, + algorithm, + valueOffset, ); fingerprints.push(fingerprintOffset); @@ -986,16 +926,18 @@ function serializeDtlsParameters( const fingerprintsOffset = FbsWebRtcTransport.DtlsParameters.createFingerprintsVector( - builder, fingerprints + builder, + fingerprints, ); - const role = dtlsParameters.role !== undefined ? - dtlsRoleToFbs(dtlsParameters.role) : - FbsWebRtcTransport.DtlsRole.AUTO; + const role = + dtlsParameters.role !== undefined + ? dtlsRoleToFbs(dtlsParameters.role) + : FbsWebRtcTransport.DtlsRole.AUTO; return FbsWebRtcTransport.DtlsParameters.createDtlsParameters( builder, fingerprintsOffset, - role + role, ); } diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 56a6d7c813..ab05ef7ccb 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -20,22 +20,21 @@ import { Protocol as FbsTransportProtocol } from './fbs/transport/protocol'; export type WorkerLogLevel = 'debug' | 'warn' | 'error' | 'none'; export type WorkerLogTag = - | 'info' - | 'ice' - | 'dtls' - | 'rtp' - | 'srtp' - | 'rtcp' - | 'rtx' - | 'bwe' - | 'score' - | 'simulcast' - | 'svc' - | 'sctp' - | 'message'; - -export type WorkerSettings = -{ + | 'info' + | 'ice' + | 'dtls' + | 'rtp' + | 'srtp' + | 'rtcp' + | 'rtx' + | 'bwe' + | 'score' + | 'simulcast' + | 'svc' + | 'sctp' + | 'message'; + +export type WorkerSettings = { /** * Logging level for logs generated by the media worker subprocesses (check * the Debugging documentation). Valid values are 'debug', 'warn', 'error' and @@ -87,8 +86,10 @@ export type WorkerSettings = appData?: WorkerAppData; }; -export type WorkerUpdateableSettings = - Pick, 'logLevel' | 'logTags'>; +export type WorkerUpdateableSettings = Pick< + WorkerSettings, + 'logLevel' | 'logTags' +>; /** * An object with the fields of the uv_rusage_t struct. @@ -96,8 +97,7 @@ export type WorkerUpdateableSettings = * - http://docs.libuv.org/en/v1.x/misc.html#c.uv_rusage_t * - https://linux.die.net/man/2/getrusage */ -export type WorkerResourceUsage = -{ +export type WorkerResourceUsage = { /* eslint-disable camelcase */ /** @@ -183,26 +183,22 @@ export type WorkerResourceUsage = /* eslint-enable camelcase */ }; -export type WorkerDump = -{ - pid : number; - webRtcServerIds : string[]; - routerIds : string[]; - channelMessageHandlers : - { - channelRequestHandlers : string[]; - channelNotificationHandlers : string[]; +export type WorkerDump = { + pid: number; + webRtcServerIds: string[]; + routerIds: string[]; + channelMessageHandlers: { + channelRequestHandlers: string[]; + channelNotificationHandlers: string[]; }; - liburing? : - { + liburing?: { sqeProcessCount: number; sqeMissCount: number; userDataMissCount: number; }; }; -export type WorkerEvents = -{ +export type WorkerEvents = { died: [Error]; listenererror: [string, Error]; // Private events. @@ -210,8 +206,7 @@ export type WorkerEvents = '@failure': [Error]; }; -export type WorkerObserverEvents = -{ +export type WorkerObserverEvents = { close: []; newwebrtcserver: [WebRtcServer]; newrouter: [Router]; @@ -223,15 +218,31 @@ export type WorkerObserverEvents = export const workerBin = process.env.MEDIASOUP_WORKER_BIN ? process.env.MEDIASOUP_WORKER_BIN : process.env.MEDIASOUP_BUILDTYPE === 'Debug' - ? path.join(__dirname, '..', '..', 'worker', 'out', 'Debug', 'mediasoup-worker') - : path.join(__dirname, '..', '..', 'worker', 'out', 'Release', 'mediasoup-worker'); + ? path.join( + __dirname, + '..', + '..', + 'worker', + 'out', + 'Debug', + 'mediasoup-worker', + ) + : path.join( + __dirname, + '..', + '..', + 'worker', + 'out', + 'Release', + 'mediasoup-worker', + ); const logger = new Logger('Worker'); const workerLogger = new Logger('Worker'); -export class Worker - extends EnhancedEventEmitter -{ +export class Worker< + WorkerAppData extends AppData = AppData, +> extends EnhancedEventEmitter { // mediasoup-worker child process. #child?: ChildProcess; @@ -262,18 +273,16 @@ export class Worker /** * @private */ - constructor( - { - logLevel, - logTags, - rtcMinPort, - rtcMaxPort, - dtlsCertificateFile, - dtlsPrivateKeyFile, - libwebrtcFieldTrials, - appData - }: WorkerSettings) - { + constructor({ + logLevel, + logTags, + rtcMinPort, + rtcMaxPort, + dtlsCertificateFile, + dtlsPrivateKeyFile, + libwebrtcFieldTrials, + appData, + }: WorkerSettings) { super(); logger.debug('constructor()'); @@ -281,58 +290,53 @@ export class Worker let spawnBin = workerBin; let spawnArgs: string[] = []; - if (process.env.MEDIASOUP_USE_VALGRIND === 'true') - { + if (process.env.MEDIASOUP_USE_VALGRIND === 'true') { spawnBin = process.env.MEDIASOUP_VALGRIND_BIN || 'valgrind'; - if (process.env.MEDIASOUP_VALGRIND_OPTIONS) - { - spawnArgs = spawnArgs.concat(process.env.MEDIASOUP_VALGRIND_OPTIONS.split(/\s+/)); + if (process.env.MEDIASOUP_VALGRIND_OPTIONS) { + spawnArgs = spawnArgs.concat( + process.env.MEDIASOUP_VALGRIND_OPTIONS.split(/\s+/), + ); } spawnArgs.push(workerBin); } - if (typeof logLevel === 'string' && logLevel) - { + if (typeof logLevel === 'string' && logLevel) { spawnArgs.push(`--logLevel=${logLevel}`); } - for (const logTag of (Array.isArray(logTags) ? logTags : [])) - { - if (typeof logTag === 'string' && logTag) - { + for (const logTag of Array.isArray(logTags) ? logTags : []) { + if (typeof logTag === 'string' && logTag) { spawnArgs.push(`--logTag=${logTag}`); } } - if (typeof rtcMinPort === 'number' && !Number.isNaN(rtcMinPort)) - { + if (typeof rtcMinPort === 'number' && !Number.isNaN(rtcMinPort)) { spawnArgs.push(`--rtcMinPort=${rtcMinPort}`); } - if (typeof rtcMaxPort === 'number' && !Number.isNaN(rtcMaxPort)) - { + if (typeof rtcMaxPort === 'number' && !Number.isNaN(rtcMaxPort)) { spawnArgs.push(`--rtcMaxPort=${rtcMaxPort}`); } - if (typeof dtlsCertificateFile === 'string' && dtlsCertificateFile) - { + if (typeof dtlsCertificateFile === 'string' && dtlsCertificateFile) { spawnArgs.push(`--dtlsCertificateFile=${dtlsCertificateFile}`); } - if (typeof dtlsPrivateKeyFile === 'string' && dtlsPrivateKeyFile) - { + if (typeof dtlsPrivateKeyFile === 'string' && dtlsPrivateKeyFile) { spawnArgs.push(`--dtlsPrivateKeyFile=${dtlsPrivateKeyFile}`); } - if (typeof libwebrtcFieldTrials === 'string' && libwebrtcFieldTrials) - { + if (typeof libwebrtcFieldTrials === 'string' && libwebrtcFieldTrials) { spawnArgs.push(`--libwebrtcFieldTrials=${libwebrtcFieldTrials}`); } logger.debug( - 'spawning worker process: %s %s', spawnBin, spawnArgs.join(' ')); + 'spawning worker process: %s %s', + spawnBin, + spawnArgs.join(' '), + ); this.#child = spawn( // command @@ -341,44 +345,41 @@ export class Worker spawnArgs, // options { - env : - { - MEDIASOUP_VERSION : version, + env: { + MEDIASOUP_VERSION: version, // Let the worker process inherit all environment variables, useful // if a custom and not in the path GCC is used so the user can set // LD_LIBRARY_PATH environment variable for runtime. - ...process.env + ...process.env, }, - detached : false, + detached: false, // fd 0 (stdin) : Just ignore it. // fd 1 (stdout) : Pipe it for 3rd libraries that log their own stuff. // fd 2 (stderr) : Same as stdout. // fd 3 (channel) : Producer Channel fd. // fd 4 (channel) : Consumer Channel fd. - stdio : [ 'ignore', 'pipe', 'pipe', 'pipe', 'pipe' ], - windowsHide : true - }); + stdio: ['ignore', 'pipe', 'pipe', 'pipe', 'pipe'], + windowsHide: true, + }, + ); this.#pid = this.#child.pid!; - this.#channel = new Channel( - { - producerSocket : this.#child.stdio[3], - consumerSocket : this.#child.stdio[4], - pid : this.#pid - }); + this.#channel = new Channel({ + producerSocket: this.#child.stdio[3], + consumerSocket: this.#child.stdio[4], + pid: this.#pid, + }); - this.#appData = appData || {} as WorkerAppData; + this.#appData = appData || ({} as WorkerAppData); let spawnDone = false; // Listen for 'running' notification. - this.#channel.once(String(this.#pid), (event: Event) => - { - if (!spawnDone && event === Event.WORKER_RUNNING) - { + this.#channel.once(String(this.#pid), (event: Event) => { + if (!spawnDone && event === Event.WORKER_RUNNING) { spawnDone = true; logger.debug('worker process running [pid:%s]', this.#pid); @@ -387,87 +388,86 @@ export class Worker } }); - this.#child.on('exit', (code, signal) => - { + this.#child.on('exit', (code, signal) => { this.#child = undefined; - if (!spawnDone) - { + if (!spawnDone) { spawnDone = true; - if (code === 42) - { + if (code === 42) { logger.error( - 'worker process failed due to wrong settings [pid:%s]', this.#pid); + 'worker process failed due to wrong settings [pid:%s]', + this.#pid, + ); this.close(); this.emit('@failure', new TypeError('wrong settings')); - } - else - { + } else { logger.error( 'worker process failed unexpectedly [pid:%s, code:%s, signal:%s]', - this.#pid, code, signal); + this.#pid, + code, + signal, + ); this.close(); this.emit( '@failure', - new Error(`[pid:${this.#pid}, code:${code}, signal:${signal}]`)); + new Error(`[pid:${this.#pid}, code:${code}, signal:${signal}]`), + ); } - } - else - { + } else { logger.error( 'worker process died unexpectedly [pid:%s, code:%s, signal:%s]', - this.#pid, code, signal); + this.#pid, + code, + signal, + ); this.workerDied( - new Error(`[pid:${this.#pid}, code:${code}, signal:${signal}]`)); + new Error(`[pid:${this.#pid}, code:${code}, signal:${signal}]`), + ); } }); - this.#child.on('error', (error) => - { + this.#child.on('error', error => { this.#child = undefined; - if (!spawnDone) - { + if (!spawnDone) { spawnDone = true; logger.error( - 'worker process failed [pid:%s]: %s', this.#pid, error.message); + 'worker process failed [pid:%s]: %s', + this.#pid, + error.message, + ); this.close(); this.emit('@failure', error); - } - else - { + } else { logger.error( - 'worker process error [pid:%s]: %s', this.#pid, error.message); + 'worker process error [pid:%s]: %s', + this.#pid, + error.message, + ); this.workerDied(error); } }); // Be ready for 3rd party worker libraries logging to stdout. - this.#child.stdout!.on('data', (buffer) => - { - for (const line of buffer.toString('utf8').split('\n')) - { - if (line) - { + this.#child.stdout!.on('data', buffer => { + for (const line of buffer.toString('utf8').split('\n')) { + if (line) { workerLogger.debug(`(stdout) ${line}`); } } }); // In case of a worker bug, mediasoup will log to stderr. - this.#child.stderr!.on('data', (buffer) => - { - for (const line of buffer.toString('utf8').split('\n')) - { - if (line) - { + this.#child.stderr!.on('data', buffer => { + for (const line of buffer.toString('utf8').split('\n')) { + if (line) { workerLogger.error(`(stderr) ${line}`); } } @@ -477,48 +477,42 @@ export class Worker /** * Worker process identifier (PID). */ - get pid(): number - { + get pid(): number { return this.#pid; } /** * Whether the Worker is closed. */ - get closed(): boolean - { + get closed(): boolean { return this.#closed; } /** * Whether the Worker died. */ - get died(): boolean - { + get died(): boolean { return this.#died; } /** * App custom data. */ - get appData(): WorkerAppData - { + get appData(): WorkerAppData { return this.#appData; } /** * App custom data setter. */ - set appData(appData: WorkerAppData) - { + set appData(appData: WorkerAppData) { this.#appData = appData; } /** * Observer. */ - get observer(): EnhancedEventEmitter - { + get observer(): EnhancedEventEmitter { return this.#observer; } @@ -526,8 +520,7 @@ export class Worker * @private * Just for testing purposes. */ - get webRtcServersForTesting(): Set - { + get webRtcServersForTesting(): Set { return this.#webRtcServers; } @@ -535,18 +528,15 @@ export class Worker * @private * Just for testing purposes. */ - get routersForTesting(): Set - { + get routersForTesting(): Set { return this.#routers; } /** * Close the Worker. */ - close(): void - { - if (this.#closed) - { + close(): void { + if (this.#closed) { return; } @@ -555,8 +545,7 @@ export class Worker this.#closed = true; // Kill the worker process. - if (this.#child) - { + if (this.#child) { // Remove event listeners but leave a fake 'error' hander to avoid // propagation. this.#child.removeAllListeners('exit'); @@ -570,15 +559,13 @@ export class Worker this.#channel.close(); // Close every Router. - for (const router of this.#routers) - { + for (const router of this.#routers) { router.workerClosed(); } this.#routers.clear(); // Close every WebRtcServer. - for (const webRtcServer of this.#webRtcServers) - { + for (const webRtcServer of this.#webRtcServers) { webRtcServer.workerClosed(); } this.#webRtcServers.clear(); @@ -590,14 +577,11 @@ export class Worker /** * Dump Worker. */ - async dump(): Promise - { + async dump(): Promise { logger.debug('dump()'); // Send the request and wait for the response. - const response = await this.#channel.request( - FbsRequest.Method.WORKER_DUMP - ); + const response = await this.#channel.request(FbsRequest.Method.WORKER_DUMP); /* Decode Response. */ const dump = new FbsWorker.DumpResponse(); @@ -610,12 +594,11 @@ export class Worker /** * Get mediasoup-worker process resource usage. */ - async getResourceUsage(): Promise - { + async getResourceUsage(): Promise { logger.debug('getResourceUsage()'); const response = await this.#channel.request( - FbsRequest.Method.WORKER_GET_RESOURCE_USAGE + FbsRequest.Method.WORKER_GET_RESOURCE_USAGE, ); /* Decode Response. */ @@ -627,22 +610,22 @@ export class Worker /* eslint-disable camelcase */ return { - ru_utime : Number(ru.ruUtime), - ru_stime : Number(ru.ruStime), - ru_maxrss : Number(ru.ruMaxrss), - ru_ixrss : Number(ru.ruIxrss), - ru_idrss : Number(ru.ruIdrss), - ru_isrss : Number(ru.ruIsrss), - ru_minflt : Number(ru.ruMinflt), - ru_majflt : Number(ru.ruMajflt), - ru_nswap : Number(ru.ruNswap), - ru_inblock : Number(ru.ruInblock), - ru_oublock : Number(ru.ruOublock), - ru_msgsnd : Number(ru.ruMsgsnd), - ru_msgrcv : Number(ru.ruMsgrcv), - ru_nsignals : Number(ru.ruNsignals), - ru_nvcsw : Number(ru.ruNvcsw), - ru_nivcsw : Number(ru.ruNivcsw) + ru_utime: Number(ru.ruUtime), + ru_stime: Number(ru.ruStime), + ru_maxrss: Number(ru.ruMaxrss), + ru_ixrss: Number(ru.ruIxrss), + ru_idrss: Number(ru.ruIdrss), + ru_isrss: Number(ru.ruIsrss), + ru_minflt: Number(ru.ruMinflt), + ru_majflt: Number(ru.ruMajflt), + ru_nswap: Number(ru.ruNswap), + ru_inblock: Number(ru.ruInblock), + ru_oublock: Number(ru.ruOublock), + ru_msgsnd: Number(ru.ruMsgsnd), + ru_msgrcv: Number(ru.ruMsgrcv), + ru_nsignals: Number(ru.ruNsignals), + ru_nvcsw: Number(ru.ruNvcsw), + ru_nivcsw: Number(ru.ruNivcsw), }; /* eslint-enable camelcase */ } @@ -650,79 +633,78 @@ export class Worker /** * Update settings. */ - async updateSettings( - { - logLevel, - logTags - }: WorkerUpdateableSettings = {} - ): Promise - { + async updateSettings({ + logLevel, + logTags, + }: WorkerUpdateableSettings = {}): Promise { logger.debug('updateSettings()'); // Build the request. - const requestOffset = new FbsWorker.UpdateSettingsRequestT(logLevel, logTags) - .pack(this.#channel.bufferBuilder); + const requestOffset = new FbsWorker.UpdateSettingsRequestT( + logLevel, + logTags, + ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.WORKER_UPDATE_SETTINGS, FbsRequest.Body.Worker_UpdateSettingsRequest, - requestOffset + requestOffset, ); } /** * Create a WebRtcServer. */ - async createWebRtcServer( - { - listenInfos, - appData - }: WebRtcServerOptions - ): Promise> - { + async createWebRtcServer({ + listenInfos, + appData, + }: WebRtcServerOptions): Promise< + WebRtcServer + > { logger.debug('createWebRtcServer()'); - if (appData && typeof appData !== 'object') - { + if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } // Build the request. const fbsListenInfos: FbsTransport.ListenInfoT[] = []; - for (const listenInfo of listenInfos) - { - fbsListenInfos.push(new FbsTransport.ListenInfoT( - listenInfo.protocol === 'udp' - ? FbsTransportProtocol.UDP - : FbsTransportProtocol.TCP, - listenInfo.ip, - listenInfo.announcedIp, - listenInfo.port, - socketFlagsToFbs(listenInfo.flags), - listenInfo.sendBufferSize, - listenInfo.recvBufferSize) + for (const listenInfo of listenInfos) { + fbsListenInfos.push( + new FbsTransport.ListenInfoT( + listenInfo.protocol === 'udp' + ? FbsTransportProtocol.UDP + : FbsTransportProtocol.TCP, + listenInfo.ip, + listenInfo.announcedIp, + listenInfo.port, + socketFlagsToFbs(listenInfo.flags), + listenInfo.sendBufferSize, + listenInfo.recvBufferSize, + ), ); } const webRtcServerId = utils.generateUUIDv4(); - const createWebRtcServerRequestOffset = new FbsWorker.CreateWebRtcServerRequestT( - webRtcServerId, fbsListenInfos - ).pack(this.#channel.bufferBuilder); + const createWebRtcServerRequestOffset = + new FbsWorker.CreateWebRtcServerRequestT( + webRtcServerId, + fbsListenInfos, + ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.WORKER_CREATE_WEBRTCSERVER, FbsRequest.Body.Worker_CreateWebRtcServerRequest, - createWebRtcServerRequestOffset + createWebRtcServerRequestOffset, ); - const webRtcServer = new WebRtcServer( - { - internal : { webRtcServerId }, - channel : this.#channel, - appData - }); + const webRtcServer = new WebRtcServer({ + internal: { webRtcServerId }, + channel: this.#channel, + appData, + }); this.#webRtcServers.add(webRtcServer); webRtcServer.on('@close', () => this.#webRtcServers.delete(webRtcServer)); @@ -736,46 +718,47 @@ export class Worker /** * Create a Router. */ - async createRouter( - { - mediaCodecs, - appData - }: RouterOptions = {}): Promise> - { + async createRouter({ + mediaCodecs, + appData, + }: RouterOptions = {}): Promise> { logger.debug('createRouter()'); - if (appData && typeof appData !== 'object') - { + if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } // Clone given media codecs to not modify input data. - const clonedMediaCodecs = - utils.clone(mediaCodecs); + const clonedMediaCodecs = utils.clone( + mediaCodecs, + ); // This may throw. - const rtpCapabilities = ortc.generateRouterRtpCapabilities(clonedMediaCodecs); + const rtpCapabilities = + ortc.generateRouterRtpCapabilities(clonedMediaCodecs); const routerId = utils.generateUUIDv4(); // Get flatbuffer builder. - const createRouterRequestOffset = - new FbsWorker.CreateRouterRequestT(routerId).pack(this.#channel.bufferBuilder); + const createRouterRequestOffset = new FbsWorker.CreateRouterRequestT( + routerId, + ).pack(this.#channel.bufferBuilder); - await this.#channel.request(FbsRequest.Method.WORKER_CREATE_ROUTER, - FbsRequest.Body.Worker_CreateRouterRequest, createRouterRequestOffset); + await this.#channel.request( + FbsRequest.Method.WORKER_CREATE_ROUTER, + FbsRequest.Body.Worker_CreateRouterRequest, + createRouterRequestOffset, + ); const data = { rtpCapabilities }; - const router = new Router( - { - internal : - { - routerId - }, - data, - channel : this.#channel, - appData - }); + const router = new Router({ + internal: { + routerId, + }, + data, + channel: this.#channel, + appData, + }); this.#routers.add(router); router.on('@close', () => this.#routers.delete(router)); @@ -786,10 +769,8 @@ export class Worker return router; } - private workerDied(error: Error): void - { - if (this.#closed) - { + private workerDied(error: Error): void { + if (this.#closed) { return; } @@ -802,15 +783,13 @@ export class Worker this.#channel.close(); // Close every Router. - for (const router of this.#routers) - { + for (const router of this.#routers) { router.workerClosed(); } this.#routers.clear(); // Close every WebRtcServer. - for (const webRtcServer of this.#webRtcServers) - { + for (const webRtcServer of this.#webRtcServers) { webRtcServer.workerClosed(); } this.#webRtcServers.clear(); @@ -823,27 +802,29 @@ export class Worker } export function parseWorkerDumpResponse( - binary: FbsWorker.DumpResponse -): WorkerDump -{ + binary: FbsWorker.DumpResponse, +): WorkerDump { const dump: WorkerDump = { - pid : binary.pid()!, - webRtcServerIds : utils.parseVector(binary, 'webRtcServerIds'), - routerIds : utils.parseVector(binary, 'routerIds'), - channelMessageHandlers : - { - channelRequestHandlers : utils.parseVector(binary.channelMessageHandlers()!, 'channelRequestHandlers'), - channelNotificationHandlers : utils.parseVector(binary.channelMessageHandlers()!, 'channelNotificationHandlers') - } + pid: binary.pid()!, + webRtcServerIds: utils.parseVector(binary, 'webRtcServerIds'), + routerIds: utils.parseVector(binary, 'routerIds'), + channelMessageHandlers: { + channelRequestHandlers: utils.parseVector( + binary.channelMessageHandlers()!, + 'channelRequestHandlers', + ), + channelNotificationHandlers: utils.parseVector( + binary.channelMessageHandlers()!, + 'channelNotificationHandlers', + ), + }, }; - if (binary.liburing()) - { - dump.liburing = - { - sqeProcessCount : Number(binary.liburing()!.sqeProcessCount()), - sqeMissCount : Number(binary.liburing()!.sqeMissCount()), - userDataMissCount : Number(binary.liburing()!.userDataMissCount()) + if (binary.liburing()) { + dump.liburing = { + sqeProcessCount: Number(binary.liburing()!.sqeProcessCount()), + sqeMissCount: Number(binary.liburing()!.sqeMissCount()), + userDataMissCount: Number(binary.liburing()!.userDataMissCount()), }; } diff --git a/node/src/errors.ts b/node/src/errors.ts index b28eba297c..e88967ff2f 100644 --- a/node/src/errors.ts +++ b/node/src/errors.ts @@ -1,21 +1,17 @@ /** * Error indicating not support for something. */ -export class UnsupportedError extends Error -{ - constructor(message: string) - { +export class UnsupportedError extends Error { + constructor(message: string) { super(message); this.name = 'UnsupportedError'; - if (Error.hasOwnProperty('captureStackTrace')) // Just in V8. - { + if (Error.hasOwnProperty('captureStackTrace')) { + // Just in V8. Error.captureStackTrace(this, UnsupportedError); - } - else - { - this.stack = (new Error(message)).stack; + } else { + this.stack = new Error(message).stack; } } } @@ -23,21 +19,17 @@ export class UnsupportedError extends Error /** * Error produced when calling a method in an invalid state. */ -export class InvalidStateError extends Error -{ - constructor(message: string) - { +export class InvalidStateError extends Error { + constructor(message: string) { super(message); this.name = 'InvalidStateError'; - if (Error.hasOwnProperty('captureStackTrace')) // Just in V8. - { + if (Error.hasOwnProperty('captureStackTrace')) { + // Just in V8. Error.captureStackTrace(this, InvalidStateError); - } - else - { - this.stack = (new Error(message)).stack; + } else { + this.stack = new Error(message).stack; } } } diff --git a/node/src/index.ts b/node/src/index.ts index 08666f51f9..b2efb864b2 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -22,8 +22,7 @@ export const version: string = require('../../package.json').version; */ export { parse as parseScalabilityMode } from './scalabilityModes'; -export type ObserverEvents = -{ +export type ObserverEvents = { newworker: [Worker]; }; @@ -44,42 +43,37 @@ const logger = new Logger(); /** * Create a Worker. */ -export async function createWorker( - { - logLevel = 'error', - logTags, - rtcMinPort = 10000, - rtcMaxPort = 59999, - dtlsCertificateFile, - dtlsPrivateKeyFile, - libwebrtcFieldTrials, - appData - }: WorkerSettings = {} -): Promise> -{ +export async function createWorker< + WorkerAppData extends types.AppData = types.AppData, +>({ + logLevel = 'error', + logTags, + rtcMinPort = 10000, + rtcMaxPort = 59999, + dtlsCertificateFile, + dtlsPrivateKeyFile, + libwebrtcFieldTrials, + appData, +}: WorkerSettings = {}): Promise> { logger.debug('createWorker()'); - if (appData && typeof appData !== 'object') - { + if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } - const worker = new Worker( - { - logLevel, - logTags, - rtcMinPort, - rtcMaxPort, - dtlsCertificateFile, - dtlsPrivateKeyFile, - libwebrtcFieldTrials, - appData - }); + const worker = new Worker({ + logLevel, + logTags, + rtcMinPort, + rtcMaxPort, + dtlsCertificateFile, + dtlsPrivateKeyFile, + libwebrtcFieldTrials, + appData, + }); - return new Promise((resolve, reject) => - { - worker.on('@success', () => - { + return new Promise((resolve, reject) => { + worker.on('@success', () => { // Emit observer event. observer.safeEmit('newworker', worker); @@ -93,7 +87,6 @@ export async function createWorker(supportedRtpCapabilities); } diff --git a/node/src/ortc.ts b/node/src/ortc.ts index c36e4ba10e..0ca8640db3 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -12,23 +12,20 @@ import { RtcpFeedback, RtpEncodingParameters, RtpHeaderExtensionParameters, - RtcpParameters + RtcpParameters, } from './RtpParameters'; import { SctpStreamParameters } from './SctpParameters'; import * as utils from './utils'; import { UnsupportedError } from './errors'; import * as FbsRtpParameters from './fbs/rtp-parameters'; -export type RtpMapping = -{ - codecs: - { +export type RtpMapping = { + codecs: { payloadType: number; mappedPayloadType: number; }[]; - encodings: - { + encodings: { ssrc?: number; rid?: string; scalabilityMode?: string; @@ -36,11 +33,10 @@ export type RtpMapping = }[]; }; -const DynamicPayloadTypes = -[ - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 96, 97, 98, 99 +const DynamicPayloadTypes = [ + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 96, 97, 98, + 99, ]; /** @@ -48,40 +44,30 @@ const DynamicPayloadTypes = * fields with default values. * It throws if invalid. */ -export function validateRtpCapabilities(caps: RtpCapabilities): void -{ - if (typeof caps !== 'object') - { +export function validateRtpCapabilities(caps: RtpCapabilities): void { + if (typeof caps !== 'object') { throw new TypeError('caps is not an object'); } // codecs is optional. If unset, fill with an empty array. - if (caps.codecs && !Array.isArray(caps.codecs)) - { + if (caps.codecs && !Array.isArray(caps.codecs)) { throw new TypeError('caps.codecs is not an array'); - } - else if (!caps.codecs) - { + } else if (!caps.codecs) { caps.codecs = []; } - for (const codec of caps.codecs) - { + for (const codec of caps.codecs) { validateRtpCodecCapability(codec); } // headerExtensions is optional. If unset, fill with an empty array. - if (caps.headerExtensions && !Array.isArray(caps.headerExtensions)) - { + if (caps.headerExtensions && !Array.isArray(caps.headerExtensions)) { throw new TypeError('caps.headerExtensions is not an array'); - } - else if (!caps.headerExtensions) - { + } else if (!caps.headerExtensions) { caps.headerExtensions = []; } - for (const ext of caps.headerExtensions) - { + for (const ext of caps.headerExtensions) { validateRtpHeaderExtension(ext); } } @@ -91,67 +77,51 @@ export function validateRtpCapabilities(caps: RtpCapabilities): void * fields with default values. * It throws if invalid. */ -export function validateRtpParameters(params: RtpParameters): void -{ - if (typeof params !== 'object') - { +export function validateRtpParameters(params: RtpParameters): void { + if (typeof params !== 'object') { throw new TypeError('params is not an object'); } // mid is optional. - if (params.mid && typeof params.mid !== 'string') - { + if (params.mid && typeof params.mid !== 'string') { throw new TypeError('params.mid is not a string'); } // codecs is mandatory. - if (!Array.isArray(params.codecs)) - { + if (!Array.isArray(params.codecs)) { throw new TypeError('missing params.codecs'); } - for (const codec of params.codecs) - { + for (const codec of params.codecs) { validateRtpCodecParameters(codec); } // headerExtensions is optional. If unset, fill with an empty array. - if (params.headerExtensions && !Array.isArray(params.headerExtensions)) - { + if (params.headerExtensions && !Array.isArray(params.headerExtensions)) { throw new TypeError('params.headerExtensions is not an array'); - } - else if (!params.headerExtensions) - { + } else if (!params.headerExtensions) { params.headerExtensions = []; } - for (const ext of params.headerExtensions) - { + for (const ext of params.headerExtensions) { validateRtpHeaderExtensionParameters(ext); } // encodings is optional. If unset, fill with an empty array. - if (params.encodings && !Array.isArray(params.encodings)) - { + if (params.encodings && !Array.isArray(params.encodings)) { throw new TypeError('params.encodings is not an array'); - } - else if (!params.encodings) - { + } else if (!params.encodings) { params.encodings = []; } - for (const encoding of params.encodings) - { + for (const encoding of params.encodings) { validateRtpEncodingParameters(encoding); } // rtcp is optional. If unset, fill with an empty object. - if (params.rtcp && typeof params.rtcp !== 'object') - { + if (params.rtcp && typeof params.rtcp !== 'object') { throw new TypeError('params.rtcp is not an object'); - } - else if (!params.rtcp) - { + } else if (!params.rtcp) { params.rtcp = {}; } @@ -163,58 +133,58 @@ export function validateRtpParameters(params: RtpParameters): void * fields with default values. * It throws if invalid. */ -export function validateSctpStreamParameters(params: SctpStreamParameters): void -{ - if (typeof params !== 'object') - { +export function validateSctpStreamParameters( + params: SctpStreamParameters, +): void { + if (typeof params !== 'object') { throw new TypeError('params is not an object'); } // streamId is mandatory. - if (typeof params.streamId !== 'number') - { + if (typeof params.streamId !== 'number') { throw new TypeError('missing params.streamId'); } // ordered is optional. let orderedGiven = false; - if (typeof params.ordered === 'boolean') - { + if (typeof params.ordered === 'boolean') { orderedGiven = true; - } - else - { + } else { params.ordered = true; } // maxPacketLifeTime is optional. - if (params.maxPacketLifeTime && typeof params.maxPacketLifeTime !== 'number') - { + if ( + params.maxPacketLifeTime && + typeof params.maxPacketLifeTime !== 'number' + ) { throw new TypeError('invalid params.maxPacketLifeTime'); } // maxRetransmits is optional. - if (params.maxRetransmits && typeof params.maxRetransmits !== 'number') - { + if (params.maxRetransmits && typeof params.maxRetransmits !== 'number') { throw new TypeError('invalid params.maxRetransmits'); } - if (params.maxPacketLifeTime && params.maxRetransmits) - { - throw new TypeError('cannot provide both maxPacketLifeTime and maxRetransmits'); + if (params.maxPacketLifeTime && params.maxRetransmits) { + throw new TypeError( + 'cannot provide both maxPacketLifeTime and maxRetransmits', + ); } if ( orderedGiven && params.ordered && (params.maxPacketLifeTime || params.maxRetransmits) - ) - { - throw new TypeError('cannot be ordered with maxPacketLifeTime or maxRetransmits'); - } - else if (!orderedGiven && (params.maxPacketLifeTime || params.maxRetransmits)) - { + ) { + throw new TypeError( + 'cannot be ordered with maxPacketLifeTime or maxRetransmits', + ); + } else if ( + !orderedGiven && + (params.maxPacketLifeTime || params.maxRetransmits) + ) { params.ordered = false; } } @@ -224,72 +194,63 @@ export function validateSctpStreamParameters(params: SctpStreamParameters): void * mediasoup supported RTP capabilities. */ export function generateRouterRtpCapabilities( - mediaCodecs: RtpCodecCapability[] = [] -): RtpCapabilities -{ + mediaCodecs: RtpCodecCapability[] = [], +): RtpCapabilities { // Normalize supported RTP capabilities. validateRtpCapabilities(supportedRtpCapabilities); - if (!Array.isArray(mediaCodecs)) - { + if (!Array.isArray(mediaCodecs)) { throw new TypeError('mediaCodecs must be an Array'); } - const clonedSupportedRtpCapabilities = - utils.clone(supportedRtpCapabilities); + const clonedSupportedRtpCapabilities = utils.clone( + supportedRtpCapabilities, + ); const dynamicPayloadTypes = utils.clone(DynamicPayloadTypes); - const caps: RtpCapabilities = - { - codecs : [], - headerExtensions : clonedSupportedRtpCapabilities.headerExtensions + const caps: RtpCapabilities = { + codecs: [], + headerExtensions: clonedSupportedRtpCapabilities.headerExtensions, }; - for (const mediaCodec of mediaCodecs) - { + for (const mediaCodec of mediaCodecs) { // This may throw. validateRtpCodecCapability(mediaCodec); - const matchedSupportedCodec = clonedSupportedRtpCapabilities - .codecs! - .find((supportedCodec) => ( - matchCodecs(mediaCodec, supportedCodec, { strict: false })) - ); + const matchedSupportedCodec = clonedSupportedRtpCapabilities.codecs!.find( + supportedCodec => + matchCodecs(mediaCodec, supportedCodec, { strict: false }), + ); - if (!matchedSupportedCodec) - { + if (!matchedSupportedCodec) { throw new UnsupportedError( - `media codec not supported [mimeType:${mediaCodec.mimeType}]`); + `media codec not supported [mimeType:${mediaCodec.mimeType}]`, + ); } // Clone the supported codec. const codec = utils.clone(matchedSupportedCodec); // If the given media codec has preferredPayloadType, keep it. - if (typeof mediaCodec.preferredPayloadType === 'number') - { + if (typeof mediaCodec.preferredPayloadType === 'number') { codec.preferredPayloadType = mediaCodec.preferredPayloadType; // Also remove the pt from the list of available dynamic values. const idx = dynamicPayloadTypes.indexOf(codec.preferredPayloadType); - if (idx > -1) - { + if (idx > -1) { dynamicPayloadTypes.splice(idx, 1); } } // Otherwise if the supported codec has preferredPayloadType, use it. - else if (typeof codec.preferredPayloadType === 'number') - { + else if (typeof codec.preferredPayloadType === 'number') { // No need to remove it from the list since it's not a dynamic value. } // Otherwise choose a dynamic one. - else - { + else { // Take the first available pt and remove it from the list. const pt = dynamicPayloadTypes.shift(); - if (!pt) - { + if (!pt) { throw new Error('cannot allocate more dynamic codec payload types'); } @@ -297,8 +258,11 @@ export function generateRouterRtpCapabilities( } // Ensure there is not duplicated preferredPayloadType values. - if (caps.codecs!.some((c) => c.preferredPayloadType === codec.preferredPayloadType)) - { + if ( + caps.codecs!.some( + c => c.preferredPayloadType === codec.preferredPayloadType, + ) + ) { throw new TypeError('duplicated codec.preferredPayloadType'); } @@ -309,27 +273,23 @@ export function generateRouterRtpCapabilities( caps.codecs!.push(codec); // Add a RTX video codec if video. - if (codec.kind === 'video') - { + if (codec.kind === 'video') { // Take the first available pt and remove it from the list. const pt = dynamicPayloadTypes.shift(); - if (!pt) - { + if (!pt) { throw new Error('cannot allocate more dynamic codec payload types'); } - const rtxCodec: RtpCodecCapability = - { - kind : codec.kind, - mimeType : `${codec.kind}/rtx`, - preferredPayloadType : pt, - clockRate : codec.clockRate, - parameters : - { - apt : codec.preferredPayloadType + const rtxCodec: RtpCodecCapability = { + kind: codec.kind, + mimeType: `${codec.kind}/rtx`, + preferredPayloadType: pt, + clockRate: codec.clockRate, + parameters: { + apt: codec.preferredPayloadType, }, - rtcpFeedback : [] + rtcpFeedback: [], }; // Append to the codec list. @@ -348,105 +308,96 @@ export function generateRouterRtpCapabilities( */ export function getProducerRtpParametersMapping( params: RtpParameters, - caps: RtpCapabilities -): RtpMapping -{ - const rtpMapping: RtpMapping = - { - codecs : [], - encodings : [] + caps: RtpCapabilities, +): RtpMapping { + const rtpMapping: RtpMapping = { + codecs: [], + encodings: [], }; // Match parameters media codecs to capabilities media codecs. - const codecToCapCodec: Map = new Map(); + const codecToCapCodec: Map = + new Map(); - for (const codec of params.codecs) - { - if (isRtxCodec(codec)) - { + for (const codec of params.codecs) { + if (isRtxCodec(codec)) { continue; } // Search for the same media codec in capabilities. - const matchedCapCodec = caps.codecs! - .find((capCodec) => ( - matchCodecs(codec, capCodec, { strict: true, modify: true })) - ); + const matchedCapCodec = caps.codecs!.find(capCodec => + matchCodecs(codec, capCodec, { strict: true, modify: true }), + ); - if (!matchedCapCodec) - { + if (!matchedCapCodec) { throw new UnsupportedError( - `unsupported codec [mimeType:${codec.mimeType}, payloadType:${codec.payloadType}]`); + `unsupported codec [mimeType:${codec.mimeType}, payloadType:${codec.payloadType}]`, + ); } codecToCapCodec.set(codec, matchedCapCodec); } // Match parameters RTX codecs to capabilities RTX codecs. - for (const codec of params.codecs) - { - if (!isRtxCodec(codec)) - { + for (const codec of params.codecs) { + if (!isRtxCodec(codec)) { continue; } // Search for the associated media codec. - const associatedMediaCodec = params.codecs - .find((mediaCodec) => mediaCodec.payloadType === codec.parameters.apt); + const associatedMediaCodec = params.codecs.find( + mediaCodec => mediaCodec.payloadType === codec.parameters.apt, + ); - if (!associatedMediaCodec) - { + if (!associatedMediaCodec) { throw new TypeError( - `missing media codec found for RTX PT ${codec.payloadType}`); + `missing media codec found for RTX PT ${codec.payloadType}`, + ); } const capMediaCodec = codecToCapCodec.get(associatedMediaCodec); // Ensure that the capabilities media codec has a RTX codec. - const associatedCapRtxCodec = caps.codecs! - .find((capCodec) => ( + const associatedCapRtxCodec = caps.codecs!.find( + capCodec => isRtxCodec(capCodec) && - capCodec.parameters.apt === capMediaCodec!.preferredPayloadType - )); + capCodec.parameters.apt === capMediaCodec!.preferredPayloadType, + ); - if (!associatedCapRtxCodec) - { + if (!associatedCapRtxCodec) { throw new UnsupportedError( - `no RTX codec for capability codec PT ${capMediaCodec!.preferredPayloadType}`); + `no RTX codec for capability codec PT ${ + capMediaCodec!.preferredPayloadType + }`, + ); } codecToCapCodec.set(codec, associatedCapRtxCodec); } // Generate codecs mapping. - for (const [ codec, capCodec ] of codecToCapCodec) - { - rtpMapping.codecs.push( - { - payloadType : codec.payloadType, - mappedPayloadType : capCodec.preferredPayloadType! - }); + for (const [codec, capCodec] of codecToCapCodec) { + rtpMapping.codecs.push({ + payloadType: codec.payloadType, + mappedPayloadType: capCodec.preferredPayloadType!, + }); } // Generate encodings mapping. let mappedSsrc = utils.generateRandomNumber(); - for (const encoding of params.encodings!) - { + for (const encoding of params.encodings!) { const mappedEncoding: any = {}; mappedEncoding.mappedSsrc = mappedSsrc++; - if (encoding.rid) - { + if (encoding.rid) { mappedEncoding.rid = encoding.rid; } - if (encoding.ssrc) - { + if (encoding.ssrc) { mappedEncoding.ssrc = encoding.ssrc; } - if (encoding.scalabilityMode) - { + if (encoding.scalabilityMode) { mappedEncoding.scalabilityMode = encoding.scalabilityMode; } @@ -464,82 +415,72 @@ export function getConsumableRtpParameters( kind: string, params: RtpParameters, caps: RtpCapabilities, - rtpMapping: RtpMapping -): RtpParameters -{ - const consumableParams: RtpParameters = - { - codecs : [], - headerExtensions : [], - encodings : [], - rtcp : {} + rtpMapping: RtpMapping, +): RtpParameters { + const consumableParams: RtpParameters = { + codecs: [], + headerExtensions: [], + encodings: [], + rtcp: {}, }; - for (const codec of params.codecs) - { - if (isRtxCodec(codec)) - { + for (const codec of params.codecs) { + if (isRtxCodec(codec)) { continue; } - const consumableCodecPt = rtpMapping.codecs - .find((entry) => entry.payloadType === codec.payloadType)! - .mappedPayloadType; - - const matchedCapCodec = caps.codecs! - .find((capCodec) => capCodec.preferredPayloadType === consumableCodecPt)!; - - const consumableCodec: RtpCodecParameters = - { - mimeType : matchedCapCodec.mimeType, - payloadType : matchedCapCodec.preferredPayloadType!, - clockRate : matchedCapCodec.clockRate, - channels : matchedCapCodec.channels, - parameters : codec.parameters, // Keep the Producer codec parameters. - rtcpFeedback : matchedCapCodec.rtcpFeedback + const consumableCodecPt = rtpMapping.codecs.find( + entry => entry.payloadType === codec.payloadType, + )!.mappedPayloadType; + + const matchedCapCodec = caps.codecs!.find( + capCodec => capCodec.preferredPayloadType === consumableCodecPt, + )!; + + const consumableCodec: RtpCodecParameters = { + mimeType: matchedCapCodec.mimeType, + payloadType: matchedCapCodec.preferredPayloadType!, + clockRate: matchedCapCodec.clockRate, + channels: matchedCapCodec.channels, + parameters: codec.parameters, // Keep the Producer codec parameters. + rtcpFeedback: matchedCapCodec.rtcpFeedback, }; consumableParams.codecs.push(consumableCodec); - const consumableCapRtxCodec = caps.codecs! - .find((capRtxCodec) => ( + const consumableCapRtxCodec = caps.codecs!.find( + capRtxCodec => isRtxCodec(capRtxCodec) && - capRtxCodec.parameters.apt === consumableCodec.payloadType - )); - - if (consumableCapRtxCodec) - { - const consumableRtxCodec: RtpCodecParameters = - { - mimeType : consumableCapRtxCodec.mimeType, - payloadType : consumableCapRtxCodec.preferredPayloadType!, - clockRate : consumableCapRtxCodec.clockRate, - parameters : consumableCapRtxCodec.parameters, - rtcpFeedback : consumableCapRtxCodec.rtcpFeedback + capRtxCodec.parameters.apt === consumableCodec.payloadType, + ); + + if (consumableCapRtxCodec) { + const consumableRtxCodec: RtpCodecParameters = { + mimeType: consumableCapRtxCodec.mimeType, + payloadType: consumableCapRtxCodec.preferredPayloadType!, + clockRate: consumableCapRtxCodec.clockRate, + parameters: consumableCapRtxCodec.parameters, + rtcpFeedback: consumableCapRtxCodec.rtcpFeedback, }; consumableParams.codecs.push(consumableRtxCodec); } } - for (const capExt of caps.headerExtensions!) - { - + for (const capExt of caps.headerExtensions!) { // Just take RTP header extension that can be used in Consumers. if ( capExt.kind !== kind || (capExt.direction !== 'sendrecv' && capExt.direction !== 'sendonly') - ) - { + ) { continue; } - const consumableExt = - { - uri : capExt.uri, - id : capExt.preferredId, - encrypt : capExt.preferredEncrypt, - parameters : {} + const consumableExt = { + uri: capExt.uri, + id: capExt.preferredId, + encrypt: capExt.preferredEncrypt, + parameters: {}, }; consumableParams.headerExtensions!.push(consumableExt); @@ -549,8 +490,7 @@ export function getConsumableRtpParameters( const consumableEncodings = utils.clone(params.encodings) ?? []; - for (let i = 0; i < consumableEncodings.length; ++i) - { + for (let i = 0; i < consumableEncodings.length; ++i) { const consumableEncoding = consumableEncodings[i]; const { mappedSsrc } = rtpMapping.encodings[i]; @@ -565,10 +505,9 @@ export function getConsumableRtpParameters( consumableParams.encodings!.push(consumableEncoding); } - consumableParams.rtcp = - { - cname : params.rtcp!.cname, - reducedSize : true + consumableParams.rtcp = { + cname: params.rtcp!.cname, + reducedSize: true, }; return consumableParams; @@ -579,21 +518,19 @@ export function getConsumableRtpParameters( */ export function canConsume( consumableParams: RtpParameters, - caps: RtpCapabilities -): boolean -{ + caps: RtpCapabilities, +): boolean { // This may throw. validateRtpCapabilities(caps); const matchingCodecs: RtpCodecParameters[] = []; - for (const codec of consumableParams.codecs) - { - const matchedCapCodec = caps.codecs! - .find((capCodec) => matchCodecs(capCodec, codec, { strict: true })); + for (const codec of consumableParams.codecs) { + const matchedCapCodec = caps.codecs!.find(capCodec => + matchCodecs(capCodec, codec, { strict: true }), + ); - if (!matchedCapCodec) - { + if (!matchedCapCodec) { continue; } @@ -601,8 +538,7 @@ export function canConsume( } // Ensure there is at least one media codec. - if (matchingCodecs.length === 0 || isRtxCodec(matchingCodecs[0])) - { + if (matchingCodecs.length === 0 || isRtxCodec(matchingCodecs[0])) { return false; } @@ -616,206 +552,185 @@ export function canConsume( * capabilities to reduce codecs, codecs' RTCP feedback and header extensions, * and also enables or disables RTX. */ -export function getConsumerRtpParameters( - { - consumableRtpParameters, - remoteRtpCapabilities, - pipe, - enableRtx - }: - { - consumableRtpParameters: RtpParameters; - remoteRtpCapabilities: RtpCapabilities; - pipe: boolean; - enableRtx: boolean; - } -): RtpParameters -{ - const consumerParams: RtpParameters = - { - codecs : [], - headerExtensions : [], - encodings : [], - rtcp : consumableRtpParameters.rtcp +export function getConsumerRtpParameters({ + consumableRtpParameters, + remoteRtpCapabilities, + pipe, + enableRtx, +}: { + consumableRtpParameters: RtpParameters; + remoteRtpCapabilities: RtpCapabilities; + pipe: boolean; + enableRtx: boolean; +}): RtpParameters { + const consumerParams: RtpParameters = { + codecs: [], + headerExtensions: [], + encodings: [], + rtcp: consumableRtpParameters.rtcp, }; - for (const capCodec of remoteRtpCapabilities.codecs!) - { + for (const capCodec of remoteRtpCapabilities.codecs!) { validateRtpCodecCapability(capCodec); } const consumableCodecs = - utils.clone(consumableRtpParameters.codecs) ?? []; + utils.clone( + consumableRtpParameters.codecs, + ) ?? []; let rtxSupported = false; - for (const codec of consumableCodecs) - { - if (!enableRtx && isRtxCodec(codec)) - { + for (const codec of consumableCodecs) { + if (!enableRtx && isRtxCodec(codec)) { continue; } - const matchedCapCodec = remoteRtpCapabilities.codecs! - .find((capCodec) => matchCodecs(capCodec, codec, { strict: true })); + const matchedCapCodec = remoteRtpCapabilities.codecs!.find(capCodec => + matchCodecs(capCodec, codec, { strict: true }), + ); - if (!matchedCapCodec) - { + if (!matchedCapCodec) { continue; } - codec.rtcpFeedback = matchedCapCodec.rtcpFeedback! - .filter((fb) => ( - (enableRtx || fb.type !== 'nack' || fb.parameter) - )); + codec.rtcpFeedback = matchedCapCodec.rtcpFeedback!.filter( + fb => enableRtx || fb.type !== 'nack' || fb.parameter, + ); consumerParams.codecs.push(codec); } // Must sanitize the list of matched codecs by removing useless RTX codecs. - for (let idx = consumerParams.codecs.length - 1; idx >= 0; --idx) - { + for (let idx = consumerParams.codecs.length - 1; idx >= 0; --idx) { const codec = consumerParams.codecs[idx]; - if (isRtxCodec(codec)) - { + if (isRtxCodec(codec)) { // Search for the associated media codec. - const associatedMediaCodec = consumerParams.codecs - .find((mediaCodec) => mediaCodec.payloadType === codec.parameters.apt); + const associatedMediaCodec = consumerParams.codecs.find( + mediaCodec => mediaCodec.payloadType === codec.parameters.apt, + ); - if (associatedMediaCodec) - { + if (associatedMediaCodec) { rtxSupported = true; - } - else - { + } else { consumerParams.codecs.splice(idx, 1); } } } // Ensure there is at least one media codec. - if (consumerParams.codecs.length === 0 || isRtxCodec(consumerParams.codecs[0])) - { + if ( + consumerParams.codecs.length === 0 || + isRtxCodec(consumerParams.codecs[0]) + ) { throw new UnsupportedError('no compatible media codecs'); } - consumerParams.headerExtensions = consumableRtpParameters.headerExtensions! - .filter((ext) => ( - remoteRtpCapabilities.headerExtensions! - .some((capExt) => ( - capExt.preferredId === ext.id && - capExt.uri === ext.uri - )) - )); + consumerParams.headerExtensions = + consumableRtpParameters.headerExtensions!.filter(ext => + remoteRtpCapabilities.headerExtensions!.some( + capExt => capExt.preferredId === ext.id && capExt.uri === ext.uri, + ), + ); // Reduce codecs' RTCP feedback. Use Transport-CC if available, REMB otherwise. if ( - consumerParams.headerExtensions.some((ext) => ( - ext.uri === 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' - )) - ) - { - for (const codec of consumerParams.codecs) - { - codec.rtcpFeedback = codec.rtcpFeedback! - .filter((fb) => fb.type !== 'goog-remb'); + consumerParams.headerExtensions.some( + ext => + ext.uri === + 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + ) + ) { + for (const codec of consumerParams.codecs) { + codec.rtcpFeedback = codec.rtcpFeedback!.filter( + fb => fb.type !== 'goog-remb', + ); } - } - else if ( - consumerParams.headerExtensions.some((ext) => ( - ext.uri === 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' - )) - ) - { - for (const codec of consumerParams.codecs) - { - codec.rtcpFeedback = codec.rtcpFeedback! - .filter((fb) => fb.type !== 'transport-cc'); + } else if ( + consumerParams.headerExtensions.some( + ext => + ext.uri === + 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + ) + ) { + for (const codec of consumerParams.codecs) { + codec.rtcpFeedback = codec.rtcpFeedback!.filter( + fb => fb.type !== 'transport-cc', + ); } - } - else - { - for (const codec of consumerParams.codecs) - { - codec.rtcpFeedback = codec.rtcpFeedback! - .filter((fb) => ( - fb.type !== 'transport-cc' && - fb.type !== 'goog-remb' - )); + } else { + for (const codec of consumerParams.codecs) { + codec.rtcpFeedback = codec.rtcpFeedback!.filter( + fb => fb.type !== 'transport-cc' && fb.type !== 'goog-remb', + ); } } - if (!pipe) - { - const consumerEncoding: RtpEncodingParameters = - { - ssrc : utils.generateRandomNumber() + if (!pipe) { + const consumerEncoding: RtpEncodingParameters = { + ssrc: utils.generateRandomNumber(), }; - if (rtxSupported) - { + if (rtxSupported) { consumerEncoding.rtx = { ssrc: consumerEncoding.ssrc! + 1 }; } // If any of the consumableRtpParameters.encodings has scalabilityMode, // process it (assume all encodings have the same value). - const encodingWithScalabilityMode = - consumableRtpParameters.encodings!.find((encoding) => encoding.scalabilityMode); + const encodingWithScalabilityMode = consumableRtpParameters.encodings!.find( + encoding => encoding.scalabilityMode, + ); let scalabilityMode = encodingWithScalabilityMode ? encodingWithScalabilityMode.scalabilityMode : undefined; // If there is simulast, mangle spatial layers in scalabilityMode. - if (consumableRtpParameters.encodings!.length > 1) - { + if (consumableRtpParameters.encodings!.length > 1) { const { temporalLayers } = parseScalabilityMode(scalabilityMode); - scalabilityMode = `L${consumableRtpParameters.encodings!.length}T${temporalLayers}`; + scalabilityMode = `L${ + consumableRtpParameters.encodings!.length + }T${temporalLayers}`; } - if (scalabilityMode) - { + if (scalabilityMode) { consumerEncoding.scalabilityMode = scalabilityMode; } // Use the maximum maxBitrate in any encoding and honor it in the Consumer's // encoding. - const maxEncodingMaxBitrate = - consumableRtpParameters.encodings!.reduce((maxBitrate, encoding) => ( + const maxEncodingMaxBitrate = consumableRtpParameters.encodings!.reduce( + (maxBitrate, encoding) => encoding.maxBitrate && encoding.maxBitrate > maxBitrate ? encoding.maxBitrate - : maxBitrate - ), 0); + : maxBitrate, + 0, + ); - if (maxEncodingMaxBitrate) - { + if (maxEncodingMaxBitrate) { consumerEncoding.maxBitrate = maxEncodingMaxBitrate; } // Set a single encoding for the Consumer. consumerParams.encodings!.push(consumerEncoding); - } - else - { + } else { const consumableEncodings = - utils.clone(consumableRtpParameters.encodings) ?? []; + utils.clone( + consumableRtpParameters.encodings, + ) ?? []; const baseSsrc = utils.generateRandomNumber(); const baseRtxSsrc = utils.generateRandomNumber(); - for (let i = 0; i < consumableEncodings.length; ++i) - { + for (let i = 0; i < consumableEncodings.length; ++i) { const encoding = consumableEncodings[i]; encoding.ssrc = baseSsrc + i; - if (rtxSupported) - { + if (rtxSupported) { encoding.rtx = { ssrc: baseRtxSsrc + i }; - } - else - { + } else { delete encoding.rtx; } @@ -832,70 +747,66 @@ export function getConsumerRtpParameters( * It keeps all original consumable encodings and removes support for BWE. If * enableRtx is false, it also removes RTX and NACK support. */ -export function getPipeConsumerRtpParameters( - { - consumableRtpParameters, - enableRtx - }: - { - consumableRtpParameters: RtpParameters; - enableRtx: boolean; - } -): RtpParameters -{ - const consumerParams: RtpParameters = - { - codecs : [], - headerExtensions : [], - encodings : [], - rtcp : consumableRtpParameters.rtcp +export function getPipeConsumerRtpParameters({ + consumableRtpParameters, + enableRtx, +}: { + consumableRtpParameters: RtpParameters; + enableRtx: boolean; +}): RtpParameters { + const consumerParams: RtpParameters = { + codecs: [], + headerExtensions: [], + encodings: [], + rtcp: consumableRtpParameters.rtcp, }; const consumableCodecs = - utils.clone(consumableRtpParameters.codecs) ?? []; + utils.clone( + consumableRtpParameters.codecs, + ) ?? []; - for (const codec of consumableCodecs) - { - if (!enableRtx && isRtxCodec(codec)) - { + for (const codec of consumableCodecs) { + if (!enableRtx && isRtxCodec(codec)) { continue; } - codec.rtcpFeedback = codec.rtcpFeedback! - .filter((fb) => ( + codec.rtcpFeedback = codec.rtcpFeedback!.filter( + fb => (fb.type === 'nack' && fb.parameter === 'pli') || (fb.type === 'ccm' && fb.parameter === 'fir') || - (enableRtx && fb.type === 'nack' && !fb.parameter) - )); + (enableRtx && fb.type === 'nack' && !fb.parameter), + ); consumerParams.codecs.push(codec); } // Reduce RTP extensions by disabling transport MID and BWE related ones. - consumerParams.headerExtensions = consumableRtpParameters.headerExtensions! - .filter((ext) => ( - ext.uri !== 'urn:ietf:params:rtp-hdrext:sdes:mid' && - ext.uri !== 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' && - ext.uri !== 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' - )); + consumerParams.headerExtensions = + consumableRtpParameters.headerExtensions!.filter( + ext => + ext.uri !== 'urn:ietf:params:rtp-hdrext:sdes:mid' && + ext.uri !== + 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' && + ext.uri !== + 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + ); const consumableEncodings = - utils.clone(consumableRtpParameters.encodings) ?? []; + utils.clone( + consumableRtpParameters.encodings, + ) ?? []; const baseSsrc = utils.generateRandomNumber(); const baseRtxSsrc = utils.generateRandomNumber(); - for (let i = 0; i < consumableEncodings.length; ++i) - { + for (let i = 0; i < consumableEncodings.length; ++i) { const encoding = consumableEncodings[i]; encoding.ssrc = baseSsrc + i; - if (enableRtx) - { + if (enableRtx) { encoding.rtx = { ssrc: baseRtxSsrc + i }; - } - else - { + } else { delete encoding.rtx; } @@ -905,53 +816,44 @@ export function getPipeConsumerRtpParameters( return consumerParams; } -function isRtxCodec(codec: RtpCodecCapability | RtpCodecParameters): boolean -{ +function isRtxCodec(codec: RtpCodecCapability | RtpCodecParameters): boolean { return /.+\/rtx$/i.test(codec.mimeType); } function matchCodecs( aCodec: RtpCodecCapability | RtpCodecParameters, bCodec: RtpCodecCapability | RtpCodecParameters, - { strict = false, modify = false } = {} -): boolean -{ + { strict = false, modify = false } = {}, +): boolean { const aMimeType = aCodec.mimeType.toLowerCase(); const bMimeType = bCodec.mimeType.toLowerCase(); - if (aMimeType !== bMimeType) - { + if (aMimeType !== bMimeType) { return false; } - if (aCodec.clockRate !== bCodec.clockRate) - { + if (aCodec.clockRate !== bCodec.clockRate) { return false; } - if (aCodec.channels !== bCodec.channels) - { + if (aCodec.channels !== bCodec.channels) { return false; } // Per codec special checks. - switch (aMimeType) - { - case 'audio/multiopus': - { + switch (aMimeType) { + case 'audio/multiopus': { const aNumStreams = aCodec.parameters['num_streams']; const bNumStreams = bCodec.parameters['num_streams']; - if (aNumStreams !== bNumStreams) - { + if (aNumStreams !== bNumStreams) { return false; } const aCoupledStreams = aCodec.parameters['coupled_streams']; const bCoupledStreams = bCodec.parameters['coupled_streams']; - if (aCoupledStreams !== bCoupledStreams) - { + if (aCoupledStreams !== bCoupledStreams) { return false; } @@ -959,45 +861,34 @@ function matchCodecs( } case 'video/h264': - case 'video/h264-svc': - { - if (strict) - { + case 'video/h264-svc': { + if (strict) { const aPacketizationMode = aCodec.parameters['packetization-mode'] || 0; const bPacketizationMode = bCodec.parameters['packetization-mode'] || 0; - if (aPacketizationMode !== bPacketizationMode) - { + if (aPacketizationMode !== bPacketizationMode) { return false; } - if (!h264.isSameProfile(aCodec.parameters, bCodec.parameters)) - { + if (!h264.isSameProfile(aCodec.parameters, bCodec.parameters)) { return false; } let selectedProfileLevelId; - try - { - selectedProfileLevelId = - h264.generateProfileLevelIdStringForAnswer( - aCodec.parameters, bCodec.parameters - ); - } - catch (error) - { + try { + selectedProfileLevelId = h264.generateProfileLevelIdStringForAnswer( + aCodec.parameters, + bCodec.parameters, + ); + } catch (error) { return false; } - if (modify) - { - if (selectedProfileLevelId) - { + if (modify) { + if (selectedProfileLevelId) { aCodec.parameters['profile-level-id'] = selectedProfileLevelId; - } - else - { + } else { delete aCodec.parameters['profile-level-id']; } } @@ -1006,15 +897,12 @@ function matchCodecs( break; } - case 'video/vp9': - { - if (strict) - { + case 'video/vp9': { + if (strict) { const aProfileId = aCodec.parameters['profile-id'] || 0; const bProfileId = bCodec.parameters['profile-id'] || 0; - if (aProfileId !== bProfileId) - { + if (aProfileId !== bProfileId) { return false; } } @@ -1027,42 +915,48 @@ function matchCodecs( } export function serializeRtpMapping( - builder: flatbuffers.Builder, rtpMapping: RtpMapping -): number -{ + builder: flatbuffers.Builder, + rtpMapping: RtpMapping, +): number { const codecs: number[] = []; - for (const codec of rtpMapping.codecs) - { + for (const codec of rtpMapping.codecs) { codecs.push( FbsRtpParameters.CodecMapping.createCodecMapping( - builder, codec.payloadType, codec.mappedPayloadType - ) + builder, + codec.payloadType, + codec.mappedPayloadType, + ), ); } - const codecsOffset = - FbsRtpParameters.RtpMapping.createCodecsVector(builder, codecs); + const codecsOffset = FbsRtpParameters.RtpMapping.createCodecsVector( + builder, + codecs, + ); const encodings: number[] = []; - for (const encoding of rtpMapping.encodings) - { + for (const encoding of rtpMapping.encodings) { encodings.push( FbsRtpParameters.EncodingMapping.createEncodingMapping( builder, builder.createString(encoding.rid), encoding.ssrc ?? null, builder.createString(encoding.scalabilityMode), - encoding.mappedSsrc - ) + encoding.mappedSsrc, + ), ); } - const encodingsOffset = - FbsRtpParameters.RtpMapping.createEncodingsVector(builder, encodings); + const encodingsOffset = FbsRtpParameters.RtpMapping.createEncodingsVector( + builder, + encodings, + ); return FbsRtpParameters.RtpMapping.createRtpMapping( - builder, codecsOffset, encodingsOffset + builder, + codecsOffset, + encodingsOffset, ); } @@ -1071,25 +965,21 @@ export function serializeRtpMapping( * fields with default values. * It throws if invalid. */ -function validateRtpCodecCapability(codec: RtpCodecCapability): void -{ +function validateRtpCodecCapability(codec: RtpCodecCapability): void { const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i'); - if (typeof codec !== 'object') - { + if (typeof codec !== 'object') { throw new TypeError('codec is not an object'); } // mimeType is mandatory. - if (!codec.mimeType || typeof codec.mimeType !== 'string') - { + if (!codec.mimeType || typeof codec.mimeType !== 'string') { throw new TypeError('missing codec.mimeType'); } const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType); - if (!mimeTypeMatch) - { + if (!mimeTypeMatch) { throw new TypeError('invalid codec.mimeType'); } @@ -1097,70 +987,60 @@ function validateRtpCodecCapability(codec: RtpCodecCapability): void codec.kind = mimeTypeMatch[1].toLowerCase() as MediaKind; // preferredPayloadType is optional. - if (codec.preferredPayloadType && typeof codec.preferredPayloadType !== 'number') - { + if ( + codec.preferredPayloadType && + typeof codec.preferredPayloadType !== 'number' + ) { throw new TypeError('invalid codec.preferredPayloadType'); } // clockRate is mandatory. - if (typeof codec.clockRate !== 'number') - { + if (typeof codec.clockRate !== 'number') { throw new TypeError('missing codec.clockRate'); } // channels is optional. If unset, set it to 1 (just if audio). - if (codec.kind === 'audio') - { - if (typeof codec.channels !== 'number') - { + if (codec.kind === 'audio') { + if (typeof codec.channels !== 'number') { codec.channels = 1; } - } - else - { + } else { delete codec.channels; } // parameters is optional. If unset, set it to an empty object. - if (!codec.parameters || typeof codec.parameters !== 'object') - { + if (!codec.parameters || typeof codec.parameters !== 'object') { codec.parameters = {}; } - for (const key of Object.keys(codec.parameters)) - { + for (const key of Object.keys(codec.parameters)) { let value = codec.parameters[key]; - if (value === undefined) - { + if (value === undefined) { codec.parameters[key] = ''; value = ''; } - if (typeof value !== 'string' && typeof value !== 'number') - { + if (typeof value !== 'string' && typeof value !== 'number') { throw new TypeError( - `invalid codec parameter [key:${key}s, value:${value}]`); + `invalid codec parameter [key:${key}s, value:${value}]`, + ); } // Specific parameters validation. - if (key === 'apt') - { - if (typeof value !== 'number') - { + if (key === 'apt') { + if (typeof value !== 'number') { throw new TypeError('invalid codec apt parameter'); } } } // rtcpFeedback is optional. If unset, set it to an empty array. - if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) - { + if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) { codec.rtcpFeedback = []; } - for (const fb of codec.rtcpFeedback) - { + for (const fb of codec.rtcpFeedback) { validateRtcpFeedback(fb); } } @@ -1170,22 +1050,18 @@ function validateRtpCodecCapability(codec: RtpCodecCapability): void * fields with default values. * It throws if invalid. */ -function validateRtcpFeedback(fb: RtcpFeedback): void -{ - if (typeof fb !== 'object') - { +function validateRtcpFeedback(fb: RtcpFeedback): void { + if (typeof fb !== 'object') { throw new TypeError('fb is not an object'); } // type is mandatory. - if (!fb.type || typeof fb.type !== 'string') - { + if (!fb.type || typeof fb.type !== 'string') { throw new TypeError('missing fb.type'); } // parameter is optional. If unset set it to an empty string. - if (!fb.parameter || typeof fb.parameter !== 'string') - { + if (!fb.parameter || typeof fb.parameter !== 'string') { fb.parameter = ''; } } @@ -1195,48 +1071,36 @@ function validateRtcpFeedback(fb: RtcpFeedback): void * fields with default values. * It throws if invalid. */ -function validateRtpHeaderExtension(ext: RtpHeaderExtension): void -{ - - if (typeof ext !== 'object') - { +function validateRtpHeaderExtension(ext: RtpHeaderExtension): void { + if (typeof ext !== 'object') { throw new TypeError('ext is not an object'); } - if (ext.kind !== 'audio' && ext.kind !== 'video') - { + if (ext.kind !== 'audio' && ext.kind !== 'video') { throw new TypeError('invalid ext.kind'); } // uri is mandatory. - if (!ext.uri || typeof ext.uri !== 'string') - { + if (!ext.uri || typeof ext.uri !== 'string') { throw new TypeError('missing ext.uri'); } // preferredId is mandatory. - if (typeof ext.preferredId !== 'number') - { + if (typeof ext.preferredId !== 'number') { throw new TypeError('missing ext.preferredId'); } // preferredEncrypt is optional. If unset set it to false. - if (ext.preferredEncrypt && typeof ext.preferredEncrypt !== 'boolean') - { + if (ext.preferredEncrypt && typeof ext.preferredEncrypt !== 'boolean') { throw new TypeError('invalid ext.preferredEncrypt'); - } - else if (!ext.preferredEncrypt) - { + } else if (!ext.preferredEncrypt) { ext.preferredEncrypt = false; } // direction is optional. If unset set it to sendrecv. - if (ext.direction && typeof ext.direction !== 'string') - { + if (ext.direction && typeof ext.direction !== 'string') { throw new TypeError('invalid ext.direction'); - } - else if (!ext.direction) - { + } else if (!ext.direction) { ext.direction = 'sendrecv'; } } @@ -1246,95 +1110,78 @@ function validateRtpHeaderExtension(ext: RtpHeaderExtension): void * fields with default values. * It throws if invalid. */ -function validateRtpCodecParameters(codec: RtpCodecParameters): void -{ +function validateRtpCodecParameters(codec: RtpCodecParameters): void { const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i'); - if (typeof codec !== 'object') - { + if (typeof codec !== 'object') { throw new TypeError('codec is not an object'); } // mimeType is mandatory. - if (!codec.mimeType || typeof codec.mimeType !== 'string') - { + if (!codec.mimeType || typeof codec.mimeType !== 'string') { throw new TypeError('missing codec.mimeType'); } const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType); - if (!mimeTypeMatch) - { + if (!mimeTypeMatch) { throw new TypeError('invalid codec.mimeType'); } // payloadType is mandatory. - if (typeof codec.payloadType !== 'number') - { + if (typeof codec.payloadType !== 'number') { throw new TypeError('missing codec.payloadType'); } // clockRate is mandatory. - if (typeof codec.clockRate !== 'number') - { + if (typeof codec.clockRate !== 'number') { throw new TypeError('missing codec.clockRate'); } const kind = mimeTypeMatch[1].toLowerCase() as MediaKind; // channels is optional. If unset, set it to 1 (just if audio). - if (kind === 'audio') - { - if (typeof codec.channels !== 'number') - { + if (kind === 'audio') { + if (typeof codec.channels !== 'number') { codec.channels = 1; } - } - else - { + } else { delete codec.channels; } // parameters is optional. If unset, set it to an empty object. - if (!codec.parameters || typeof codec.parameters !== 'object') - { + if (!codec.parameters || typeof codec.parameters !== 'object') { codec.parameters = {}; } - for (const key of Object.keys(codec.parameters)) - { + for (const key of Object.keys(codec.parameters)) { let value = codec.parameters[key]; - if (value === undefined) - { + if (value === undefined) { codec.parameters[key] = ''; value = ''; } - if (typeof value !== 'string' && typeof value !== 'number') - { + if (typeof value !== 'string' && typeof value !== 'number') { throw new TypeError( - `invalid codec parameter [key:${key}s, value:${value}]`); + `invalid codec parameter [key:${key}s, value:${value}]`, + ); } // Specific parameters validation. - if (key === 'apt') - { - if (typeof value !== 'number') - { + if (key === 'apt') { + if (typeof value !== 'number') { throw new TypeError('invalid codec apt parameter'); } } } // rtcpFeedback is optional. If unset, set it to an empty array. - if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) - { + if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) { codec.rtcpFeedback = []; } - for (const fb of codec.rtcpFeedback) - { + for (const fb of codec.rtcpFeedback) { validateRtcpFeedback(fb); } } @@ -1344,55 +1191,43 @@ function validateRtpCodecParameters(codec: RtpCodecParameters): void * missing fields with default values. It throws if invalid. */ function validateRtpHeaderExtensionParameters( - ext: RtpHeaderExtensionParameters -): void -{ - - if (typeof ext !== 'object') - { + ext: RtpHeaderExtensionParameters, +): void { + if (typeof ext !== 'object') { throw new TypeError('ext is not an object'); } // uri is mandatory. - if (!ext.uri || typeof ext.uri !== 'string') - { + if (!ext.uri || typeof ext.uri !== 'string') { throw new TypeError('missing ext.uri'); } // id is mandatory. - if (typeof ext.id !== 'number') - { + if (typeof ext.id !== 'number') { throw new TypeError('missing ext.id'); } // encrypt is optional. If unset set it to false. - if (ext.encrypt && typeof ext.encrypt !== 'boolean') - { + if (ext.encrypt && typeof ext.encrypt !== 'boolean') { throw new TypeError('invalid ext.encrypt'); - } - else if (!ext.encrypt) - { + } else if (!ext.encrypt) { ext.encrypt = false; } // parameters is optional. If unset, set it to an empty object. - if (!ext.parameters || typeof ext.parameters !== 'object') - { + if (!ext.parameters || typeof ext.parameters !== 'object') { ext.parameters = {}; } - for (const key of Object.keys(ext.parameters)) - { + for (const key of Object.keys(ext.parameters)) { let value = ext.parameters[key]; - if (value === undefined) - { + if (value === undefined) { ext.parameters[key] = ''; value = ''; } - if (typeof value !== 'string' && typeof value !== 'number') - { + if (typeof value !== 'string' && typeof value !== 'number') { throw new TypeError('invalid header extension parameter'); } } @@ -1403,48 +1238,41 @@ function validateRtpHeaderExtensionParameters( * fields with default values. * It throws if invalid. */ -function validateRtpEncodingParameters(encoding: RtpEncodingParameters): void -{ - if (typeof encoding !== 'object') - { +function validateRtpEncodingParameters(encoding: RtpEncodingParameters): void { + if (typeof encoding !== 'object') { throw new TypeError('encoding is not an object'); } // ssrc is optional. - if (encoding.ssrc && typeof encoding.ssrc !== 'number') - { + if (encoding.ssrc && typeof encoding.ssrc !== 'number') { throw new TypeError('invalid encoding.ssrc'); } // rid is optional. - if (encoding.rid && typeof encoding.rid !== 'string') - { + if (encoding.rid && typeof encoding.rid !== 'string') { throw new TypeError('invalid encoding.rid'); } // rtx is optional. - if (encoding.rtx && typeof encoding.rtx !== 'object') - { + if (encoding.rtx && typeof encoding.rtx !== 'object') { throw new TypeError('invalid encoding.rtx'); - } - else if (encoding.rtx) - { + } else if (encoding.rtx) { // RTX ssrc is mandatory if rtx is present. - if (typeof encoding.rtx.ssrc !== 'number') - { + if (typeof encoding.rtx.ssrc !== 'number') { throw new TypeError('missing encoding.rtx.ssrc'); } } // dtx is optional. If unset set it to false. - if (!encoding.dtx || typeof encoding.dtx !== 'boolean') - { + if (!encoding.dtx || typeof encoding.dtx !== 'boolean') { encoding.dtx = false; } // scalabilityMode is optional. - if (encoding.scalabilityMode && typeof encoding.scalabilityMode !== 'string') - { + if ( + encoding.scalabilityMode && + typeof encoding.scalabilityMode !== 'string' + ) { throw new TypeError('invalid encoding.scalabilityMode'); } } @@ -1454,22 +1282,18 @@ function validateRtpEncodingParameters(encoding: RtpEncodingParameters): void * fields with default values. * It throws if invalid. */ -function validateRtcpParameters(rtcp: RtcpParameters): void -{ - if (typeof rtcp !== 'object') - { +function validateRtcpParameters(rtcp: RtcpParameters): void { + if (typeof rtcp !== 'object') { throw new TypeError('rtcp is not an object'); } // cname is optional. - if (rtcp.cname && typeof rtcp.cname !== 'string') - { + if (rtcp.cname && typeof rtcp.cname !== 'string') { throw new TypeError('invalid rtcp.cname'); } // reducedSize is optional. If unset set it to true. - if (!rtcp.reducedSize || typeof rtcp.reducedSize !== 'boolean') - { + if (!rtcp.reducedSize || typeof rtcp.reducedSize !== 'boolean') { rtcp.reducedSize = true; } } diff --git a/node/src/scalabilityModes.ts b/node/src/scalabilityModes.ts index 1c749ed1da..4f9f93845d 100644 --- a/node/src/scalabilityModes.ts +++ b/node/src/scalabilityModes.ts @@ -1,32 +1,27 @@ const ScalabilityModeRegex = new RegExp( - '^[LS]([1-9]\\d{0,1})T([1-9]\\d{0,1})(_KEY)?' + '^[LS]([1-9]\\d{0,1})T([1-9]\\d{0,1})(_KEY)?', ); -export type ScalabilityMode = -{ +export type ScalabilityMode = { spatialLayers: number; temporalLayers: number; ksvc: boolean; }; -export function parse(scalabilityMode?: string): ScalabilityMode -{ +export function parse(scalabilityMode?: string): ScalabilityMode { const match = ScalabilityModeRegex.exec(scalabilityMode || ''); - if (match) - { + if (match) { return { - spatialLayers : Number(match[1]), - temporalLayers : Number(match[2]), - ksvc : Boolean(match[3]) + spatialLayers: Number(match[1]), + temporalLayers: Number(match[2]), + ksvc: Boolean(match[3]), }; - } - else - { + } else { return { - spatialLayers : 1, - temporalLayers : 1, - ksvc : false + spatialLayers: 1, + temporalLayers: 1, + ksvc: false, }; } } diff --git a/node/src/supportedRtpCapabilities.ts b/node/src/supportedRtpCapabilities.ts index aa3618c28c..a1aa48164e 100644 --- a/node/src/supportedRtpCapabilities.ts +++ b/node/src/supportedRtpCapabilities.ts @@ -1,392 +1,334 @@ import { RtpCapabilities } from './RtpParameters'; -const supportedRtpCapabilities: RtpCapabilities = -{ - codecs : - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'transport-cc' } - ] +const supportedRtpCapabilities: RtpCapabilities = { + codecs: [ + { + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + rtcpFeedback: [{ type: 'nack' }, { type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/multiopus', - clockRate : 48000, - channels : 4, + kind: 'audio', + mimeType: 'audio/multiopus', + clockRate: 48000, + channels: 4, // Quad channel. - parameters : - { - 'channel_mapping' : '0,1,2,3', - 'num_streams' : 2, - 'coupled_streams' : 2 + parameters: { + channel_mapping: '0,1,2,3', + num_streams: 2, + coupled_streams: 2, }, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'transport-cc' } - ] + rtcpFeedback: [{ type: 'nack' }, { type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/multiopus', - clockRate : 48000, - channels : 6, + kind: 'audio', + mimeType: 'audio/multiopus', + clockRate: 48000, + channels: 6, // 5.1. - parameters : - { - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 + parameters: { + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 2, }, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'transport-cc' } - ] + rtcpFeedback: [{ type: 'nack' }, { type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/multiopus', - clockRate : 48000, - channels : 8, + kind: 'audio', + mimeType: 'audio/multiopus', + clockRate: 48000, + channels: 8, // 7.1. - parameters : - { - 'channel_mapping' : '0,6,1,2,3,4,5,7', - 'num_streams' : 5, - 'coupled_streams' : 3 + parameters: { + channel_mapping: '0,6,1,2,3,4,5,7', + num_streams: 5, + coupled_streams: 3, }, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'transport-cc' } - ] - }, - { - kind : 'audio', - mimeType : 'audio/PCMU', - preferredPayloadType : 0, - clockRate : 8000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] - }, - { - kind : 'audio', - mimeType : 'audio/PCMA', - preferredPayloadType : 8, - clockRate : 8000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] + rtcpFeedback: [{ type: 'nack' }, { type: 'transport-cc' }], + }, + { + kind: 'audio', + mimeType: 'audio/PCMU', + preferredPayloadType: 0, + clockRate: 8000, + rtcpFeedback: [{ type: 'transport-cc' }], + }, + { + kind: 'audio', + mimeType: 'audio/PCMA', + preferredPayloadType: 8, + clockRate: 8000, + rtcpFeedback: [{ type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/ISAC', - clockRate : 32000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] + kind: 'audio', + mimeType: 'audio/ISAC', + clockRate: 32000, + rtcpFeedback: [{ type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/ISAC', - clockRate : 16000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] + kind: 'audio', + mimeType: 'audio/ISAC', + clockRate: 16000, + rtcpFeedback: [{ type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/G722', - preferredPayloadType : 9, - clockRate : 8000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] + kind: 'audio', + mimeType: 'audio/G722', + preferredPayloadType: 9, + clockRate: 8000, + rtcpFeedback: [{ type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/iLBC', - clockRate : 8000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] + kind: 'audio', + mimeType: 'audio/iLBC', + clockRate: 8000, + rtcpFeedback: [{ type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/SILK', - clockRate : 24000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] + kind: 'audio', + mimeType: 'audio/SILK', + clockRate: 24000, + rtcpFeedback: [{ type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/SILK', - clockRate : 16000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] + kind: 'audio', + mimeType: 'audio/SILK', + clockRate: 16000, + rtcpFeedback: [{ type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/SILK', - clockRate : 12000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] + kind: 'audio', + mimeType: 'audio/SILK', + clockRate: 12000, + rtcpFeedback: [{ type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/SILK', - clockRate : 8000, - rtcpFeedback : - [ - { type: 'transport-cc' } - ] + kind: 'audio', + mimeType: 'audio/SILK', + clockRate: 8000, + rtcpFeedback: [{ type: 'transport-cc' }], }, { - kind : 'audio', - mimeType : 'audio/CN', - preferredPayloadType : 13, - clockRate : 32000 + kind: 'audio', + mimeType: 'audio/CN', + preferredPayloadType: 13, + clockRate: 32000, }, { - kind : 'audio', - mimeType : 'audio/CN', - preferredPayloadType : 13, - clockRate : 16000 + kind: 'audio', + mimeType: 'audio/CN', + preferredPayloadType: 13, + clockRate: 16000, }, { - kind : 'audio', - mimeType : 'audio/CN', - preferredPayloadType : 13, - clockRate : 8000 + kind: 'audio', + mimeType: 'audio/CN', + preferredPayloadType: 13, + clockRate: 8000, }, { - kind : 'audio', - mimeType : 'audio/telephone-event', - clockRate : 48000 + kind: 'audio', + mimeType: 'audio/telephone-event', + clockRate: 48000, }, { - kind : 'audio', - mimeType : 'audio/telephone-event', - clockRate : 32000 + kind: 'audio', + mimeType: 'audio/telephone-event', + clockRate: 32000, }, { - kind : 'audio', - mimeType : 'audio/telephone-event', - clockRate : 16000 + kind: 'audio', + mimeType: 'audio/telephone-event', + clockRate: 16000, }, { - kind : 'audio', - mimeType : 'audio/telephone-event', - clockRate : 8000 + kind: 'audio', + mimeType: 'audio/telephone-event', + clockRate: 8000, }, { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000, - rtcpFeedback : - [ + kind: 'video', + mimeType: 'video/VP8', + clockRate: 90000, + rtcpFeedback: [ { type: 'nack' }, { type: 'nack', parameter: 'pli' }, { type: 'ccm', parameter: 'fir' }, { type: 'goog-remb' }, - { type: 'transport-cc' } - ] + { type: 'transport-cc' }, + ], }, { - kind : 'video', - mimeType : 'video/VP9', - clockRate : 90000, - rtcpFeedback : - [ + kind: 'video', + mimeType: 'video/VP9', + clockRate: 90000, + rtcpFeedback: [ { type: 'nack' }, { type: 'nack', parameter: 'pli' }, { type: 'ccm', parameter: 'fir' }, { type: 'goog-remb' }, - { type: 'transport-cc' } - ] + { type: 'transport-cc' }, + ], }, { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1 + kind: 'video', + mimeType: 'video/H264', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, }, - rtcpFeedback : - [ + rtcpFeedback: [ { type: 'nack' }, { type: 'nack', parameter: 'pli' }, { type: 'ccm', parameter: 'fir' }, { type: 'goog-remb' }, - { type: 'transport-cc' } - ] + { type: 'transport-cc' }, + ], }, { - kind : 'video', - mimeType : 'video/H264-SVC', - clockRate : 90000, - parameters : { - 'level-asymmetry-allowed' : 1 + kind: 'video', + mimeType: 'video/H264-SVC', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, }, - rtcpFeedback : [ + rtcpFeedback: [ { type: 'nack' }, { type: 'nack', parameter: 'pli' }, { type: 'ccm', parameter: 'fir' }, { type: 'goog-remb' }, - { type: 'transport-cc' } - ] + { type: 'transport-cc' }, + ], }, { - kind : 'video', - mimeType : 'video/H265', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1 + kind: 'video', + mimeType: 'video/H265', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, }, - rtcpFeedback : - [ + rtcpFeedback: [ { type: 'nack' }, { type: 'nack', parameter: 'pli' }, { type: 'ccm', parameter: 'fir' }, { type: 'goog-remb' }, - { type: 'transport-cc' } - ] - } + { type: 'transport-cc' }, + ], + }, ], - headerExtensions : - [ + headerExtensions: [ { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', - preferredId : 2, - preferredEncrypt : false, - direction : 'recvonly' + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', + preferredId: 2, + preferredEncrypt: false, + direction: 'recvonly', }, { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id', - preferredId : 3, - preferredEncrypt : false, - direction : 'recvonly' + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id', + preferredId: 3, + preferredEncrypt: false, + direction: 'recvonly', }, { - kind : 'audio', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId : 4, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'audio', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + preferredId: 4, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId : 4, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + preferredId: 4, + preferredEncrypt: false, + direction: 'sendrecv', }, // NOTE: For audio we just enable transport-wide-cc-01 when receiving media. { - kind : 'audio', - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - preferredId : 5, - preferredEncrypt : false, - direction : 'recvonly' + kind: 'audio', + uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + preferredId: 5, + preferredEncrypt: false, + direction: 'recvonly', }, { - kind : 'video', - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - preferredId : 5, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + preferredId: 5, + preferredEncrypt: false, + direction: 'sendrecv', }, // NOTE: Remove this once framemarking draft becomes RFC. { - kind : 'video', - uri : 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', - preferredId : 6, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', + preferredId: 6, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:framemarking', - preferredId : 7, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:framemarking', + preferredId: 7, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 10, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'urn:3gpp:video-orientation', - preferredId : 11, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'urn:3gpp:video-orientation', + preferredId: 11, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:toffset', - preferredId : 12, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:toffset', + preferredId: 12, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'audio', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', - preferredId : 13, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'audio', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', + preferredId: 13, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', - preferredId : 13, - preferredEncrypt : false, - direction : 'sendrecv' - } - ] + kind: 'video', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', + preferredId: 13, + preferredEncrypt: false, + direction: 'sendrecv', + }, + ], }; export { supportedRtpCapabilities }; diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index 99e8686c34..c42462c553 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -1,47 +1,37 @@ import * as mediasoup from '../'; import * as utils from '../utils'; -type TestContext = -{ +type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; }; -const ctx: TestContext = -{ - mediaCodecs : utils.deepFreeze( - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } - } - ] - ) +const ctx: TestContext = { + mediaCodecs: utils.deepFreeze([ + { + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar', + }, + }, + ]), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); - ctx.router = await ctx.worker.createRouter( - { mediaCodecs: ctx.mediaCodecs } - ); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('router.createActiveSpeakerObserver() succeeds', async () => -{ +test('router.createActiveSpeakerObserver() succeeds', async () => { const onObserverNewRtpObserver = jest.fn(); ctx.router!.observer.once('newrtpobserver', onObserverNewRtpObserver); @@ -55,33 +45,28 @@ test('router.createActiveSpeakerObserver() succeeds', async () => expect(activeSpeakerObserver.paused).toBe(false); expect(activeSpeakerObserver.appData).toEqual({}); - await expect(ctx.router!.dump()) - .resolves - .toMatchObject( - { - rtpObserverIds : [ activeSpeakerObserver.id ] - }); + await expect(ctx.router!.dump()).resolves.toMatchObject({ + rtpObserverIds: [activeSpeakerObserver.id], + }); }, 2000); -test('router.createActiveSpeakerObserver() with wrong arguments rejects with TypeError', async () => -{ - await expect(ctx.router!.createActiveSpeakerObserver( - // @ts-ignore - { interval: false } - )) - .rejects - .toThrow(TypeError); - - await expect(ctx.router!.createActiveSpeakerObserver( - // @ts-ignore - { appData: 'NOT-AN-OBJECT' } - )) - .rejects - .toThrow(TypeError); +test('router.createActiveSpeakerObserver() with wrong arguments rejects with TypeError', async () => { + await expect( + ctx.router!.createActiveSpeakerObserver( + // @ts-ignore + { interval: false }, + ), + ).rejects.toThrow(TypeError); + + await expect( + ctx.router!.createActiveSpeakerObserver( + // @ts-ignore + { appData: 'NOT-AN-OBJECT' }, + ), + ).rejects.toThrow(TypeError); }, 2000); -test('activeSpeakerObserver.pause() and resume() succeed', async () => -{ +test('activeSpeakerObserver.pause() and resume() succeed', async () => { const activeSpeakerObserver = await ctx.router!.createActiveSpeakerObserver(); await activeSpeakerObserver.pause(); @@ -93,10 +78,10 @@ test('activeSpeakerObserver.pause() and resume() succeed', async () => expect(activeSpeakerObserver.paused).toBe(false); }, 2000); -test('activeSpeakerObserver.close() succeeds', async () => -{ - const activeSpeakerObserver = - await ctx.router!.createAudioLevelObserver({ maxEntries: 8 }); +test('activeSpeakerObserver.close() succeeds', async () => { + const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver({ + maxEntries: 8, + }); let dump = await ctx.router!.dump(); @@ -111,12 +96,10 @@ test('activeSpeakerObserver.close() succeeds', async () => expect(dump.rtpObserverIds.length).toBe(0); }, 2000); -test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () => -{ +test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () => { const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise((resolve) => - { + await new Promise(resolve => { activeSpeakerObserver.on('routerclose', resolve); ctx.router!.close(); }); @@ -124,12 +107,10 @@ test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () = expect(activeSpeakerObserver.closed).toBe(true); }, 2000); -test('ActiveSpeakerObserver emits "routerclose" if Worker is closed', async () => -{ +test('ActiveSpeakerObserver emits "routerclose" if Worker is closed', async () => { const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise((resolve) => - { + await new Promise(resolve => { activeSpeakerObserver.on('routerclose', resolve); ctx.worker!.close(); }); diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index 3603d7da83..e96537a5c8 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -1,47 +1,37 @@ import * as mediasoup from '../'; import * as utils from '../utils'; -type TestContext = -{ +type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; }; -const ctx: TestContext = -{ - mediaCodecs : utils.deepFreeze( - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } - } - ] - ) +const ctx: TestContext = { + mediaCodecs: utils.deepFreeze([ + { + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar', + }, + }, + ]), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); - ctx.router = await ctx.worker.createRouter( - { mediaCodecs: ctx.mediaCodecs } - ); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('router.createAudioLevelObserver() succeeds', async () => -{ +test('router.createAudioLevelObserver() succeeds', async () => { const onObserverNewRtpObserver = jest.fn(); ctx.router!.observer.once('newrtpobserver', onObserverNewRtpObserver); @@ -55,42 +45,37 @@ test('router.createAudioLevelObserver() succeeds', async () => expect(audioLevelObserver.paused).toBe(false); expect(audioLevelObserver.appData).toEqual({}); - await expect(ctx.router!.dump()) - .resolves - .toMatchObject( - { - rtpObserverIds : [ audioLevelObserver.id ] - }); + await expect(ctx.router!.dump()).resolves.toMatchObject({ + rtpObserverIds: [audioLevelObserver.id], + }); }, 2000); -test('router.createAudioLevelObserver() with wrong arguments rejects with TypeError', async () => -{ - await expect(ctx.router!.createAudioLevelObserver({ maxEntries: 0 })) - .rejects - .toThrow(TypeError); - - await expect(ctx.router!.createAudioLevelObserver({ maxEntries: -10 })) - .rejects - .toThrow(TypeError); - - // @ts-ignore - await expect(ctx.router!.createAudioLevelObserver({ threshold: 'foo' })) - .rejects - .toThrow(TypeError); - - // @ts-ignore - await expect(ctx.router!.createAudioLevelObserver({ interval: false })) - .rejects - .toThrow(TypeError); - - // @ts-ignore - await expect(ctx.router!.createAudioLevelObserver({ appData: 'NOT-AN-OBJECT' })) - .rejects - .toThrow(TypeError); +test('router.createAudioLevelObserver() with wrong arguments rejects with TypeError', async () => { + await expect( + ctx.router!.createAudioLevelObserver({ maxEntries: 0 }), + ).rejects.toThrow(TypeError); + + await expect( + ctx.router!.createAudioLevelObserver({ maxEntries: -10 }), + ).rejects.toThrow(TypeError); + + await expect( + // @ts-ignore + ctx.router!.createAudioLevelObserver({ threshold: 'foo' }), + ).rejects.toThrow(TypeError); + + await expect( + // @ts-ignore + ctx.router!.createAudioLevelObserver({ interval: false }), + ).rejects.toThrow(TypeError); + + await expect( + // @ts-ignore + ctx.router!.createAudioLevelObserver({ appData: 'NOT-AN-OBJECT' }), + ).rejects.toThrow(TypeError); }, 2000); -test('audioLevelObserver.pause() and resume() succeed', async () => -{ +test('audioLevelObserver.pause() and resume() succeed', async () => { const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); await audioLevelObserver.pause(); @@ -102,10 +87,10 @@ test('audioLevelObserver.pause() and resume() succeed', async () => expect(audioLevelObserver.paused).toBe(false); }, 2000); -test('audioLevelObserver.close() succeeds', async () => -{ - const audioLevelObserver = - await ctx.router!.createAudioLevelObserver({ maxEntries: 8 }); +test('audioLevelObserver.close() succeeds', async () => { + const audioLevelObserver = await ctx.router!.createAudioLevelObserver({ + maxEntries: 8, + }); let dump = await ctx.router!.dump(); @@ -120,12 +105,10 @@ test('audioLevelObserver.close() succeeds', async () => expect(dump.rtpObserverIds.length).toBe(0); }, 2000); -test('AudioLevelObserver emits "routerclose" if Router is closed', async () => -{ +test('AudioLevelObserver emits "routerclose" if Router is closed', async () => { const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise((resolve) => - { + await new Promise(resolve => { audioLevelObserver.on('routerclose', resolve); ctx.router!.close(); }); @@ -133,12 +116,10 @@ test('AudioLevelObserver emits "routerclose" if Router is closed', async () => expect(audioLevelObserver.closed).toBe(true); }, 2000); -test('AudioLevelObserver emits "routerclose" if Worker is closed', async () => -{ +test('AudioLevelObserver emits "routerclose" if Worker is closed', async () => { const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise((resolve) => - { + await new Promise(resolve => { audioLevelObserver.on('routerclose', resolve); ctx.worker!.close(); }); diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index 92bf19cd07..d2d7e8a751 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -5,12 +5,11 @@ import * as utils from '../utils'; import { Notification, Body as NotificationBody, - Event + Event, } from '../fbs/notification'; import * as FbsConsumer from '../fbs/consumer'; -type TestContext = -{ +type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; audioProducerOptions: mediasoup.types.ProducerOptions; videoProducerOptions: mediasoup.types.ProducerOptions; @@ -23,279 +22,246 @@ type TestContext = videoProducer?: mediasoup.types.Producer; }; -const ctx: TestContext = -{ - mediaCodecs : utils.deepFreeze( - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - foo : 'bar' - } - }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 - }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - foo : 'bar' - } - } - ] - ), - audioProducerOptions : utils.deepFreeze( +const ctx: TestContext = { + mediaCodecs: utils.deepFreeze([ { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ - { - mimeType : 'audio/opus', - payloadType : 111, - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - usedtx : 1, - foo : 222.222, - bar : '333' - } - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 - }, - { - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id : 12 - } - ], - encodings : [ { ssrc: 11111111 } ], - rtcp : - { - cname : 'FOOBAR' - } + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + parameters: { + foo: 'bar', }, - appData : { foo: 1, bar: '2' } - } - ), - videoProducerOptions : utils.deepFreeze( + }, { - kind : 'video', - rtpParameters : - { - mid : 'VIDEO', - codecs : - [ - { - mimeType : 'video/h264', - payloadType : 112, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'goog-remb', parameter: '' } - ] - }, - { - mimeType : 'video/rtx', - payloadType : 113, - clockRate : 90000, - parameters : { apt: 112 } - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 - }, - { - uri : 'urn:3gpp:video-orientation', - id : 13 - } - ], - encodings : - [ - { ssrc: 22222222, rtx: { ssrc: 22222223 } }, - { ssrc: 22222224, rtx: { ssrc: 22222225 } }, - { ssrc: 22222226, rtx: { ssrc: 22222227 } }, - { ssrc: 22222228, rtx: { ssrc: 22222229 } } - ], - rtcp : - { - cname : 'FOOBAR' - } - }, - appData : { foo: 1, bar: '2' } - } - ), - consumerDeviceCapabilities : utils.deepFreeze( + kind: 'video', + mimeType: 'video/VP8', + clockRate: 90000, + }, { - codecs : - [ - { - mimeType : 'audio/opus', - kind : 'audio', - preferredPayloadType : 100, - clockRate : 48000, - channels : 2, - rtcpFeedback : - [ - { type: 'nack', parameter: '' } - ] - }, + kind: 'video', + mimeType: 'video/H264', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + foo: 'bar', + }, + }, + ]), + audioProducerOptions: utils.deepFreeze({ + kind: 'audio', + rtpParameters: { + mid: 'AUDIO', + codecs: [ { - mimeType : 'video/H264', - kind : 'video', - preferredPayloadType : 101, - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' + mimeType: 'audio/opus', + payloadType: 111, + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + usedtx: 1, + foo: 222.222, + bar: '333', }, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb', parameter: '' } - ] }, - { - mimeType : 'video/rtx', - kind : 'video', - preferredPayloadType : 102, - clockRate : 90000, - parameters : - { - apt : 101 - }, - rtcpFeedback : [] - } ], - headerExtensions : - [ + headerExtensions: [ { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, }, { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + id: 12, }, + ], + encodings: [{ ssrc: 11111111 }], + rtcp: { + cname: 'FOOBAR', + }, + }, + appData: { foo: 1, bar: '2' }, + }), + videoProducerOptions: utils.deepFreeze({ + kind: 'video', + rtpParameters: { + mid: 'VIDEO', + codecs: [ { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', - preferredId : 2, - preferredEncrypt : false + mimeType: 'video/h264', + payloadType: 112, + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'goog-remb', parameter: '' }, + ], }, { - kind : 'audio', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId : 4, - preferredEncrypt : false + mimeType: 'video/rtx', + payloadType: 113, + clockRate: 90000, + parameters: { apt: 112 }, }, + ], + headerExtensions: [ { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId : 4, - preferredEncrypt : false + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, }, { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 10, - preferredEncrypt : false + uri: 'urn:3gpp:video-orientation', + id: 13, }, - { - kind : 'video', - uri : 'urn:3gpp:video-orientation', - preferredId : 11, - preferredEncrypt : false + ], + encodings: [ + { ssrc: 22222222, rtx: { ssrc: 22222223 } }, + { ssrc: 22222224, rtx: { ssrc: 22222225 } }, + { ssrc: 22222226, rtx: { ssrc: 22222227 } }, + { ssrc: 22222228, rtx: { ssrc: 22222229 } }, + ], + rtcp: { + cname: 'FOOBAR', + }, + }, + appData: { foo: 1, bar: '2' }, + }), + consumerDeviceCapabilities: utils.deepFreeze({ + codecs: [ + { + mimeType: 'audio/opus', + kind: 'audio', + preferredPayloadType: 100, + clockRate: 48000, + channels: 2, + rtcpFeedback: [{ type: 'nack', parameter: '' }], + }, + { + mimeType: 'video/H264', + kind: 'video', + preferredPayloadType: 101, + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:toffset', - preferredId : 12, - preferredEncrypt : false - } - ] - } - ) + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb', parameter: '' }, + ], + }, + { + mimeType: 'video/rtx', + kind: 'video', + preferredPayloadType: 102, + clockRate: 90000, + parameters: { + apt: 101, + }, + rtcpFeedback: [], + }, + ], + headerExtensions: [ + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', + preferredId: 2, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId: 4, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId: 4, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:3gpp:video-orientation', + preferredId: 11, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:toffset', + preferredId: 12, + preferredEncrypt: false, + }, + ], + }), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); - ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ] - }); - ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ] - }); - ctx.audioProducer = await ctx.webRtcTransport1.produce(ctx.audioProducerOptions); - ctx.videoProducer = await ctx.webRtcTransport1.produce(ctx.videoProducerOptions); + ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + }); + ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + }); + ctx.audioProducer = await ctx.webRtcTransport1.produce( + ctx.audioProducerOptions, + ); + ctx.videoProducer = await ctx.webRtcTransport1.produce( + ctx.videoProducerOptions, + ); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('transport.consume() succeeds', async () => -{ +test('transport.consume() succeeds', async () => { const onObserverNewConsumer1 = jest.fn(); ctx.webRtcTransport2!.observer.once('newconsumer', onObserverNewConsumer1); - expect(ctx.router!.canConsume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - })) - .toBe(true); - - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities, - appData : { baz: 'LOL' } - }); + expect( + ctx.router!.canConsume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }), + ).toBe(true); + + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + appData: { baz: 'LOL' }, + }); expect(onObserverNewConsumer1).toHaveBeenCalledTimes(1); expect(onObserverNewConsumer1).toHaveBeenCalledWith(audioConsumer); @@ -306,76 +272,73 @@ test('transport.consume() succeeds', async () => expect(typeof audioConsumer.rtpParameters).toBe('object'); expect(audioConsumer.rtpParameters.mid).toBe('0'); expect(audioConsumer.rtpParameters.codecs.length).toBe(1); - expect(audioConsumer.rtpParameters.codecs[0]).toEqual( - { - mimeType : 'audio/opus', - payloadType : 100, - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - usedtx : 1, - foo : 222.222, - bar : '333' - }, - rtcpFeedback : [] - }); + expect(audioConsumer.rtpParameters.codecs[0]).toEqual({ + mimeType: 'audio/opus', + payloadType: 100, + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + usedtx: 1, + foo: 222.222, + bar: '333', + }, + rtcpFeedback: [], + }); expect(audioConsumer.type).toBe('simple'); expect(audioConsumer.paused).toBe(false); expect(audioConsumer.producerPaused).toBe(false); expect(audioConsumer.priority).toBe(1); - expect(audioConsumer.score).toEqual( - { score: 10, producerScore: 0, producerScores: [ 0 ] }); + expect(audioConsumer.score).toEqual({ + score: 10, + producerScore: 0, + producerScores: [0], + }); expect(audioConsumer.preferredLayers).toBeUndefined(); expect(audioConsumer.currentLayers).toBeUndefined(); expect(audioConsumer.appData).toEqual({ baz: 'LOL' }); const dump1 = await ctx.router!.dump(); - expect(dump1.mapProducerIdConsumerIds) - .toEqual(expect.arrayContaining( - [ - { key: ctx.audioProducer!.id, values: [ audioConsumer.id ] } - ])); - - expect(dump1.mapConsumerIdProducerId) - .toEqual(expect.arrayContaining( - [ - { key: audioConsumer.id, value: ctx.audioProducer!.id } - ])); - - await expect(ctx.webRtcTransport2!.dump()) - .resolves - .toMatchObject( - { - id : ctx.webRtcTransport2!.id, - producerIds : [], - consumerIds : [ audioConsumer.id ] - }); + expect(dump1.mapProducerIdConsumerIds).toEqual( + expect.arrayContaining([ + { key: ctx.audioProducer!.id, values: [audioConsumer.id] }, + ]), + ); + + expect(dump1.mapConsumerIdProducerId).toEqual( + expect.arrayContaining([ + { key: audioConsumer.id, value: ctx.audioProducer!.id }, + ]), + ); + + await expect(ctx.webRtcTransport2!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport2!.id, + producerIds: [], + consumerIds: [audioConsumer.id], + }); const onObserverNewConsumer2 = jest.fn(); ctx.webRtcTransport2!.observer.once('newconsumer', onObserverNewConsumer2); - expect(ctx.router!.canConsume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - })) - .toBe(true); + expect( + ctx.router!.canConsume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }), + ).toBe(true); // Pause videoProducer. ctx.videoProducer!.pause(); - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities, - paused : true, - preferredLayers : { spatialLayer: 12 }, - appData : { baz: 'LOL' } - }); + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + paused: true, + preferredLayers: { spatialLayer: 12 }, + appData: { baz: 'LOL' }, + }); expect(onObserverNewConsumer2).toHaveBeenCalledTimes(1); expect(onObserverNewConsumer2).toHaveBeenCalledWith(videoConsumer); @@ -386,41 +349,41 @@ test('transport.consume() succeeds', async () => expect(typeof videoConsumer.rtpParameters).toBe('object'); expect(videoConsumer.rtpParameters.mid).toBe('1'); expect(videoConsumer.rtpParameters.codecs.length).toBe(2); - expect(videoConsumer.rtpParameters.codecs[0]).toEqual( - { - mimeType : 'video/H264', - payloadType : 103, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb', parameter: '' } - ] - }); - expect(videoConsumer.rtpParameters.codecs[1]).toEqual( - { - mimeType : 'video/rtx', - payloadType : 104, - clockRate : 90000, - parameters : { apt: 103 }, - rtcpFeedback : [] - }); + expect(videoConsumer.rtpParameters.codecs[0]).toEqual({ + mimeType: 'video/H264', + payloadType: 103, + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb', parameter: '' }, + ], + }); + expect(videoConsumer.rtpParameters.codecs[1]).toEqual({ + mimeType: 'video/rtx', + payloadType: 104, + clockRate: 90000, + parameters: { apt: 103 }, + rtcpFeedback: [], + }); expect(videoConsumer.type).toBe('simulcast'); expect(videoConsumer.paused).toBe(true); expect(videoConsumer.producerPaused).toBe(true); expect(videoConsumer.priority).toBe(1); - expect(videoConsumer.score).toEqual( - { score: 10, producerScore: 0, producerScores: [ 0, 0, 0, 0 ] }); - expect(videoConsumer.preferredLayers).toEqual( - { spatialLayer: 3, temporalLayer: 0 } - ); + expect(videoConsumer.score).toEqual({ + score: 10, + producerScore: 0, + producerScores: [0, 0, 0, 0], + }); + expect(videoConsumer.preferredLayers).toEqual({ + spatialLayer: 3, + temporalLayer: 0, + }); expect(videoConsumer.currentLayers).toBeUndefined(); expect(videoConsumer.appData).toEqual({ baz: 'LOL' }); @@ -428,19 +391,18 @@ test('transport.consume() succeeds', async () => ctx.webRtcTransport2!.observer.once('newconsumer', onObserverNewConsumer3); - expect(ctx.router!.canConsume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - })) - .toBe(true); - - const videoPipeConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities, - pipe : true - }); + expect( + ctx.router!.canConsume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }), + ).toBe(true); + + const videoPipeConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + pipe: true, + }); expect(onObserverNewConsumer3).toHaveBeenCalledTimes(1); expect(onObserverNewConsumer3).toHaveBeenCalledWith(videoPipeConsumer); @@ -451,38 +413,37 @@ test('transport.consume() succeeds', async () => expect(typeof videoPipeConsumer.rtpParameters).toBe('object'); expect(videoPipeConsumer.rtpParameters.mid).toBeUndefined(); expect(videoPipeConsumer.rtpParameters.codecs.length).toBe(2); - expect(videoPipeConsumer.rtpParameters.codecs[0]).toEqual( - { - mimeType : 'video/H264', - payloadType : 103, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb', parameter: '' } - ] - }); - expect(videoPipeConsumer.rtpParameters.codecs[1]).toEqual( - { - mimeType : 'video/rtx', - payloadType : 104, - clockRate : 90000, - parameters : { apt: 103 }, - rtcpFeedback : [] - }); + expect(videoPipeConsumer.rtpParameters.codecs[0]).toEqual({ + mimeType: 'video/H264', + payloadType: 103, + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb', parameter: '' }, + ], + }); + expect(videoPipeConsumer.rtpParameters.codecs[1]).toEqual({ + mimeType: 'video/rtx', + payloadType: 104, + clockRate: 90000, + parameters: { apt: 103 }, + rtcpFeedback: [], + }); expect(videoPipeConsumer.type).toBe('pipe'); expect(videoPipeConsumer.paused).toBe(false); expect(videoPipeConsumer.producerPaused).toBe(true); expect(videoPipeConsumer.priority).toBe(1); - expect(videoPipeConsumer.score).toEqual( - { score: 10, producerScore: 10, producerScores: [ 0, 0, 0, 0 ] }); + expect(videoPipeConsumer.score).toEqual({ + score: 10, + producerScore: 10, + producerScores: [0, 0, 0, 0], + }); expect(videoPipeConsumer.preferredLayers).toBeUndefined(); expect(videoPipeConsumer.currentLayers).toBeUndefined(); expect(videoPipeConsumer.appData).toBeUndefined; @@ -491,166 +452,150 @@ test('transport.consume() succeeds', async () => expect(Array.isArray(dump2.mapProducerIdConsumerIds)).toBe(true); - expect(dump2.mapProducerIdConsumerIds) - .toEqual(expect.arrayContaining( - [ - { - key : ctx.audioProducer!.id, - values : [ audioConsumer.id ] - }, - { - key : ctx.videoProducer!.id, - values : expect.arrayContaining( - [ videoConsumer.id, videoPipeConsumer.id ] - ) - } - ])); - expect(dump2.mapConsumerIdProducerId) - .toEqual(expect.arrayContaining( - [ - { key: audioConsumer.id, value: ctx.audioProducer!.id }, - { key: videoConsumer.id, value: ctx.videoProducer!.id }, - { key: videoPipeConsumer.id, value: ctx.videoProducer!.id } - ])); - - await expect(ctx.webRtcTransport2!.dump()) - .resolves - .toMatchObject( + expect(dump2.mapProducerIdConsumerIds).toEqual( + expect.arrayContaining([ { - id : ctx.webRtcTransport2!.id, - producerIds : [], - consumerIds : expect.arrayContaining( - [ - audioConsumer.id, - videoConsumer.id, - videoPipeConsumer.id - ]) - }); + key: ctx.audioProducer!.id, + values: [audioConsumer.id], + }, + { + key: ctx.videoProducer!.id, + values: expect.arrayContaining([ + videoConsumer.id, + videoPipeConsumer.id, + ]), + }, + ]), + ); + expect(dump2.mapConsumerIdProducerId).toEqual( + expect.arrayContaining([ + { key: audioConsumer.id, value: ctx.audioProducer!.id }, + { key: videoConsumer.id, value: ctx.videoProducer!.id }, + { key: videoPipeConsumer.id, value: ctx.videoProducer!.id }, + ]), + ); + + await expect(ctx.webRtcTransport2!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport2!.id, + producerIds: [], + consumerIds: expect.arrayContaining([ + audioConsumer.id, + videoConsumer.id, + videoPipeConsumer.id, + ]), + }); }, 2000); -test('transport.consume() with enableRtx succeeds', async () => -{ - const audioConsumer2 = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities, - enableRtx : true - }); +test('transport.consume() with enableRtx succeeds', async () => { + const audioConsumer2 = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + enableRtx: true, + }); expect(audioConsumer2.kind).toBe('audio'); expect(audioConsumer2.rtpParameters.codecs.length).toBe(1); - expect(audioConsumer2.rtpParameters.codecs[0]).toEqual( - { - mimeType : 'audio/opus', - payloadType : 100, - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - usedtx : 1, - foo : 222.222, - bar : '333' - }, - rtcpFeedback : [ { type: 'nack', parameter: '' } ] - }); + expect(audioConsumer2.rtpParameters.codecs[0]).toEqual({ + mimeType: 'audio/opus', + payloadType: 100, + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + usedtx: 1, + foo: 222.222, + bar: '333', + }, + rtcpFeedback: [{ type: 'nack', parameter: '' }], + }); }, 2000); -test('transport.consume() can be created with user provided mid', async () => -{ - const audioConsumer1 = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('transport.consume() can be created with user provided mid', async () => { + const audioConsumer1 = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); expect(audioConsumer1.rtpParameters.mid).toEqual( - expect.stringMatching(/^[0-9]+/)); + expect.stringMatching(/^[0-9]+/), + ); - const audioConsumer2 = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - mid : 'custom-mid', - rtpCapabilities : ctx.consumerDeviceCapabilities - }); + const audioConsumer2 = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + mid: 'custom-mid', + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); expect(audioConsumer2.rtpParameters.mid).toBe('custom-mid'); - const audioConsumer3 = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); + const audioConsumer3 = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); expect(audioConsumer3.rtpParameters.mid).toEqual( - expect.stringMatching(/^[0-9]+/)); + expect.stringMatching(/^[0-9]+/), + ); expect(Number(audioConsumer1.rtpParameters.mid) + 1).toBe( - Number(audioConsumer3.rtpParameters.mid)); + Number(audioConsumer3.rtpParameters.mid), + ); }, 2000); -test('transport.consume() with incompatible rtpCapabilities rejects with UnsupportedError', async () => -{ +test('transport.consume() with incompatible rtpCapabilities rejects with UnsupportedError', async () => { let invalidDeviceCapabilities: mediasoup.types.RtpCapabilities; - invalidDeviceCapabilities = - { - codecs : - [ + invalidDeviceCapabilities = { + codecs: [ { - kind : 'audio', - mimeType : 'audio/ISAC', - preferredPayloadType : 100, - clockRate : 32000, - channels : 1 - } + kind: 'audio', + mimeType: 'audio/ISAC', + preferredPayloadType: 100, + clockRate: 32000, + channels: 1, + }, ], - headerExtensions : [] + headerExtensions: [], }; - expect(ctx.router!.canConsume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : invalidDeviceCapabilities - })) - .toBe(false); - - await expect(ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : invalidDeviceCapabilities - })) - .rejects - .toThrow(UnsupportedError); - - invalidDeviceCapabilities = - { - codecs : [], - headerExtensions : [] + expect( + ctx.router!.canConsume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: invalidDeviceCapabilities, + }), + ).toBe(false); + + await expect( + ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: invalidDeviceCapabilities, + }), + ).rejects.toThrow(UnsupportedError); + + invalidDeviceCapabilities = { + codecs: [], + headerExtensions: [], }; - expect(ctx.router!.canConsume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : invalidDeviceCapabilities - })) - .toBe(false); - - await expect(ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : invalidDeviceCapabilities - })) - .rejects - .toThrow(UnsupportedError); + expect( + ctx.router!.canConsume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: invalidDeviceCapabilities, + }), + ).toBe(false); + + await expect( + ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: invalidDeviceCapabilities, + }), + ).rejects.toThrow(UnsupportedError); }, 2000); -test('consumer.dump() succeeds', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.dump() succeeds', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); const dump1 = await audioConsumer.dump(); expect(dump1.id).toBe(audioConsumer.id); @@ -663,69 +608,61 @@ test('consumer.dump() succeeds', async () => expect(dump1.rtpParameters.codecs[0].payloadType).toBe(100); expect(dump1.rtpParameters.codecs[0].clockRate).toBe(48000); expect(dump1.rtpParameters.codecs[0].channels).toBe(2); - expect(dump1.rtpParameters.codecs[0].parameters) - .toEqual( - { - useinbandfec : 1, - usedtx : 1, - foo : 222.222, - bar : '333' - }); + expect(dump1.rtpParameters.codecs[0].parameters).toEqual({ + useinbandfec: 1, + usedtx: 1, + foo: 222.222, + bar: '333', + }); expect(dump1.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); expect(Array.isArray(dump1.rtpParameters.headerExtensions)).toBe(true); expect(dump1.rtpParameters.headerExtensions!.length).toBe(3); - expect(dump1.rtpParameters.headerExtensions).toEqual( - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 1, - encrypt : false, - parameters : {} - }, - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - id : 4, - parameters : {}, - encrypt : false - }, - { - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id : 10, - parameters : {}, - encrypt : false - } - ]); + expect(dump1.rtpParameters.headerExtensions).toEqual([ + { + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 1, + encrypt: false, + parameters: {}, + }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + id: 4, + parameters: {}, + encrypt: false, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + id: 10, + parameters: {}, + encrypt: false, + }, + ]); expect(Array.isArray(dump1.rtpParameters.encodings)).toBe(true); expect(dump1.rtpParameters.encodings!.length).toBe(1); - expect(dump1.rtpParameters.encodings).toEqual( - [ - expect.objectContaining( - { - codecPayloadType : 100, - ssrc : audioConsumer.rtpParameters.encodings?.[0].ssrc - }) - ]); + expect(dump1.rtpParameters.encodings).toEqual([ + expect.objectContaining({ + codecPayloadType: 100, + ssrc: audioConsumer.rtpParameters.encodings?.[0].ssrc, + }), + ]); expect(dump1.type).toBe('simple'); expect(Array.isArray(dump1.consumableRtpEncodings)).toBe(true); expect(dump1.consumableRtpEncodings!.length).toBe(1); - expect(dump1.consumableRtpEncodings).toEqual( - [ - expect.objectContaining( - { - ssrc : ctx.audioProducer!.consumableRtpParameters.encodings?.[0].ssrc - }) - ]); - expect(dump1.supportedCodecPayloadTypes).toEqual([ 100 ]); + expect(dump1.consumableRtpEncodings).toEqual([ + expect.objectContaining({ + ssrc: ctx.audioProducer!.consumableRtpParameters.encodings?.[0].ssrc, + }), + ]); + expect(dump1.supportedCodecPayloadTypes).toEqual([100]); expect(dump1.paused).toBe(false); expect(dump1.producerPaused).toBe(false); expect(dump1.priority).toBe(1); - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities, - paused : true - }); + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + paused: true, + }); const dump2 = await videoConsumer.dump(); expect(dump2.id).toBe(videoConsumer.id); @@ -738,138 +675,119 @@ test('consumer.dump() succeeds', async () => expect(dump2.rtpParameters.codecs[0].payloadType).toBe(103); expect(dump2.rtpParameters.codecs[0].clockRate).toBe(90000); expect(dump2.rtpParameters.codecs[0].channels).toBeUndefined(); - expect(dump2.rtpParameters.codecs[0].parameters) - .toEqual( - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }); - expect(dump2.rtpParameters.codecs[0].rtcpFeedback).toEqual( - [ - { type: 'nack' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb' } - ]); + expect(dump2.rtpParameters.codecs[0].parameters).toEqual({ + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }); + expect(dump2.rtpParameters.codecs[0].rtcpFeedback).toEqual([ + { type: 'nack' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb' }, + ]); expect(Array.isArray(dump2.rtpParameters.headerExtensions)).toBe(true); expect(dump2.rtpParameters.headerExtensions!.length).toBe(4); - expect(dump2.rtpParameters.headerExtensions).toEqual( - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 1, - encrypt : false, - parameters : {} - }, - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - id : 4, - parameters : {}, - encrypt : false - }, - { - uri : 'urn:3gpp:video-orientation', - id : 11, - parameters : {}, - encrypt : false - }, - { - uri : 'urn:ietf:params:rtp-hdrext:toffset', - id : 12, - parameters : {}, - encrypt : false - } - ]); + expect(dump2.rtpParameters.headerExtensions).toEqual([ + { + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 1, + encrypt: false, + parameters: {}, + }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + id: 4, + parameters: {}, + encrypt: false, + }, + { + uri: 'urn:3gpp:video-orientation', + id: 11, + parameters: {}, + encrypt: false, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:toffset', + id: 12, + parameters: {}, + encrypt: false, + }, + ]); expect(Array.isArray(dump2.rtpParameters.encodings)).toBe(true); expect(dump2.rtpParameters.encodings!.length).toBe(1); - expect(dump2.rtpParameters.encodings).toMatchObject( - [ - { - codecPayloadType : 103, - ssrc : videoConsumer.rtpParameters.encodings?.[0].ssrc, - rtx : - { - ssrc : videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc - }, - scalabilityMode : 'L4T1' - } - ]); + expect(dump2.rtpParameters.encodings).toMatchObject([ + { + codecPayloadType: 103, + ssrc: videoConsumer.rtpParameters.encodings?.[0].ssrc, + rtx: { + ssrc: videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc, + }, + scalabilityMode: 'L4T1', + }, + ]); expect(Array.isArray(dump2.consumableRtpEncodings)).toBe(true); expect(dump2.consumableRtpEncodings!.length).toBe(4); expect(dump2.consumableRtpEncodings![0]).toEqual( - expect.objectContaining( - { - ssrc : ctx.videoProducer!.consumableRtpParameters.encodings?.[0].ssrc - })); + expect.objectContaining({ + ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[0].ssrc, + }), + ); expect(dump2.consumableRtpEncodings![1]).toEqual( - expect.objectContaining( - { - ssrc : ctx.videoProducer!.consumableRtpParameters.encodings?.[1].ssrc - })); + expect.objectContaining({ + ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[1].ssrc, + }), + ); expect(dump2.consumableRtpEncodings![2]).toEqual( - expect.objectContaining( - { - ssrc : ctx.videoProducer!.consumableRtpParameters.encodings?.[2].ssrc - })); + expect.objectContaining({ + ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[2].ssrc, + }), + ); expect(dump2.consumableRtpEncodings![3]).toEqual( - expect.objectContaining( - { - ssrc : ctx.videoProducer!.consumableRtpParameters.encodings?.[3].ssrc - })); - expect(dump2.supportedCodecPayloadTypes).toEqual([ 103 ]); + expect.objectContaining({ + ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[3].ssrc, + }), + ); + expect(dump2.supportedCodecPayloadTypes).toEqual([103]); expect(dump2.paused).toBe(true); expect(dump2.producerPaused).toBe(false); expect(dump2.priority).toBe(1); }, 2000); -test('consumer.getStats() succeeds', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); - - await expect(audioConsumer.getStats()) - .resolves - .toEqual( - [ - expect.objectContaining( - { - type : 'outbound-rtp', - kind : 'audio', - mimeType : 'audio/opus', - ssrc : audioConsumer.rtpParameters.encodings?.[0].ssrc - }) - ]); - - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); - - await expect(videoConsumer.getStats()) - .resolves - .toEqual( - [ - expect.objectContaining( - { - type : 'outbound-rtp', - kind : 'video', - mimeType : 'video/H264', - ssrc : videoConsumer.rtpParameters.encodings?.[0].ssrc - }) - ]); +test('consumer.getStats() succeeds', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); + + await expect(audioConsumer.getStats()).resolves.toEqual([ + expect.objectContaining({ + type: 'outbound-rtp', + kind: 'audio', + mimeType: 'audio/opus', + ssrc: audioConsumer.rtpParameters.encodings?.[0].ssrc, + }), + ]); + + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); + + await expect(videoConsumer.getStats()).resolves.toEqual([ + expect.objectContaining({ + type: 'outbound-rtp', + kind: 'video', + mimeType: 'video/H264', + ssrc: videoConsumer.rtpParameters.encodings?.[0].ssrc, + }), + ]); }, 2000); -test('consumer.pause() and resume() succeed', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.pause() and resume() succeed', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); const onObserverPause = jest.fn(); const onObserverResume = jest.fn(); @@ -879,16 +797,12 @@ test('consumer.pause() and resume() succeed', async () => await audioConsumer.pause(); expect(audioConsumer.paused).toBe(true); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ paused: true }); + await expect(audioConsumer.dump()).resolves.toMatchObject({ paused: true }); await audioConsumer.resume(); expect(audioConsumer.paused).toBe(false); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ paused: false }); + await expect(audioConsumer.dump()).resolves.toMatchObject({ paused: false }); // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. @@ -903,23 +817,19 @@ test('consumer.pause() and resume() succeed', async () => expect(onObserverResume).toHaveBeenCalledTimes(3); }, 2000); -test('producer.pause() and resume() emit events', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('producer.pause() and resume() emit events', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); const promises = []; const events: string[] = []; - - audioConsumer.observer.once('resume', () => - { + + audioConsumer.observer.once('resume', () => { events.push('resume'); }); - audioConsumer.observer.once('pause', () => - { + audioConsumer.observer.once('pause', () => { events.push('pause'); }); @@ -929,189 +839,155 @@ test('producer.pause() and resume() emit events', async () => await Promise.all(promises); // Must also wait a bit for the corresponding events in the consumer. - await new Promise((resolve) => setTimeout(resolve, 100)); - - expect(events).toEqual([ 'pause', 'resume' ]); + await new Promise(resolve => setTimeout(resolve, 100)); + + expect(events).toEqual(['pause', 'resume']); expect(audioConsumer.paused).toBe(false); }, 2000); -test('consumer.setPreferredLayers() succeed', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.setPreferredLayers() succeed', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); - await audioConsumer.setPreferredLayers( - { spatialLayer: 1, temporalLayer: 1 } - ); + await audioConsumer.setPreferredLayers({ spatialLayer: 1, temporalLayer: 1 }); expect(audioConsumer.preferredLayers).toBeUndefined(); - await videoConsumer.setPreferredLayers( - { spatialLayer: 2, temporalLayer: 3 } - ); + await videoConsumer.setPreferredLayers({ spatialLayer: 2, temporalLayer: 3 }); - expect( - videoConsumer.preferredLayers).toEqual( - { spatialLayer: 2, temporalLayer: 0 } - ); + expect(videoConsumer.preferredLayers).toEqual({ + spatialLayer: 2, + temporalLayer: 0, + }); }, 2000); -test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError', async () => -{ - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError', async () => { + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); // @ts-ignore - await expect(videoConsumer.setPreferredLayers({})) - .rejects - .toThrow(TypeError); + await expect(videoConsumer.setPreferredLayers({})).rejects.toThrow(TypeError); - // @ts-ignore - await expect(videoConsumer.setPreferredLayers({ foo: '123' })) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + videoConsumer.setPreferredLayers({ foo: '123' }), + ).rejects.toThrow(TypeError); // @ts-ignore - await expect(videoConsumer.setPreferredLayers('foo')) - .rejects - .toThrow(TypeError); + await expect(videoConsumer.setPreferredLayers('foo')).rejects.toThrow( + TypeError, + ); // Missing spatialLayer. - // @ts-ignore - await expect(videoConsumer.setPreferredLayers({ temporalLayer: 2 })) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + videoConsumer.setPreferredLayers({ temporalLayer: 2 }), + ).rejects.toThrow(TypeError); }, 2000); -test('consumer.setPriority() succeed', async () => -{ - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.setPriority() succeed', async () => { + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); await videoConsumer.setPriority(2); expect(videoConsumer.priority).toBe(2); }, 2000); -test('consumer.setPriority() with wrong arguments rejects with TypeError', async () => -{ - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.setPriority() with wrong arguments rejects with TypeError', async () => { + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); // @ts-ignore - await expect(videoConsumer.setPriority()) - .rejects - .toThrow(TypeError); + await expect(videoConsumer.setPriority()).rejects.toThrow(TypeError); - await expect(videoConsumer.setPriority(0)) - .rejects - .toThrow(TypeError); + await expect(videoConsumer.setPriority(0)).rejects.toThrow(TypeError); // @ts-ignore - await expect(videoConsumer.setPriority('foo')) - .rejects - .toThrow(TypeError); + await expect(videoConsumer.setPriority('foo')).rejects.toThrow(TypeError); }, 2000); -test('consumer.unsetPriority() succeed', async () => -{ - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.unsetPriority() succeed', async () => { + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); await videoConsumer.unsetPriority(); expect(videoConsumer.priority).toBe(1); }, 2000); -test('consumer.enableTraceEvent() succeed', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.enableTraceEvent() succeed', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); - await audioConsumer.enableTraceEvent([ 'rtp', 'pli' ]); + await audioConsumer.enableTraceEvent(['rtp', 'pli']); const dump1 = await audioConsumer.dump(); - expect(dump1.traceEventTypes) - .toEqual(expect.arrayContaining([ 'rtp', 'pli' ])); + expect(dump1.traceEventTypes).toEqual(expect.arrayContaining(['rtp', 'pli'])); await audioConsumer.enableTraceEvent([]); const dump2 = await audioConsumer.dump(); - expect(dump2.traceEventTypes) - .toEqual(expect.arrayContaining([])); + expect(dump2.traceEventTypes).toEqual(expect.arrayContaining([])); // @ts-ignore - await audioConsumer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); + await audioConsumer.enableTraceEvent(['nack', 'FOO', 'fir']); const dump3 = await audioConsumer.dump(); - expect(dump3.traceEventTypes) - .toEqual(expect.arrayContaining([ 'nack', 'fir' ])); + expect(dump3.traceEventTypes).toEqual( + expect.arrayContaining(['nack', 'fir']), + ); await audioConsumer.enableTraceEvent(); const dump4 = await audioConsumer.dump(); - expect(dump4.traceEventTypes) - .toEqual(expect.arrayContaining([])); + expect(dump4.traceEventTypes).toEqual(expect.arrayContaining([])); }, 2000); -test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); // @ts-ignore - await expect(audioConsumer.enableTraceEvent(123)) - .rejects - .toThrow(TypeError); + await expect(audioConsumer.enableTraceEvent(123)).rejects.toThrow(TypeError); // @ts-ignore - await expect(audioConsumer.enableTraceEvent('rtp')) - .rejects - .toThrow(TypeError); + await expect(audioConsumer.enableTraceEvent('rtp')).rejects.toThrow( + TypeError, + ); - // @ts-ignore - await expect(audioConsumer.enableTraceEvent([ 'fir', 123.123 ])) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + audioConsumer.enableTraceEvent(['fir', 123.123]), + ).rejects.toThrow(TypeError); }, 2000); -test('Consumer emits "producerpause" and "producerresume"', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('Consumer emits "producerpause" and "producerresume"', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); - await new Promise((resolve) => - { + await new Promise(resolve => { audioConsumer.on('producerpause', resolve); ctx.audioProducer!.pause().catch(() => {}); @@ -1120,8 +996,7 @@ test('Consumer emits "producerpause" and "producerresume"', async () => expect(audioConsumer.paused).toBe(false); expect(audioConsumer.producerPaused).toBe(true); - await new Promise((resolve) => - { + await new Promise(resolve => { audioConsumer.on('producerresume', resolve); // Let's catch rejection since the test will complete before we get the @@ -1134,13 +1009,11 @@ test('Consumer emits "producerpause" and "producerresume"', async () => expect(audioConsumer.producerPaused).toBe(false); }, 2000); -test('Consumer emits "score"', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('Consumer emits "score"', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); // Private API. const channel = audioConsumer.channelForTesting; @@ -1150,21 +1023,22 @@ test('Consumer emits "score"', async () => // Simulate a 'score' notification coming through the channel. const builder = new flatbuffers.Builder(); - const consumerScore = new FbsConsumer.ConsumerScoreT(9, 10, [ 8 ]); - const consumerScoreNotification = - new FbsConsumer.ScoreNotificationT(consumerScore); + const consumerScore = new FbsConsumer.ConsumerScoreT(9, 10, [8]); + const consumerScoreNotification = new FbsConsumer.ScoreNotificationT( + consumerScore, + ); const notificationOffset = Notification.createNotification( builder, builder.createString(audioConsumer.id), Event.CONSUMER_SCORE, NotificationBody.Consumer_ScoreNotification, - consumerScoreNotification.pack(builder) + consumerScoreNotification.pack(builder), ); builder.finish(notificationOffset); const notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array()) + new flatbuffers.ByteBuffer(builder.asUint8Array()), ); channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); @@ -1172,22 +1046,22 @@ test('Consumer emits "score"', async () => channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); expect(onScore).toHaveBeenCalledTimes(3); - expect(audioConsumer.score).toEqual( - { score: 9, producerScore: 10, producerScores: [ 8 ] }); + expect(audioConsumer.score).toEqual({ + score: 9, + producerScore: 10, + producerScores: [8], + }); }, 2000); -test('consumer.close() succeeds', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('consumer.close() succeeds', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); const onObserverClose = jest.fn(); audioConsumer.observer.once('close', onObserverClose); @@ -1198,82 +1072,59 @@ test('consumer.close() succeeds', async () => const routerDump = await ctx.router!.dump(); - expect(routerDump.mapProducerIdConsumerIds) - .toEqual(expect.arrayContaining( - [ - { key: ctx.audioProducer!.id, values: [] }, - { key: ctx.videoProducer!.id, values: [ videoConsumer.id ] } - ])); - expect(routerDump.mapConsumerIdProducerId) - .toEqual( - [ - { key: videoConsumer!.id, value: ctx.videoProducer!.id } - ]); + expect(routerDump.mapProducerIdConsumerIds).toEqual( + expect.arrayContaining([ + { key: ctx.audioProducer!.id, values: [] }, + { key: ctx.videoProducer!.id, values: [videoConsumer.id] }, + ]), + ); + expect(routerDump.mapConsumerIdProducerId).toEqual([ + { key: videoConsumer!.id, value: ctx.videoProducer!.id }, + ]); const transportDump = await ctx.webRtcTransport2!.dump(); - expect(transportDump) - .toMatchObject( - { - id : ctx.webRtcTransport2!.id, - producerIds : [], - consumerIds : [ videoConsumer.id ] - }); + expect(transportDump).toMatchObject({ + id: ctx.webRtcTransport2!.id, + producerIds: [], + consumerIds: [videoConsumer.id], + }); }, 2000); -test('Consumer methods reject if closed', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('Consumer methods reject if closed', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); audioConsumer.close(); - await expect(audioConsumer.dump()) - .rejects - .toThrow(Error); + await expect(audioConsumer.dump()).rejects.toThrow(Error); - await expect(audioConsumer.getStats()) - .rejects - .toThrow(Error); + await expect(audioConsumer.getStats()).rejects.toThrow(Error); - await expect(audioConsumer.pause()) - .rejects - .toThrow(Error); + await expect(audioConsumer.pause()).rejects.toThrow(Error); - await expect(audioConsumer.resume()) - .rejects - .toThrow(Error); + await expect(audioConsumer.resume()).rejects.toThrow(Error); // @ts-ignore - await expect(audioConsumer.setPreferredLayers({})) - .rejects - .toThrow(Error); + await expect(audioConsumer.setPreferredLayers({})).rejects.toThrow(Error); - await expect(audioConsumer.setPriority(2)) - .rejects - .toThrow(Error); + await expect(audioConsumer.setPriority(2)).rejects.toThrow(Error); - await expect(audioConsumer.requestKeyFrame()) - .rejects - .toThrow(Error); + await expect(audioConsumer.requestKeyFrame()).rejects.toThrow(Error); }, 2000); -test('Consumer emits "producerclose" if Producer is closed', async () => -{ - const audioConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.audioProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('Consumer emits "producerclose" if Producer is closed', async () => { + const audioConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.audioProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); const onObserverClose = jest.fn(); audioConsumer.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { audioConsumer.on('producerclose', resolve); ctx.audioProducer!.close(); }); @@ -1282,20 +1133,17 @@ test('Consumer emits "producerclose" if Producer is closed', async () => expect(audioConsumer.closed).toBe(true); }, 2000); -test('Consumer emits "transportclose" if Transport is closed', async () => -{ - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); +test('Consumer emits "transportclose" if Transport is closed', async () => { + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); const onObserverClose = jest.fn(); videoConsumer.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { videoConsumer.on('transportclose', resolve); ctx.webRtcTransport2!.close(); }); @@ -1303,16 +1151,11 @@ test('Consumer emits "transportclose" if Transport is closed', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(videoConsumer.closed).toBe(true); - await expect(ctx.router!.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : expect.arrayContaining( - [ - { key: ctx.audioProducer!.id, values: [] }, - { key: ctx.videoProducer!.id, values: [] } - ] - ), - mapConsumerIdProducerId : [] - }); + await expect(ctx.router!.dump()).resolves.toMatchObject({ + mapProducerIdConsumerIds: expect.arrayContaining([ + { key: ctx.audioProducer!.id, values: [] }, + { key: ctx.videoProducer!.id, values: [] }, + ]), + mapConsumerIdProducerId: [], + }); }, 2000); diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index 74de277b8a..230f1d9d77 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -1,8 +1,7 @@ import * as mediasoup from '../'; import * as utils from '../utils'; -type TestContext = -{ +type TestContext = { dataProducerOptions: mediasoup.types.DataProducerOptions; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; @@ -12,61 +11,55 @@ type TestContext = dataProducer?: mediasoup.types.DataProducer; }; -const ctx: TestContext = -{ - dataProducerOptions : utils.deepFreeze( - { - sctpStreamParameters : - { - streamId : 12345, - ordered : false, - maxPacketLifeTime : 5000 - }, - label : 'foo', - protocol : 'bar' - } - ) +const ctx: TestContext = { + dataProducerOptions: utils.deepFreeze({ + sctpStreamParameters: { + streamId: 12345, + ordered: false, + maxPacketLifeTime: 5000, + }, + label: 'foo', + protocol: 'bar', + }), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter(); - ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ], - enableSctp : true - }); - ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ], - enableSctp : true - }); + ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + enableSctp: true, + }); + ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + enableSctp: true, + }); ctx.directTransport = await ctx.router.createDirectTransport(); - ctx.dataProducer = - await ctx.webRtcTransport1.produceData(ctx.dataProducerOptions); + ctx.dataProducer = await ctx.webRtcTransport1.produceData( + ctx.dataProducerOptions, + ); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('transport.consumeData() succeeds', async () => -{ +test('transport.consumeData() succeeds', async () => { const onObserverNewDataConsumer = jest.fn(); - ctx.webRtcTransport2!.observer.once('newdataconsumer', onObserverNewDataConsumer); + ctx.webRtcTransport2!.observer.once( + 'newdataconsumer', + onObserverNewDataConsumer, + ); - const dataConsumer1 = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id, - maxPacketLifeTime : 4000, - // Valid values are 0...65535 so others and duplicated ones will be - // discarded. - subchannels : [ 0, 1, 1, 1, 2, 65535, 65536, 65537, 100 ], - appData : { baz: 'LOL' } - }); + const dataConsumer1 = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + maxPacketLifeTime: 4000, + // Valid values are 0...65535 so others and duplicated ones will be + // discarded. + subchannels: [0, 1, 1, 1, 2, 65535, 65536, 65537, 100], + appData: { baz: 'LOL' }, + }); expect(onObserverNewDataConsumer).toHaveBeenCalledTimes(1); expect(onObserverNewDataConsumer).toHaveBeenCalledWith(dataConsumer1); @@ -83,43 +76,40 @@ test('transport.consumeData() succeeds', async () => expect(dataConsumer1.protocol).toBe('bar'); expect(dataConsumer1.paused).toBe(false); expect(dataConsumer1.subchannels).toEqual( - expect.arrayContaining([ 0, 1, 2, 100, 65535 ]) + expect.arrayContaining([0, 1, 2, 100, 65535]), ); expect(dataConsumer1.appData).toEqual({ baz: 'LOL' }); const dump = await ctx.router!.dump(); - expect(dump.mapDataProducerIdDataConsumerIds) - .toEqual(expect.arrayContaining([ - { key: ctx.dataProducer!.id, values: [ dataConsumer1.id ] } - ])); - - expect(dump.mapDataConsumerIdDataProducerId) - .toEqual(expect.arrayContaining([ - { key: dataConsumer1.id, value: ctx.dataProducer!.id } - ])); - - await expect(ctx.webRtcTransport2!.dump()) - .resolves - .toMatchObject( - { - id : ctx.webRtcTransport2!.id, - dataProducerIds : [], - dataConsumerIds : [ dataConsumer1.id ] - }); + expect(dump.mapDataProducerIdDataConsumerIds).toEqual( + expect.arrayContaining([ + { key: ctx.dataProducer!.id, values: [dataConsumer1.id] }, + ]), + ); + + expect(dump.mapDataConsumerIdDataProducerId).toEqual( + expect.arrayContaining([ + { key: dataConsumer1.id, value: ctx.dataProducer!.id }, + ]), + ); + + await expect(ctx.webRtcTransport2!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport2!.id, + dataProducerIds: [], + dataConsumerIds: [dataConsumer1.id], + }); }, 2000); -test('dataConsumer.dump() succeeds', async () => -{ - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id, - maxPacketLifeTime : 4000, - // Valid values are 0...65535 so others and duplicated ones will be - // discarded. - subchannels : [ 0, 1, 1, 1, 2, 65535, 65536, 65537, 100 ], - appData : { baz: 'LOL' } - }); +test('dataConsumer.dump() succeeds', async () => { + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + maxPacketLifeTime: 4000, + // Valid values are 0...65535 so others and duplicated ones will be + // discarded. + subchannels: [0, 1, 1, 1, 2, 65535, 65536, 65537, 100], + appData: { baz: 'LOL' }, + }); const dump = await dataConsumer.dump(); @@ -127,8 +117,9 @@ test('dataConsumer.dump() succeeds', async () => expect(dump.dataProducerId).toBe(dataConsumer.dataProducerId); expect(dump.type).toBe('sctp'); expect(typeof dump.sctpStreamParameters).toBe('object'); - expect(dump.sctpStreamParameters!.streamId) - .toBe(dataConsumer.sctpStreamParameters?.streamId); + expect(dump.sctpStreamParameters!.streamId).toBe( + dataConsumer.sctpStreamParameters?.streamId, + ); expect(dump.sctpStreamParameters!.ordered).toBe(false); expect(dump.sctpStreamParameters!.maxPacketLifeTime).toBe(4000); expect(dump.sctpStreamParameters!.maxRetransmits).toBeUndefined(); @@ -137,88 +128,78 @@ test('dataConsumer.dump() succeeds', async () => expect(dump.paused).toBe(false); expect(dump.dataProducerPaused).toBe(false); expect(dump.subchannels).toEqual( - expect.arrayContaining([ 0, 1, 2, 100, 65535 ]) + expect.arrayContaining([0, 1, 2, 100, 65535]), ); }, 2000); -test('dataConsumer.getStats() succeeds', async () => -{ - const dataConsumer = await ctx.webRtcTransport2!.consumeData( +test('dataConsumer.getStats() succeeds', async () => { + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); + + await expect(dataConsumer.getStats()).resolves.toMatchObject([ { - dataProducerId : ctx.dataProducer!.id - }); - - await expect(dataConsumer.getStats()) - .resolves - .toMatchObject( - [ - { - type : 'data-consumer', - label : dataConsumer.label, - protocol : dataConsumer.protocol, - messagesSent : 0, - bytesSent : 0 - } - ]); + type: 'data-consumer', + label: dataConsumer.label, + protocol: dataConsumer.protocol, + messagesSent: 0, + bytesSent: 0, + }, + ]); }, 2000); -test('dataConsumer.setSubchannels() succeeds', async () => -{ - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); +test('dataConsumer.setSubchannels() succeeds', async () => { + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); - await dataConsumer.setSubchannels([ 999, 999, 998, 65536 ]); + await dataConsumer.setSubchannels([999, 999, 998, 65536]); expect(dataConsumer.subchannels).toEqual( - expect.arrayContaining([ 0, 998, 999 ]) + expect.arrayContaining([0, 998, 999]), ); }, 2000); -test('dataConsumer.addSubchannel() and .removeSubchannel() succeed', async () => -{ - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); +test('dataConsumer.addSubchannel() and .removeSubchannel() succeed', async () => { + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); await dataConsumer.setSubchannels([]); expect(dataConsumer.subchannels).toEqual([]); await dataConsumer.addSubchannel(5); - expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 5 ])); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([5])); await dataConsumer.addSubchannel(10); - expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 5, 10 ])); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([5, 10])); await dataConsumer.addSubchannel(5); - expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 5, 10 ])); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([5, 10])); await dataConsumer.removeSubchannel(666); - expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 5, 10 ])); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([5, 10])); await dataConsumer.removeSubchannel(5); - expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([ 10 ])); + expect(dataConsumer.subchannels).toEqual(expect.arrayContaining([10])); await dataConsumer.setSubchannels([]); expect(dataConsumer.subchannels).toEqual([]); }, 2000); -test('transport.consumeData() on a DirectTransport succeeds', async () => -{ +test('transport.consumeData() on a DirectTransport succeeds', async () => { const onObserverNewDataConsumer = jest.fn(); ctx.directTransport!.observer.once( - 'newdataconsumer', onObserverNewDataConsumer + 'newdataconsumer', + onObserverNewDataConsumer, ); - const dataConsumer = await ctx.directTransport!.consumeData( - { - dataProducerId : ctx.dataProducer!.id, - paused : true, - appData : { hehe: 'HEHE' } - }); + const dataConsumer = await ctx.directTransport!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + paused: true, + appData: { hehe: 'HEHE' }, + }); expect(onObserverNewDataConsumer).toHaveBeenCalledTimes(1); expect(onObserverNewDataConsumer).toHaveBeenCalledWith(dataConsumer); @@ -232,23 +213,18 @@ test('transport.consumeData() on a DirectTransport succeeds', async () => expect(dataConsumer.paused).toBe(true); expect(dataConsumer.appData).toEqual({ hehe: 'HEHE' }); - await expect(ctx.directTransport!.dump()) - .resolves - .toMatchObject( - { - id : ctx.directTransport!.id, - dataProducerIds : [], - dataConsumerIds : [ dataConsumer.id ] - }); + await expect(ctx.directTransport!.dump()).resolves.toMatchObject({ + id: ctx.directTransport!.id, + dataProducerIds: [], + dataConsumerIds: [dataConsumer.id], + }); }, 2000); -test('dataConsumer.dump() on a DirectTransport succeeds', async () => -{ - const dataConsumer = await ctx.directTransport!.consumeData( - { - dataProducerId : ctx.dataProducer!.id, - paused : true - }); +test('dataConsumer.dump() on a DirectTransport succeeds', async () => { + const dataConsumer = await ctx.directTransport!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + paused: true, + }); const dump = await dataConsumer.dump(); @@ -262,36 +238,29 @@ test('dataConsumer.dump() on a DirectTransport succeeds', async () => expect(dump.subchannels).toEqual([]); }, 2000); -test('dataConsumer.getStats() on a DirectTransport succeeds', async () => -{ - const dataConsumer = await ctx.directTransport!.consumeData( +test('dataConsumer.getStats() on a DirectTransport succeeds', async () => { + const dataConsumer = await ctx.directTransport!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); + + await expect(dataConsumer.getStats()).resolves.toMatchObject([ { - dataProducerId : ctx.dataProducer!.id - }); - - await expect(dataConsumer.getStats()) - .resolves - .toMatchObject( - [ - { - type : 'data-consumer', - label : dataConsumer.label, - protocol : dataConsumer.protocol, - messagesSent : 0, - bytesSent : 0 - } - ]); + type: 'data-consumer', + label: dataConsumer.label, + protocol: dataConsumer.protocol, + messagesSent: 0, + bytesSent: 0, + }, + ]); }, 2000); -test('dataConsumer.pause() and resume() succeed', async () => -{ +test('dataConsumer.pause() and resume() succeed', async () => { const onObserverPause = jest.fn(); const onObserverResume = jest.fn(); - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); dataConsumer.observer.on('pause', onObserverPause); dataConsumer.observer.on('resume', onObserverResume); @@ -325,22 +294,18 @@ test('dataConsumer.pause() and resume() succeed', async () => expect(onObserverResume).toHaveBeenCalledTimes(3); }, 2000); -test('dataProducer.pause() and resume() emit events', async () => -{ - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); +test('dataProducer.pause() and resume() emit events', async () => { + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); const promises = []; const events: string[] = []; - dataConsumer.observer.once('resume', () => - { + dataConsumer.observer.once('resume', () => { events.push('resume'); }); - dataConsumer.observer.once('pause', () => - { + dataConsumer.observer.once('pause', () => { events.push('pause'); }); @@ -350,19 +315,17 @@ test('dataProducer.pause() and resume() emit events', async () => await Promise.all(promises); // Must also wait a bit for the corresponding events in the data consumer. - await new Promise((resolve) => setTimeout(resolve, 100)); + await new Promise(resolve => setTimeout(resolve, 100)); - expect(events).toEqual([ 'pause', 'resume' ]); + expect(events).toEqual(['pause', 'resume']); expect(dataConsumer.paused).toBe(false); }, 2000); -test('dataConsumer.close() succeeds', async () => -{ +test('dataConsumer.close() succeeds', async () => { const onObserverClose = jest.fn(); - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); dataConsumer.observer.once('close', onObserverClose); dataConsumer.close(); @@ -372,53 +335,40 @@ test('dataConsumer.close() succeeds', async () => const dump = await ctx.router!.dump(); - expect(dump.mapDataProducerIdDataConsumerIds) - .toEqual(expect.arrayContaining([ - { key: ctx.dataProducer!.id, values: [] } - ])); + expect(dump.mapDataProducerIdDataConsumerIds).toEqual( + expect.arrayContaining([{ key: ctx.dataProducer!.id, values: [] }]), + ); expect(dump.mapDataConsumerIdDataProducerId).toEqual([]); - await expect(ctx.webRtcTransport2!.dump()) - .resolves - .toMatchObject( - { - id : ctx.webRtcTransport2!.id, - dataProducerIds : [], - dataConsumerIds : [] - }); + await expect(ctx.webRtcTransport2!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport2!.id, + dataProducerIds: [], + dataConsumerIds: [], + }); }, 2000); -test('Consumer methods reject if closed', async () => -{ - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); +test('Consumer methods reject if closed', async () => { + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); dataConsumer.close(); - await expect(dataConsumer.dump()) - .rejects - .toThrow(Error); + await expect(dataConsumer.dump()).rejects.toThrow(Error); - await expect(dataConsumer.getStats()) - .rejects - .toThrow(Error); + await expect(dataConsumer.getStats()).rejects.toThrow(Error); }, 2000); -test('DataConsumer emits "dataproducerclose" if DataProducer is closed', async () => -{ - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); +test('DataConsumer emits "dataproducerclose" if DataProducer is closed', async () => { + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); const onObserverClose = jest.fn(); dataConsumer.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { dataConsumer.on('dataproducerclose', resolve); ctx.dataProducer!.close(); @@ -428,18 +378,15 @@ test('DataConsumer emits "dataproducerclose" if DataProducer is closed', async ( expect(dataConsumer.closed).toBe(true); }, 2000); -test('DataConsumer emits "transportclose" if Transport is closed', async () => -{ - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); +test('DataConsumer emits "transportclose" if Transport is closed', async () => { + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); const onObserverClose = jest.fn(); dataConsumer.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { dataConsumer.on('transportclose', resolve); ctx.webRtcTransport2!.close(); @@ -448,11 +395,8 @@ test('DataConsumer emits "transportclose" if Transport is closed', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataConsumer.closed).toBe(true); - await expect(ctx.router!.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : {}, - mapDataConsumerIdDataProducerId : {} - }); + await expect(ctx.router!.dump()).resolves.toMatchObject({ + mapDataProducerIdDataConsumerIds: {}, + mapDataConsumerIdDataProducerId: {}, + }); }, 2000); diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index 54dcbc734e..1577e0ed05 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -1,8 +1,7 @@ import * as mediasoup from '../'; import * as utils from '../utils'; -type TestContext = -{ +type TestContext = { dataProducerOptions1: mediasoup.types.DataProducerOptions; dataProducerOptions2: mediasoup.types.DataProducerOptions; worker?: mediasoup.types.Worker; @@ -11,65 +10,54 @@ type TestContext = webRtcTransport2?: mediasoup.types.WebRtcTransport; }; -const ctx: TestContext = -{ - dataProducerOptions1 : utils.deepFreeze( - { - sctpStreamParameters : - { - streamId : 666 - }, - label : 'foo', - protocol : 'bar', - appData : { foo: 1, bar: '2' } - } - ), - dataProducerOptions2 : utils.deepFreeze( - { - sctpStreamParameters : - { - streamId : 777, - maxRetransmits : 3 - }, - label : 'foo', - protocol : 'bar', - paused : true, - appData : { foo: 1, bar: '2' } - } - ) +const ctx: TestContext = { + dataProducerOptions1: utils.deepFreeze({ + sctpStreamParameters: { + streamId: 666, + }, + label: 'foo', + protocol: 'bar', + appData: { foo: 1, bar: '2' }, + }), + dataProducerOptions2: utils.deepFreeze({ + sctpStreamParameters: { + streamId: 777, + maxRetransmits: 3, + }, + label: 'foo', + protocol: 'bar', + paused: true, + appData: { foo: 1, bar: '2' }, + }), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter(); - ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ], - enableSctp : true - }); - ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ], - enableSctp : true - }); + ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + enableSctp: true, + }); + ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + enableSctp: true, + }); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('webRtcTransport1.produceData() succeeds', async () => -{ +test('webRtcTransport1.produceData() succeeds', async () => { const onObserverNewDataProducer = jest.fn(); ctx.webRtcTransport1!.observer.once( - 'newdataproducer', onObserverNewDataProducer + 'newdataproducer', + onObserverNewDataProducer, ); const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1 + ctx.dataProducerOptions1, ); expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); @@ -89,33 +77,29 @@ test('webRtcTransport1.produceData() succeeds', async () => const dump = await ctx.router!.dump(); - expect(dump.mapDataProducerIdDataConsumerIds) - .toEqual(expect.arrayContaining([ - { key: dataProducer1.id, values: [ ] } - ])); + expect(dump.mapDataProducerIdDataConsumerIds).toEqual( + expect.arrayContaining([{ key: dataProducer1.id, values: [] }]), + ); expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); - await expect(ctx.webRtcTransport1!.dump()) - .resolves - .toMatchObject( - { - id : ctx.webRtcTransport1!.id, - dataProducerIds : [ dataProducer1.id ], - dataConsumerIds : [] - }); + await expect(ctx.webRtcTransport1!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport1!.id, + dataProducerIds: [dataProducer1.id], + dataConsumerIds: [], + }); }, 2000); -test('webRtcTransport2.produceData() succeeds', async () => -{ +test('webRtcTransport2.produceData() succeeds', async () => { const onObserverNewDataProducer = jest.fn(); ctx.webRtcTransport2!.observer.once( - 'newdataproducer', onObserverNewDataProducer + 'newdataproducer', + onObserverNewDataProducer, ); const dataProducer2 = await ctx.webRtcTransport2!.produceData( - ctx.dataProducerOptions2 + ctx.dataProducerOptions2, ); expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); @@ -135,73 +119,60 @@ test('webRtcTransport2.produceData() succeeds', async () => const dump = await ctx.router!.dump(); - expect(dump.mapDataProducerIdDataConsumerIds) - .toEqual(expect.arrayContaining([ - { key: dataProducer2.id, values: [ ] } - ])); + expect(dump.mapDataProducerIdDataConsumerIds).toEqual( + expect.arrayContaining([{ key: dataProducer2.id, values: [] }]), + ); expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); - await expect(ctx.webRtcTransport2!.dump()) - .resolves - .toMatchObject( - { - id : ctx.webRtcTransport2!.id, - dataProducerIds : [ dataProducer2.id ], - dataConsumerIds : [] - }); + await expect(ctx.webRtcTransport2!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport2!.id, + dataProducerIds: [dataProducer2.id], + dataConsumerIds: [], + }); }, 2000); -test('webRtcTransport1.produceData() with wrong arguments rejects with TypeError', async () => -{ - await expect(ctx.webRtcTransport1!.produceData({})) - .rejects - .toThrow(TypeError); +test('webRtcTransport1.produceData() with wrong arguments rejects with TypeError', async () => { + await expect(ctx.webRtcTransport1!.produceData({})).rejects.toThrow( + TypeError, + ); // Missing or empty sctpStreamParameters.streamId. - await expect(ctx.webRtcTransport1!.produceData( - { + await expect( + ctx.webRtcTransport1!.produceData({ // @ts-ignore - sctpStreamParameters : { foo: 'foo' } - })) - .rejects - .toThrow(TypeError); + sctpStreamParameters: { foo: 'foo' }, + }), + ).rejects.toThrow(TypeError); }, 2000); -test('transport.produceData() with already used streamId rejects with Error', async () => -{ +test('transport.produceData() with already used streamId rejects with Error', async () => { await ctx.webRtcTransport1!.produceData(ctx.dataProducerOptions1); - await expect(ctx.webRtcTransport1!.produceData( - { - sctpStreamParameters : - { - streamId : 666 - } - })) - .rejects - .toThrow(Error); + await expect( + ctx.webRtcTransport1!.produceData({ + sctpStreamParameters: { + streamId: 666, + }, + }), + ).rejects.toThrow(Error); }, 2000); -test('transport.produceData() with ordered and maxPacketLifeTime rejects with TypeError', async () => -{ - await expect(ctx.webRtcTransport1!.produceData( - { - sctpStreamParameters : - { - streamId : 999, - ordered : true, - maxPacketLifeTime : 4000 - } - })) - .rejects - .toThrow(TypeError); +test('transport.produceData() with ordered and maxPacketLifeTime rejects with TypeError', async () => { + await expect( + ctx.webRtcTransport1!.produceData({ + sctpStreamParameters: { + streamId: 999, + ordered: true, + maxPacketLifeTime: 4000, + }, + }), + ).rejects.toThrow(TypeError); }, 2000); -test('dataProducer.dump() succeeds', async () => -{ +test('dataProducer.dump() succeeds', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1 + ctx.dataProducerOptions1, ); const dump1 = await dataProducer1.dump(); @@ -218,7 +189,7 @@ test('dataProducer.dump() succeeds', async () => expect(dump1.paused).toBe(false); const dataProducer2 = await ctx.webRtcTransport2!.produceData( - ctx.dataProducerOptions2 + ctx.dataProducerOptions2, ); const dump2 = await dataProducer2.dump(); @@ -235,47 +206,39 @@ test('dataProducer.dump() succeeds', async () => expect(dump2.paused).toBe(true); }, 2000); -test('dataProducer.getStats() succeeds', async () => -{ +test('dataProducer.getStats() succeeds', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1 + ctx.dataProducerOptions1, ); - await expect(dataProducer1.getStats()) - .resolves - .toMatchObject( - [ - { - type : 'data-producer', - label : dataProducer1.label, - protocol : dataProducer1.protocol, - messagesReceived : 0, - bytesReceived : 0 - } - ]); + await expect(dataProducer1.getStats()).resolves.toMatchObject([ + { + type: 'data-producer', + label: dataProducer1.label, + protocol: dataProducer1.protocol, + messagesReceived: 0, + bytesReceived: 0, + }, + ]); const dataProducer2 = await ctx.webRtcTransport2!.produceData( - ctx.dataProducerOptions2 + ctx.dataProducerOptions2, ); - await expect(dataProducer2.getStats()) - .resolves - .toMatchObject( - [ - { - type : 'data-producer', - label : dataProducer2.label, - protocol : dataProducer2.protocol, - messagesReceived : 0, - bytesReceived : 0 - } - ]); + await expect(dataProducer2.getStats()).resolves.toMatchObject([ + { + type: 'data-producer', + label: dataProducer2.label, + protocol: dataProducer2.protocol, + messagesReceived: 0, + bytesReceived: 0, + }, + ]); }, 2000); -test('dataProducer.pause() and resume() succeed', async () => -{ +test('dataProducer.pause() and resume() succeed', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1 + ctx.dataProducerOptions1, ); const onObserverPause = jest.fn(); @@ -313,22 +276,19 @@ test('dataProducer.pause() and resume() succeed', async () => expect(onObserverResume).toHaveBeenCalledTimes(3); }, 2000); -test('producer.pause() and resume() emit events', async () => -{ +test('producer.pause() and resume() emit events', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1 + ctx.dataProducerOptions1, ); const promises = []; const events: string[] = []; - - dataProducer1.observer.once('resume', () => - { + + dataProducer1.observer.once('resume', () => { events.push('resume'); }); - dataProducer1.observer.once('pause', () => - { + dataProducer1.observer.once('pause', () => { events.push('pause'); }); @@ -336,15 +296,14 @@ test('producer.pause() and resume() emit events', async () => promises.push(dataProducer1.resume()); await Promise.all(promises); - - expect(events).toEqual([ 'pause', 'resume' ]); + + expect(events).toEqual(['pause', 'resume']); expect(dataProducer1.paused).toBe(false); }, 2000); -test('dataProducer.close() succeeds', async () => -{ +test('dataProducer.close() succeeds', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1 + ctx.dataProducerOptions1, ); const onObserverClose = jest.fn(); @@ -355,53 +314,40 @@ test('dataProducer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataProducer1.closed).toBe(true); - await expect(ctx.router!.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : {}, - mapDataConsumerIdDataProducerId : {} - }); - - await expect(ctx.webRtcTransport1!.dump()) - .resolves - .toMatchObject( - { - id : ctx.webRtcTransport1!.id, - dataProducerIds : [], - dataConsumerIds : [] - }); + await expect(ctx.router!.dump()).resolves.toMatchObject({ + mapDataProducerIdDataConsumerIds: {}, + mapDataConsumerIdDataProducerId: {}, + }); + + await expect(ctx.webRtcTransport1!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport1!.id, + dataProducerIds: [], + dataConsumerIds: [], + }); }, 2000); -test('DataProducer methods reject if closed', async () => -{ +test('DataProducer methods reject if closed', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1 + ctx.dataProducerOptions1, ); dataProducer1.close(); - await expect(dataProducer1.dump()) - .rejects - .toThrow(Error); + await expect(dataProducer1.dump()).rejects.toThrow(Error); - await expect(dataProducer1.getStats()) - .rejects - .toThrow(Error); + await expect(dataProducer1.getStats()).rejects.toThrow(Error); }, 2000); -test('DataProducer emits "transportclose" if Transport is closed', async () => -{ +test('DataProducer emits "transportclose" if Transport is closed', async () => { const dataProducer2 = await ctx.webRtcTransport2!.produceData( - ctx.dataProducerOptions2 + ctx.dataProducerOptions2, ); const onObserverClose = jest.fn(); dataProducer2.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { dataProducer2.on('transportclose', resolve); ctx.webRtcTransport2!.close(); diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index 60608b7e95..25a39b6411 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -1,39 +1,34 @@ import * as mediasoup from '../'; -type TestContext = -{ +type TestContext = { worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; }; const ctx: TestContext = {}; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter(); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('router.createDirectTransport() succeeds', async () => -{ +test('router.createDirectTransport() succeeds', async () => { const onObserverNewTransport = jest.fn(); ctx.router!.observer.once('newtransport', onObserverNewTransport); - const directTransport = await ctx.router!.createDirectTransport( - { - maxMessageSize : 1024, - appData : { foo: 'bar' } - }); + const directTransport = await ctx.router!.createDirectTransport({ + maxMessageSize: 1024, + appData: { foo: 'bar' }, + }); - await expect(ctx.router!.dump()) - .resolves - .toMatchObject({ transportIds: [ directTransport.id ] }); + await expect(ctx.router!.dump()).resolves.toMatchObject({ + transportIds: [directTransport.id], + }); expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(directTransport); @@ -56,20 +51,18 @@ test('router.createDirectTransport() succeeds', async () => expect(directTransport.closed).toBe(true); }, 2000); -test('router.createDirectTransport() with wrong arguments rejects with TypeError', async () => -{ - // @ts-ignore - await expect(ctx.router!.createDirectTransport({ maxMessageSize: 'foo' })) - .rejects - .toThrow(TypeError); +test('router.createDirectTransport() with wrong arguments rejects with TypeError', async () => { + await expect( + // @ts-ignore + ctx.router!.createDirectTransport({ maxMessageSize: 'foo' }), + ).rejects.toThrow(TypeError); - await expect(ctx.router!.createDirectTransport({ maxMessageSize: -2000 })) - .rejects - .toThrow(TypeError); + await expect( + ctx.router!.createDirectTransport({ maxMessageSize: -2000 }), + ).rejects.toThrow(TypeError); }, 2000); -test('directTransport.getStats() succeeds', async () => -{ +test('directTransport.getStats() succeeds', async () => { const directTransport = await ctx.router!.createDirectTransport(); const stats = await directTransport.getStats(); @@ -95,28 +88,22 @@ test('directTransport.getStats() succeeds', async () => expect(stats[0].probationSendBitrate).toBe(0); }, 2000); -test('directTransport.connect() succeeds', async () => -{ +test('directTransport.connect() succeeds', async () => { const directTransport = await ctx.router!.createDirectTransport(); - await expect(directTransport.connect()) - .resolves - .toBeUndefined(); + await expect(directTransport.connect()).resolves.toBeUndefined(); }, 2000); -test('dataProducer.send() succeeds', async () => -{ +test('dataProducer.send() succeeds', async () => { const directTransport = await ctx.router!.createDirectTransport(); - const dataProducer = await directTransport.produceData( - { - label : 'foo', - protocol : 'bar', - appData : { foo: 'bar' } - }); - const dataConsumer = await directTransport.consumeData( - { - dataProducerId : dataProducer.id - }); + const dataProducer = await directTransport.produceData({ + label: 'foo', + protocol: 'bar', + appData: { foo: 'bar' }, + }); + const dataConsumer = await directTransport.consumeData({ + dataProducerId: dataProducer.id, + }); const numMessages = 200; const pauseSendingAtMessage = 10; const resumeSendingAtMessage = 20; @@ -134,54 +121,45 @@ test('dataProducer.send() succeeds', async () => let numReceivedMessages = 0; // eslint-disable-next-line no-async-promise-executor - await new Promise(async (resolve, reject) => - { - dataProducer.on('listenererror', (eventName, error) => - { - reject(new Error( - `dataProducer 'listenererror' [eventName:${eventName}]: ${error}` - )); + await new Promise(async (resolve, reject) => { + dataProducer.on('listenererror', (eventName, error) => { + reject( + new Error( + `dataProducer 'listenererror' [eventName:${eventName}]: ${error}`, + ), + ); }); - dataConsumer.on('listenererror', (eventName, error) => - { - reject(new Error( - `dataConsumer 'listenererror' [eventName:${eventName}]: ${error}` - )); + dataConsumer.on('listenererror', (eventName, error) => { + reject( + new Error( + `dataConsumer 'listenererror' [eventName:${eventName}]: ${error}`, + ), + ); }); sendNextMessage(); - async function sendNextMessage(): Promise - { + async function sendNextMessage(): Promise { const id = ++numSentMessages; let message: Buffer | string; - if (id === pauseSendingAtMessage) - { + if (id === pauseSendingAtMessage) { await dataProducer.pause(); - } - else if (id === resumeSendingAtMessage) - { + } else if (id === resumeSendingAtMessage) { await dataProducer.resume(); - } - else if (id === pauseReceivingAtMessage) - { + } else if (id === pauseReceivingAtMessage) { await dataConsumer.pause(); - } - else if (id === resumeReceivingAtMessage) - { + } else if (id === resumeReceivingAtMessage) { await dataConsumer.resume(); } // Send string (WebRTC DataChannel string). - if (id < numMessages / 2) - { + if (id < numMessages / 2) { message = String(id); } // Send string (WebRTC DataChannel binary). - else - { + else { message = Buffer.from(String(id)); } @@ -191,19 +169,16 @@ test('dataProducer.send() succeeds', async () => sentMessageBytes += messageSize; - if (!dataProducer.paused && !dataConsumer.paused) - { + if (!dataProducer.paused && !dataConsumer.paused) { effectivelySentMessageBytes += messageSize; } - if (id < numMessages) - { + if (id < numMessages) { sendNextMessage(); } } - dataConsumer.on('message', (message, ppid) => - { + dataConsumer.on('message', (message, ppid) => { ++numReceivedMessages; // message is always a Buffer. @@ -211,23 +186,24 @@ test('dataProducer.send() succeeds', async () => const id = Number(message.toString('utf8')); - if (id === numMessages) - { + if (id === numMessages) { resolve(); } // PPID of WebRTC DataChannel string. - else if (id < numMessages / 2 && ppid !== 51) - { - reject(new Error( - `ppid in message with id ${id} should be 51 but it is ${ppid}` - )); + else if (id < numMessages / 2 && ppid !== 51) { + reject( + new Error( + `ppid in message with id ${id} should be 51 but it is ${ppid}`, + ), + ); } // PPID of WebRTC DataChannel binary. - else if (id > numMessages / 2 && ppid !== 53) - { - reject(new Error( - `ppid in message with id ${id} should be 53 but it is ${ppid}` - )); + else if (id > numMessages / 2 && ppid !== 53) { + reject( + new Error( + `ppid in message with id ${id} should be 53 but it is ${ppid}`, + ), + ); } }); }); @@ -236,161 +212,147 @@ test('dataProducer.send() succeeds', async () => expect(numReceivedMessages).toBe(expectedReceivedNumMessages); expect(recvMessageBytes).toBe(effectivelySentMessageBytes); - await expect(dataProducer.getStats()) - .resolves - .toMatchObject( - [ - { - type : 'data-producer', - label : dataProducer.label, - protocol : dataProducer.protocol, - messagesReceived : numMessages, - bytesReceived : sentMessageBytes - } - ]); - - await expect(dataConsumer.getStats()) - .resolves - .toMatchObject( - [ - { - type : 'data-consumer', - label : dataConsumer.label, - protocol : dataConsumer.protocol, - messagesSent : expectedReceivedNumMessages, - bytesSent : recvMessageBytes - } - ]); + await expect(dataProducer.getStats()).resolves.toMatchObject([ + { + type: 'data-producer', + label: dataProducer.label, + protocol: dataProducer.protocol, + messagesReceived: numMessages, + bytesReceived: sentMessageBytes, + }, + ]); + + await expect(dataConsumer.getStats()).resolves.toMatchObject([ + { + type: 'data-consumer', + label: dataConsumer.label, + protocol: dataConsumer.protocol, + messagesSent: expectedReceivedNumMessages, + bytesSent: recvMessageBytes, + }, + ]); }, 5000); -test('dataProducer.send() with subchannels succeeds', async () => -{ +test('dataProducer.send() with subchannels succeeds', async () => { const directTransport = await ctx.router!.createDirectTransport(); const dataProducer = await directTransport.produceData(); - const dataConsumer1 = await directTransport.consumeData( - { - dataProducerId : dataProducer.id, - subchannels : [ 1, 11, 666 ] - }); - const dataConsumer2 = await directTransport.consumeData( - { - dataProducerId : dataProducer.id, - subchannels : [ 2, 22, 666 ] - }); + const dataConsumer1 = await directTransport.consumeData({ + dataProducerId: dataProducer.id, + subchannels: [1, 11, 666], + }); + const dataConsumer2 = await directTransport.consumeData({ + dataProducerId: dataProducer.id, + subchannels: [2, 22, 666], + }); const expectedReceivedNumMessages1 = 7; const expectedReceivedNumMessages2 = 5; const receivedMessages1: string[] = []; const receivedMessages2: string[] = []; // eslint-disable-next-line no-async-promise-executor - await new Promise(async (resolve) => - { + await new Promise(async resolve => { // Must be received by dataConsumer1 and dataConsumer2. dataProducer.send( 'both', /* ppid */ undefined, /* subchannels */ undefined, - /* requiredSubchannel */ undefined + /* requiredSubchannel */ undefined, ); // Must be received by dataConsumer1 and dataConsumer2. dataProducer.send( 'both', /* ppid */ undefined, - /* subchannels */ [ 1, 2 ], - /* requiredSubchannel */ undefined + /* subchannels */ [1, 2], + /* requiredSubchannel */ undefined, ); // Must be received by dataConsumer1 and dataConsumer2. dataProducer.send( 'both', /* ppid */ undefined, - /* subchannels */ [ 11, 22, 33 ], - /* requiredSubchannel */ 666 + /* subchannels */ [11, 22, 33], + /* requiredSubchannel */ 666, ); // Must not be received by neither dataConsumer1 nor dataConsumer2. dataProducer.send( 'none', /* ppid */ undefined, - /* subchannels */ [ 3 ], - /* requiredSubchannel */ 666 + /* subchannels */ [3], + /* requiredSubchannel */ 666, ); // Must not be received by neither dataConsumer1 nor dataConsumer2. dataProducer.send( 'none', /* ppid */ undefined, - /* subchannels */ [ 666 ], - /* requiredSubchannel */ 3 + /* subchannels */ [666], + /* requiredSubchannel */ 3, ); // Must be received by dataConsumer1. dataProducer.send( 'dc1', /* ppid */ undefined, - /* subchannels */ [ 1 ], - /* requiredSubchannel */ undefined + /* subchannels */ [1], + /* requiredSubchannel */ undefined, ); // Must be received by dataConsumer1. dataProducer.send( 'dc1', /* ppid */ undefined, - /* subchannels */ [ 11 ], - /* requiredSubchannel */ 1 + /* subchannels */ [11], + /* requiredSubchannel */ 1, ); // Must be received by dataConsumer1. dataProducer.send( 'dc1', /* ppid */ undefined, - /* subchannels */ [ 666 ], - /* requiredSubchannel */ 11 + /* subchannels */ [666], + /* requiredSubchannel */ 11, ); // Must be received by dataConsumer2. dataProducer.send( 'dc2', /* ppid */ undefined, - /* subchannels */ [ 666 ], - /* requiredSubchannel */ 2 + /* subchannels */ [666], + /* requiredSubchannel */ 2, ); // Make dataConsumer2 also subscribe to subchannel 1. // NOTE: No need to await for this call. - void dataConsumer2.setSubchannels([ ...dataConsumer2.subchannels, 1 ]); + void dataConsumer2.setSubchannels([...dataConsumer2.subchannels, 1]); // Must be received by dataConsumer1 and dataConsumer2. dataProducer.send( 'both', /* ppid */ undefined, - /* subchannels */ [ 1 ], - /* requiredSubchannel */ 666 + /* subchannels */ [1], + /* requiredSubchannel */ 666, ); - dataConsumer1.on('message', (message) => - { + dataConsumer1.on('message', message => { receivedMessages1.push(message.toString('utf8')); if ( receivedMessages1.length === expectedReceivedNumMessages1 && receivedMessages2.length === expectedReceivedNumMessages2 - ) - { + ) { resolve(); } }); - dataConsumer2.on('message', (message) => - { + dataConsumer2.on('message', message => { receivedMessages2.push(message.toString('utf8')); if ( receivedMessages1.length === expectedReceivedNumMessages1 && receivedMessages2.length === expectedReceivedNumMessages2 - ) - { + ) { resolve(); } }); @@ -399,21 +361,18 @@ test('dataProducer.send() with subchannels succeeds', async () => expect(receivedMessages1.length).toBe(expectedReceivedNumMessages1); expect(receivedMessages2.length).toBe(expectedReceivedNumMessages2); - for (const message of receivedMessages1) - { - expect([ 'both', 'dc1' ].includes(message)).toBe(true); - expect([ 'dc2' ].includes(message)).toBe(false); + for (const message of receivedMessages1) { + expect(['both', 'dc1'].includes(message)).toBe(true); + expect(['dc2'].includes(message)).toBe(false); } - for (const message of receivedMessages2) - { - expect([ 'both', 'dc2' ].includes(message)).toBe(true); - expect([ 'dc1' ].includes(message)).toBe(false); + for (const message of receivedMessages2) { + expect(['both', 'dc2'].includes(message)).toBe(true); + expect(['dc1'].includes(message)).toBe(false); } }, 5000); -test('DirectTransport methods reject if closed', async () => -{ +test('DirectTransport methods reject if closed', async () => { const directTransport = await ctx.router!.createDirectTransport(); const onObserverClose = jest.fn(); @@ -423,24 +382,18 @@ test('DirectTransport methods reject if closed', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(directTransport.closed).toBe(true); - await expect(directTransport.dump()) - .rejects - .toThrow(Error); + await expect(directTransport.dump()).rejects.toThrow(Error); - await expect(directTransport.getStats()) - .rejects - .toThrow(Error); + await expect(directTransport.getStats()).rejects.toThrow(Error); }, 2000); -test('DirectTransport emits "routerclose" if Router is closed', async () => -{ +test('DirectTransport emits "routerclose" if Router is closed', async () => { const directTransport = await ctx.router!.createDirectTransport(); const onObserverClose = jest.fn(); directTransport.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { directTransport.on('routerclose', resolve); ctx.router!.close(); @@ -450,15 +403,13 @@ test('DirectTransport emits "routerclose" if Router is closed', async () => expect(directTransport.closed).toBe(true); }, 2000); -test('DirectTransport emits "routerclose" if Worker is closed', async () => -{ +test('DirectTransport emits "routerclose" if Worker is closed', async () => { const directTransport = await ctx.router!.createDirectTransport(); const onObserverClose = jest.fn(); directTransport.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { directTransport.on('routerclose', resolve); ctx.worker!.close(); diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index fa92483e01..2249c2bdea 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -3,8 +3,7 @@ import * as pickPort from 'pick-port'; import * as mediasoup from '../'; import * as utils from '../utils'; -type TestContext = -{ +type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; audioProducerOptions: mediasoup.types.ProducerOptions; videoProducerOptions: mediasoup.types.ProducerOptions; @@ -23,230 +22,192 @@ type TestContext = dataConsumer?: mediasoup.types.DataConsumer; }; -const ctx: TestContext = -{ - mediaCodecs : utils.deepFreeze( - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2 - }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 - } - ] - ), - audioProducerOptions : utils.deepFreeze( +const ctx: TestContext = { + mediaCodecs: utils.deepFreeze([ { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ - { - mimeType : 'audio/opus', - payloadType : 111, - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar1' - } - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 - } - ], - encodings : [ { ssrc: 11111111 } ], - rtcp : - { - cname : 'FOOBAR' - } - }, - appData : { foo: 'bar1' } - } - ), - videoProducerOptions : utils.deepFreeze( + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + }, { - kind : 'video', - rtpParameters : - { - mid : 'VIDEO', - codecs : - [ - { - mimeType : 'video/VP8', - payloadType : 112, - clockRate : 90000, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'nack', parameter: 'pli' }, - { type: 'goog-remb' }, - { type: 'lalala' } - ] - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 - }, - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - id : 11 - }, - { - uri : 'urn:3gpp:video-orientation', - id : 13 - } - ], - encodings : - [ - { ssrc: 22222222 }, - { ssrc: 22222223 }, - { ssrc: 22222224 } - ], - rtcp : + kind: 'video', + mimeType: 'video/VP8', + clockRate: 90000, + }, + ]), + audioProducerOptions: utils.deepFreeze({ + kind: 'audio', + rtpParameters: { + mid: 'AUDIO', + codecs: [ { - cname : 'FOOBAR' - } - }, - appData : { foo: 'bar2' } - } - ), - dataProducerOptions : utils.deepFreeze( - { - sctpStreamParameters : - { - streamId : 666, - ordered : false, - maxPacketLifeTime : 5000 - }, - label : 'foo', - protocol : 'bar' - } - ), - consumerDeviceCapabilities : utils.deepFreeze( - { - codecs : - [ + mimeType: 'audio/opus', + payloadType: 111, + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar1', + }, + }, + ], + headerExtensions: [ { - kind : 'audio', - mimeType : 'audio/opus', - preferredPayloadType : 100, - clockRate : 48000, - channels : 2 + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, }, + ], + encodings: [{ ssrc: 11111111 }], + rtcp: { + cname: 'FOOBAR', + }, + }, + appData: { foo: 'bar1' }, + }), + videoProducerOptions: utils.deepFreeze({ + kind: 'video', + rtpParameters: { + mid: 'VIDEO', + codecs: [ { - kind : 'video', - mimeType : 'video/VP8', - preferredPayloadType : 101, - clockRate : 90000, - rtcpFeedback : - [ + mimeType: 'video/VP8', + payloadType: 112, + clockRate: 90000, + rtcpFeedback: [ { type: 'nack' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'transport-cc' } - ] + { type: 'nack', parameter: 'pli' }, + { type: 'goog-remb' }, + { type: 'lalala' }, + ], }, - { - kind : 'video', - mimeType : 'video/rtx', - preferredPayloadType : 102, - clockRate : 90000, - parameters : - { - apt : 101 - }, - rtcpFeedback : [] - } ], - headerExtensions : - [ + headerExtensions: [ { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId : 4, - preferredEncrypt : false, - direction : 'sendrecv' + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, }, { - kind : 'video', - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - preferredId : 5, - preferredEncrypt : false + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + id: 11, }, { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 10, - preferredEncrypt : false - } - ] - } - ) + uri: 'urn:3gpp:video-orientation', + id: 13, + }, + ], + encodings: [{ ssrc: 22222222 }, { ssrc: 22222223 }, { ssrc: 22222224 }], + rtcp: { + cname: 'FOOBAR', + }, + }, + appData: { foo: 'bar2' }, + }), + dataProducerOptions: utils.deepFreeze({ + sctpStreamParameters: { + streamId: 666, + ordered: false, + maxPacketLifeTime: 5000, + }, + label: 'foo', + protocol: 'bar', + }), + consumerDeviceCapabilities: utils.deepFreeze({ + codecs: [ + { + kind: 'audio', + mimeType: 'audio/opus', + preferredPayloadType: 100, + clockRate: 48000, + channels: 2, + }, + { + kind: 'video', + mimeType: 'video/VP8', + preferredPayloadType: 101, + clockRate: 90000, + rtcpFeedback: [ + { type: 'nack' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'transport-cc' }, + ], + }, + { + kind: 'video', + mimeType: 'video/rtx', + preferredPayloadType: 102, + clockRate: 90000, + parameters: { + apt: 101, + }, + rtcpFeedback: [], + }, + ], + headerExtensions: [ + { + kind: 'video', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + preferredId: 4, + preferredEncrypt: false, + direction: 'sendrecv', + }, + { + kind: 'video', + uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + preferredId: 5, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + }, + ], + }), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker1 = await mediasoup.createWorker(); ctx.worker2 = await mediasoup.createWorker(); - ctx.router1 = await ctx.worker1.createRouter( - { mediaCodecs: ctx.mediaCodecs } - ); - ctx.router2 = await ctx.worker2.createRouter( - { mediaCodecs: ctx.mediaCodecs } - ); - ctx.webRtcTransport1 = await ctx.router1.createWebRtcTransport( - { - listenInfos : [ { protocol: 'udp', ip: '127.0.0.1' } ], - enableSctp : true - }); - ctx.webRtcTransport2 = await ctx.router2.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ], - enableSctp : true - }); + ctx.router1 = await ctx.worker1.createRouter({ + mediaCodecs: ctx.mediaCodecs, + }); + ctx.router2 = await ctx.worker2.createRouter({ + mediaCodecs: ctx.mediaCodecs, + }); + ctx.webRtcTransport1 = await ctx.router1.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + enableSctp: true, + }); + ctx.webRtcTransport2 = await ctx.router2.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + enableSctp: true, + }); ctx.audioProducer = await ctx.webRtcTransport1.produce( - ctx.audioProducerOptions + ctx.audioProducerOptions, ); ctx.videoProducer = await ctx.webRtcTransport1.produce( - ctx.videoProducerOptions + ctx.videoProducerOptions, ); ctx.dataProducer = await ctx.webRtcTransport1.produceData( - ctx.dataProducerOptions + ctx.dataProducerOptions, ); }); -afterEach(() => -{ +afterEach(() => { ctx.worker1?.close(); ctx.worker2?.close(); }); -test('router.pipeToRouter() succeeds with audio', async () => -{ - const { pipeConsumer, pipeProducer } = await ctx.router1!.pipeToRouter( - { - producerId : ctx.audioProducer!.id, - router : ctx.router2! - }) as - { - pipeConsumer: mediasoup.types.Consumer; - pipeProducer: mediasoup.types.Producer; - }; +test('router.pipeToRouter() succeeds with audio', async () => { + const { pipeConsumer, pipeProducer } = (await ctx.router1!.pipeToRouter({ + producerId: ctx.audioProducer!.id, + router: ctx.router2!, + })) as { + pipeConsumer: mediasoup.types.Consumer; + pipeProducer: mediasoup.types.Producer; + }; const dump1 = await ctx.router1!.dump(); @@ -267,42 +228,42 @@ test('router.pipeToRouter() succeeds with audio', async () => expect(pipeConsumer.kind).toBe('audio'); expect(typeof pipeConsumer.rtpParameters).toBe('object'); expect(pipeConsumer.rtpParameters.mid).toBeUndefined(); - expect(pipeConsumer.rtpParameters.codecs).toEqual( - [ - { - mimeType : 'audio/opus', - clockRate : 48000, - payloadType : 100, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar1' - }, - rtcpFeedback : [] - } - ]); - - expect(pipeConsumer.rtpParameters.headerExtensions).toEqual( - [ - { - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id : 10, - encrypt : false, - parameters : {} + expect(pipeConsumer.rtpParameters.codecs).toEqual([ + { + mimeType: 'audio/opus', + clockRate: 48000, + payloadType: 100, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar1', }, - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', - id : 13, - encrypt : false, - parameters : {} - } - ]); + rtcpFeedback: [], + }, + ]); + + expect(pipeConsumer.rtpParameters.headerExtensions).toEqual([ + { + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + id: 10, + encrypt: false, + parameters: {}, + }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', + id: 13, + encrypt: false, + parameters: {}, + }, + ]); expect(pipeConsumer.type).toBe('pipe'); expect(pipeConsumer.paused).toBe(false); expect(pipeConsumer.producerPaused).toBe(false); - expect(pipeConsumer.score).toEqual( - { score: 10, producerScore: 10, producerScores: [] }); + expect(pipeConsumer.score).toEqual({ + score: 10, + producerScore: 10, + producerScores: [], + }); expect(pipeConsumer.appData).toEqual({}); expect(pipeProducer.id).toBe(ctx.audioProducer!.id); @@ -310,52 +271,46 @@ test('router.pipeToRouter() succeeds with audio', async () => expect(pipeProducer.kind).toBe('audio'); expect(typeof pipeProducer.rtpParameters).toBe('object'); expect(pipeProducer.rtpParameters.mid).toBeUndefined(); - expect(pipeProducer.rtpParameters.codecs).toEqual( - [ - { - mimeType : 'audio/opus', - payloadType : 100, - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar1' - }, - rtcpFeedback : [] - } - ]); - expect(pipeProducer.rtpParameters.headerExtensions).toEqual( - [ - { - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id : 10, - encrypt : false, - parameters : {} + expect(pipeProducer.rtpParameters.codecs).toEqual([ + { + mimeType: 'audio/opus', + payloadType: 100, + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar1', }, - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', - id : 13, - encrypt : false, - parameters : {} - } - ]); + rtcpFeedback: [], + }, + ]); + expect(pipeProducer.rtpParameters.headerExtensions).toEqual([ + { + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + id: 10, + encrypt: false, + parameters: {}, + }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', + id: 13, + encrypt: false, + parameters: {}, + }, + ]); expect(pipeProducer.paused).toBe(false); }, 2000); -test('router.pipeToRouter() succeeds with video', async () => -{ +test('router.pipeToRouter() succeeds with video', async () => { await ctx.videoProducer!.pause(); - const { pipeConsumer, pipeProducer } = await ctx.router1!.pipeToRouter( - { - producerId : ctx.videoProducer!.id, - router : ctx.router2! - }) as - { - pipeConsumer: mediasoup.types.Consumer; - pipeProducer: mediasoup.types.Producer; - }; + const { pipeConsumer, pipeProducer } = (await ctx.router1!.pipeToRouter({ + producerId: ctx.videoProducer!.id, + router: ctx.router2!, + })) as { + pipeConsumer: mediasoup.types.Consumer; + pipeProducer: mediasoup.types.Producer; + }; const dump1 = await ctx.router1!.dump(); @@ -372,60 +327,60 @@ test('router.pipeToRouter() succeeds with video', async () => expect(pipeConsumer.kind).toBe('video'); expect(typeof pipeConsumer.rtpParameters).toBe('object'); expect(pipeConsumer.rtpParameters.mid).toBeUndefined(); - expect(pipeConsumer.rtpParameters.codecs).toEqual( - [ - { - mimeType : 'video/VP8', - payloadType : 101, - clockRate : 90000, - parameters : {}, - rtcpFeedback : - [ - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' } - ] - } - ]); - expect(pipeConsumer.rtpParameters.headerExtensions).toEqual( - [ - // NOTE: Remove this once framemarking draft becomes RFC. - { - uri : 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', - id : 6, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:ietf:params:rtp-hdrext:framemarking', - id : 7, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:3gpp:video-orientation', - id : 11, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:ietf:params:rtp-hdrext:toffset', - id : 12, - encrypt : false, - parameters : {} - }, - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', - id : 13, - encrypt : false, - parameters : {} - } - ]); + expect(pipeConsumer.rtpParameters.codecs).toEqual([ + { + mimeType: 'video/VP8', + payloadType: 101, + clockRate: 90000, + parameters: {}, + rtcpFeedback: [ + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + ], + }, + ]); + expect(pipeConsumer.rtpParameters.headerExtensions).toEqual([ + // NOTE: Remove this once framemarking draft becomes RFC. + { + uri: 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', + id: 6, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:framemarking', + id: 7, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:3gpp:video-orientation', + id: 11, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:toffset', + id: 12, + encrypt: false, + parameters: {}, + }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', + id: 13, + encrypt: false, + parameters: {}, + }, + ]); expect(pipeConsumer.type).toBe('pipe'); expect(pipeConsumer.paused).toBe(false); expect(pipeConsumer.producerPaused).toBe(true); - expect(pipeConsumer.score).toEqual( - { score: 10, producerScore: 10, producerScores: [] }); + expect(pipeConsumer.score).toEqual({ + score: 10, + producerScore: 10, + producerScores: [], + }); expect(pipeConsumer.appData).toEqual({}); expect(pipeProducer.id).toBe(ctx.videoProducer!.id); @@ -433,242 +388,223 @@ test('router.pipeToRouter() succeeds with video', async () => expect(pipeProducer.kind).toBe('video'); expect(typeof pipeProducer.rtpParameters).toBe('object'); expect(pipeProducer.rtpParameters.mid).toBeUndefined(); - expect(pipeProducer.rtpParameters.codecs).toEqual( - [ - { - mimeType : 'video/VP8', - payloadType : 101, - clockRate : 90000, - parameters : {}, - rtcpFeedback : - [ - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' } - ] - } - ]); - expect(pipeProducer.rtpParameters.headerExtensions).toEqual( - [ - // NOTE: Remove this once framemarking draft becomes RFC. - { - uri : 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', - id : 6, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:ietf:params:rtp-hdrext:framemarking', - id : 7, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:3gpp:video-orientation', - id : 11, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:ietf:params:rtp-hdrext:toffset', - id : 12, - encrypt : false, - parameters : {} - }, - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', - id : 13, - encrypt : false, - parameters : {} - } - ]); + expect(pipeProducer.rtpParameters.codecs).toEqual([ + { + mimeType: 'video/VP8', + payloadType: 101, + clockRate: 90000, + parameters: {}, + rtcpFeedback: [ + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + ], + }, + ]); + expect(pipeProducer.rtpParameters.headerExtensions).toEqual([ + // NOTE: Remove this once framemarking draft becomes RFC. + { + uri: 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', + id: 6, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:framemarking', + id: 7, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:3gpp:video-orientation', + id: 11, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:toffset', + id: 12, + encrypt: false, + parameters: {}, + }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', + id: 13, + encrypt: false, + parameters: {}, + }, + ]); expect(pipeProducer.paused).toBe(true); }, 2000); -test('router.createPipeTransport() with wrong arguments rejects with TypeError', async () => -{ +test('router.createPipeTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore - await expect(ctx.router1!.createPipeTransport({})) - .rejects - .toThrow(TypeError); - - await expect(ctx.router1!.createPipeTransport({ listenIp: '123' })) - .rejects - .toThrow(TypeError); - - // @ts-ignore - await expect(ctx.router1!.createPipeTransport({ listenIp: [ '127.0.0.1' ] })) - .rejects - .toThrow(TypeError); - - await expect(ctx.router1!.createPipeTransport( - { - listenInfo : { protocol: 'tcp', ip: '127.0.0.1' } - })) - .rejects - .toThrow(TypeError); - - await expect(ctx.router1!.createPipeTransport( - { - listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, + await expect(ctx.router1!.createPipeTransport({})).rejects.toThrow(TypeError); + + await expect( + ctx.router1!.createPipeTransport({ listenIp: '123' }), + ).rejects.toThrow(TypeError); + + await expect( + // @ts-ignore + ctx.router1!.createPipeTransport({ listenIp: ['127.0.0.1'] }), + ).rejects.toThrow(TypeError); + + await expect( + ctx.router1!.createPipeTransport({ + listenInfo: { protocol: 'tcp', ip: '127.0.0.1' }, + }), + ).rejects.toThrow(TypeError); + + await expect( + ctx.router1!.createPipeTransport({ + listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, // @ts-ignore - appData : 'NOT-AN-OBJECT' - })) - .rejects - .toThrow(TypeError); + appData: 'NOT-AN-OBJECT', + }), + ).rejects.toThrow(TypeError); }, 2000); -test('router.createPipeTransport() with enableRtx succeeds', async () => -{ - const pipeTransport = await ctx.router1!.createPipeTransport( - { - listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, - enableRtx : true - }); +test('router.createPipeTransport() with enableRtx succeeds', async () => { + const pipeTransport = await ctx.router1!.createPipeTransport({ + listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, + enableRtx: true, + }); - const pipeConsumer = - await pipeTransport.consume({ producerId: ctx.videoProducer!.id }); + const pipeConsumer = await pipeTransport.consume({ + producerId: ctx.videoProducer!.id, + }); expect(typeof pipeConsumer.id).toBe('string'); expect(pipeConsumer.closed).toBe(false); expect(pipeConsumer.kind).toBe('video'); expect(typeof pipeConsumer.rtpParameters).toBe('object'); expect(pipeConsumer.rtpParameters.mid).toBeUndefined(); - expect(pipeConsumer.rtpParameters.codecs).toEqual( - [ - { - mimeType : 'video/VP8', - payloadType : 101, - clockRate : 90000, - parameters : {}, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' } - ] - }, - { - mimeType : 'video/rtx', - payloadType : 102, - clockRate : 90000, - parameters : { apt: 101 }, - rtcpFeedback : [] - } - ]); - expect(pipeConsumer.rtpParameters.headerExtensions).toEqual( - [ - // NOTE: Remove this once framemarking draft becomes RFC. - { - uri : 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', - id : 6, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:ietf:params:rtp-hdrext:framemarking', - id : 7, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:3gpp:video-orientation', - id : 11, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:ietf:params:rtp-hdrext:toffset', - id : 12, - encrypt : false, - parameters : {} - }, - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', - id : 13, - encrypt : false, - parameters : {} - } - ]); + expect(pipeConsumer.rtpParameters.codecs).toEqual([ + { + mimeType: 'video/VP8', + payloadType: 101, + clockRate: 90000, + parameters: {}, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + ], + }, + { + mimeType: 'video/rtx', + payloadType: 102, + clockRate: 90000, + parameters: { apt: 101 }, + rtcpFeedback: [], + }, + ]); + expect(pipeConsumer.rtpParameters.headerExtensions).toEqual([ + // NOTE: Remove this once framemarking draft becomes RFC. + { + uri: 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', + id: 6, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:framemarking', + id: 7, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:3gpp:video-orientation', + id: 11, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:toffset', + id: 12, + encrypt: false, + parameters: {}, + }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time', + id: 13, + encrypt: false, + parameters: {}, + }, + ]); expect(pipeConsumer.type).toBe('pipe'); expect(pipeConsumer.paused).toBe(false); expect(pipeConsumer.producerPaused).toBe(false); - expect(pipeConsumer.score).toEqual( - { score: 10, producerScore: 10, producerScores: [] } - ); + expect(pipeConsumer.score).toEqual({ + score: 10, + producerScore: 10, + producerScores: [], + }); expect(pipeConsumer.appData).toEqual({}); }, 2000); -test('pipeTransport.connect() with valid SRTP parameters succeeds', async () => -{ - const pipeTransport = await ctx.router1!.createPipeTransport( - { - listenIp : '127.0.0.1', - enableSrtp : true - }); +test('pipeTransport.connect() with valid SRTP parameters succeeds', async () => { + const pipeTransport = await ctx.router1!.createPipeTransport({ + listenIp: '127.0.0.1', + enableSrtp: true, + }); expect(typeof pipeTransport.srtpParameters).toBe('object'); // The master length of AEAD_AES_256_GCM. expect(pipeTransport.srtpParameters?.keyBase64.length).toBe(60); // Valid srtpParameters. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { - cryptoSuite : 'AEAD_AES_256_GCM', - keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' - } - })) - .resolves - .toBeUndefined(); + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, + srtpParameters: { + cryptoSuite: 'AEAD_AES_256_GCM', + keyBase64: + 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', + }, + }), + ).resolves.toBeUndefined(); }, 2000); -test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', async () => -{ - const pipeTransport = await ctx.router1!.createPipeTransport( - { - listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, - enableRtx : true - }); +test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', async () => { + const pipeTransport = await ctx.router1!.createPipeTransport({ + listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, + enableRtx: true, + }); expect(pipeTransport.srtpParameters).toBeUndefined(); // No SRTP enabled so passing srtpParameters must fail. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { - cryptoSuite : 'AEAD_AES_256_GCM', - keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' - } - })) - .rejects - .toThrow(TypeError); + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, + srtpParameters: { + cryptoSuite: 'AEAD_AES_256_GCM', + keyBase64: + 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', + }, + }), + ).rejects.toThrow(TypeError); // No SRTP enabled so passing srtpParameters (even if invalid) must fail. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, // @ts-ignore - srtpParameters : 'invalid' - })) - .rejects - .toThrow(TypeError); + srtpParameters: 'invalid', + }), + ).rejects.toThrow(TypeError); }); -test('pipeTransport.connect() with invalid srtpParameters fails', async () => -{ - const pipeTransport = await ctx.router1!.createPipeTransport( - { - listenIp : '127.0.0.1', - enableSrtp : true - }); +test('pipeTransport.connect() with invalid srtpParameters fails', async () => { + const pipeTransport = await ctx.router1!.createPipeTransport({ + listenIp: '127.0.0.1', + enableSrtp: true, + }); expect(typeof pipeTransport.id).toBe('string'); expect(typeof pipeTransport.srtpParameters).toBe('object'); @@ -676,196 +612,179 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => expect(pipeTransport.srtpParameters?.keyBase64.length).toBe(60); // Missing srtpParameters. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999 - })) - .rejects - .toThrow(TypeError); + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, + }), + ).rejects.toThrow(TypeError); // Invalid srtpParameters. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, // @ts-ignore - srtpParameters : 1 - })) - .rejects - .toThrow(TypeError); + srtpParameters: 1, + }), + ).rejects.toThrow(TypeError); // Missing srtpParameters.cryptoSuite. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, // @ts-ignore - srtpParameters : - { - keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' - } - })) - .rejects - .toThrow(TypeError); + srtpParameters: { + keyBase64: + 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', + }, + }), + ).rejects.toThrow(TypeError); // Missing srtpParameters.keyBase64. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, // @ts-ignore - srtpParameters : - { - cryptoSuite : 'AEAD_AES_256_GCM' - } - })) - .rejects - .toThrow(TypeError); + srtpParameters: { + cryptoSuite: 'AEAD_AES_256_GCM', + }, + }), + ).rejects.toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, + srtpParameters: { // @ts-ignore - cryptoSuite : 'FOO', - keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' - } - })) - .rejects - .toThrow(TypeError); + cryptoSuite: 'FOO', + keyBase64: + 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', + }, + }), + ).rejects.toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, + srtpParameters: { // @ts-ignore - cryptoSuite : 123, - keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' - } - })) - .rejects - .toThrow(TypeError); + cryptoSuite: 123, + keyBase64: + 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', + }, + }), + ).rejects.toThrow(TypeError); // Invalid srtpParameters.keyBase64. - await expect(pipeTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { - cryptoSuite : 'AEAD_AES_256_GCM', + await expect( + pipeTransport.connect({ + ip: '127.0.0.2', + port: 9999, + srtpParameters: { + cryptoSuite: 'AEAD_AES_256_GCM', // @ts-ignore - keyBase64 : [] - } - })) - .rejects - .toThrow(TypeError); + keyBase64: [], + }, + }), + ).rejects.toThrow(TypeError); }, 2000); -test('router.createPipeTransport() with fixed port succeeds', async () => -{ +test('router.createPipeTransport() with fixed port succeeds', async () => { const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const pipeTransport = await ctx.router1!.createPipeTransport( - { - listenInfo : { protocol: 'udp', ip: '127.0.0.1', port } - }); + const pipeTransport = await ctx.router1!.createPipeTransport({ + listenInfo: { protocol: 'udp', ip: '127.0.0.1', port }, + }); expect(pipeTransport.tuple.localPort).toEqual(port); }, 2000); -test('transport.consume() for a pipe Producer succeeds', async () => -{ - await ctx.router1!.pipeToRouter( - { - producerId : ctx.videoProducer!.id, - router : ctx.router2! - }); +test('transport.consume() for a pipe Producer succeeds', async () => { + await ctx.router1!.pipeToRouter({ + producerId: ctx.videoProducer!.id, + router: ctx.router2!, + }); - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); expect(typeof videoConsumer.id).toBe('string'); expect(videoConsumer.closed).toBe(false); expect(videoConsumer.kind).toBe('video'); expect(typeof videoConsumer.rtpParameters).toBe('object'); expect(videoConsumer.rtpParameters.mid).toBe('0'); - expect(videoConsumer.rtpParameters.codecs).toEqual( - [ - { - mimeType : 'video/VP8', - payloadType : 101, - clockRate : 90000, - parameters : {}, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'transport-cc', parameter: '' } - ] - }, - { - mimeType : 'video/rtx', - payloadType : 102, - clockRate : 90000, - parameters : - { - apt : 101 - }, - rtcpFeedback : [] - } - ]); - expect(videoConsumer.rtpParameters.headerExtensions).toEqual( - [ - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - id : 4, - encrypt : false, - parameters : {} + expect(videoConsumer.rtpParameters.codecs).toEqual([ + { + mimeType: 'video/VP8', + payloadType: 101, + clockRate: 90000, + parameters: {}, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'transport-cc', parameter: '' }, + ], + }, + { + mimeType: 'video/rtx', + payloadType: 102, + clockRate: 90000, + parameters: { + apt: 101, }, - { - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - id : 5, - encrypt : false, - parameters : {} - } - ]); + rtcpFeedback: [], + }, + ]); + expect(videoConsumer.rtpParameters.headerExtensions).toEqual([ + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + id: 4, + encrypt: false, + parameters: {}, + }, + { + uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + id: 5, + encrypt: false, + parameters: {}, + }, + ]); expect(videoConsumer.rtpParameters.encodings?.length).toBe(1); expect(typeof videoConsumer.rtpParameters.encodings?.[0].ssrc).toBe('number'); expect(typeof videoConsumer.rtpParameters.encodings?.[0].rtx).toBe('object'); - expect(typeof videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc).toBe('number'); + expect(typeof videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc).toBe( + 'number', + ); expect(videoConsumer.type).toBe('simulcast'); expect(videoConsumer.paused).toBe(false); expect(videoConsumer.producerPaused).toBe(false); - expect(videoConsumer.score).toEqual( - { score: 10, producerScore: 0, producerScores: [ 0, 0, 0 ] } - ); + expect(videoConsumer.score).toEqual({ + score: 10, + producerScore: 0, + producerScores: [0, 0, 0], + }); expect(videoConsumer.appData).toEqual({}); }, 2000); -test('producer.pause() and producer.resume() are transmitted to pipe Consumer', async () => -{ +test('producer.pause() and producer.resume() are transmitted to pipe Consumer', async () => { await ctx.videoProducer!.pause(); - await ctx.router1!.pipeToRouter( - { - producerId : ctx.videoProducer!.id, - router : ctx.router2! - }); + await ctx.router1!.pipeToRouter({ + producerId: ctx.videoProducer!.id, + router: ctx.router2!, + }); - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); expect(ctx.videoProducer!.paused).toBe(true); expect(videoConsumer.producerPaused).toBe(true); @@ -873,8 +792,8 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', // NOTE: Let's use a Promise since otherwise there may be race conditions // between events and await lines below. - const promise1 = new Promise( - (resolve) => videoConsumer.once('producerresume', resolve) + const promise1 = new Promise(resolve => + videoConsumer.once('producerresume', resolve), ); await ctx.videoProducer!.resume(); @@ -883,8 +802,8 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', expect(videoConsumer.producerPaused).toBe(false); expect(videoConsumer.paused).toBe(false); - const promise2 = new Promise( - (resolve) => videoConsumer.once('producerpause', resolve) + const promise2 = new Promise(resolve => + videoConsumer.once('producerpause', resolve), ); await ctx.videoProducer!.pause(); @@ -894,57 +813,49 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', expect(videoConsumer.paused).toBe(false); }, 2000); -test('producer.close() is transmitted to pipe Consumer', async () => -{ - await ctx.router1!.pipeToRouter( - { - producerId : ctx.videoProducer!.id, - router : ctx.router2! - }); +test('producer.close() is transmitted to pipe Consumer', async () => { + await ctx.router1!.pipeToRouter({ + producerId: ctx.videoProducer!.id, + router: ctx.router2!, + }); - const videoConsumer = await ctx.webRtcTransport2!.consume( - { - producerId : ctx.videoProducer!.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); + const videoConsumer = await ctx.webRtcTransport2!.consume({ + producerId: ctx.videoProducer!.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); await ctx.videoProducer!.close(); expect(ctx.videoProducer!.closed).toBe(true); - if (!videoConsumer.closed) - { - await new Promise( - (resolve) => videoConsumer.once('producerclose', resolve) + if (!videoConsumer.closed) { + await new Promise(resolve => + videoConsumer.once('producerclose', resolve), ); } expect(videoConsumer.closed).toBe(true); }, 2000); -test('router.pipeToRouter() fails if both Routers belong to the same Worker', async () => -{ - const router1bis = await ctx.worker1!.createRouter( - { mediaCodecs: ctx.mediaCodecs } - ); +test('router.pipeToRouter() fails if both Routers belong to the same Worker', async () => { + const router1bis = await ctx.worker1!.createRouter({ + mediaCodecs: ctx.mediaCodecs, + }); - await expect(ctx.router1!.pipeToRouter( - { - producerId : ctx.videoProducer!.id, - router : router1bis - })) - .rejects - .toThrow(Error); + await expect( + ctx.router1!.pipeToRouter({ + producerId: ctx.videoProducer!.id, + router: router1bis, + }), + ).rejects.toThrow(Error); }, 2000); -test('router.pipeToRouter() succeeds with data', async () => -{ - const { pipeDataConsumer, pipeDataProducer } = await ctx.router1!.pipeToRouter( - { - dataProducerId : ctx.dataProducer!.id, - router : ctx.router2! - }) as - { +test('router.pipeToRouter() succeeds with data', async () => { + const { pipeDataConsumer, pipeDataProducer } = + (await ctx.router1!.pipeToRouter({ + dataProducerId: ctx.dataProducer!.id, + router: ctx.router2!, + })) as { pipeDataConsumer: mediasoup.types.DataConsumer; pipeDataProducer: mediasoup.types.DataProducer; }; @@ -986,18 +897,15 @@ test('router.pipeToRouter() succeeds with data', async () => expect(pipeDataProducer.protocol).toBe('bar'); }, 2000); -test('transport.dataConsume() for a pipe DataProducer succeeds', async () => -{ - await ctx.router1!.pipeToRouter( - { - dataProducerId : ctx.dataProducer!.id, - router : ctx.router2! - }); +test('transport.dataConsume() for a pipe DataProducer succeeds', async () => { + await ctx.router1!.pipeToRouter({ + dataProducerId: ctx.dataProducer!.id, + router: ctx.router2!, + }); - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); expect(typeof dataConsumer.id).toBe('string'); expect(dataConsumer.closed).toBe(false); @@ -1011,59 +919,55 @@ test('transport.dataConsume() for a pipe DataProducer succeeds', async () => expect(dataConsumer.protocol).toBe('bar'); }, 2000); -test('dataProducer.close() is transmitted to pipe DataConsumer', async () => -{ - await ctx.router1!.pipeToRouter( - { - dataProducerId : ctx.dataProducer!.id, - router : ctx.router2! - }); +test('dataProducer.close() is transmitted to pipe DataConsumer', async () => { + await ctx.router1!.pipeToRouter({ + dataProducerId: ctx.dataProducer!.id, + router: ctx.router2!, + }); - const dataConsumer = await ctx.webRtcTransport2!.consumeData( - { - dataProducerId : ctx.dataProducer!.id - }); + const dataConsumer = await ctx.webRtcTransport2!.consumeData({ + dataProducerId: ctx.dataProducer!.id, + }); await ctx.dataProducer!.close(); expect(ctx.dataProducer!.closed).toBe(true); - if (!dataConsumer.closed) - { - await new Promise( - (resolve) => dataConsumer.once('dataproducerclose', resolve) + if (!dataConsumer.closed) { + await new Promise(resolve => + dataConsumer.once('dataproducerclose', resolve), ); } expect(dataConsumer.closed).toBe(true); }, 2000); -test('router.pipeToRouter() called twice generates a single PipeTransport pair', async () => -{ - const routerA = - await ctx.worker1!.createRouter({ mediaCodecs: ctx.mediaCodecs }); - const routerB = - await ctx.worker2!.createRouter({ mediaCodecs: ctx.mediaCodecs }); - const transportA1 = - await routerA.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); - const transportA2 - = await routerA.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); +test('router.pipeToRouter() called twice generates a single PipeTransport pair', async () => { + const routerA = await ctx.worker1!.createRouter({ + mediaCodecs: ctx.mediaCodecs, + }); + const routerB = await ctx.worker2!.createRouter({ + mediaCodecs: ctx.mediaCodecs, + }); + const transportA1 = await routerA.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + }); + const transportA2 = await routerA.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + }); const audioProducerA1 = await transportA1.produce(ctx.audioProducerOptions); const audioProducerA2 = await transportA2.produce(ctx.audioProducerOptions); - await Promise.all( - [ - routerA.pipeToRouter( - { - producerId : audioProducerA1.id, - router : routerB - }), - routerA.pipeToRouter( - { - producerId : audioProducerA2.id, - router : routerB - }) - ]); + await Promise.all([ + routerA.pipeToRouter({ + producerId: audioProducerA1.id, + router: routerB, + }), + routerA.pipeToRouter({ + producerId: audioProducerA2.id, + router: routerB, + }), + ]); const dump1 = await routerA.dump(); @@ -1079,25 +983,26 @@ test('router.pipeToRouter() called twice generates a single PipeTransport pair', expect(dump2.transportIds.length).toBe(1); }, 2000); -test('router.pipeToRouter() called in two Routers passing one to each other as argument generates a single a single PipeTransport pair', async () => -{ - const routerA = - await ctx.worker1!.createRouter({ mediaCodecs: ctx.mediaCodecs }); - const routerB = - await ctx.worker2!.createRouter({ mediaCodecs: ctx.mediaCodecs }); - const transportA = - await routerA.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); - const transportB = - await routerB.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] }); +test('router.pipeToRouter() called in two Routers passing one to each other as argument generates a single a single PipeTransport pair', async () => { + const routerA = await ctx.worker1!.createRouter({ + mediaCodecs: ctx.mediaCodecs, + }); + const routerB = await ctx.worker2!.createRouter({ + mediaCodecs: ctx.mediaCodecs, + }); + const transportA = await routerA.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + }); + const transportB = await routerB.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + }); const audioProducerA = await transportA.produce(ctx.audioProducerOptions); const audioProducerB = await transportB.produce(ctx.audioProducerOptions); const pipeTransportsA = new Map(); const pipeTransportsB = new Map(); - routerA.observer.on('newtransport', (transport) => - { - if (transport.constructor.name !== 'PipeTransport') - { + routerA.observer.on('newtransport', transport => { + if (transport.constructor.name !== 'PipeTransport') { return; } @@ -1105,10 +1010,8 @@ test('router.pipeToRouter() called in two Routers passing one to each other as a transport.observer.on('close', () => pipeTransportsA.delete(transport.id)); }); - routerB.observer.on('newtransport', (transport) => - { - if (transport.constructor.name !== 'PipeTransport') - { + routerB.observer.on('newtransport', transport => { + if (transport.constructor.name !== 'PipeTransport') { return; } @@ -1116,19 +1019,16 @@ test('router.pipeToRouter() called in two Routers passing one to each other as a transport.observer.on('close', () => pipeTransportsB.delete(transport.id)); }); - await Promise.all( - [ - routerA.pipeToRouter( - { - producerId : audioProducerA.id, - router : routerB - }), - routerB.pipeToRouter( - { - producerId : audioProducerB.id, - router : routerA - }) - ]); + await Promise.all([ + routerA.pipeToRouter({ + producerId: audioProducerA.id, + router: routerB, + }), + routerB.pipeToRouter({ + producerId: audioProducerB.id, + router: routerA, + }), + ]); // There should be a single PipeTransport in each Router and they must be // connected. diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index c6c1ce2966..ccf85c0720 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -6,82 +6,72 @@ import * as utils from '../utils'; const IS_WINDOWS = os.platform() === 'win32'; -type TestContext = -{ +type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; }; -const ctx: TestContext = -{ - mediaCodecs : utils.deepFreeze( - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } +const ctx: TestContext = { + mediaCodecs: utils.deepFreeze([ + { + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar', }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 + }, + { + kind: 'video', + mimeType: 'video/VP8', + clockRate: 90000, + }, + { + kind: 'video', + mimeType: 'video/H264', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + foo: 'bar', }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - foo : 'bar' - }, - rtcpFeedback : [] // Will be ignored. - } - ] - ) + rtcpFeedback: [], // Will be ignored. + }, + ]), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('router.createPlainTransport() succeeds', async () => -{ - const plainTransport = await ctx.router!.createPlainTransport( - { listenInfo: { protocol: 'udp', ip: '127.0.0.1' } } - ); +test('router.createPlainTransport() succeeds', async () => { + const plainTransport = await ctx.router!.createPlainTransport({ + listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, + }); - await expect(ctx.router!.dump()) - .resolves - .toMatchObject({ transportIds: [ plainTransport.id ] }); + await expect(ctx.router!.dump()).resolves.toMatchObject({ + transportIds: [plainTransport.id], + }); const onObserverNewTransport = jest.fn(); ctx.router!.observer.once('newtransport', onObserverNewTransport); // Create a separate transport here. - const plainTransport2 = await ctx.router!.createPlainTransport( - { - listenInfo : { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, - enableSctp : true, - appData : { foo: 'bar' } - }); + const plainTransport2 = await ctx.router!.createPlainTransport({ + listenInfo: { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, + enableSctp: true, + appData: { foo: 'bar' }, + }); expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(plainTransport2); @@ -93,13 +83,12 @@ test('router.createPlainTransport() succeeds', async () => expect(typeof plainTransport2.tuple.localPort).toBe('number'); expect(plainTransport2.tuple.protocol).toBe('udp'); expect(plainTransport2.rtcpTuple).toBeUndefined(); - expect(plainTransport2.sctpParameters).toMatchObject( - { - port : 5000, - OS : 1024, - MIS : 1024, - maxMessageSize : 262144 - }); + expect(plainTransport2.sctpParameters).toMatchObject({ + port: 5000, + OS: 1024, + MIS: 1024, + maxMessageSize: 262144, + }); expect(plainTransport2.sctpState).toBe('new'); expect(plainTransport2.srtpParameters).toBeUndefined(); @@ -119,18 +108,18 @@ test('router.createPlainTransport() succeeds', async () => plainTransport2.close(); expect(plainTransport2.closed).toBe(true); - const anotherTransport = - await ctx.router!.createPlainTransport({ listenIp: '127.0.0.1' }); + const anotherTransport = await ctx.router!.createPlainTransport({ + listenIp: '127.0.0.1', + }); expect(typeof anotherTransport).toBe('object'); const rtpPort = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const rtcpPort = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const transport2 = await ctx.router!.createPlainTransport( - { - listenInfo : { protocol: 'udp', ip: '127.0.0.1', port: rtpPort }, - rtcpListenInfo : { protocol: 'udp', ip: '127.0.0.1', port: rtcpPort } - }); + const transport2 = await ctx.router!.createPlainTransport({ + listenInfo: { protocol: 'udp', ip: '127.0.0.1', port: rtpPort }, + rtcpListenInfo: { protocol: 'udp', ip: '127.0.0.1', port: rtcpPort }, + }); expect(typeof transport2.id).toBe('string'); expect(transport2.closed).toBe(false); @@ -155,240 +144,213 @@ test('router.createPlainTransport() succeeds', async () => expect(dump2.sctpState).toBeUndefined(); }, 2000); -test('router.createPlainTransport() with wrong arguments rejects with TypeError', async () => -{ - // @ts-ignore - await expect(ctx.router!.createPlainTransport({})) - .rejects - .toThrow(TypeError); - - await expect(ctx.router!.createPlainTransport({ listenIp: '123' })) - .rejects - .toThrow(TypeError); - +test('router.createPlainTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore - await expect(ctx.router!.createPlainTransport({ listenIp: [ '127.0.0.1' ] })) - .rejects - .toThrow(TypeError); - - await expect(ctx.router!.createPipeTransport( - { - listenInfo : { protocol: 'tcp', ip: '127.0.0.1' } - })) - .rejects - .toThrow(TypeError); - - await expect(ctx.router!.createPlainTransport( - { - listenInfo : { protocol: 'udp', ip: '127.0.0.1' }, + await expect(ctx.router!.createPlainTransport({})).rejects.toThrow(TypeError); + + await expect( + ctx.router!.createPlainTransport({ listenIp: '123' }), + ).rejects.toThrow(TypeError); + + await expect( + // @ts-ignore + ctx.router!.createPlainTransport({ listenIp: ['127.0.0.1'] }), + ).rejects.toThrow(TypeError); + + await expect( + ctx.router!.createPipeTransport({ + listenInfo: { protocol: 'tcp', ip: '127.0.0.1' }, + }), + ).rejects.toThrow(TypeError); + + await expect( + ctx.router!.createPlainTransport({ + listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, // @ts-ignore - appData : 'NOT-AN-OBJECT' - })) - .rejects - .toThrow(TypeError); + appData: 'NOT-AN-OBJECT', + }), + ).rejects.toThrow(TypeError); }, 2000); -test('router.createPlainTransport() with enableSrtp succeeds', async () => -{ +test('router.createPlainTransport() with enableSrtp succeeds', async () => { // Use default cryptoSuite: 'AES_CM_128_HMAC_SHA1_80'. - const plainTransport = await ctx.router!.createPlainTransport( - { - listenIp : '127.0.0.1', - enableSrtp : true - }); + const plainTransport = await ctx.router!.createPlainTransport({ + listenIp: '127.0.0.1', + enableSrtp: true, + }); expect(typeof plainTransport.id).toBe('string'); expect(typeof plainTransport.srtpParameters).toBe('object'); - expect(plainTransport.srtpParameters?.cryptoSuite).toBe('AES_CM_128_HMAC_SHA1_80'); + expect(plainTransport.srtpParameters?.cryptoSuite).toBe( + 'AES_CM_128_HMAC_SHA1_80', + ); expect(plainTransport.srtpParameters?.keyBase64.length).toBe(40); // Missing srtpParameters. - await expect(plainTransport.connect( - { - ip : '127.0.0.2', - port : 9999 - })) - .rejects - .toThrow(TypeError); + await expect( + plainTransport.connect({ + ip: '127.0.0.2', + port: 9999, + }), + ).rejects.toThrow(TypeError); // Invalid srtpParameters. - await expect(plainTransport.connect( - { - ip : '127.0.0.2', - port : 9999, + await expect( + plainTransport.connect({ + ip: '127.0.0.2', + port: 9999, // @ts-ignore - srtpParameters : 1 - })) - .rejects - .toThrow(TypeError); + srtpParameters: 1, + }), + ).rejects.toThrow(TypeError); // Missing srtpParameters.cryptoSuite. - await expect(plainTransport.connect( - { - ip : '127.0.0.2', - port : 9999, + await expect( + plainTransport.connect({ + ip: '127.0.0.2', + port: 9999, // @ts-ignore - srtpParameters : - { - keyBase64 : 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv' - } - })) - .rejects - .toThrow(TypeError); + srtpParameters: { + keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', + }, + }), + ).rejects.toThrow(TypeError); // Missing srtpParameters.keyBase64. - await expect(plainTransport.connect( - { - ip : '127.0.0.2', - port : 9999, + await expect( + plainTransport.connect({ + ip: '127.0.0.2', + port: 9999, // @ts-ignore - srtpParameters : - { - cryptoSuite : 'AES_CM_128_HMAC_SHA1_80' - } - })) - .rejects - .toThrow(TypeError); + srtpParameters: { + cryptoSuite: 'AES_CM_128_HMAC_SHA1_80', + }, + }), + ).rejects.toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. - await expect(plainTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { + await expect( + plainTransport.connect({ + ip: '127.0.0.2', + port: 9999, + srtpParameters: { // @ts-ignore - cryptoSuite : 'FOO', - keyBase64 : 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv' - } - })) - .rejects - .toThrow(TypeError); + cryptoSuite: 'FOO', + keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', + }, + }), + ).rejects.toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. - await expect(plainTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { + await expect( + plainTransport.connect({ + ip: '127.0.0.2', + port: 9999, + srtpParameters: { // @ts-ignore - cryptoSuite : 123, - keyBase64 : 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv' - } - })) - .rejects - .toThrow(TypeError); + cryptoSuite: 123, + keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', + }, + }), + ).rejects.toThrow(TypeError); // Invalid srtpParameters.keyBase64. - await expect(plainTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { - cryptoSuite : 'AES_CM_128_HMAC_SHA1_80', + await expect( + plainTransport.connect({ + ip: '127.0.0.2', + port: 9999, + srtpParameters: { + cryptoSuite: 'AES_CM_128_HMAC_SHA1_80', // @ts-ignore - keyBase64 : [] - } - })) - .rejects - .toThrow(TypeError); + keyBase64: [], + }, + }), + ).rejects.toThrow(TypeError); // Valid srtpParameters. And let's update the crypto suite. - await expect(plainTransport.connect( - { - ip : '127.0.0.2', - port : 9999, - srtpParameters : - { - cryptoSuite : 'AEAD_AES_256_GCM', - keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' - } - })) - .resolves - .toBeUndefined(); + await expect( + plainTransport.connect({ + ip: '127.0.0.2', + port: 9999, + srtpParameters: { + cryptoSuite: 'AEAD_AES_256_GCM', + keyBase64: + 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', + }, + }), + ).resolves.toBeUndefined(); expect(plainTransport.srtpParameters?.cryptoSuite).toBe('AEAD_AES_256_GCM'); expect(plainTransport.srtpParameters?.keyBase64.length).toBe(60); }, 2000); -test('router.createPlainTransport() with non bindable IP rejects with Error', async () => -{ - await expect(ctx.router!.createPlainTransport({ listenIp: '8.8.8.8' })) - .rejects - .toThrow(Error); +test('router.createPlainTransport() with non bindable IP rejects with Error', async () => { + await expect( + ctx.router!.createPlainTransport({ listenIp: '8.8.8.8' }), + ).rejects.toThrow(Error); }, 2000); -if (!IS_WINDOWS) -{ - test('two transports binding to the same IP:port with udpReusePort flag succeed', async () => - { +if (!IS_WINDOWS) { + test('two transports binding to the same IP:port with udpReusePort flag succeed', async () => { const multicastIp = '224.0.0.1'; const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); - await expect(ctx.router!.createPlainTransport( - { - listenInfo : - { - protocol : 'udp', - ip : multicastIp, - port : port, + await expect( + ctx.router!.createPlainTransport({ + listenInfo: { + protocol: 'udp', + ip: multicastIp, + port: port, // NOTE: ipv6Only flag will be ignored since ip is IPv4. - flags : { udpReusePort: true, ipv6Only: true } - } - } - )).resolves.toBeDefined(); - - await expect(ctx.router!.createPlainTransport( - { - listenInfo : - { - protocol : 'udp', - ip : multicastIp, - port : port, - flags : { udpReusePort: true } - } - } - )).resolves.toBeDefined(); + flags: { udpReusePort: true, ipv6Only: true }, + }, + }), + ).resolves.toBeDefined(); + + await expect( + ctx.router!.createPlainTransport({ + listenInfo: { + protocol: 'udp', + ip: multicastIp, + port: port, + flags: { udpReusePort: true }, + }, + }), + ).resolves.toBeDefined(); }, 2000); - test('two transports binding to the same IP:port without udpReusePort flag fail', async () => - { + test('two transports binding to the same IP:port without udpReusePort flag fail', async () => { const multicastIp = '224.0.0.1'; const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); - await expect(ctx.router!.createPlainTransport( - { - listenInfo : - { - protocol : 'udp', - ip : multicastIp, - port : port, - flags : { udpReusePort: false } - } - } - )).resolves.toBeDefined(); - - await expect(ctx.router!.createPlainTransport( - { - listenInfo : - { - protocol : 'udp', - ip : multicastIp, - port : port, - flags : { udpReusePort: false } - } - } - )).rejects.toThrow(); + await expect( + ctx.router!.createPlainTransport({ + listenInfo: { + protocol: 'udp', + ip: multicastIp, + port: port, + flags: { udpReusePort: false }, + }, + }), + ).resolves.toBeDefined(); + + await expect( + ctx.router!.createPlainTransport({ + listenInfo: { + protocol: 'udp', + ip: multicastIp, + port: port, + flags: { udpReusePort: false }, + }, + }), + ).rejects.toThrow(); }, 2000); } -test('plainTransport.getStats() succeeds', async () => -{ - const plainTransport = await ctx.router!.createPlainTransport( - { listenIp: '127.0.0.1' } - ); +test('plainTransport.getStats() succeeds', async () => { + const plainTransport = await ctx.router!.createPlainTransport({ + listenIp: '127.0.0.1', + }); const stats = await plainTransport.getStats(); @@ -418,24 +380,20 @@ test('plainTransport.getStats() succeeds', async () => expect(stats[0].rtcpTuple).toBeUndefined(); }, 2000); -test('plainTransport.connect() succeeds', async () => -{ - const plainTransport = await ctx.router!.createPlainTransport( - { listenIp: '127.0.0.1', rtcpMux: false } - ); +test('plainTransport.connect() succeeds', async () => { + const plainTransport = await ctx.router!.createPlainTransport({ + listenIp: '127.0.0.1', + rtcpMux: false, + }); - await expect(plainTransport.connect( - { ip: '1.2.3.4', port: 1234, rtcpPort: 1235 } - )) - .resolves - .toBeUndefined(); + await expect( + plainTransport.connect({ ip: '1.2.3.4', port: 1234, rtcpPort: 1235 }), + ).resolves.toBeUndefined(); // Must fail if connected. - await expect(plainTransport.connect( - { ip: '1.2.3.4', port: 1234, rtcpPort: 1235 } - )) - .rejects - .toThrow(Error); + await expect( + plainTransport.connect({ ip: '1.2.3.4', port: 1234, rtcpPort: 1235 }), + ).rejects.toThrow(Error); expect(plainTransport.tuple.remoteIp).toBe('1.2.3.4'); expect(plainTransport.tuple.remotePort).toBe(1234); @@ -445,64 +403,56 @@ test('plainTransport.connect() succeeds', async () => expect(plainTransport.rtcpTuple?.protocol).toBe('udp'); }, 2000); -test('plainTransport.connect() with wrong arguments rejects with TypeError', async () => -{ - const plainTransport = await ctx.router!.createPlainTransport( - { listenIp: '127.0.0.1', rtcpMux: false } - ); +test('plainTransport.connect() with wrong arguments rejects with TypeError', async () => { + const plainTransport = await ctx.router!.createPlainTransport({ + listenIp: '127.0.0.1', + rtcpMux: false, + }); // No SRTP enabled so passing srtpParameters must fail. - await expect(plainTransport.connect( - { - ip : '127.0.0.2', - port : 9998, - rtcpPort : 9999, - srtpParameters : - { - cryptoSuite : 'AES_CM_128_HMAC_SHA1_80', - keyBase64 : 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv' - } - })) - .rejects - .toThrow(TypeError); - - await expect(plainTransport.connect({})) - .rejects - .toThrow(TypeError); - - await expect(plainTransport.connect({ ip: '::::1234' })) - .rejects - .toThrow(TypeError); + await expect( + plainTransport.connect({ + ip: '127.0.0.2', + port: 9998, + rtcpPort: 9999, + srtpParameters: { + cryptoSuite: 'AES_CM_128_HMAC_SHA1_80', + keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', + }, + }), + ).rejects.toThrow(TypeError); + + await expect(plainTransport.connect({})).rejects.toThrow(TypeError); + + await expect(plainTransport.connect({ ip: '::::1234' })).rejects.toThrow( + TypeError, + ); // Must fail because transport has rtcpMux: false so rtcpPort must be given // in connect(). - await expect(plainTransport.connect( - { - ip : '127.0.0.1', - port : 1234, + await expect( + plainTransport.connect({ + ip: '127.0.0.1', + port: 1234, // @ts-ignore - __rtcpPort : 1235 - } - )) - .rejects - .toThrow(TypeError); + __rtcpPort: 1235, + }), + ).rejects.toThrow(TypeError); - await expect(plainTransport.connect( - { - ip : '127.0.0.1', + await expect( + plainTransport.connect({ + ip: '127.0.0.1', // @ts-ignore - __port : 'chicken', - rtcpPort : 1235 - })) - .rejects - .toThrow(TypeError); + __port: 'chicken', + rtcpPort: 1235, + }), + ).rejects.toThrow(TypeError); }, 2000); -test('PlainTransport methods reject if closed', async () => -{ - const plainTransport = await ctx.router!.createPlainTransport( - { listenIp: '127.0.0.1' } - ); +test('PlainTransport methods reject if closed', async () => { + const plainTransport = await ctx.router!.createPlainTransport({ + listenIp: '127.0.0.1', + }); const onObserverClose = jest.fn(); @@ -512,42 +462,32 @@ test('PlainTransport methods reject if closed', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(plainTransport.closed).toBe(true); - await expect(plainTransport.dump()) - .rejects - .toThrow(Error); + await expect(plainTransport.dump()).rejects.toThrow(Error); - await expect(plainTransport.getStats()) - .rejects - .toThrow(Error); + await expect(plainTransport.getStats()).rejects.toThrow(Error); - await expect(plainTransport.connect({})) - .rejects - .toThrow(Error); + await expect(plainTransport.connect({})).rejects.toThrow(Error); }, 2000); -test('router.createPlainTransport() with fixed port succeeds', async () => -{ +test('router.createPlainTransport() with fixed port succeeds', async () => { const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const plainTransport = await ctx.router!.createPlainTransport( - { - listenInfo : { protocol: 'udp', ip: '127.0.0.1', port } - }); + const plainTransport = await ctx.router!.createPlainTransport({ + listenInfo: { protocol: 'udp', ip: '127.0.0.1', port }, + }); expect(plainTransport.tuple.localPort).toEqual(port); }, 2000); -test('PlainTransport emits "routerclose" if Router is closed', async () => -{ - const plainTransport = await ctx.router!.createPlainTransport( - { listenIp: '127.0.0.1' } - ); +test('PlainTransport emits "routerclose" if Router is closed', async () => { + const plainTransport = await ctx.router!.createPlainTransport({ + listenIp: '127.0.0.1', + }); const onObserverClose = jest.fn(); plainTransport.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { plainTransport.on('routerclose', resolve); ctx.router!.close(); @@ -557,18 +497,16 @@ test('PlainTransport emits "routerclose" if Router is closed', async () => expect(plainTransport.closed).toBe(true); }, 2000); -test('PlainTransport emits "routerclose" if Worker is closed', async () => -{ - const plainTransport = await ctx.router!.createPlainTransport( - { listenIp: '127.0.0.1' } - ); +test('PlainTransport emits "routerclose" if Worker is closed', async () => { + const plainTransport = await ctx.router!.createPlainTransport({ + listenIp: '127.0.0.1', + }); const onObserverClose = jest.fn(); plainTransport.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { plainTransport.on('routerclose', resolve); ctx.worker!.close(); diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index c5e79a93cc..0533033eb3 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -5,12 +5,11 @@ import * as utils from '../utils'; import { Notification, Body as NotificationBody, - Event + Event, } from '../fbs/notification'; import * as FbsProducer from '../fbs/producer'; -type TestContext = -{ +type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; audioProducerOptions: mediasoup.types.ProducerOptions; videoProducerOptions: mediasoup.types.ProducerOptions; @@ -20,168 +19,143 @@ type TestContext = webRtcTransport2?: mediasoup.types.WebRtcTransport; }; -const ctx: TestContext = -{ - mediaCodecs : utils.deepFreeze( - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - foo : '111' - } +const ctx: TestContext = { + mediaCodecs: utils.deepFreeze([ + { + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + parameters: { + foo: '111', }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 + }, + { + kind: 'video', + mimeType: 'video/VP8', + clockRate: 90000, + }, + { + kind: 'video', + mimeType: 'video/H264', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + foo: 'bar', }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : + rtcpFeedback: [], // Will be ignored. + }, + ]), + audioProducerOptions: utils.deepFreeze({ + kind: 'audio', + rtpParameters: { + mid: 'AUDIO', + codecs: [ { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - foo : 'bar' - }, - rtcpFeedback : [] // Will be ignored. - } - ] - ), - audioProducerOptions : utils.deepFreeze( - { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ - { - mimeType : 'audio/opus', - payloadType : 0, - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - usedtx : 1, - foo : 222.222, - bar : '333' - } - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 + mimeType: 'audio/opus', + payloadType: 0, + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + usedtx: 1, + foo: 222.222, + bar: '333', }, - { - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id : 12 - } - ], - // Missing encodings on purpose. - rtcp : + }, + ], + headerExtensions: [ { - cname : 'audio-1' - } + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + id: 12, + }, + ], + // Missing encodings on purpose. + rtcp: { + cname: 'audio-1', }, - appData : { foo: 1, bar: '2' } - } - ), - videoProducerOptions : utils.deepFreeze( - { - kind : 'video', - rtpParameters : - { - mid : 'VIDEO', - codecs : - [ - { - mimeType : 'video/h264', - payloadType : 112, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'nack', parameter: 'pli' }, - { type: 'goog-remb' } - ] - }, - { - mimeType : 'video/rtx', - payloadType : 113, - clockRate : 90000, - parameters : { apt: 112 } - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 + }, + appData: { foo: 1, bar: '2' }, + }), + videoProducerOptions: utils.deepFreeze({ + kind: 'video', + rtpParameters: { + mid: 'VIDEO', + codecs: [ + { + mimeType: 'video/h264', + payloadType: 112, + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': '4d0032', }, - { - uri : 'urn:3gpp:video-orientation', - id : 13 - } - ], - encodings : - [ - { ssrc: 22222222, rtx: { ssrc: 22222223 }, scalabilityMode: 'L1T3' }, - { ssrc: 22222224, rtx: { ssrc: 22222225 } }, - { ssrc: 22222226, rtx: { ssrc: 22222227 } }, - { ssrc: 22222228, rtx: { ssrc: 22222229 } } - ], - rtcp : + rtcpFeedback: [ + { type: 'nack' }, + { type: 'nack', parameter: 'pli' }, + { type: 'goog-remb' }, + ], + }, { - cname : 'video-1' - } + mimeType: 'video/rtx', + payloadType: 113, + clockRate: 90000, + parameters: { apt: 112 }, + }, + ], + headerExtensions: [ + { + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, + }, + { + uri: 'urn:3gpp:video-orientation', + id: 13, + }, + ], + encodings: [ + { ssrc: 22222222, rtx: { ssrc: 22222223 }, scalabilityMode: 'L1T3' }, + { ssrc: 22222224, rtx: { ssrc: 22222225 } }, + { ssrc: 22222226, rtx: { ssrc: 22222227 } }, + { ssrc: 22222228, rtx: { ssrc: 22222229 } }, + ], + rtcp: { + cname: 'video-1', }, - appData : { foo: 1, bar: '2' } - } - ) + }, + appData: { foo: 1, bar: '2' }, + }), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); - ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ] - }); - ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ] - }); + ctx.webRtcTransport1 = await ctx.router.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + }); + ctx.webRtcTransport2 = await ctx.router.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + }); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('webRtcTransport1.produce() succeeds', async () => -{ +test('webRtcTransport1.produce() succeeds', async () => { const onObserverNewProducer = jest.fn(); ctx.webRtcTransport1!.observer.once('newproducer', onObserverNewProducer); - const audioProducer = - await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); + const audioProducer = await ctx.webRtcTransport1!.produce( + ctx.audioProducerOptions, + ); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer); @@ -196,32 +170,26 @@ test('webRtcTransport1.produce() succeeds', async () => expect(audioProducer.score).toEqual([]); expect(audioProducer.appData).toEqual({ foo: 1, bar: '2' }); - await expect(ctx.router!.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : [ { key: audioProducer.id, values: [] } ], - mapConsumerIdProducerId : [] - }); - - await expect(ctx.webRtcTransport1!.dump()) - .resolves - .toMatchObject( - { - id : ctx.webRtcTransport1!.id, - producerIds : [ audioProducer.id ], - consumerIds : [] - }); + await expect(ctx.router!.dump()).resolves.toMatchObject({ + mapProducerIdConsumerIds: [{ key: audioProducer.id, values: [] }], + mapConsumerIdProducerId: [], + }); + + await expect(ctx.webRtcTransport1!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport1!.id, + producerIds: [audioProducer.id], + consumerIds: [], + }); }, 2000); -test('webRtcTransport2.produce() succeeds', async () => -{ +test('webRtcTransport2.produce() succeeds', async () => { const onObserverNewProducer = jest.fn(); ctx.webRtcTransport2!.observer.once('newproducer', onObserverNewProducer); - const videoProducer = - await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); + const videoProducer = await ctx.webRtcTransport2!.produce( + ctx.videoProducerOptions, + ); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); expect(onObserverNewProducer).toHaveBeenCalledWith(videoProducer); @@ -238,55 +206,45 @@ test('webRtcTransport2.produce() succeeds', async () => const dump = await ctx.router!.dump(); - expect(dump.mapProducerIdConsumerIds) - .toEqual(expect.arrayContaining( - [ - { key: videoProducer.id, values: [] } - ])); + expect(dump.mapProducerIdConsumerIds).toEqual( + expect.arrayContaining([{ key: videoProducer.id, values: [] }]), + ); expect(dump.mapConsumerIdProducerId.length).toBe(0); - await expect(ctx.webRtcTransport2!.dump()) - .resolves - .toMatchObject( - { - id : ctx.webRtcTransport2!.id, - producerIds : [ videoProducer.id ], - consumerIds : [] - }); + await expect(ctx.webRtcTransport2!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport2!.id, + producerIds: [videoProducer.id], + consumerIds: [], + }); }, 2000); -test('webRtcTransport1.produce() without header extensions and rtcp succeeds', async () => -{ +test('webRtcTransport1.produce() without header extensions and rtcp succeeds', async () => { const onObserverNewProducer = jest.fn(); ctx.webRtcTransport1!.observer.once('newproducer', onObserverNewProducer); - const audioProducer = await ctx.webRtcTransport1!.produce( - { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO2', - codecs : - [ - { - mimeType : 'audio/opus', - payloadType : 0, - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - usedtx : 1, - foo : 222.222, - bar : '333' - } - } - ] - }, - appData : { foo: 1, bar: '2' } - }); + const audioProducer = await ctx.webRtcTransport1!.produce({ + kind: 'audio', + rtpParameters: { + mid: 'AUDIO2', + codecs: [ + { + mimeType: 'audio/opus', + payloadType: 0, + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + usedtx: 1, + foo: 222.222, + bar: '333', + }, + }, + ], + }, + appData: { foo: 1, bar: '2' }, + }); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer!); @@ -304,273 +262,228 @@ test('webRtcTransport1.produce() without header extensions and rtcp succeeds', a audioProducer.close(); }, 2000); -test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', async () => -{ - await expect(ctx.webRtcTransport1!.produce( - { +test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', async () => { + await expect( + ctx.webRtcTransport1!.produce({ // @ts-ignore - kind : 'chicken', + kind: 'chicken', // @ts-ignore - rtpParameters : {} - })) - .rejects - .toThrow(TypeError); + rtpParameters: {}, + }), + ).rejects.toThrow(TypeError); - await expect(ctx.webRtcTransport1!.produce( - { - kind : 'audio', + await expect( + ctx.webRtcTransport1!.produce({ + kind: 'audio', // @ts-ignore - rtpParameters : {} - })) - .rejects - .toThrow(TypeError); + rtpParameters: {}, + }), + ).rejects.toThrow(TypeError); // Invalid ssrc. - await expect(ctx.webRtcTransport1!.produce( - { - kind : 'audio', - rtpParameters : - { - codecs : [], - headerExtensions : [], + await expect( + ctx.webRtcTransport1!.produce({ + kind: 'audio', + rtpParameters: { + codecs: [], + headerExtensions: [], // @ts-ignore - encodings : [ { ssrc: '1111' } ], - rtcp : { cname: 'qwerty' } - } - })) - .rejects - .toThrow(TypeError); + encodings: [{ ssrc: '1111' }], + rtcp: { cname: 'qwerty' }, + }, + }), + ).rejects.toThrow(TypeError); // Missing or empty rtpParameters.encodings. - await expect(ctx.webRtcTransport1!.produce( - { - kind : 'video', - rtpParameters : - { - codecs : - [ + await expect( + ctx.webRtcTransport1!.produce({ + kind: 'video', + rtpParameters: { + codecs: [ { - mimeType : 'video/h264', - payloadType : 112, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - } + mimeType: 'video/h264', + payloadType: 112, + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, }, { - mimeType : 'video/rtx', - payloadType : 113, - clockRate : 90000, - parameters : { apt: 112 } - } + mimeType: 'video/rtx', + payloadType: 113, + clockRate: 90000, + parameters: { apt: 112 }, + }, ], - headerExtensions : [], - encodings : [], - rtcp : { cname: 'qwerty' } - } - })) - .rejects - .toThrow(TypeError); + headerExtensions: [], + encodings: [], + rtcp: { cname: 'qwerty' }, + }, + }), + ).rejects.toThrow(TypeError); // Wrong apt in RTX codec. - await expect(ctx.webRtcTransport1!.produce( - { - kind : 'audio', - rtpParameters : - { - codecs : - [ + await expect( + ctx.webRtcTransport1!.produce({ + kind: 'audio', + rtpParameters: { + codecs: [ { - mimeType : 'video/h264', - payloadType : 112, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - } + mimeType: 'video/h264', + payloadType: 112, + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, }, { - mimeType : 'video/rtx', - payloadType : 113, - clockRate : 90000, - parameters : { apt: 111 } - } - ], - headerExtensions : [], - encodings : - [ - { ssrc: 6666, rtx: { ssrc: 6667 } } + mimeType: 'video/rtx', + payloadType: 113, + clockRate: 90000, + parameters: { apt: 111 }, + }, ], - rtcp : - { - cname : 'video-1' - } - } - })) - .rejects - .toThrow(TypeError); + headerExtensions: [], + encodings: [{ ssrc: 6666, rtx: { ssrc: 6667 } }], + rtcp: { + cname: 'video-1', + }, + }, + }), + ).rejects.toThrow(TypeError); }, 2000); -test('webRtcTransport1.produce() with unsupported codecs rejects with UnsupportedError', async () => -{ - await expect(ctx.webRtcTransport1!.produce( - { - kind : 'audio', - rtpParameters : - { - codecs : - [ +test('webRtcTransport1.produce() with unsupported codecs rejects with UnsupportedError', async () => { + await expect( + ctx.webRtcTransport1!.produce({ + kind: 'audio', + rtpParameters: { + codecs: [ { - mimeType : 'audio/ISAC', - payloadType : 108, - clockRate : 32000 - } + mimeType: 'audio/ISAC', + payloadType: 108, + clockRate: 32000, + }, ], - headerExtensions : [], - encodings : [ { ssrc: 1111 } ], - rtcp : { cname: 'audio' } - } - })) - .rejects - .toThrow(UnsupportedError); + headerExtensions: [], + encodings: [{ ssrc: 1111 }], + rtcp: { cname: 'audio' }, + }, + }), + ).rejects.toThrow(UnsupportedError); // Invalid H264 profile-level-id. - await expect(ctx.webRtcTransport1!.produce( - { - kind : 'video', - rtpParameters : - { - codecs : - [ + await expect( + ctx.webRtcTransport1!.produce({ + kind: 'video', + rtpParameters: { + codecs: [ { - mimeType : 'video/h264', - payloadType : 112, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : 'CHICKEN' - } + mimeType: 'video/h264', + payloadType: 112, + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': 'CHICKEN', + }, }, { - mimeType : 'video/rtx', - payloadType : 113, - clockRate : 90000, - parameters : { apt: 112 } - } + mimeType: 'video/rtx', + payloadType: 113, + clockRate: 90000, + parameters: { apt: 112 }, + }, ], - headerExtensions : [], - encodings : - [ - { ssrc: 6666, rtx: { ssrc: 6667 } } - ] - } - })) - .rejects - .toThrow(UnsupportedError); + headerExtensions: [], + encodings: [{ ssrc: 6666, rtx: { ssrc: 6667 } }], + }, + }), + ).rejects.toThrow(UnsupportedError); }, 2000); -test('transport.produce() with already used MID or SSRC rejects with Error', async () => -{ - const audioProducerOptions: mediasoup.types.ProducerOptions = - { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ +test('transport.produce() with already used MID or SSRC rejects with Error', async () => { + const audioProducerOptions: mediasoup.types.ProducerOptions = { + kind: 'audio', + rtpParameters: { + mid: 'AUDIO', + codecs: [ { - mimeType : 'audio/opus', - payloadType : 0, - clockRate : 48000, - channels : 2 - } + mimeType: 'audio/opus', + payloadType: 0, + clockRate: 48000, + channels: 2, + }, ], - encodings : [ { ssrc: 33333333 } ] - } + encodings: [{ ssrc: 33333333 }], + }, }; - const videoProducerOptions: mediasoup.types.ProducerOptions = - { - kind : 'video', - rtpParameters : - { - mid : 'VIDEO2', - codecs : - [ + const videoProducerOptions: mediasoup.types.ProducerOptions = { + kind: 'video', + rtpParameters: { + mid: 'VIDEO2', + codecs: [ { - mimeType : 'video/h264', - payloadType : 112, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - } - } + mimeType: 'video/h264', + payloadType: 112, + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, + }, ], - headerExtensions : - [ + headerExtensions: [ { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 - } - ], - encodings : - [ - { ssrc: 22222222 } + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, + }, ], - rtcp : - { - cname : 'video-1' - } - } + encodings: [{ ssrc: 22222222 }], + rtcp: { + cname: 'video-1', + }, + }, }; await ctx.webRtcTransport1!.produce(audioProducerOptions); - await expect(ctx.webRtcTransport1!.produce(audioProducerOptions)) - .rejects - .toThrow(Error); + await expect( + ctx.webRtcTransport1!.produce(audioProducerOptions), + ).rejects.toThrow(Error); await ctx.webRtcTransport2!.produce(videoProducerOptions); - await expect(ctx.webRtcTransport2!.produce(videoProducerOptions)) - .rejects - .toThrow(Error); + await expect( + ctx.webRtcTransport2!.produce(videoProducerOptions), + ).rejects.toThrow(Error); }, 2000); -test('transport.produce() with no MID and with single encoding without RID or SSRC rejects with Error', async () => -{ - await expect(ctx.webRtcTransport1!.produce( - { - kind : 'audio', - rtpParameters : - { - codecs : - [ +test('transport.produce() with no MID and with single encoding without RID or SSRC rejects with Error', async () => { + await expect( + ctx.webRtcTransport1!.produce({ + kind: 'audio', + rtpParameters: { + codecs: [ { - mimeType : 'audio/opus', - payloadType : 111, - clockRate : 48000, - channels : 2 - } + mimeType: 'audio/opus', + payloadType: 111, + clockRate: 48000, + channels: 2, + }, ], - encodings : [ {} ] - } - })) - .rejects - .toThrow(Error); + encodings: [{}], + }, + }), + ).rejects.toThrow(Error); }, 2000); -test('producer.dump() succeeds', async () => -{ - const audioProducer = - await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); +test('producer.dump() succeeds', async () => { + const audioProducer = await ctx.webRtcTransport1!.produce( + ctx.audioProducerOptions, + ); const dump1 = await audioProducer.dump(); @@ -583,44 +496,41 @@ test('producer.dump() succeeds', async () => expect(dump1.rtpParameters.codecs[0].payloadType).toBe(0); expect(dump1.rtpParameters.codecs[0].clockRate).toBe(48000); expect(dump1.rtpParameters.codecs[0].channels).toBe(2); - expect(dump1.rtpParameters.codecs[0].parameters) - .toEqual( - { - useinbandfec : 1, - usedtx : 1, - foo : 222.222, - bar : '333' - }); + expect(dump1.rtpParameters.codecs[0].parameters).toEqual({ + useinbandfec: 1, + usedtx: 1, + foo: 222.222, + bar: '333', + }); expect(dump1.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); expect(Array.isArray(dump1.rtpParameters.headerExtensions)).toBe(true); expect(dump1.rtpParameters.headerExtensions!.length).toBe(2); - expect(dump1.rtpParameters.headerExtensions).toEqual( - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10, - parameters : {}, - encrypt : false - }, - { - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id : 12, - parameters : {}, - encrypt : false - } - ]); + expect(dump1.rtpParameters.headerExtensions).toEqual([ + { + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, + parameters: {}, + encrypt: false, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + id: 12, + parameters: {}, + encrypt: false, + }, + ]); expect(Array.isArray(dump1.rtpParameters.encodings)).toBe(true); expect(dump1.rtpParameters.encodings!.length).toBe(1); expect(dump1.rtpParameters.encodings![0]).toEqual( - expect.objectContaining( - { - codecPayloadType : 0 - }) + expect.objectContaining({ + codecPayloadType: 0, + }), ); expect(dump1.type).toBe('simple'); - const videoProducer = - await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); + const videoProducer = await ctx.webRtcTransport2!.produce( + ctx.videoProducerOptions, + ); const dump2 = await videoProducer.dump(); @@ -633,19 +543,15 @@ test('producer.dump() succeeds', async () => expect(dump2.rtpParameters.codecs[0].payloadType).toBe(112); expect(dump2.rtpParameters.codecs[0].clockRate).toBe(90000); expect(dump2.rtpParameters.codecs[0].channels).toBeUndefined(); - expect(dump2.rtpParameters.codecs[0].parameters) - .toEqual( - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }); - expect(dump2.rtpParameters.codecs[0].rtcpFeedback) - .toEqual( - [ - { type: 'nack' }, - { type: 'nack', parameter: 'pli' }, - { type: 'goog-remb' } - ]); + expect(dump2.rtpParameters.codecs[0].parameters).toEqual({ + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }); + expect(dump2.rtpParameters.codecs[0].rtcpFeedback).toEqual([ + { type: 'nack' }, + { type: 'nack', parameter: 'pli' }, + { type: 'goog-remb' }, + ]); expect(dump2.rtpParameters.codecs[1].mimeType).toBe('video/rtx'); expect(dump2.rtpParameters.codecs[1].payloadType).toBe(113); expect(dump2.rtpParameters.codecs[1].clockRate).toBe(90000); @@ -654,59 +560,54 @@ test('producer.dump() succeeds', async () => expect(dump2.rtpParameters.codecs[1].rtcpFeedback).toEqual([]); expect(Array.isArray(dump2.rtpParameters.headerExtensions)).toBe(true); expect(dump2.rtpParameters.headerExtensions!.length).toBe(2); - expect(dump2.rtpParameters.headerExtensions).toEqual( - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10, - parameters : {}, - encrypt : false - }, - { - uri : 'urn:3gpp:video-orientation', - id : 13, - parameters : {}, - encrypt : false - } - ]); + expect(dump2.rtpParameters.headerExtensions).toEqual([ + { + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, + parameters: {}, + encrypt: false, + }, + { + uri: 'urn:3gpp:video-orientation', + id: 13, + parameters: {}, + encrypt: false, + }, + ]); expect(Array.isArray(dump2.rtpParameters.encodings)).toBe(true); expect(dump2.rtpParameters.encodings!.length).toBe(4); - expect(dump2.rtpParameters.encodings).toMatchObject( - [ - { - codecPayloadType : 112, - ssrc : 22222222, - rtx : { ssrc: 22222223 }, - scalabilityMode : 'L1T3' - }, - { codecPayloadType: 112, ssrc: 22222224, rtx: { ssrc: 22222225 } }, - { codecPayloadType: 112, ssrc: 22222226, rtx: { ssrc: 22222227 } }, - { codecPayloadType: 112, ssrc: 22222228, rtx: { ssrc: 22222229 } } - ]); + expect(dump2.rtpParameters.encodings).toMatchObject([ + { + codecPayloadType: 112, + ssrc: 22222222, + rtx: { ssrc: 22222223 }, + scalabilityMode: 'L1T3', + }, + { codecPayloadType: 112, ssrc: 22222224, rtx: { ssrc: 22222225 } }, + { codecPayloadType: 112, ssrc: 22222226, rtx: { ssrc: 22222227 } }, + { codecPayloadType: 112, ssrc: 22222228, rtx: { ssrc: 22222229 } }, + ]); expect(dump2.type).toBe('simulcast'); }, 2000); -test('producer.getStats() succeeds', async () => -{ - const audioProducer = - await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); +test('producer.getStats() succeeds', async () => { + const audioProducer = await ctx.webRtcTransport1!.produce( + ctx.audioProducerOptions, + ); - const videoProducer = - await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); + const videoProducer = await ctx.webRtcTransport2!.produce( + ctx.videoProducerOptions, + ); - await expect(audioProducer.getStats()) - .resolves - .toEqual([]); + await expect(audioProducer.getStats()).resolves.toEqual([]); - await expect(videoProducer.getStats()) - .resolves - .toEqual([]); + await expect(videoProducer.getStats()).resolves.toEqual([]); }, 2000); -test('producer.pause() and resume() succeed', async () => -{ - const audioProducer = - await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); +test('producer.pause() and resume() succeed', async () => { + const audioProducer = await ctx.webRtcTransport1!.produce( + ctx.audioProducerOptions, + ); const onObserverPause = jest.fn(); const onObserverResume = jest.fn(); @@ -717,16 +618,12 @@ test('producer.pause() and resume() succeed', async () => await audioProducer.pause(); expect(audioProducer.paused).toBe(true); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ paused: true }); + await expect(audioProducer.dump()).resolves.toMatchObject({ paused: true }); await audioProducer.resume(); expect(audioProducer.paused).toBe(false); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ paused: false }); + await expect(audioProducer.dump()).resolves.toMatchObject({ paused: false }); // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. @@ -741,21 +638,19 @@ test('producer.pause() and resume() succeed', async () => expect(onObserverResume).toHaveBeenCalledTimes(3); }, 2000); -test('producer.pause() and resume() emit events', async () => -{ - const audioProducer = - await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); +test('producer.pause() and resume() emit events', async () => { + const audioProducer = await ctx.webRtcTransport1!.produce( + ctx.audioProducerOptions, + ); const promises = []; const events: string[] = []; - - audioProducer.observer.once('resume', () => - { + + audioProducer.observer.once('resume', () => { events.push('resume'); }); - audioProducer.observer.once('pause', () => - { + audioProducer.observer.once('pause', () => { events.push('pause'); }); @@ -763,71 +658,67 @@ test('producer.pause() and resume() emit events', async () => promises.push(audioProducer.resume()); await Promise.all(promises); - - expect(events).toEqual([ 'pause', 'resume' ]); + + expect(events).toEqual(['pause', 'resume']); expect(audioProducer.paused).toBe(false); }, 2000); -test('producer.enableTraceEvent() succeed', async () => -{ - const audioProducer = - await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); +test('producer.enableTraceEvent() succeed', async () => { + const audioProducer = await ctx.webRtcTransport1!.produce( + ctx.audioProducerOptions, + ); - await audioProducer.enableTraceEvent([ 'rtp', 'pli' ]); + await audioProducer.enableTraceEvent(['rtp', 'pli']); const dump1 = await audioProducer.dump(); - expect(dump1.traceEventTypes) - .toEqual(expect.arrayContaining([ 'rtp', 'pli' ])); + expect(dump1.traceEventTypes).toEqual(expect.arrayContaining(['rtp', 'pli'])); await audioProducer.enableTraceEvent([]); const dump2 = await audioProducer.dump(); - expect(dump2.traceEventTypes) - .toEqual(expect.arrayContaining([])); + expect(dump2.traceEventTypes).toEqual(expect.arrayContaining([])); // @ts-ignore - await audioProducer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); + await audioProducer.enableTraceEvent(['nack', 'FOO', 'fir']); const dump3 = await audioProducer.dump(); - expect(dump3.traceEventTypes) - .toEqual(expect.arrayContaining([ 'nack', 'fir' ])); + expect(dump3.traceEventTypes).toEqual( + expect.arrayContaining(['nack', 'fir']), + ); await audioProducer.enableTraceEvent(); const dump4 = await audioProducer.dump(); - expect(dump4.traceEventTypes) - .toEqual(expect.arrayContaining([])); + expect(dump4.traceEventTypes).toEqual(expect.arrayContaining([])); }, 2000); -test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => -{ - const audioProducer = - await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); +test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { + const audioProducer = await ctx.webRtcTransport1!.produce( + ctx.audioProducerOptions, + ); // @ts-ignore - await expect(audioProducer.enableTraceEvent(123)) - .rejects - .toThrow(TypeError); + await expect(audioProducer.enableTraceEvent(123)).rejects.toThrow(TypeError); // @ts-ignore - await expect(audioProducer.enableTraceEvent('rtp')) - .rejects - .toThrow(TypeError); + await expect(audioProducer.enableTraceEvent('rtp')).rejects.toThrow( + TypeError, + ); - // @ts-ignore - await expect(audioProducer.enableTraceEvent([ 'fir', 123.123 ])) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + audioProducer.enableTraceEvent(['fir', 123.123]), + ).rejects.toThrow(TypeError); }, 2000); -test('Producer emits "score"', async () => -{ - const videoProducer = - await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); +test('Producer emits "score"', async () => { + const videoProducer = await ctx.webRtcTransport2!.produce( + ctx.videoProducerOptions, + ); // Private API. const channel = videoProducer.channelForTesting; @@ -837,33 +728,32 @@ test('Producer emits "score"', async () => // Simulate a 'score' notification coming through the channel. const builder = new flatbuffers.Builder(); - const producerScoreNotification = new FbsProducer.ScoreNotificationT( - [ - new FbsProducer.ScoreT( - /* encodingIdx */ 0, - /* ssrc */ 11, - /* rid */ undefined, - /* score */ 10 - ), - new FbsProducer.ScoreT( - /* encodingIdx */ 1, - /* ssrc */ 22, - /* rid */ undefined, - /* score */ 9 - ) - ]); + const producerScoreNotification = new FbsProducer.ScoreNotificationT([ + new FbsProducer.ScoreT( + /* encodingIdx */ 0, + /* ssrc */ 11, + /* rid */ undefined, + /* score */ 10, + ), + new FbsProducer.ScoreT( + /* encodingIdx */ 1, + /* ssrc */ 22, + /* rid */ undefined, + /* score */ 9, + ), + ]); const notificationOffset = Notification.createNotification( builder, builder.createString(videoProducer.id), Event.PRODUCER_SCORE, NotificationBody.Producer_ScoreNotification, - producerScoreNotification.pack(builder) + producerScoreNotification.pack(builder), ); builder.finish(notificationOffset); const notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array()) + new flatbuffers.ByteBuffer(builder.asUint8Array()), ); channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); @@ -871,17 +761,16 @@ test('Producer emits "score"', async () => channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); expect(onScore).toHaveBeenCalledTimes(3); - expect(videoProducer.score).toEqual( - [ - { ssrc: 11, rid: undefined, score: 10, encodingIdx: 0 }, - { ssrc: 22, rid: undefined, score: 9, encodingIdx: 1 } - ]); + expect(videoProducer.score).toEqual([ + { ssrc: 11, rid: undefined, score: 10, encodingIdx: 0 }, + { ssrc: 22, rid: undefined, score: 9, encodingIdx: 1 }, + ]); }, 2000); -test('producer.close() succeeds', async () => -{ - const audioProducer = - await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); +test('producer.close() succeeds', async () => { + const audioProducer = await ctx.webRtcTransport1!.produce( + ctx.audioProducerOptions, + ); const onObserverClose = jest.fn(); @@ -891,59 +780,44 @@ test('producer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(audioProducer.closed).toBe(true); - await expect(ctx.router!.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : [], - mapConsumerIdProducerId : [] - }); - - await expect(ctx.webRtcTransport1!.dump()) - .resolves - .toMatchObject( - { - id : ctx.webRtcTransport1!.id, - producerIds : [], - consumerIds : [] - }); + await expect(ctx.router!.dump()).resolves.toMatchObject({ + mapProducerIdConsumerIds: [], + mapConsumerIdProducerId: [], + }); + + await expect(ctx.webRtcTransport1!.dump()).resolves.toMatchObject({ + id: ctx.webRtcTransport1!.id, + producerIds: [], + consumerIds: [], + }); }, 2000); -test('Producer methods reject if closed', async () => -{ - const audioProducer = - await ctx.webRtcTransport1!.produce(ctx.audioProducerOptions); +test('Producer methods reject if closed', async () => { + const audioProducer = await ctx.webRtcTransport1!.produce( + ctx.audioProducerOptions, + ); audioProducer.close(); - await expect(audioProducer.dump()) - .rejects - .toThrow(Error); + await expect(audioProducer.dump()).rejects.toThrow(Error); - await expect(audioProducer.getStats()) - .rejects - .toThrow(Error); + await expect(audioProducer.getStats()).rejects.toThrow(Error); - await expect(audioProducer.pause()) - .rejects - .toThrow(Error); + await expect(audioProducer.pause()).rejects.toThrow(Error); - await expect(audioProducer.resume()) - .rejects - .toThrow(Error); + await expect(audioProducer.resume()).rejects.toThrow(Error); }, 2000); -test('Producer emits "transportclose" if Transport is closed', async () => -{ - const videoProducer = - await ctx.webRtcTransport2!.produce(ctx.videoProducerOptions); +test('Producer emits "transportclose" if Transport is closed', async () => { + const videoProducer = await ctx.webRtcTransport2!.produce( + ctx.videoProducerOptions, + ); const onObserverClose = jest.fn(); videoProducer.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { videoProducer.on('transportclose', resolve); ctx.webRtcTransport2!.close(); }); diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index 6c2b5db991..877a6e1b32 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -2,69 +2,59 @@ import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; import * as utils from '../utils'; -type TestContext = -{ +type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; worker?: mediasoup.types.Worker; }; -const ctx: TestContext = -{ - mediaCodecs : utils.deepFreeze( - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } +const ctx: TestContext = { + mediaCodecs: utils.deepFreeze([ + { + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar', }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 + }, + { + kind: 'video', + mimeType: 'video/VP8', + clockRate: 90000, + }, + { + kind: 'video', + mimeType: 'video/H264', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : [] // Will be ignored. - } - ] - ) + rtcpFeedback: [], // Will be ignored. + }, + ]), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('worker.createRouter() succeeds', async () => -{ +test('worker.createRouter() succeeds', async () => { const onObserverNewRouter = jest.fn(); ctx.worker!.observer.once('newrouter', onObserverNewRouter); - const router = await ctx.worker!.createRouter<{ foo: number; bar?: string }>( - { - mediaCodecs : ctx.mediaCodecs, - appData : { foo: 123 } - }); + const router = await ctx.worker!.createRouter<{ foo: number; bar?: string }>({ + mediaCodecs: ctx.mediaCodecs, + appData: { foo: 123 }, + }); expect(onObserverNewRouter).toHaveBeenCalledTimes(1); expect(onObserverNewRouter).toHaveBeenCalledWith(router); @@ -77,33 +67,26 @@ test('worker.createRouter() succeeds', async () => expect(() => (router.appData = { foo: 222, bar: 'BBB' })).not.toThrow(); - await expect(ctx.worker!.dump()) - .resolves - .toMatchObject( - { - pid : ctx.worker!.pid, - webRtcServerIds : [], - routerIds : [ router.id ], - channelMessageHandlers : - { - channelRequestHandlers : [ router.id ], - channelNotificationHandlers : [] - } - }); - - await expect(router.dump()) - .resolves - .toMatchObject( - { - id : router.id, - transportIds : [], - rtpObserverIds : [], - mapProducerIdConsumerIds : {}, - mapConsumerIdProducerId : {}, - mapProducerIdObserverIds : {}, - mapDataProducerIdDataConsumerIds : {}, - mapDataConsumerIdDataProducerId : {} - }); + await expect(ctx.worker!.dump()).resolves.toMatchObject({ + pid: ctx.worker!.pid, + webRtcServerIds: [], + routerIds: [router.id], + channelMessageHandlers: { + channelRequestHandlers: [router.id], + channelNotificationHandlers: [], + }, + }); + + await expect(router.dump()).resolves.toMatchObject({ + id: router.id, + transportIds: [], + rtpObserverIds: [], + mapProducerIdConsumerIds: {}, + mapConsumerIdProducerId: {}, + mapProducerIdObserverIds: {}, + mapDataProducerIdDataConsumerIds: {}, + mapDataConsumerIdDataProducerId: {}, + }); // Private API. expect(ctx.worker!.routersForTesting.size).toBe(1); @@ -116,33 +99,30 @@ test('worker.createRouter() succeeds', async () => expect(ctx.worker!.routersForTesting.size).toBe(0); }, 2000); -test('worker.createRouter() with wrong arguments rejects with TypeError', async () => -{ +test('worker.createRouter() with wrong arguments rejects with TypeError', async () => { // @ts-ignore - await expect(ctx.worker!.createRouter({ mediaCodecs: {} })) - .rejects - .toThrow(TypeError); + await expect(ctx.worker!.createRouter({ mediaCodecs: {} })).rejects.toThrow( + TypeError, + ); - // @ts-ignore - await expect(ctx.worker!.createRouter({ appData: 'NOT-AN-OBJECT' })) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + ctx.worker!.createRouter({ appData: 'NOT-AN-OBJECT' }), + ).rejects.toThrow(TypeError); }, 2000); -test('worker.createRouter() rejects with InvalidStateError if Worker is closed', async () => -{ +test('worker.createRouter() rejects with InvalidStateError if Worker is closed', async () => { ctx.worker!.close(); - await expect(ctx.worker!.createRouter({ mediaCodecs: ctx.mediaCodecs })) - .rejects - .toThrow(InvalidStateError); + await expect( + ctx.worker!.createRouter({ mediaCodecs: ctx.mediaCodecs }), + ).rejects.toThrow(InvalidStateError); }, 2000); -test('router.close() succeeds', async () => -{ - const router = await ctx.worker!.createRouter( - { mediaCodecs: ctx.mediaCodecs } - ); +test('router.close() succeeds', async () => { + const router = await ctx.worker!.createRouter({ + mediaCodecs: ctx.mediaCodecs, + }); const onObserverClose = jest.fn(); @@ -153,18 +133,16 @@ test('router.close() succeeds', async () => expect(router.closed).toBe(true); }, 2000); -test('Router emits "workerclose" if Worker is closed', async () => -{ - const router = await ctx.worker!.createRouter( - { mediaCodecs: ctx.mediaCodecs } - ); +test('Router emits "workerclose" if Worker is closed', async () => { + const router = await ctx.worker!.createRouter({ + mediaCodecs: ctx.mediaCodecs, + }); const onObserverClose = jest.fn(); router.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { router.on('workerclose', resolve); ctx.worker!.close(); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index 909863975a..0ed13fb9aa 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -3,50 +3,48 @@ import * as pickPort from 'pick-port'; import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; -type TestContext = -{ +type TestContext = { worker?: mediasoup.types.Worker; }; const ctx: TestContext = {}; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('worker.createWebRtcServer() succeeds', async () => -{ +test('worker.createWebRtcServer() succeeds', async () => { const onObserverNewWebRtcServer = jest.fn(); ctx.worker!.observer.once('newwebrtcserver', onObserverNewWebRtcServer); const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); + const port2 = await pickPort({ + type: 'tcp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); - const webRtcServer = await ctx.worker!.createWebRtcServer<{ foo?: number }>( - { - listenInfos : - [ - { - protocol : 'udp', - ip : '127.0.0.1', - port : port1 - }, - { - protocol : 'tcp', - ip : '127.0.0.1', - announcedIp : '1.2.3.4', - port : port2 - } - ], - appData : { foo: 123 } - }); + const webRtcServer = await ctx.worker!.createWebRtcServer<{ foo?: number }>({ + listenInfos: [ + { + protocol: 'udp', + ip: '127.0.0.1', + port: port1, + }, + { + protocol: 'tcp', + ip: '127.0.0.1', + announcedIp: '1.2.3.4', + port: port2, + }, + ], + appData: { foo: 123 }, + }); expect(onObserverNewWebRtcServer).toHaveBeenCalledTimes(1); expect(onObserverNewWebRtcServer).toHaveBeenCalledWith(webRtcServer); @@ -54,37 +52,24 @@ test('worker.createWebRtcServer() succeeds', async () => expect(webRtcServer.closed).toBe(false); expect(webRtcServer.appData).toEqual({ foo: 123 }); - await expect(ctx.worker!.dump()) - .resolves - .toMatchObject( - { - pid : ctx.worker!.pid, - webRtcServerIds : [ webRtcServer.id ], - routerIds : [], - channelMessageHandlers : - { - channelRequestHandlers : [ webRtcServer.id ], - channelNotificationHandlers : [] - } - }); - - await expect(webRtcServer.dump()) - .resolves - .toMatchObject( - { - id : webRtcServer.id, - udpSockets : - [ - { ip: '127.0.0.1', port: port1 } - ], - tcpServers : - [ - { ip: '127.0.0.1', port: port2 } - ], - webRtcTransportIds : [], - localIceUsernameFragments : [], - tupleHashes : [] - }); + await expect(ctx.worker!.dump()).resolves.toMatchObject({ + pid: ctx.worker!.pid, + webRtcServerIds: [webRtcServer.id], + routerIds: [], + channelMessageHandlers: { + channelRequestHandlers: [webRtcServer.id], + channelNotificationHandlers: [], + }, + }); + + await expect(webRtcServer.dump()).resolves.toMatchObject({ + id: webRtcServer.id, + udpSockets: [{ ip: '127.0.0.1', port: port1 }], + tcpServers: [{ ip: '127.0.0.1', port: port2 }], + webRtcTransportIds: [], + localIceUsernameFragments: [], + tupleHashes: [], + }); // Private API. expect(ctx.worker!.webRtcServersForTesting.size).toBe(1); @@ -97,28 +82,25 @@ test('worker.createWebRtcServer() succeeds', async () => expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); }, 2000); -test('worker.createWebRtcServer() without specifying port succeeds', async () => -{ +test('worker.createWebRtcServer() without specifying port succeeds', async () => { const onObserverNewWebRtcServer = jest.fn(); ctx.worker!.observer.once('newwebrtcserver', onObserverNewWebRtcServer); - const webRtcServer = await ctx.worker!.createWebRtcServer( - { - listenInfos : - [ - { - protocol : 'udp', - ip : '127.0.0.1' - }, - { - protocol : 'tcp', - ip : '127.0.0.1', - announcedIp : '1.2.3.4' - } - ], - appData : { foo: 123 } - }); + const webRtcServer = await ctx.worker!.createWebRtcServer({ + listenInfos: [ + { + protocol: 'udp', + ip: '127.0.0.1', + }, + { + protocol: 'tcp', + ip: '127.0.0.1', + announcedIp: '1.2.3.4', + }, + ], + appData: { foo: 123 }, + }); expect(onObserverNewWebRtcServer).toHaveBeenCalledTimes(1); expect(onObserverNewWebRtcServer).toHaveBeenCalledWith(webRtcServer); @@ -126,37 +108,24 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => expect(webRtcServer.closed).toBe(false); expect(webRtcServer.appData).toEqual({ foo: 123 }); - await expect(ctx.worker!.dump()) - .resolves - .toMatchObject( - { - pid : ctx.worker!.pid, - webRtcServerIds : [ webRtcServer.id ], - routerIds : [], - channelMessageHandlers : - { - channelRequestHandlers : [ webRtcServer.id ], - channelNotificationHandlers : [] - } - }); - - await expect(webRtcServer.dump()) - .resolves - .toMatchObject( - { - id : webRtcServer.id, - udpSockets : - [ - { ip: '127.0.0.1', port: expect.any(Number) } - ], - tcpServers : - [ - { ip: '127.0.0.1', port: expect.any(Number) } - ], - webRtcTransportIds : [], - localIceUsernameFragments : [], - tupleHashes : [] - }); + await expect(ctx.worker!.dump()).resolves.toMatchObject({ + pid: ctx.worker!.pid, + webRtcServerIds: [webRtcServer.id], + routerIds: [], + channelMessageHandlers: { + channelRequestHandlers: [webRtcServer.id], + channelNotificationHandlers: [], + }, + }); + + await expect(webRtcServer.dump()).resolves.toMatchObject({ + id: webRtcServer.id, + udpSockets: [{ ip: '127.0.0.1', port: expect.any(Number) }], + tcpServers: [{ ip: '127.0.0.1', port: expect.any(Number) }], + webRtcTransportIds: [], + localIceUsernameFragments: [], + tupleHashes: [], + }); // Private API. expect(ctx.worker!.webRtcServersForTesting.size).toBe(1); @@ -169,127 +138,111 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); }, 2000); -test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', async () => -{ +test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', async () => { // @ts-ignore - await expect(ctx.worker!.createWebRtcServer({})) - .rejects - .toThrow(TypeError); + await expect(ctx.worker!.createWebRtcServer({})).rejects.toThrow(TypeError); - // @ts-ignore - await expect(ctx.worker!.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' })) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + ctx.worker!.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' }), + ).rejects.toThrow(TypeError); - // @ts-ignore - await expect(ctx.worker!.createWebRtcServer({ listenInfos: [ 'NOT-AN-OBJECT' ] })) - .rejects - .toThrow(Error); + await expect( + // @ts-ignore + ctx.worker!.createWebRtcServer({ listenInfos: ['NOT-AN-OBJECT'] }), + ).rejects.toThrow(Error); // Empty listenInfos so should fail. - await expect(ctx.worker!.createWebRtcServer({ listenInfos: [] })) - .rejects - .toThrow(TypeError); + await expect( + ctx.worker!.createWebRtcServer({ listenInfos: [] }), + ).rejects.toThrow(TypeError); }, 2000); -test('worker.createWebRtcServer() with unavailable listenInfos rejects with Error', async () => -{ +test('worker.createWebRtcServer() with unavailable listenInfos rejects with Error', async () => { const worker2 = await mediasoup.createWorker(); const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); // Using an unavailable listen IP. - await expect(ctx.worker!.createWebRtcServer( - { - listenInfos : - [ + await expect( + ctx.worker!.createWebRtcServer({ + listenInfos: [ { - protocol : 'udp', - ip : '127.0.0.1', - port : port1 + protocol: 'udp', + ip: '127.0.0.1', + port: port1, }, { - protocol : 'udp', - ip : '1.2.3.4', - port : port2 - } - ] - })) - .rejects - .toThrow(Error); + protocol: 'udp', + ip: '1.2.3.4', + port: port2, + }, + ], + }), + ).rejects.toThrow(Error); // Using the same UDP port in two listenInfos. - await expect(ctx.worker!.createWebRtcServer( - { - listenInfos : - [ + await expect( + ctx.worker!.createWebRtcServer({ + listenInfos: [ { - protocol : 'udp', - ip : '127.0.0.1', - port : port1 + protocol: 'udp', + ip: '127.0.0.1', + port: port1, }, { - protocol : 'udp', - ip : '127.0.0.1', - announcedIp : '1.2.3.4', - port : port1 - } - ] - })) - .rejects - .toThrow(Error); - - await ctx.worker!.createWebRtcServer( - { - listenInfos : - [ - { - protocol : 'udp', - ip : '127.0.0.1', - port : port1 - } - ] - }); + protocol: 'udp', + ip: '127.0.0.1', + announcedIp: '1.2.3.4', + port: port1, + }, + ], + }), + ).rejects.toThrow(Error); + + await ctx.worker!.createWebRtcServer({ + listenInfos: [ + { + protocol: 'udp', + ip: '127.0.0.1', + port: port1, + }, + ], + }); // Using the same UDP port in a second Worker. - await expect(worker2.createWebRtcServer( - { - listenInfos : - [ + await expect( + worker2.createWebRtcServer({ + listenInfos: [ { - protocol : 'udp', - ip : '127.0.0.1', - port : port1 - } - ] - })) - .rejects - .toThrow(Error); + protocol: 'udp', + ip: '127.0.0.1', + port: port1, + }, + ], + }), + ).rejects.toThrow(Error); worker2.close(); }, 2000); -test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is closed', async () => -{ +test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is closed', async () => { ctx.worker!.close(); const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - await expect(ctx.worker!.createWebRtcServer( - { - listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port } ] - })) - .rejects - .toThrow(InvalidStateError); + await expect( + ctx.worker!.createWebRtcServer({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', port }], + }), + ).rejects.toThrow(InvalidStateError); }, 2000); -test('webRtcServer.close() succeeds', async () => -{ +test('webRtcServer.close() succeeds', async () => { const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await ctx.worker!.createWebRtcServer( - { - listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port } ] - }); + const webRtcServer = await ctx.worker!.createWebRtcServer({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', port }], + }); const onObserverClose = jest.fn(); webRtcServer.observer.once('close', onObserverClose); @@ -299,19 +252,16 @@ test('webRtcServer.close() succeeds', async () => expect(webRtcServer.closed).toBe(true); }, 2000); -test('WebRtcServer emits "workerclose" if Worker is closed', async () => -{ +test('WebRtcServer emits "workerclose" if Worker is closed', async () => { const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await ctx.worker!.createWebRtcServer( - { - listenInfos : [ { protocol: 'tcp', ip: '127.0.0.1', port } ] - }); + const webRtcServer = await ctx.worker!.createWebRtcServer({ + listenInfos: [{ protocol: 'tcp', ip: '127.0.0.1', port }], + }); const onObserverClose = jest.fn(); webRtcServer.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { webRtcServer.on('workerclose', resolve); ctx.worker!.close(); }); @@ -320,24 +270,31 @@ test('WebRtcServer emits "workerclose" if Worker is closed', async () => expect(webRtcServer.closed).toBe(true); }, 2000); -test('router.createWebRtcTransport() with webRtcServer succeeds and transport is closed', async () => -{ +test('router.createWebRtcTransport() with webRtcServer succeeds and transport is closed', async () => { const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await ctx.worker!.createWebRtcServer( - { - listenInfos : - [ - { protocol: 'udp', ip: '127.0.0.1', port: port1 }, - { protocol: 'tcp', ip: '127.0.0.1', port: port2 } - ] - }); + const port2 = await pickPort({ + type: 'tcp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + const webRtcServer = await ctx.worker!.createWebRtcServer({ + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', port: port1 }, + { protocol: 'tcp', ip: '127.0.0.1', port: port2 }, + ], + }); const onObserverWebRtcTransportHandled = jest.fn(); const onObserverWebRtcTransportUnhandled = jest.fn(); - webRtcServer.observer.once('webrtctransporthandled', onObserverWebRtcTransportHandled); - webRtcServer.observer.once('webrtctransportunhandled', onObserverWebRtcTransportUnhandled); + webRtcServer.observer.once( + 'webrtctransporthandled', + onObserverWebRtcTransportHandled, + ); + webRtcServer.observer.once( + 'webrtctransportunhandled', + onObserverWebRtcTransportUnhandled, + ); const router = await ctx.worker!.createRouter(); @@ -345,17 +302,16 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is router.observer.once('newtransport', onObserverNewTransport); - const transport = await router.createWebRtcTransport( - { - webRtcServer, - // Let's disable UDP so resulting ICE candidates should only contain TCP. - enableUdp : false, - appData : { foo: 'bar' } - }); + const transport = await router.createWebRtcTransport({ + webRtcServer, + // Let's disable UDP so resulting ICE candidates should only contain TCP. + enableUdp: false, + appData: { foo: 'bar' }, + }); - await expect(router.dump()) - .resolves - .toMatchObject({ transportIds: [ transport.id ] }); + await expect(router.dump()).resolves.toMatchObject({ + transportIds: [transport.id], + }); expect(onObserverWebRtcTransportHandled).toHaveBeenCalledTimes(1); expect(onObserverWebRtcTransportHandled).toHaveBeenCalledWith(transport); @@ -380,26 +336,16 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is expect(webRtcServer.webRtcTransportsForTesting.size).toBe(1); expect(router.transportsForTesting.size).toBe(1); - await expect(webRtcServer.dump()) - .resolves - .toMatchObject( - { - id : webRtcServer.id, - udpSockets : - [ - { ip: '127.0.0.1', port: port1 } - ], - tcpServers : - [ - { ip: '127.0.0.1', port: port2 } - ], - webRtcTransportIds : [ transport.id ], - localIceUsernameFragments : - [ - { /* localIceUsernameFragment: xxx, */ webRtcTransportId: transport.id } - ], - tupleHashes : [] - }); + await expect(webRtcServer.dump()).resolves.toMatchObject({ + id: webRtcServer.id, + udpSockets: [{ ip: '127.0.0.1', port: port1 }], + tcpServers: [{ ip: '127.0.0.1', port: port2 }], + webRtcTransportIds: [transport.id], + localIceUsernameFragments: [ + { /* localIceUsernameFragment: xxx, */ webRtcTransportId: transport.id }, + ], + tupleHashes: [], + }); transport.close(); @@ -409,57 +355,54 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); expect(router.transportsForTesting.size).toBe(0); - await expect(webRtcServer.dump()) - .resolves - .toMatchObject( - { - id : webRtcServer.id, - udpSockets : - [ - { ip: '127.0.0.1', port: port1 } - ], - tcpServers : - [ - { ip: '127.0.0.1', port: port2 } - ], - webRtcTransportIds : [], - localIceUsernameFragments : [], - tupleHashes : [] - }); + await expect(webRtcServer.dump()).resolves.toMatchObject({ + id: webRtcServer.id, + udpSockets: [{ ip: '127.0.0.1', port: port1 }], + tcpServers: [{ ip: '127.0.0.1', port: port2 }], + webRtcTransportIds: [], + localIceUsernameFragments: [], + tupleHashes: [], + }); }, 2000); -test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer is closed', async () => -{ +test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer is closed', async () => { const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcServer = await ctx.worker!.createWebRtcServer( - { - listenInfos : - [ - { protocol: 'udp', ip: '127.0.0.1', port: port1 }, - { protocol: 'tcp', ip: '127.0.0.1', port: port2 } - ] - }); + const port2 = await pickPort({ + type: 'tcp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + const webRtcServer = await ctx.worker!.createWebRtcServer({ + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', port: port1 }, + { protocol: 'tcp', ip: '127.0.0.1', port: port2 }, + ], + }); const onObserverWebRtcTransportHandled = jest.fn(); const onObserverWebRtcTransportUnhandled = jest.fn(); - webRtcServer.observer.once('webrtctransporthandled', onObserverWebRtcTransportHandled); - webRtcServer.observer.once('webrtctransportunhandled', onObserverWebRtcTransportUnhandled); + webRtcServer.observer.once( + 'webrtctransporthandled', + onObserverWebRtcTransportHandled, + ); + webRtcServer.observer.once( + 'webrtctransportunhandled', + onObserverWebRtcTransportUnhandled, + ); const router = await ctx.worker!.createRouter(); - const transport = await router.createWebRtcTransport( - { - webRtcServer, - appData : { foo: 'bar' } - }); + const transport = await router.createWebRtcTransport({ + webRtcServer, + appData: { foo: 'bar' }, + }); expect(onObserverWebRtcTransportHandled).toHaveBeenCalledTimes(1); expect(onObserverWebRtcTransportHandled).toHaveBeenCalledWith(transport); - await expect(router.dump()) - .resolves - .toMatchObject({ transportIds: [ transport.id ] }); + await expect(router.dump()).resolves.toMatchObject({ + transportIds: [transport.id], + }); expect(typeof transport.id).toBe('string'); expect(transport.closed).toBe(false); @@ -485,52 +428,32 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer expect(webRtcServer.webRtcTransportsForTesting.size).toBe(1); expect(router.transportsForTesting.size).toBe(1); - await expect(webRtcServer.dump()) - .resolves - .toMatchObject( - { - id : webRtcServer.id, - udpSockets : - [ - { ip: '127.0.0.1', port: port1 } - ], - tcpServers : - [ - { ip: '127.0.0.1', port: port2 } - ], - webRtcTransportIds : [ transport.id ], - localIceUsernameFragments : - [ - { /* localIceUsernameFragment: xxx, */ webRtcTransportId: transport.id } - ], - tupleHashes : [] - }); + await expect(webRtcServer.dump()).resolves.toMatchObject({ + id: webRtcServer.id, + udpSockets: [{ ip: '127.0.0.1', port: port1 }], + tcpServers: [{ ip: '127.0.0.1', port: port2 }], + webRtcTransportIds: [transport.id], + localIceUsernameFragments: [ + { /* localIceUsernameFragment: xxx, */ webRtcTransportId: transport.id }, + ], + tupleHashes: [], + }); // Let's restart ICE in the transport so it should add a new entry in // localIceUsernameFragments in the WebRtcServer. await transport.restartIce(); - await expect(webRtcServer.dump()) - .resolves - .toMatchObject( - { - id : webRtcServer.id, - udpSockets : - [ - { ip: '127.0.0.1', port: port1 } - ], - tcpServers : - [ - { ip: '127.0.0.1', port: port2 } - ], - webRtcTransportIds : [ transport.id ], - localIceUsernameFragments : - [ - { /* localIceUsernameFragment: xxx, */ webRtcTransportId: transport.id }, - { /* localIceUsernameFragment: yyy, */ webRtcTransportId: transport.id } - ], - tupleHashes : [] - }); + await expect(webRtcServer.dump()).resolves.toMatchObject({ + id: webRtcServer.id, + udpSockets: [{ ip: '127.0.0.1', port: port1 }], + tcpServers: [{ ip: '127.0.0.1', port: port2 }], + webRtcTransportIds: [transport.id], + localIceUsernameFragments: [ + { /* localIceUsernameFragment: xxx, */ webRtcTransportId: transport.id }, + { /* localIceUsernameFragment: yyy, */ webRtcTransportId: transport.id }, + ], + tupleHashes: [], + }); const onObserverClose = jest.fn(); @@ -555,25 +478,18 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); expect(router.transportsForTesting.size).toBe(0); - await expect(ctx.worker!.dump()) - .resolves - .toMatchObject( - { - pid : ctx.worker!.pid, - webRtcServerIds : [], - routerIds : [ router.id ], - channelMessageHandlers : - { - channelRequestHandlers : [ router.id ], - channelNotificationHandlers : [] - } - }); - - await expect(router.dump()) - .resolves - .toMatchObject( - { - id : router.id, - transportIds : [] - }); + await expect(ctx.worker!.dump()).resolves.toMatchObject({ + pid: ctx.worker!.pid, + webRtcServerIds: [], + routerIds: [router.id], + channelMessageHandlers: { + channelRequestHandlers: [router.id], + channelNotificationHandlers: [], + }, + }); + + await expect(router.dump()).resolves.toMatchObject({ + id: router.id, + transportIds: [], + }); }, 2000); diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 3cf16037eb..5e37072184 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -7,94 +7,83 @@ import { serializeProtocol, TransportTuple } from '../Transport'; import { Notification, Body as NotificationBody, - Event + Event, } from '../fbs/notification'; import * as FbsTransport from '../fbs/transport'; import * as FbsWebRtcTransport from '../fbs/web-rtc-transport'; -type TestContext = -{ +type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; }; -const ctx: TestContext = -{ - mediaCodecs : utils.deepFreeze( - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } +const ctx: TestContext = { + mediaCodecs: utils.deepFreeze([ + { + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar', }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000 + }, + { + kind: 'video', + mimeType: 'video/VP8', + clockRate: 90000, + }, + { + kind: 'video', + mimeType: 'video/H264', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + foo: 'bar', }, - { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - foo : 'bar' - } - } - ] - ) + }, + ]), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('router.createWebRtcTransport() succeeds', async () => -{ +test('router.createWebRtcTransport() succeeds', async () => { const onObserverNewTransport = jest.fn(); ctx.router!.observer.once('newtransport', onObserverNewTransport); // Create a separate transport here. - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { - listenInfos : - [ - { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, - { protocol: 'tcp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, - { protocol: 'udp', ip: '0.0.0.0', announcedIp: '9.9.9.2' }, - { protocol: 'tcp', ip: '0.0.0.0', announcedIp: '9.9.9.2' }, - { protocol: 'udp', ip: '127.0.0.1', announcedIp: undefined }, - { protocol: 'tcp', ip: '127.0.0.1', announcedIp: undefined } - ], - enableTcp : true, - preferUdp : true, - enableSctp : true, - numSctpStreams : { OS: 2048, MIS: 2048 }, - maxSctpMessageSize : 1000000, - appData : { foo: 'bar' } - }); - - await expect(ctx.router!.dump()) - .resolves - .toMatchObject({ transportIds: [ webRtcTransport.id ] }); + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, + { protocol: 'tcp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, + { protocol: 'udp', ip: '0.0.0.0', announcedIp: '9.9.9.2' }, + { protocol: 'tcp', ip: '0.0.0.0', announcedIp: '9.9.9.2' }, + { protocol: 'udp', ip: '127.0.0.1', announcedIp: undefined }, + { protocol: 'tcp', ip: '127.0.0.1', announcedIp: undefined }, + ], + enableTcp: true, + preferUdp: true, + enableSctp: true, + numSctpStreams: { OS: 2048, MIS: 2048 }, + maxSctpMessageSize: 1000000, + appData: { foo: 'bar' }, + }); + + await expect(ctx.router!.dump()).resolves.toMatchObject({ + transportIds: [webRtcTransport.id], + }); expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(webRtcTransport); @@ -106,13 +95,12 @@ test('router.createWebRtcTransport() succeeds', async () => expect(webRtcTransport.iceParameters.iceLite).toBe(true); expect(typeof webRtcTransport.iceParameters.usernameFragment).toBe('string'); expect(typeof webRtcTransport.iceParameters.password).toBe('string'); - expect(webRtcTransport.sctpParameters).toMatchObject( - { - port : 5000, - OS : 2048, - MIS : 2048, - maxMessageSize : 1000000 - }); + expect(webRtcTransport.sctpParameters).toMatchObject({ + port: 5000, + OS: 2048, + MIS: 2048, + maxMessageSize: 1000000, + }); expect(Array.isArray(webRtcTransport.iceCandidates)).toBe(true); expect(webRtcTransport.iceCandidates.length).toBe(6); @@ -180,67 +168,57 @@ test('router.createWebRtcTransport() succeeds', async () => expect(webRtcTransport.closed).toBe(true); }, 2000); -test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => -{ +test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore - await expect(ctx.router!.createWebRtcTransport({})) - .rejects - .toThrow(TypeError); + await expect(ctx.router!.createWebRtcTransport({})).rejects.toThrow( + TypeError, + ); - // @ts-ignore - await expect(ctx.router!.createWebRtcTransport({ listenIps: [ 123 ] })) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + ctx.router!.createWebRtcTransport({ listenIps: [123] }), + ).rejects.toThrow(TypeError); - // @ts-ignore - await expect(ctx.router!.createWebRtcTransport({ listenInfos: '127.0.0.1' })) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + ctx.router!.createWebRtcTransport({ listenInfos: '127.0.0.1' }), + ).rejects.toThrow(TypeError); - // @ts-ignore - await expect(ctx.router!.createWebRtcTransport({ listenIps: '127.0.0.1' })) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + ctx.router!.createWebRtcTransport({ listenIps: '127.0.0.1' }), + ).rejects.toThrow(TypeError); - await expect(ctx.router!.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ], + await expect( + ctx.router!.createWebRtcTransport({ + listenIps: ['127.0.0.1'], // @ts-ignore - appData : 'NOT-AN-OBJECT' - })) - .rejects - .toThrow(TypeError); - - await expect(ctx.router!.createWebRtcTransport( - { - listenIps : [ '127.0.0.1' ], - enableSctp : true, + appData: 'NOT-AN-OBJECT', + }), + ).rejects.toThrow(TypeError); + + await expect( + ctx.router!.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + enableSctp: true, // @ts-ignore - numSctpStreams : 'foo' - })) - .rejects - .toThrow(TypeError); + numSctpStreams: 'foo', + }), + ).rejects.toThrow(TypeError); }, 2000); -test('router.createWebRtcTransport() with non bindable IP rejects with Error', async () => -{ - await expect(ctx.router!.createWebRtcTransport( - { - listenInfos : [ { protocol: 'udp', ip: '8.8.8.8' } ] - })) - .rejects - .toThrow(Error); +test('router.createWebRtcTransport() with non bindable IP rejects with Error', async () => { + await expect( + ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '8.8.8.8' }], + }), + ).rejects.toThrow(Error); }, 2000); -test('webRtcTransport.getStats() succeeds', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { - listenInfos : - [ - { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } - ] - }); +test('webRtcTransport.getStats() succeeds', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }], + }); const stats = await webRtcTransport.getStats(); @@ -271,282 +249,251 @@ test('webRtcTransport.getStats() succeeds', async () => expect(stats[0].maxIncomingBitrate).toBeUndefined(); }, 2000); -test('webRtcTransport.connect() succeeds', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { - listenInfos : - [ - { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } - ] - }); - - const dtlsRemoteParameters: mediasoup.types.DtlsParameters = - { - fingerprints : - [ +test('webRtcTransport.connect() succeeds', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }], + }); + + const dtlsRemoteParameters: mediasoup.types.DtlsParameters = { + fingerprints: [ { - algorithm : 'sha-256', - value : '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD' - } + algorithm: 'sha-256', + value: + '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD', + }, ], - role : 'client' + role: 'client', }; - await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + ).resolves.toBeUndefined(); // Must fail if connected. - await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) - .rejects - .toThrow(Error); + await expect( + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + ).rejects.toThrow(Error); expect(webRtcTransport.dtlsParameters.role).toBe('server'); }, 2000); -test('webRtcTransport.connect() with wrong arguments rejects with TypeError', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { - listenInfos : - [ - { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } - ] - }); +test('webRtcTransport.connect() with wrong arguments rejects with TypeError', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }], + }); let dtlsRemoteParameters: mediasoup.types.DtlsParameters; // @ts-ignore - await expect(webRtcTransport.connect({})) - .rejects - .toThrow(TypeError); - - dtlsRemoteParameters = - { - fingerprints : - [ + await expect(webRtcTransport.connect({})).rejects.toThrow(TypeError); + + dtlsRemoteParameters = { + fingerprints: [ { // @ts-ignore. - algorithm : 'sha-256000', - value : '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD' - } + algorithm: 'sha-256000', + value: + '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD', + }, ], - role : 'client' + role: 'client', }; - await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) - .rejects - .toThrow(TypeError); + await expect( + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + ).rejects.toThrow(TypeError); - dtlsRemoteParameters = - { - fingerprints : - [ + dtlsRemoteParameters = { + fingerprints: [ { - algorithm : 'sha-256', - value : '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD' - } + algorithm: 'sha-256', + value: + '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD', + }, ], // @ts-ignore - role : 'chicken' + role: 'chicken', }; - await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) - .rejects - .toThrow(TypeError); + await expect( + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + ).rejects.toThrow(TypeError); - dtlsRemoteParameters = - { - fingerprints : [], - role : 'client' + dtlsRemoteParameters = { + fingerprints: [], + role: 'client', }; - await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) - .rejects - .toThrow(TypeError); + await expect( + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + ).rejects.toThrow(TypeError); - await expect(webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters })) - .rejects - .toThrow(TypeError); + await expect( + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + ).rejects.toThrow(TypeError); expect(webRtcTransport.dtlsParameters.role).toBe('auto'); }, 2000); -test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { - listenInfos : - [ - { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' } - ] - }); +test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }], + }); - await expect(webRtcTransport.setMaxIncomingBitrate(1000000)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMaxIncomingBitrate(1000000), + ).resolves.toBeUndefined(); // Remove limit. - await expect(webRtcTransport.setMaxIncomingBitrate(0)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMaxIncomingBitrate(0), + ).resolves.toBeUndefined(); }, 2000); -test('webRtcTransport.setMaxOutgoingBitrate() succeeds', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('webRtcTransport.setMaxOutgoingBitrate() succeeds', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); - await expect(webRtcTransport.setMaxOutgoingBitrate(2000000)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMaxOutgoingBitrate(2000000), + ).resolves.toBeUndefined(); // Remove limit. - await expect(webRtcTransport.setMaxOutgoingBitrate(0)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMaxOutgoingBitrate(0), + ).resolves.toBeUndefined(); }, 2000); -test('webRtcTransport.setMinOutgoingBitrate() succeeds', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('webRtcTransport.setMinOutgoingBitrate() succeeds', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); - await expect(webRtcTransport.setMinOutgoingBitrate(100000)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMinOutgoingBitrate(100000), + ).resolves.toBeUndefined(); // Remove limit. - await expect(webRtcTransport.setMinOutgoingBitrate(0)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMinOutgoingBitrate(0), + ).resolves.toBeUndefined(); }, 2000); -test('webRtcTransport.setMaxOutgoingBitrate() fails if value is lower than current min limit', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('webRtcTransport.setMaxOutgoingBitrate() fails if value is lower than current min limit', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); - await expect(webRtcTransport.setMinOutgoingBitrate(3000000)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMinOutgoingBitrate(3000000), + ).resolves.toBeUndefined(); - await expect(webRtcTransport.setMaxOutgoingBitrate(2000000)) - .rejects - .toThrow(Error); + await expect(webRtcTransport.setMaxOutgoingBitrate(2000000)).rejects.toThrow( + Error, + ); // Remove limit. - await expect(webRtcTransport.setMinOutgoingBitrate(0)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMinOutgoingBitrate(0), + ).resolves.toBeUndefined(); }, 2000); -test('webRtcTransport.setMinOutgoingBitrate() fails if value is higher than current max limit', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('webRtcTransport.setMinOutgoingBitrate() fails if value is higher than current max limit', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); - await expect(webRtcTransport.setMaxOutgoingBitrate(2000000)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMaxOutgoingBitrate(2000000), + ).resolves.toBeUndefined(); - await expect(webRtcTransport.setMinOutgoingBitrate(3000000)) - .rejects - .toThrow(Error); + await expect(webRtcTransport.setMinOutgoingBitrate(3000000)).rejects.toThrow( + Error, + ); // Remove limit. - await expect(webRtcTransport.setMaxOutgoingBitrate(0)) - .resolves - .toBeUndefined(); + await expect( + webRtcTransport.setMaxOutgoingBitrate(0), + ).resolves.toBeUndefined(); }, 2000); -test('webRtcTransport.restartIce() succeeds', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('webRtcTransport.restartIce() succeeds', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); const previousIceUsernameFragment = webRtcTransport.iceParameters.usernameFragment; const previousIcePassword = webRtcTransport.iceParameters.password; - await expect(webRtcTransport.restartIce()) - .resolves - .toMatchObject( - { - usernameFragment : expect.any(String), - password : expect.any(String), - iceLite : true - }); + await expect(webRtcTransport.restartIce()).resolves.toMatchObject({ + usernameFragment: expect.any(String), + password: expect.any(String), + iceLite: true, + }); expect(typeof webRtcTransport.iceParameters.usernameFragment).toBe('string'); expect(typeof webRtcTransport.iceParameters.password).toBe('string'); - expect(webRtcTransport.iceParameters.usernameFragment) - .not.toBe(previousIceUsernameFragment); + expect(webRtcTransport.iceParameters.usernameFragment).not.toBe( + previousIceUsernameFragment, + ); expect(webRtcTransport.iceParameters.password).not.toBe(previousIcePassword); }, 2000); -test('transport.enableTraceEvent() succeed', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('transport.enableTraceEvent() succeed', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); // @ts-ignore - await webRtcTransport.enableTraceEvent([ 'foo', 'probation' ]); - await expect(webRtcTransport.dump()) - .resolves - .toMatchObject({ traceEventTypes: [ 'probation' ] }); + await webRtcTransport.enableTraceEvent(['foo', 'probation']); + await expect(webRtcTransport.dump()).resolves.toMatchObject({ + traceEventTypes: ['probation'], + }); await webRtcTransport.enableTraceEvent([]); - await expect(webRtcTransport.dump()) - .resolves - .toMatchObject({ traceEventTypes: [] }); + await expect(webRtcTransport.dump()).resolves.toMatchObject({ + traceEventTypes: [], + }); // @ts-ignore - await webRtcTransport.enableTraceEvent([ 'probation', 'FOO', 'bwe', 'BAR' ]); - await expect(webRtcTransport.dump()) - .resolves - .toMatchObject({ traceEventTypes: [ 'probation', 'bwe' ] }); + await webRtcTransport.enableTraceEvent(['probation', 'FOO', 'bwe', 'BAR']); + await expect(webRtcTransport.dump()).resolves.toMatchObject({ + traceEventTypes: ['probation', 'bwe'], + }); await webRtcTransport.enableTraceEvent(); - await expect(webRtcTransport.dump()) - .resolves - .toMatchObject({ traceEventTypes: [] }); + await expect(webRtcTransport.dump()).resolves.toMatchObject({ + traceEventTypes: [], + }); }, 2000); -test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); // @ts-ignore - await expect(webRtcTransport.enableTraceEvent(123)) - .rejects - .toThrow(TypeError); + await expect(webRtcTransport.enableTraceEvent(123)).rejects.toThrow( + TypeError, + ); // @ts-ignore - await expect(webRtcTransport.enableTraceEvent('probation')) - .rejects - .toThrow(TypeError); + await expect(webRtcTransport.enableTraceEvent('probation')).rejects.toThrow( + TypeError, + ); - // @ts-ignore - await expect(webRtcTransport.enableTraceEvent([ 'probation', 123.123 ])) - .rejects - .toThrow(TypeError); + await expect( + // @ts-ignore + webRtcTransport.enableTraceEvent(['probation', 123.123]), + ).rejects.toThrow(TypeError); }, 2000); -test('WebRtcTransport events succeed', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('WebRtcTransport events succeed', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); // Private API. const channel = webRtcTransport.channelForTesting; @@ -557,27 +504,29 @@ test('WebRtcTransport events succeed', async () => // Simulate a 'iceselectedtuplechange' notification coming through the // channel. const builder = new flatbuffers.Builder(); - const iceStateChangeNotification = new FbsWebRtcTransport.IceStateChangeNotificationT( - FbsWebRtcTransport.IceState.COMPLETED); + const iceStateChangeNotification = + new FbsWebRtcTransport.IceStateChangeNotificationT( + FbsWebRtcTransport.IceState.COMPLETED, + ); let notificationOffset = Notification.createNotification( builder, builder.createString(webRtcTransport.id), Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, NotificationBody.WebRtcTransport_IceStateChangeNotification, - iceStateChangeNotification.pack(builder) + iceStateChangeNotification.pack(builder), ); builder.finish(notificationOffset); let notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array()) + new flatbuffers.ByteBuffer(builder.asUint8Array()), ); channel.emit( webRtcTransport.id, Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, - notification + notification, ); expect(onIceStateChange).toHaveBeenCalledTimes(1); @@ -587,13 +536,12 @@ test('WebRtcTransport events succeed', async () => builder.clear(); const onIceSelectedTuple = jest.fn(); - const iceSelectedTuple: TransportTuple = - { - localIp : '1.1.1.1', - localPort : 1111, - remoteIp : '2.2.2.2', - remotePort : 2222, - protocol : 'udp' + const iceSelectedTuple: TransportTuple = { + localIp: '1.1.1.1', + localPort: 1111, + remoteIp: '2.2.2.2', + remotePort: 2222, + protocol: 'udp', }; webRtcTransport.on('iceselectedtuplechange', onIceSelectedTuple); @@ -606,8 +554,8 @@ test('WebRtcTransport events succeed', async () => iceSelectedTuple.localPort, iceSelectedTuple.remoteIp, iceSelectedTuple.remotePort, - serializeProtocol(iceSelectedTuple.protocol) - ) + serializeProtocol(iceSelectedTuple.protocol), + ), ); notificationOffset = Notification.createNotification( @@ -615,19 +563,19 @@ test('WebRtcTransport events succeed', async () => builder.createString(webRtcTransport.id), Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, NotificationBody.WebRtcTransport_IceSelectedTupleChangeNotification, - iceSelectedTupleChangeNotification.pack(builder) + iceSelectedTupleChangeNotification.pack(builder), ); builder.finish(notificationOffset); notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array()) + new flatbuffers.ByteBuffer(builder.asUint8Array()), ); channel.emit( webRtcTransport.id, Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, - notification + notification, ); expect(onIceSelectedTuple).toHaveBeenCalledTimes(1); @@ -641,26 +589,29 @@ test('WebRtcTransport events succeed', async () => webRtcTransport.on('dtlsstatechange', onDtlsStateChange); // Simulate a 'dtlsstatechange' notification coming through the channel. - const dtlsStateChangeNotification = new FbsWebRtcTransport.DtlsStateChangeNotificationT( - FbsWebRtcTransport.DtlsState.CONNECTING); + const dtlsStateChangeNotification = + new FbsWebRtcTransport.DtlsStateChangeNotificationT( + FbsWebRtcTransport.DtlsState.CONNECTING, + ); notificationOffset = Notification.createNotification( builder, builder.createString(webRtcTransport.id), Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, NotificationBody.WebRtcTransport_DtlsStateChangeNotification, - dtlsStateChangeNotification.pack(builder) + dtlsStateChangeNotification.pack(builder), ); builder.finish(notificationOffset); notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array())); + new flatbuffers.ByteBuffer(builder.asUint8Array()), + ); channel.emit( webRtcTransport.id, Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, - notification + notification, ); expect(onDtlsStateChange).toHaveBeenCalledTimes(1); @@ -668,11 +619,10 @@ test('WebRtcTransport events succeed', async () => expect(webRtcTransport.dtlsState).toBe('connecting'); }, 2000); -test('WebRtcTransport methods reject if closed', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('WebRtcTransport methods reject if closed', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); const onObserverClose = jest.fn(); @@ -686,65 +636,57 @@ test('WebRtcTransport methods reject if closed', async () => expect(webRtcTransport.dtlsState).toBe('closed'); expect(webRtcTransport.sctpState).toBeUndefined(); - await expect(webRtcTransport.dump()) - .rejects - .toThrow(Error); + await expect(webRtcTransport.dump()).rejects.toThrow(Error); - await expect(webRtcTransport.getStats()) - .rejects - .toThrow(Error); + await expect(webRtcTransport.getStats()).rejects.toThrow(Error); // @ts-ignore - await expect(webRtcTransport.connect({})) - .rejects - .toThrow(Error); + await expect(webRtcTransport.connect({})).rejects.toThrow(Error); - await expect(webRtcTransport.setMaxIncomingBitrate(200000)) - .rejects - .toThrow(Error); + await expect(webRtcTransport.setMaxIncomingBitrate(200000)).rejects.toThrow( + Error, + ); - await expect(webRtcTransport.setMaxOutgoingBitrate(200000)) - .rejects - .toThrow(Error); + await expect(webRtcTransport.setMaxOutgoingBitrate(200000)).rejects.toThrow( + Error, + ); - await expect(webRtcTransport.setMinOutgoingBitrate(100000)) - .rejects - .toThrow(Error); + await expect(webRtcTransport.setMinOutgoingBitrate(100000)).rejects.toThrow( + Error, + ); - await expect(webRtcTransport.restartIce()) - .rejects - .toThrow(Error); + await expect(webRtcTransport.restartIce()).rejects.toThrow(Error); }, 2000); -test('router.createWebRtcTransport() with fixed port succeeds', async () => -{ - const port = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { - listenInfos : - [ - // NOTE: udpReusePort flag will be ignored since protocol is TCP. - { protocol: 'tcp', ip: '127.0.0.1', port, flags: { udpReusePort: true } } - ] - }); +test('router.createWebRtcTransport() with fixed port succeeds', async () => { + const port = await pickPort({ + type: 'tcp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [ + // NOTE: udpReusePort flag will be ignored since protocol is TCP. + { protocol: 'tcp', ip: '127.0.0.1', port, flags: { udpReusePort: true } }, + ], + }); expect(webRtcTransport.iceCandidates[0].port).toEqual(port); webRtcTransport.close(); }, 2000); -test('WebRtcTransport emits "routerclose" if Router is closed', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenIps: [ '127.0.0.1' ], enableSctp: true } - ); +test('WebRtcTransport emits "routerclose" if Router is closed', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenIps: ['127.0.0.1'], + enableSctp: true, + }); const onObserverClose = jest.fn(); webRtcTransport.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { webRtcTransport.on('routerclose', resolve); ctx.router!.close(); @@ -758,18 +700,16 @@ test('WebRtcTransport emits "routerclose" if Router is closed', async () => expect(webRtcTransport.sctpState).toBe('closed'); }, 2000); -test('WebRtcTransport emits "routerclose" if Worker is closed', async () => -{ - const webRtcTransport = await ctx.router!.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); +test('WebRtcTransport emits "routerclose" if Worker is closed', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); const onObserverClose = jest.fn(); webRtcTransport.observer.once('close', onObserverClose); - await new Promise((resolve) => - { + await new Promise(resolve => { webRtcTransport.on('routerclose', resolve); ctx.worker!.close(); diff --git a/node/src/test/test-Worker.ts b/node/src/test/test-Worker.ts index 9be4451f5b..75baec9c4c 100644 --- a/node/src/test/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -4,19 +4,35 @@ import * as path from 'node:path'; import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; -test('Worker.workerBin matches mediasoup-worker absolute path', () => -{ +test('Worker.workerBin matches mediasoup-worker absolute path', () => { const workerBin = process.env.MEDIASOUP_WORKER_BIN ? process.env.MEDIASOUP_WORKER_BIN : process.env.MEDIASOUP_BUILDTYPE === 'Debug' - ? path.join(__dirname, '..', '..', '..', 'worker', 'out', 'Debug', 'mediasoup-worker') - : path.join(__dirname, '..', '..', '..', 'worker', 'out', 'Release', 'mediasoup-worker'); + ? path.join( + __dirname, + '..', + '..', + '..', + 'worker', + 'out', + 'Debug', + 'mediasoup-worker', + ) + : path.join( + __dirname, + '..', + '..', + '..', + 'worker', + 'out', + 'Release', + 'mediasoup-worker', + ); expect(mediasoup.workerBin).toBe(workerBin); }); -test('createWorker() succeeds', async () => -{ +test('createWorker() succeeds', async () => { const onObserverNewWorker = jest.fn(); mediasoup.observer.once('newworker', onObserverNewWorker); @@ -35,17 +51,16 @@ test('createWorker() succeeds', async () => expect(worker1.closed).toBe(true); expect(worker1.died).toBe(false); - const worker2 = await mediasoup.createWorker<{ foo: number; bar?: string }>( - { - logLevel : 'debug', - logTags : [ 'info' ], - rtcMinPort : 0, - rtcMaxPort : 9999, - dtlsCertificateFile : path.join(__dirname, 'data', 'dtls-cert.pem'), - dtlsPrivateKeyFile : path.join(__dirname, 'data', 'dtls-key.pem'), - libwebrtcFieldTrials : 'WebRTC-Bwe-AlrLimitedBackoff/Disabled/', - appData : { foo: 456 } - }); + const worker2 = await mediasoup.createWorker<{ foo: number; bar?: string }>({ + logLevel: 'debug', + logTags: ['info'], + rtcMinPort: 0, + rtcMaxPort: 9999, + dtlsCertificateFile: path.join(__dirname, 'data', 'dtls-cert.pem'), + dtlsPrivateKeyFile: path.join(__dirname, 'data', 'dtls-key.pem'), + libwebrtcFieldTrials: 'WebRTC-Bwe-AlrLimitedBackoff/Disabled/', + appData: { foo: 456 }, + }); expect(worker2.constructor.name).toBe('Worker'); expect(typeof worker2.pid).toBe('number'); @@ -59,115 +74,99 @@ test('createWorker() succeeds', async () => expect(worker2.died).toBe(false); }, 2000); -test('createWorker() with wrong settings rejects with TypeError', async () => -{ +test('createWorker() with wrong settings rejects with TypeError', async () => { // @ts-ignore - await expect(mediasoup.createWorker({ logLevel: 'chicken' })) - .rejects - .toThrow(TypeError); + await expect(mediasoup.createWorker({ logLevel: 'chicken' })).rejects.toThrow( + TypeError, + ); - await expect(mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 999 })) - .rejects - .toThrow(TypeError); + await expect( + mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 999 }), + ).rejects.toThrow(TypeError); // Port is from 0 to 65535. - await expect(mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 65536 })) - .rejects - .toThrow(TypeError); - - await expect(mediasoup.createWorker({ dtlsCertificateFile: '/notfound/cert.pem' })) - .rejects - .toThrow(TypeError); - - await expect(mediasoup.createWorker({ dtlsPrivateKeyFile: '/notfound/priv.pem' })) - .rejects - .toThrow(TypeError); - - // @ts-ignore - await expect(mediasoup.createWorker({ appData: 'NOT-AN-OBJECT' })) - .rejects - .toThrow(TypeError); + await expect( + mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 65536 }), + ).rejects.toThrow(TypeError); + + await expect( + mediasoup.createWorker({ dtlsCertificateFile: '/notfound/cert.pem' }), + ).rejects.toThrow(TypeError); + + await expect( + mediasoup.createWorker({ dtlsPrivateKeyFile: '/notfound/priv.pem' }), + ).rejects.toThrow(TypeError); + + await expect( + // @ts-ignore + mediasoup.createWorker({ appData: 'NOT-AN-OBJECT' }), + ).rejects.toThrow(TypeError); }, 2000); -test('worker.updateSettings() succeeds', async () => -{ +test('worker.updateSettings() succeeds', async () => { const worker = await mediasoup.createWorker(); - await expect(worker.updateSettings({ logLevel: 'debug', logTags: [ 'ice' ] })) - .resolves - .toBeUndefined(); + await expect( + worker.updateSettings({ logLevel: 'debug', logTags: ['ice'] }), + ).resolves.toBeUndefined(); worker.close(); }, 2000); -test('worker.updateSettings() with wrong settings rejects with TypeError', async () => -{ +test('worker.updateSettings() with wrong settings rejects with TypeError', async () => { const worker = await mediasoup.createWorker(); // @ts-ignore - await expect(worker.updateSettings({ logLevel: 'chicken' })) - .rejects - .toThrow(TypeError); + await expect(worker.updateSettings({ logLevel: 'chicken' })).rejects.toThrow( + TypeError, + ); worker.close(); }, 2000); -test('worker.updateSettings() rejects with InvalidStateError if closed', async () => -{ +test('worker.updateSettings() rejects with InvalidStateError if closed', async () => { const worker = await mediasoup.createWorker(); worker.close(); - await expect(worker.updateSettings({ logLevel: 'error' })) - .rejects - .toThrow(InvalidStateError); + await expect(worker.updateSettings({ logLevel: 'error' })).rejects.toThrow( + InvalidStateError, + ); }, 2000); -test('worker.dump() succeeds', async () => -{ +test('worker.dump() succeeds', async () => { const worker = await mediasoup.createWorker(); - await expect(worker.dump()) - .resolves - .toMatchObject( - { - pid : worker.pid, - webRtcServerIds : [], - routerIds : [], - channelMessageHandlers : - { - channelRequestHandlers : [], - channelNotificationHandlers : [] - } - }); + await expect(worker.dump()).resolves.toMatchObject({ + pid: worker.pid, + webRtcServerIds: [], + routerIds: [], + channelMessageHandlers: { + channelRequestHandlers: [], + channelNotificationHandlers: [], + }, + }); worker.close(); }, 2000); -test('worker.dump() rejects with InvalidStateError if closed', async () => -{ +test('worker.dump() rejects with InvalidStateError if closed', async () => { const worker = await mediasoup.createWorker(); worker.close(); - await expect(worker.dump()) - .rejects - .toThrow(InvalidStateError); + await expect(worker.dump()).rejects.toThrow(InvalidStateError); }, 2000); -test('worker.getResourceUsage() succeeds', async () => -{ +test('worker.getResourceUsage() succeeds', async () => { const worker = await mediasoup.createWorker(); - await expect(worker.getResourceUsage()) - .resolves - .toMatchObject({}); + await expect(worker.getResourceUsage()).resolves.toMatchObject({}); worker.close(); }, 2000); -test('worker.close() succeeds', async () => -{ +test('worker.close() succeeds', async () => { const worker = await mediasoup.createWorker({ logLevel: 'warn' }); const onObserverClose = jest.fn(); @@ -179,8 +178,7 @@ test('worker.close() succeeds', async () => expect(worker.died).toBe(false); }, 2000); -test('Worker emits "died" if worker process died unexpectedly', async () => -{ +test('Worker emits "died" if worker process died unexpectedly', async () => { let onDied: ReturnType; let onObserverClose: ReturnType; @@ -191,24 +189,19 @@ test('Worker emits "died" if worker process died unexpectedly', async () => worker1.observer.once('close', onObserverClose); - await new Promise((resolve, reject) => - { - worker1.on('died', () => - { + await new Promise((resolve, reject) => { + worker1.on('died', () => { onDied(); - if (onObserverClose.mock.calls.length > 0) - { + if (onObserverClose.mock.calls.length > 0) { reject( - new Error('observer "close" event emitted before worker "died" event') + new Error( + 'observer "close" event emitted before worker "died" event', + ), ); - } - else if (worker1.closed) - { + } else if (worker1.closed) { resolve(); - } - else - { + } else { reject(new Error('worker.closed is false')); } }); @@ -228,24 +221,19 @@ test('Worker emits "died" if worker process died unexpectedly', async () => worker2.observer.once('close', onObserverClose); - await new Promise((resolve, reject) => - { - worker2.on('died', () => - { + await new Promise((resolve, reject) => { + worker2.on('died', () => { onDied(); - if (onObserverClose.mock.calls.length > 0) - { + if (onObserverClose.mock.calls.length > 0) { reject( - new Error('observer "close" event emitted before worker "died" event') + new Error( + 'observer "close" event emitted before worker "died" event', + ), ); - } - else if (worker2.closed) - { + } else if (worker2.closed) { resolve(); - } - else - { + } else { reject(new Error('worker.closed is false')); } }); @@ -265,24 +253,19 @@ test('Worker emits "died" if worker process died unexpectedly', async () => worker3.observer.once('close', onObserverClose); - await new Promise((resolve, reject) => - { - worker3.on('died', () => - { + await new Promise((resolve, reject) => { + worker3.on('died', () => { onDied(); - if (onObserverClose.mock.calls.length > 0) - { + if (onObserverClose.mock.calls.length > 0) { reject( - new Error('observer "close" event emitted before worker "died" event') + new Error( + 'observer "close" event emitted before worker "died" event', + ), ); - } - else if (worker3.closed) - { + } else if (worker3.closed) { resolve(); - } - else - { + } else { reject(new Error('worker.closed is false')); } }); @@ -298,14 +281,11 @@ test('Worker emits "died" if worker process died unexpectedly', async () => // Windows doesn't have some signals such as SIGPIPE, SIGALRM, SIGUSR1, SIGUSR2 // so we just skip this test in Windows. -if (os.platform() !== 'win32') -{ - test('worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () => - { +if (os.platform() !== 'win32') { + test('worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () => { const worker = await mediasoup.createWorker({ logLevel: 'warn' }); - await new Promise((resolve, reject) => - { + await new Promise((resolve, reject) => { worker.on('died', reject); process.kill(worker.pid, 'SIGPIPE'); @@ -314,8 +294,7 @@ if (os.platform() !== 'win32') process.kill(worker.pid, 'SIGUSR1'); process.kill(worker.pid, 'SIGUSR2'); - setTimeout(() => - { + setTimeout(() => { expect(worker.closed).toBe(false); worker.close(); diff --git a/node/src/test/test-mediasoup.ts b/node/src/test/test-mediasoup.ts index 294506d960..d3643639a8 100644 --- a/node/src/test/test-mediasoup.ts +++ b/node/src/test/test-mediasoup.ts @@ -2,24 +2,20 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; import * as mediasoup from '../'; -const PKG = JSON.parse(fs.readFileSync( - path.join(__dirname, '..', '..', '..', 'package.json'), - { encoding: 'utf-8' } -)); - -const { - version, - getSupportedRtpCapabilities, - parseScalabilityMode -} = mediasoup; - -test('mediasoup.version matches version field in package.json', () => -{ +const PKG = JSON.parse( + fs.readFileSync(path.join(__dirname, '..', '..', '..', 'package.json'), { + encoding: 'utf-8', + }), +); + +const { version, getSupportedRtpCapabilities, parseScalabilityMode } = + mediasoup; + +test('mediasoup.version matches version field in package.json', () => { expect(version).toBe(PKG.version); }); -test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabilities', () => -{ +test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabilities', () => { const rtpCapabilities = getSupportedRtpCapabilities(); expect(typeof rtpCapabilities).toBe('object'); @@ -34,35 +30,64 @@ test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabili expect(rtpCapabilities2).not.toEqual(rtpCapabilities); }); -test('parseScalabilityMode() works', () => -{ - expect(parseScalabilityMode('L1T3')) - .toEqual({ spatialLayers: 1, temporalLayers: 3, ksvc: false }); - - expect(parseScalabilityMode('L3T2_KEY')) - .toEqual({ spatialLayers: 3, temporalLayers: 2, ksvc: true }); - - expect(parseScalabilityMode('S2T3')) - .toEqual({ spatialLayers: 2, temporalLayers: 3, ksvc: false }); - - expect(parseScalabilityMode('foo')) - .toEqual({ spatialLayers: 1, temporalLayers: 1, ksvc: false }); - - expect(parseScalabilityMode(undefined)) - .toEqual({ spatialLayers: 1, temporalLayers: 1, ksvc: false }); - - expect(parseScalabilityMode('S0T3')) - .toEqual({ spatialLayers: 1, temporalLayers: 1, ksvc: false }); - - expect(parseScalabilityMode('S1T0')) - .toEqual({ spatialLayers: 1, temporalLayers: 1, ksvc: false }); - - expect(parseScalabilityMode('L20T3')) - .toEqual({ spatialLayers: 20, temporalLayers: 3, ksvc: false }); - - expect(parseScalabilityMode('S200T3')) - .toEqual({ spatialLayers: 1, temporalLayers: 1, ksvc: false }); - - expect(parseScalabilityMode('L4T7_KEY_SHIFT')) - .toEqual({ spatialLayers: 4, temporalLayers: 7, ksvc: true }); +test('parseScalabilityMode() works', () => { + expect(parseScalabilityMode('L1T3')).toEqual({ + spatialLayers: 1, + temporalLayers: 3, + ksvc: false, + }); + + expect(parseScalabilityMode('L3T2_KEY')).toEqual({ + spatialLayers: 3, + temporalLayers: 2, + ksvc: true, + }); + + expect(parseScalabilityMode('S2T3')).toEqual({ + spatialLayers: 2, + temporalLayers: 3, + ksvc: false, + }); + + expect(parseScalabilityMode('foo')).toEqual({ + spatialLayers: 1, + temporalLayers: 1, + ksvc: false, + }); + + expect(parseScalabilityMode(undefined)).toEqual({ + spatialLayers: 1, + temporalLayers: 1, + ksvc: false, + }); + + expect(parseScalabilityMode('S0T3')).toEqual({ + spatialLayers: 1, + temporalLayers: 1, + ksvc: false, + }); + + expect(parseScalabilityMode('S1T0')).toEqual({ + spatialLayers: 1, + temporalLayers: 1, + ksvc: false, + }); + + expect(parseScalabilityMode('L20T3')).toEqual({ + spatialLayers: 20, + temporalLayers: 3, + ksvc: false, + }); + + expect(parseScalabilityMode('S200T3')).toEqual({ + spatialLayers: 1, + temporalLayers: 1, + ksvc: false, + }); + + expect(parseScalabilityMode('L4T7_KEY_SHIFT')).toEqual({ + spatialLayers: 4, + temporalLayers: 7, + ksvc: true, + }); }); diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index 1ebc848084..45e328ea82 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -2,8 +2,7 @@ import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; -type TestContext = -{ +type TestContext = { mediaCodecs: mediasoup.types.RtpCodecCapability[]; audioProducerOptions: mediasoup.types.ProducerOptions; consumerDeviceCapabilities: mediasoup.types.RtpCapabilities; @@ -12,267 +11,231 @@ type TestContext = webRtcTransport?: mediasoup.types.WebRtcTransport; }; -const ctx: TestContext = -{ - mediaCodecs : utils.deepFreeze( - [ - { - kind : 'audio', - mimeType : 'audio/multiopus', - preferredPayloadType : 100, - clockRate : 48000, - channels : 6, - parameters : - { - useinbandfec : 1, - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 - } - } - ] - ), - audioProducerOptions : utils.deepFreeze( +const ctx: TestContext = { + mediaCodecs: utils.deepFreeze([ { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ - { - mimeType : 'audio/multiopus', - payloadType : 0, - clockRate : 48000, - channels : 6, - parameters : - { - useinbandfec : 1, - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 - } - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 10 - }, - { - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id : 12 - } - ] - } - } - ), - consumerDeviceCapabilities : utils.deepFreeze( - { - codecs : - [ + kind: 'audio', + mimeType: 'audio/multiopus', + preferredPayloadType: 100, + clockRate: 48000, + channels: 6, + parameters: { + useinbandfec: 1, + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 2, + }, + }, + ]), + audioProducerOptions: utils.deepFreeze({ + kind: 'audio', + rtpParameters: { + mid: 'AUDIO', + codecs: [ { - mimeType : 'audio/multiopus', - kind : 'audio', - preferredPayloadType : 100, - clockRate : 48000, - channels : 6, - parameters : - { - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 - } - } + mimeType: 'audio/multiopus', + payloadType: 0, + clockRate: 48000, + channels: 6, + parameters: { + useinbandfec: 1, + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 2, + }, + }, ], - headerExtensions : - [ + headerExtensions: [ { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 10, }, { - kind : 'audio', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId : 4, - preferredEncrypt : false + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + id: 12, }, - { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 10, - preferredEncrypt : false - } - ] - } - ) + ], + }, + }), + consumerDeviceCapabilities: utils.deepFreeze({ + codecs: [ + { + mimeType: 'audio/multiopus', + kind: 'audio', + preferredPayloadType: 100, + clockRate: 48000, + channels: 6, + parameters: { + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 2, + }, + }, + ], + headerExtensions: [ + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId: 4, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + }, + ], + }), }; -beforeEach(async () => -{ +beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); - ctx.router = await ctx.worker.createRouter( - { mediaCodecs: ctx.mediaCodecs } - ); - ctx.webRtcTransport = await ctx.router.createWebRtcTransport( - { listenInfos: [ { protocol: 'udp', ip: '127.0.0.1' } ] } - ); + ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); + ctx.webRtcTransport = await ctx.router.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + }); }); -afterEach(() => -{ +afterEach(() => { ctx.worker?.close(); }); -test('produce() and consume() succeed', async () => -{ +test('produce() and consume() succeed', async () => { const audioProducer = await ctx.webRtcTransport!.produce( - ctx.audioProducerOptions + ctx.audioProducerOptions, ); expect(audioProducer.rtpParameters.codecs).toEqual([ { - mimeType : 'audio/multiopus', - payloadType : 0, - clockRate : 48000, - channels : 6, - parameters : - { - useinbandfec : 1, - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 + mimeType: 'audio/multiopus', + payloadType: 0, + clockRate: 48000, + channels: 6, + parameters: { + useinbandfec: 1, + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 2, }, - rtcpFeedback : [] - } + rtcpFeedback: [], + }, ]); - expect(ctx.router!.canConsume( - { - producerId : audioProducer.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }) + expect( + ctx.router!.canConsume({ + producerId: audioProducer.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }), ).toBe(true); - const audioConsumer = await ctx.webRtcTransport!.consume( - { - producerId : audioProducer.id, - rtpCapabilities : ctx.consumerDeviceCapabilities - }); + const audioConsumer = await ctx.webRtcTransport!.consume({ + producerId: audioProducer.id, + rtpCapabilities: ctx.consumerDeviceCapabilities, + }); expect(audioConsumer.rtpParameters.codecs).toEqual([ { - mimeType : 'audio/multiopus', - payloadType : 100, - clockRate : 48000, - channels : 6, - parameters : - { - useinbandfec : 1, - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 - }, - rtcpFeedback : [] - } + mimeType: 'audio/multiopus', + payloadType: 100, + clockRate: 48000, + channels: 6, + parameters: { + useinbandfec: 1, + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 2, + }, + rtcpFeedback: [], + }, ]); }, 2000); -test('fails to produce wrong parameters', async () => -{ - await expect(ctx.webRtcTransport!.produce( - { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ - { - mimeType : 'audio/multiopus', - payloadType : 0, - clockRate : 48000, - channels : 6, - parameters : - { - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 2, - 'coupled_streams' : 2 - } - } - ] - } - })) - .rejects - .toThrow(UnsupportedError); +test('fails to produce wrong parameters', async () => { + await expect( + ctx.webRtcTransport!.produce({ + kind: 'audio', + rtpParameters: { + mid: 'AUDIO', + codecs: [ + { + mimeType: 'audio/multiopus', + payloadType: 0, + clockRate: 48000, + channels: 6, + parameters: { + channel_mapping: '0,4,1,2,3,5', + num_streams: 2, + coupled_streams: 2, + }, + }, + ], + }, + }), + ).rejects.toThrow(UnsupportedError); - await expect(ctx.webRtcTransport!.produce( - { - kind : 'audio', - rtpParameters : - { - mid : 'AUDIO', - codecs : - [ - { - mimeType : 'audio/multiopus', - payloadType : 0, - clockRate : 48000, - channels : 6, - parameters : - { - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 1 - } - } - ] - } - })) - .rejects - .toThrow(UnsupportedError); + await expect( + ctx.webRtcTransport!.produce({ + kind: 'audio', + rtpParameters: { + mid: 'AUDIO', + codecs: [ + { + mimeType: 'audio/multiopus', + payloadType: 0, + clockRate: 48000, + channels: 6, + parameters: { + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 1, + }, + }, + ], + }, + }), + ).rejects.toThrow(UnsupportedError); }, 2000); -test('fails to consume wrong channels', async () => -{ +test('fails to consume wrong channels', async () => { const audioProducer = await ctx.webRtcTransport!.produce( - ctx.audioProducerOptions + ctx.audioProducerOptions, ); const localConsumerDeviceCapabilities: mediasoup.types.RtpCapabilities = { - codecs : - [ - { - mimeType : 'audio/multiopus', - kind : 'audio', - preferredPayloadType : 100, - clockRate : 48000, - channels : 8, - parameters : - { - 'channel_mapping' : '0,4,1,2,3,5', - 'num_streams' : 4, - 'coupled_streams' : 2 - } - } - ] + codecs: [ + { + mimeType: 'audio/multiopus', + kind: 'audio', + preferredPayloadType: 100, + clockRate: 48000, + channels: 8, + parameters: { + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 2, + }, + }, + ], }; - expect(!ctx.router!.canConsume( - { - producerId : audioProducer.id, - rtpCapabilities : localConsumerDeviceCapabilities - })) - .toBe(true); + expect( + !ctx.router!.canConsume({ + producerId: audioProducer.id, + rtpCapabilities: localConsumerDeviceCapabilities, + }), + ).toBe(true); - await expect(ctx.webRtcTransport!.consume( - { - producerId : audioProducer.id, - rtpCapabilities : localConsumerDeviceCapabilities - })) - .rejects - .toThrow(Error); + await expect( + ctx.webRtcTransport!.consume({ + producerId: audioProducer.id, + rtpCapabilities: localConsumerDeviceCapabilities, + }), + ).rejects.toThrow(Error); }, 2000); diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index b9a3b0ff5d..228cc391e5 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -3,8 +3,7 @@ import * as dgram from 'node:dgram'; import * as sctp from 'sctp'; import * as mediasoup from '../'; -type TestContext = -{ +type TestContext = { worker?: mediasoup.types.Worker; router?: mediasoup.types.Router; plainTransport?: mediasoup.types.PlainTransport; @@ -18,28 +17,25 @@ type TestContext = const ctx: TestContext = {}; -beforeEach(async () => -{ +beforeEach(async () => { // Set node-sctp default PMTU to 1200. sctp.defaults({ PMTU: 1200 }); ctx.worker = await mediasoup.createWorker(); ctx.router = await ctx.worker.createRouter(); - ctx.plainTransport = await ctx.router.createPlainTransport( - { - // https://github.com/nodejs/node/issues/14900. - listenIp : '127.0.0.1', - // So we don't need to call plainTransport.connect(). - comedia : true, - enableSctp : true, - numSctpStreams : { OS: 256, MIS: 256 } - }); + ctx.plainTransport = await ctx.router.createPlainTransport({ + // https://github.com/nodejs/node/issues/14900. + listenIp: '127.0.0.1', + // So we don't need to call plainTransport.connect(). + comedia: true, + enableSctp: true, + numSctpStreams: { OS: 256, MIS: 256 }, + }); // Node UDP socket for SCTP. ctx.udpSocket = dgram.createSocket({ type: 'udp4' }); - await new Promise((resolve) => - { + await new Promise(resolve => { ctx.udpSocket!.bind(0, '127.0.0.1', resolve); }); @@ -47,39 +43,34 @@ beforeEach(async () => const remoteUdpPort = ctx.plainTransport.tuple.localPort; const { OS, MIS } = ctx.plainTransport.sctpParameters!; - await new Promise((resolve, reject) => - { + await new Promise((resolve, reject) => { // @ts-ignore - ctx.udpSocket.connect(remoteUdpPort, remoteUdpIp, (error: Error) => - { - if (error) - { + ctx.udpSocket.connect(remoteUdpPort, remoteUdpIp, (error: Error) => { + if (error) { reject(error); return; } - ctx.sctpSocket = sctp.connect( - { - localPort : 5000, // Required for SCTP over UDP in mediasoup. - port : 5000, // Required for SCTP over UDP in mediasoup. - OS : OS, - MIS : MIS, - udpTransport : ctx.udpSocket - }); + ctx.sctpSocket = sctp.connect({ + localPort: 5000, // Required for SCTP over UDP in mediasoup. + port: 5000, // Required for SCTP over UDP in mediasoup. + OS: OS, + MIS: MIS, + udpTransport: ctx.udpSocket, + }); resolve(); }); }); // Wait for the SCTP association to be open. - await Promise.race( - [ - new Promise((resolve) => ctx.sctpSocket.on('connect', resolve)), - new Promise((resolve, reject) => ( - setTimeout(() => reject(new Error('SCTP connection timeout')), 3000) - )) - ]); + await Promise.race([ + new Promise(resolve => ctx.sctpSocket.on('connect', resolve)), + new Promise((resolve, reject) => + setTimeout(() => reject(new Error('SCTP connection timeout')), 3000), + ), + ]); // Create an explicit SCTP outgoing stream with id 123 (id 0 is already used // by the implicit SCTP outgoing stream built-in the SCTP socket). @@ -87,26 +78,23 @@ beforeEach(async () => ctx.sctpSendStream = ctx.sctpSocket.createStream(ctx.sctpSendStreamId); // Create a DataProducer with the corresponding SCTP stream id. - ctx.dataProducer = await ctx.plainTransport.produceData( - { - sctpStreamParameters : - { - streamId : ctx.sctpSendStreamId, - ordered : true - }, - label : 'node-sctp', - protocol : 'foo & bar 😀😀😀' - }); + ctx.dataProducer = await ctx.plainTransport.produceData({ + sctpStreamParameters: { + streamId: ctx.sctpSendStreamId, + ordered: true, + }, + label: 'node-sctp', + protocol: 'foo & bar 😀😀😀', + }); // Create a DataConsumer to receive messages from the DataProducer over the // same plainTransport. - ctx.dataConsumer = await ctx.plainTransport.consumeData( - { dataProducerId: ctx.dataProducer.id } - ); + ctx.dataConsumer = await ctx.plainTransport.consumeData({ + dataProducerId: ctx.dataProducer.id, + }); }); -afterEach(async () => -{ +afterEach(async () => { ctx.udpSocket?.close(); ctx.sctpSocket?.end(); ctx.worker?.close(); @@ -114,11 +102,10 @@ afterEach(async () => // NOTE: For some reason we have to wait a bit for the SCTP stuff to release // internal things, otherwise Jest reports open handles. We don't care much // honestly. - await new Promise((resolve) => setTimeout(resolve, 2000)); + await new Promise(resolve => setTimeout(resolve, 2000)); }); -test('ordered DataProducer delivers all SCTP messages to the DataConsumer', async () => -{ +test('ordered DataProducer delivers all SCTP messages to the DataConsumer', async () => { const onStream = jest.fn(); const numMessages = 200; let sentMessageBytes = 0; @@ -130,24 +117,20 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn expect(ctx.dataConsumer!.sctpStreamParameters?.streamId).toBe(0); // eslint-disable-next-line no-async-promise-executor - await new Promise(async (resolve, reject) => - { + await new Promise(async (resolve, reject) => { sendNextMessage(); - async function sendNextMessage(): Promise - { + async function sendNextMessage(): Promise { const id = ++numSentMessages; const data = Buffer.from(String(id)); // Set ppid of type WebRTC DataChannel string. - if (id < numMessages / 2) - { + if (id < numMessages / 2) { // @ts-ignore data.ppid = sctp.PPID.WEBRTC_STRING; } // Set ppid of type WebRTC DataChannel binary. - else - { + else { // @ts-ignore data.ppid = sctp.PPID.WEBRTC_BINARY; } @@ -155,8 +138,7 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn ctx.sctpSendStream!.write(data); sentMessageBytes += data.byteLength; - if (id < numMessages) - { + if (id < numMessages) { sendNextMessage(); } } @@ -165,20 +147,17 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn // Handle the generated SCTP incoming stream and SCTP messages receives on it. // @ts-ignore - ctx.sctpSocket.on('stream', (stream, streamId) => - { + ctx.sctpSocket.on('stream', (stream, streamId) => { // It must be zero because it's the first SCTP incoming stream (so first // DataConsumer). - if (streamId !== 0) - { + if (streamId !== 0) { reject(new Error(`streamId should be 0 but it is ${streamId}`)); return; } // @ts-ignore - stream.on('data', (data: Buffer) => - { + stream.on('data', (data: Buffer) => { ++numReceivedMessages; recvMessageBytes += data.byteLength; @@ -186,26 +165,25 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn // @ts-ignore const ppid = data.ppid; - if (id !== numReceivedMessages) - { + if (id !== numReceivedMessages) { reject( - new Error(`id ${id} in message should match numReceivedMessages ${numReceivedMessages}`) + new Error( + `id ${id} in message should match numReceivedMessages ${numReceivedMessages}`, + ), ); - } - else if (id === numMessages) - { + } else if (id === numMessages) { resolve(); - } - else if (id < numMessages / 2 && ppid !== sctp.PPID.WEBRTC_STRING) - { + } else if (id < numMessages / 2 && ppid !== sctp.PPID.WEBRTC_STRING) { reject( - new Error(`ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_STRING} but it is ${ppid}`) + new Error( + `ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_STRING} but it is ${ppid}`, + ), ); - } - else if (id > numMessages / 2 && ppid !== sctp.PPID.WEBRTC_BINARY) - { + } else if (id > numMessages / 2 && ppid !== sctp.PPID.WEBRTC_BINARY) { reject( - new Error(`ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_BINARY} but it is ${ppid}`) + new Error( + `ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_BINARY} but it is ${ppid}`, + ), ); return; @@ -219,29 +197,23 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn expect(numReceivedMessages).toBe(numMessages); expect(recvMessageBytes).toBe(sentMessageBytes); - await expect(ctx.dataProducer!.getStats()) - .resolves - .toMatchObject( - [ - { - type : 'data-producer', - label : ctx.dataProducer!.label, - protocol : ctx.dataProducer!.protocol, - messagesReceived : numMessages, - bytesReceived : sentMessageBytes - } - ]); - - await expect(ctx.dataConsumer!.getStats()) - .resolves - .toMatchObject( - [ - { - type : 'data-consumer', - label : ctx.dataConsumer!.label, - protocol : ctx.dataConsumer!.protocol, - messagesSent : numMessages, - bytesSent : recvMessageBytes - } - ]); + await expect(ctx.dataProducer!.getStats()).resolves.toMatchObject([ + { + type: 'data-producer', + label: ctx.dataProducer!.label, + protocol: ctx.dataProducer!.protocol, + messagesReceived: numMessages, + bytesReceived: sentMessageBytes, + }, + ]); + + await expect(ctx.dataConsumer!.getStats()).resolves.toMatchObject([ + { + type: 'data-consumer', + label: ctx.dataConsumer!.label, + protocol: ctx.dataConsumer!.protocol, + messagesSent: numMessages, + bytesSent: recvMessageBytes, + }, + ]); }, 10000); diff --git a/node/src/test/test-ortc.ts b/node/src/test/test-ortc.ts index 94bab10103..11b8cbbec9 100644 --- a/node/src/test/test-ortc.ts +++ b/node/src/test/test-ortc.ts @@ -2,39 +2,35 @@ import * as mediasoup from '../'; import * as ortc from '../ortc'; import { UnsupportedError } from '../errors'; -test('generateRouterRtpCapabilities() succeeds', () => -{ - const mediaCodecs: mediasoup.types.RtpCodecCapability[] = - [ +test('generateRouterRtpCapabilities() succeeds', () => { + const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - } + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar', + }, }, { - kind : 'video', - mimeType : 'video/VP8', - preferredPayloadType : 125, // Let's force it. - clockRate : 90000 + kind: 'video', + mimeType: 'video/VP8', + preferredPayloadType: 125, // Let's force it. + clockRate: 90000, }, { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'profile-level-id' : '42e01f', - foo : 'bar' + kind: 'video', + mimeType: 'video/H264', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'profile-level-id': '42e01f', + foo: 'bar', }, - rtcpFeedback : [] // Will be ignored. - } + rtcpFeedback: [], // Will be ignored. + }, ]; const rtpCapabilities = ortc.generateRouterRtpCapabilities(mediaCodecs); @@ -42,252 +38,226 @@ test('generateRouterRtpCapabilities() succeeds', () => expect(rtpCapabilities.codecs?.length).toBe(5); // opus. - expect(rtpCapabilities.codecs?.[0]).toEqual( - { - kind : 'audio', - mimeType : 'audio/opus', - preferredPayloadType : 100, // 100 is the first available dynamic PT. - clockRate : 48000, - channels : 2, - parameters : - { - useinbandfec : 1, - foo : 'bar' - }, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'transport-cc', parameter: '' } - ] - }); + expect(rtpCapabilities.codecs?.[0]).toEqual({ + kind: 'audio', + mimeType: 'audio/opus', + preferredPayloadType: 100, // 100 is the first available dynamic PT. + clockRate: 48000, + channels: 2, + parameters: { + useinbandfec: 1, + foo: 'bar', + }, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'transport-cc', parameter: '' }, + ], + }); // VP8. - expect(rtpCapabilities.codecs?.[1]).toEqual( - { - kind : 'video', - mimeType : 'video/VP8', - preferredPayloadType : 125, - clockRate : 90000, - parameters : {}, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb', parameter: '' }, - { type: 'transport-cc', parameter: '' } - ] - }); + expect(rtpCapabilities.codecs?.[1]).toEqual({ + kind: 'video', + mimeType: 'video/VP8', + preferredPayloadType: 125, + clockRate: 90000, + parameters: {}, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb', parameter: '' }, + { type: 'transport-cc', parameter: '' }, + ], + }); // VP8 RTX. - expect(rtpCapabilities.codecs?.[2]).toEqual( - { - kind : 'video', - mimeType : 'video/rtx', - preferredPayloadType : 101, // 101 is the second available dynamic PT. - clockRate : 90000, - parameters : - { - apt : 125 - }, - rtcpFeedback : [] - }); + expect(rtpCapabilities.codecs?.[2]).toEqual({ + kind: 'video', + mimeType: 'video/rtx', + preferredPayloadType: 101, // 101 is the second available dynamic PT. + clockRate: 90000, + parameters: { + apt: 125, + }, + rtcpFeedback: [], + }); // H264. - expect(rtpCapabilities.codecs?.[3]).toEqual( - { - kind : 'video', - mimeType : 'video/H264', - preferredPayloadType : 102, // 102 is the third available dynamic PT. - clockRate : 90000, - parameters : - { - // Since packetization-mode param was not included in the H264 codec - // and it's default value is 0, it's not added by ortc file. - // 'packetization-mode' : 0, - 'level-asymmetry-allowed' : 1, - 'profile-level-id' : '42e01f', - foo : 'bar' - }, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb', parameter: '' }, - { type: 'transport-cc', parameter: '' } - ] - }); + expect(rtpCapabilities.codecs?.[3]).toEqual({ + kind: 'video', + mimeType: 'video/H264', + preferredPayloadType: 102, // 102 is the third available dynamic PT. + clockRate: 90000, + parameters: { + // Since packetization-mode param was not included in the H264 codec + // and it's default value is 0, it's not added by ortc file. + // 'packetization-mode' : 0, + 'level-asymmetry-allowed': 1, + 'profile-level-id': '42e01f', + foo: 'bar', + }, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb', parameter: '' }, + { type: 'transport-cc', parameter: '' }, + ], + }); // H264 RTX. - expect(rtpCapabilities.codecs?.[4]).toEqual( - { - kind : 'video', - mimeType : 'video/rtx', - preferredPayloadType : 103, - clockRate : 90000, - parameters : - { - apt : 102 - }, - rtcpFeedback : [] - }); + expect(rtpCapabilities.codecs?.[4]).toEqual({ + kind: 'video', + mimeType: 'video/rtx', + preferredPayloadType: 103, + clockRate: 90000, + parameters: { + apt: 102, + }, + rtcpFeedback: [], + }); }); -test('generateRouterRtpCapabilities() with unsupported codecs throws UnsupportedError', () => -{ +test('generateRouterRtpCapabilities() with unsupported codecs throws UnsupportedError', () => { let mediaCodecs: mediasoup.types.RtpCodecCapability[]; - mediaCodecs = - [ + mediaCodecs = [ { - kind : 'audio', - mimeType : 'audio/chicken', - clockRate : 8000, - channels : 4 - } + kind: 'audio', + mimeType: 'audio/chicken', + clockRate: 8000, + channels: 4, + }, ]; - expect(() => ortc.generateRouterRtpCapabilities(mediaCodecs)) - .toThrow(UnsupportedError); + expect(() => ortc.generateRouterRtpCapabilities(mediaCodecs)).toThrow( + UnsupportedError, + ); - mediaCodecs = - [ + mediaCodecs = [ { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 1 - } + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 1, + }, ]; - expect(() => ortc.generateRouterRtpCapabilities(mediaCodecs)) - .toThrow(UnsupportedError); + expect(() => ortc.generateRouterRtpCapabilities(mediaCodecs)).toThrow( + UnsupportedError, + ); }); -test('generateRouterRtpCapabilities() with too many codecs throws', () => -{ +test('generateRouterRtpCapabilities() with too many codecs throws', () => { const mediaCodecs: mediasoup.types.RtpCodecCapability[] = []; - for (let i = 0; i < 100; ++i) - { - mediaCodecs.push( - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2 - }); + for (let i = 0; i < 100; ++i) { + mediaCodecs.push({ + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, + }); } - expect(() => ortc.generateRouterRtpCapabilities(mediaCodecs)) - .toThrow('cannot allocate'); + expect(() => ortc.generateRouterRtpCapabilities(mediaCodecs)).toThrow( + 'cannot allocate', + ); }); -test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsumerRtpParameters() and getPipeConsumerRtpParameters() succeed', () => -{ - const mediaCodecs: mediasoup.types.RtpCodecCapability[] = - [ +test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsumerRtpParameters() and getPipeConsumerRtpParameters() succeed', () => { + const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2 + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, }, { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - bar : 'lalala' - } - } + kind: 'video', + mimeType: 'video/H264', + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + bar: 'lalala', + }, + }, ]; const routerRtpCapabilities = ortc.generateRouterRtpCapabilities(mediaCodecs); - const rtpParameters: mediasoup.types.RtpParameters = - { - codecs : - [ + const rtpParameters: mediasoup.types.RtpParameters = { + codecs: [ { - mimeType : 'video/H264', - payloadType : 111, - clockRate : 90000, - parameters : - { - foo : 1234, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' + mimeType: 'video/H264', + payloadType: 111, + clockRate: 90000, + parameters: { + foo: 1234, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', }, - rtcpFeedback : - [ + rtcpFeedback: [ { type: 'nack', parameter: '' }, { type: 'nack', parameter: 'pli' }, - { type: 'goog-remb', parameter: '' } - ] + { type: 'goog-remb', parameter: '' }, + ], }, { - mimeType : 'video/rtx', - payloadType : 112, - clockRate : 90000, - parameters : - { - apt : 111 + mimeType: 'video/rtx', + payloadType: 112, + clockRate: 90000, + parameters: { + apt: 111, }, - rtcpFeedback : [] - } + rtcpFeedback: [], + }, ], - headerExtensions : - [ + headerExtensions: [ { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 1 + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 1, }, { - uri : 'urn:3gpp:video-orientation', - id : 2 - } + uri: 'urn:3gpp:video-orientation', + id: 2, + }, ], - encodings : - [ + encodings: [ { - ssrc : 11111111, - rtx : { ssrc: 11111112 }, - maxBitrate : 111111, - scalabilityMode : 'L1T3' + ssrc: 11111111, + rtx: { ssrc: 11111112 }, + maxBitrate: 111111, + scalabilityMode: 'L1T3', }, { - ssrc : 21111111, - rtx : { ssrc: 21111112 }, - maxBitrate : 222222, - scalabilityMode : 'L1T3' + ssrc: 21111111, + rtx: { ssrc: 21111112 }, + maxBitrate: 222222, + scalabilityMode: 'L1T3', }, { - rid : 'high', - maxBitrate : 333333, - scalabilityMode : 'L1T3' - } + rid: 'high', + maxBitrate: 333333, + scalabilityMode: 'L1T3', + }, ], - rtcp : - { - cname : 'qwerty1234' - } + rtcp: { + cname: 'qwerty1234', + }, }; const rtpMapping = ortc.getProducerRtpParametersMapping( - rtpParameters, routerRtpCapabilities + rtpParameters, + routerRtpCapabilities, ); - expect(rtpMapping.codecs).toEqual( - [ - { payloadType: 111, mappedPayloadType: 101 }, - { payloadType: 112, mappedPayloadType: 102 } - ]); + expect(rtpMapping.codecs).toEqual([ + { payloadType: 111, mappedPayloadType: 101 }, + { payloadType: 112, mappedPayloadType: 102 }, + ]); expect(rtpMapping.encodings[0].ssrc).toBe(11111111); expect(rtpMapping.encodings[0].rid).toBeUndefined(); @@ -300,178 +270,163 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(typeof rtpMapping.encodings[2].mappedSsrc).toBe('number'); const consumableRtpParameters = ortc.getConsumableRtpParameters( - 'video', rtpParameters, routerRtpCapabilities, rtpMapping + 'video', + rtpParameters, + routerRtpCapabilities, + rtpMapping, ); expect(consumableRtpParameters.codecs[0].mimeType).toBe('video/H264'); expect(consumableRtpParameters.codecs[0].payloadType).toBe(101); expect(consumableRtpParameters.codecs[0].clockRate).toBe(90000); - expect(consumableRtpParameters.codecs[0].parameters).toEqual( - { - foo : 1234, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }); + expect(consumableRtpParameters.codecs[0].parameters).toEqual({ + foo: 1234, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }); expect(consumableRtpParameters.codecs[1].mimeType).toBe('video/rtx'); expect(consumableRtpParameters.codecs[1].payloadType).toBe(102); expect(consumableRtpParameters.codecs[1].clockRate).toBe(90000); expect(consumableRtpParameters.codecs[1].parameters).toEqual({ apt: 101 }); - expect(consumableRtpParameters.encodings?.[0]).toEqual( - { - ssrc : rtpMapping.encodings[0].mappedSsrc, - maxBitrate : 111111, - scalabilityMode : 'L1T3' - }); - expect(consumableRtpParameters.encodings?.[1]).toEqual( - { - ssrc : rtpMapping.encodings[1].mappedSsrc, - maxBitrate : 222222, - scalabilityMode : 'L1T3' - }); - expect(consumableRtpParameters.encodings?.[2]).toEqual( - { - ssrc : rtpMapping.encodings[2].mappedSsrc, - maxBitrate : 333333, - scalabilityMode : 'L1T3' - }); - - expect(consumableRtpParameters.rtcp).toEqual( - { - cname : rtpParameters.rtcp?.cname, - reducedSize : true - }); - - const remoteRtpCapabilities: mediasoup.types.RtpCapabilities = - { - codecs : - [ - { - kind : 'audio', - mimeType : 'audio/opus', - preferredPayloadType : 100, - clockRate : 48000, - channels : 2, - parameters : {}, - rtcpFeedback : [] + expect(consumableRtpParameters.encodings?.[0]).toEqual({ + ssrc: rtpMapping.encodings[0].mappedSsrc, + maxBitrate: 111111, + scalabilityMode: 'L1T3', + }); + expect(consumableRtpParameters.encodings?.[1]).toEqual({ + ssrc: rtpMapping.encodings[1].mappedSsrc, + maxBitrate: 222222, + scalabilityMode: 'L1T3', + }); + expect(consumableRtpParameters.encodings?.[2]).toEqual({ + ssrc: rtpMapping.encodings[2].mappedSsrc, + maxBitrate: 333333, + scalabilityMode: 'L1T3', + }); + + expect(consumableRtpParameters.rtcp).toEqual({ + cname: rtpParameters.rtcp?.cname, + reducedSize: true, + }); + + const remoteRtpCapabilities: mediasoup.types.RtpCapabilities = { + codecs: [ + { + kind: 'audio', + mimeType: 'audio/opus', + preferredPayloadType: 100, + clockRate: 48000, + channels: 2, + parameters: {}, + rtcpFeedback: [], }, { - kind : 'video', - mimeType : 'video/H264', - preferredPayloadType : 101, - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - baz : 'LOLOLO' + kind: 'video', + mimeType: 'video/H264', + preferredPayloadType: 101, + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + baz: 'LOLOLO', }, - rtcpFeedback : - [ + rtcpFeedback: [ { type: 'nack', parameter: '' }, { type: 'nack', parameter: 'pli' }, - { type: 'foo', parameter: 'FOO' } - ] + { type: 'foo', parameter: 'FOO' }, + ], }, { - kind : 'video', - mimeType : 'video/rtx', - preferredPayloadType : 102, - clockRate : 90000, - parameters : - { - apt : 101 + kind: 'video', + mimeType: 'video/rtx', + preferredPayloadType: 102, + clockRate: 90000, + parameters: { + apt: 101, }, - rtcpFeedback : [] - } + rtcpFeedback: [], + }, ], - headerExtensions : - [ + headerExtensions: [ { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', - preferredId : 2, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', + preferredId: 2, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 8, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 8, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'urn:3gpp:video-orientation', - preferredId : 11, - preferredEncrypt : false, - direction : 'sendrecv' + kind: 'video', + uri: 'urn:3gpp:video-orientation', + preferredId: 11, + preferredEncrypt: false, + direction: 'sendrecv', }, { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:toffset', - preferredId : 12, - preferredEncrypt : false, - direction : 'sendrecv' - } - ] + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:toffset', + preferredId: 12, + preferredEncrypt: false, + direction: 'sendrecv', + }, + ], }; - const consumerRtpParameters = ortc.getConsumerRtpParameters( - { - consumableRtpParameters, - remoteRtpCapabilities, - pipe : false, - enableRtx : true - } - ); + const consumerRtpParameters = ortc.getConsumerRtpParameters({ + consumableRtpParameters, + remoteRtpCapabilities, + pipe: false, + enableRtx: true, + }); expect(consumerRtpParameters.codecs.length).toEqual(2); - expect(consumerRtpParameters.codecs[0]).toEqual( - { - mimeType : 'video/H264', - payloadType : 101, - clockRate : 90000, - parameters : - { - foo : 1234, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : - [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'foo', parameter: 'FOO' } - ] - }); - expect(consumerRtpParameters.codecs[1]).toEqual( - { - mimeType : 'video/rtx', - payloadType : 102, - clockRate : 90000, - parameters : - { - apt : 101 - }, - rtcpFeedback : [] - }); + expect(consumerRtpParameters.codecs[0]).toEqual({ + mimeType: 'video/H264', + payloadType: 101, + clockRate: 90000, + parameters: { + foo: 1234, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'foo', parameter: 'FOO' }, + ], + }); + expect(consumerRtpParameters.codecs[1]).toEqual({ + mimeType: 'video/rtx', + payloadType: 102, + clockRate: 90000, + parameters: { + apt: 101, + }, + rtcpFeedback: [], + }); expect(consumerRtpParameters.encodings?.length).toBe(1); expect(typeof consumerRtpParameters.encodings?.[0].ssrc).toBe('number'); @@ -480,131 +435,120 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(consumerRtpParameters.encodings?.[0].scalabilityMode).toBe('L3T3'); expect(consumerRtpParameters.encodings?.[0].maxBitrate).toBe(333333); - expect(consumerRtpParameters.headerExtensions).toEqual( - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 1, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:3gpp:video-orientation', - id : 11, - encrypt : false, - parameters : {} - }, - { - uri : 'urn:ietf:params:rtp-hdrext:toffset', - id : 12, - encrypt : false, - parameters : {} - } - ]); - - expect(consumerRtpParameters.rtcp).toEqual( + expect(consumerRtpParameters.headerExtensions).toEqual([ { - cname : rtpParameters.rtcp?.cname, - reducedSize : true - }); - - const pipeConsumerRtpParameters = ortc.getPipeConsumerRtpParameters( + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + id: 1, + encrypt: false, + parameters: {}, + }, { - consumableRtpParameters, - enableRtx : false - }); + uri: 'urn:3gpp:video-orientation', + id: 11, + encrypt: false, + parameters: {}, + }, + { + uri: 'urn:ietf:params:rtp-hdrext:toffset', + id: 12, + encrypt: false, + parameters: {}, + }, + ]); + + expect(consumerRtpParameters.rtcp).toEqual({ + cname: rtpParameters.rtcp?.cname, + reducedSize: true, + }); + + const pipeConsumerRtpParameters = ortc.getPipeConsumerRtpParameters({ + consumableRtpParameters, + enableRtx: false, + }); expect(pipeConsumerRtpParameters.codecs.length).toEqual(1); - expect(pipeConsumerRtpParameters.codecs[0]).toEqual( - { - mimeType : 'video/H264', - payloadType : 101, - clockRate : 90000, - parameters : - { - foo : 1234, - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032' - }, - rtcpFeedback : - [ - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' } - ] - }); + expect(pipeConsumerRtpParameters.codecs[0]).toEqual({ + mimeType: 'video/H264', + payloadType: 101, + clockRate: 90000, + parameters: { + foo: 1234, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, + rtcpFeedback: [ + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + ], + }); expect(pipeConsumerRtpParameters.encodings?.length).toBe(3); expect(typeof pipeConsumerRtpParameters.encodings?.[0].ssrc).toBe('number'); expect(pipeConsumerRtpParameters.encodings?.[0].rtx).toBeUndefined(); - expect(typeof pipeConsumerRtpParameters.encodings?.[0].maxBitrate).toBe('number'); + expect(typeof pipeConsumerRtpParameters.encodings?.[0].maxBitrate).toBe( + 'number', + ); expect(pipeConsumerRtpParameters.encodings?.[0].scalabilityMode).toBe('L1T3'); expect(typeof pipeConsumerRtpParameters.encodings?.[1].ssrc).toBe('number'); expect(pipeConsumerRtpParameters.encodings?.[1].rtx).toBeUndefined(); - expect(typeof pipeConsumerRtpParameters.encodings?.[1].maxBitrate).toBe('number'); + expect(typeof pipeConsumerRtpParameters.encodings?.[1].maxBitrate).toBe( + 'number', + ); expect(pipeConsumerRtpParameters.encodings?.[1].scalabilityMode).toBe('L1T3'); expect(typeof pipeConsumerRtpParameters.encodings?.[2].ssrc).toBe('number'); expect(pipeConsumerRtpParameters.encodings?.[2].rtx).toBeUndefined(); - expect(typeof pipeConsumerRtpParameters.encodings?.[2].maxBitrate).toBe('number'); + expect(typeof pipeConsumerRtpParameters.encodings?.[2].maxBitrate).toBe( + 'number', + ); expect(pipeConsumerRtpParameters.encodings?.[2].scalabilityMode).toBe('L1T3'); - expect(pipeConsumerRtpParameters.rtcp).toEqual( - { - cname : rtpParameters.rtcp?.cname, - reducedSize : true - }); + expect(pipeConsumerRtpParameters.rtcp).toEqual({ + cname: rtpParameters.rtcp?.cname, + reducedSize: true, + }); }); -test('getProducerRtpParametersMapping() with incompatible params throws UnsupportedError', () => -{ - const mediaCodecs: mediasoup.types.RtpCodecCapability[] = - [ +test('getProducerRtpParametersMapping() with incompatible params throws UnsupportedError', () => { + const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2 + kind: 'audio', + mimeType: 'audio/opus', + clockRate: 48000, + channels: 2, }, { - kind : 'video', - mimeType : 'video/H264', - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '640032' - } - } + kind: 'video', + mimeType: 'video/H264', + clockRate: 90000, + parameters: { + 'packetization-mode': 1, + 'profile-level-id': '640032', + }, + }, ]; const routerRtpCapabilities = ortc.generateRouterRtpCapabilities(mediaCodecs); - const rtpParameters = - { - codecs : - [ + const rtpParameters = { + codecs: [ { - mimeType : 'video/VP8', - payloadType : 120, - clockRate : 90000, - rtcpFeedback : - [ + mimeType: 'video/VP8', + payloadType: 120, + clockRate: 90000, + rtcpFeedback: [ { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'fir' } - ] - } - ], - headerExtensions : [], - encodings : - [ - { ssrc: 11111111 } + { type: 'nack', parameter: 'fir' }, + ], + }, ], - rtcp : - { - cname : 'qwerty1234' - } + headerExtensions: [], + encodings: [{ ssrc: 11111111 }], + rtcp: { + cname: 'qwerty1234', + }, }; - expect(() => ortc.getProducerRtpParametersMapping( - rtpParameters, routerRtpCapabilities - )).toThrow(UnsupportedError); + expect(() => + ortc.getProducerRtpParametersMapping(rtpParameters, routerRtpCapabilities), + ).toThrow(UnsupportedError); }); diff --git a/node/src/types.ts b/node/src/types.ts index 2ede7f2c10..45ef78af89 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -19,16 +19,13 @@ export * from './SrtpParameters'; export * from './errors'; export type { ScalabilityMode } from './scalabilityModes'; -export type AppData = -{ +export type AppData = { [key: string]: unknown; }; -type Only = -{ +type Only = { [P in keyof T]: T[P]; -} & -{ +} & { [P in keyof U]?: never; }; diff --git a/node/src/utils.ts b/node/src/utils.ts index f0ad39ff1e..f7af5c17f3 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -5,23 +5,15 @@ import { Type as FbsRtpParametersType } from './fbs/rtp-parameters'; /** * Clones the given value. */ -export function clone(value: T): T -{ - if (value === undefined) - { +export function clone(value: T): T { + if (value === undefined) { return undefined as unknown as T; - } - else if (Number.isNaN(value)) - { + } else if (Number.isNaN(value)) { return NaN as unknown as T; - } - else if (typeof structuredClone === 'function') - { + } else if (typeof structuredClone === 'function') { // Available in Node >= 18. return structuredClone(value); - } - else - { + } else { return JSON.parse(JSON.stringify(value)); } } @@ -29,16 +21,14 @@ export function clone(value: T): T /** * Generates a random UUID v4. */ -export function generateUUIDv4(): string -{ +export function generateUUIDv4(): string { return randomUUID(); } /** * Generates a random positive integer. */ -export function generateRandomNumber(): number -{ +export function generateRandomNumber(): number { return randomInt(100_000_000, 999_999_999); } @@ -46,28 +36,23 @@ export function generateRandomNumber(): number * Get the flatbuffers RtpParameters type for a given Producer. */ export function getRtpParametersType( - producerType: ProducerType, pipe: boolean -): FbsRtpParametersType -{ - if (pipe) - { + producerType: ProducerType, + pipe: boolean, +): FbsRtpParametersType { + if (pipe) { return FbsRtpParametersType.PIPE; } - switch (producerType) - { - case 'simple': - { + switch (producerType) { + case 'simple': { return FbsRtpParametersType.SIMPLE; } - case 'simulcast': - { + case 'simulcast': { return FbsRtpParametersType.SIMULCAST; } - case 'svc': - { + case 'svc': { return FbsRtpParametersType.SVC; } } @@ -77,19 +62,16 @@ export function getRtpParametersType( * Parse flatbuffers vector into an array of the given type. */ export function parseVector( - binary: any, methodName: string, parseFn?: (binary2: any) => Type -): Type[] -{ + binary: any, + methodName: string, + parseFn?: (binary2: any) => Type, +): Type[] { const array: Type[] = []; - for (let i = 0; i < binary[`${methodName}Length`](); ++i) - { - if (parseFn) - { + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { + if (parseFn) { array.push(parseFn(binary[methodName](i))); - } - else - { + } else { array.push(binary[methodName](i)); } } @@ -101,13 +83,12 @@ export function parseVector( * Parse flatbuffers vector of StringString into the corresponding array. */ export function parseStringStringVector( - binary: any, methodName: string -): { key: string; value: string }[] -{ + binary: any, + methodName: string, +): { key: string; value: string }[] { const array: { key: string; value: string }[] = []; - for (let i = 0; i < binary[`${methodName}Length`](); ++i) - { + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { const kv = binary[methodName](i)!; array.push({ key: kv.key(), value: kv.value() }); @@ -120,13 +101,12 @@ export function parseStringStringVector( * Parse flatbuffers vector of StringUint8 into the corresponding array. */ export function parseStringUint8Vector( - binary: any, methodName: string -): {key: string; value: number}[] -{ - const array: {key: string; value: number}[] = []; + binary: any, + methodName: string, +): { key: string; value: number }[] { + const array: { key: string; value: number }[] = []; - for (let i = 0; i < binary[`${methodName}Length`](); ++i) - { + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { const kv = binary[methodName](i)!; array.push({ key: kv.key(), value: kv.value() }); @@ -139,13 +119,12 @@ export function parseStringUint8Vector( * Parse flatbuffers vector of Uint16String into the corresponding array. */ export function parseUint16StringVector( - binary: any, methodName: string -): { key: number; value: string }[] -{ + binary: any, + methodName: string, +): { key: number; value: string }[] { const array: { key: number; value: string }[] = []; - for (let i = 0; i < binary[`${methodName}Length`](); ++i) - { + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { const kv = binary[methodName](i)!; array.push({ key: kv.key(), value: kv.value() }); @@ -158,13 +137,12 @@ export function parseUint16StringVector( * Parse flatbuffers vector of Uint32String into the corresponding array. */ export function parseUint32StringVector( - binary: any, methodName: string -): { key: number; value: string }[] -{ + binary: any, + methodName: string, +): { key: number; value: string }[] { const array: { key: number; value: string }[] = []; - for (let i = 0; i < binary[`${methodName}Length`](); ++i) - { + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { const kv = binary[methodName](i)!; array.push({ key: kv.key(), value: kv.value() }); @@ -177,18 +155,16 @@ export function parseUint32StringVector( * Parse flatbuffers vector of StringStringArray into the corresponding array. */ export function parseStringStringArrayVector( - binary: any, methodName: string -): { key: string; values: string[] }[] -{ + binary: any, + methodName: string, +): { key: string; values: string[] }[] { const array: { key: string; values: string[] }[] = []; - for (let i = 0; i < binary[`${methodName}Length`](); ++i) - { + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { const kv = binary[methodName](i)!; const values: string[] = []; - for (let i2 = 0; i2 < kv.valuesLength(); ++i2) - { + for (let i2 = 0; i2 < kv.valuesLength(); ++i2) { values.push(kv.values(i2)!); } @@ -202,18 +178,15 @@ export function parseStringStringArrayVector( * Make an object or array recursively immutable. * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze. */ -export function deepFreeze(object: T): T -{ +export function deepFreeze(object: T): T { // Retrieve the property names defined on object. const propNames = Reflect.ownKeys(object as any); // Freeze properties before freezing self. - for (const name of propNames) - { + for (const name of propNames) { const value = (object as any)[name]; - if ((value && typeof value === 'object') || typeof value === 'function') - { + if ((value && typeof value === 'object') || typeof value === 'function') { deepFreeze(value); } } diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 28b5b8bc46..741eec7236 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -13,7 +13,9 @@ const PYTHON = getPython(); const PIP_INVOKE_DIR = path.resolve('worker/pip_invoke'); const FLATBUFFERS_VERSION = '23.3.3'; const WORKER_RELEASE_DIR = 'worker/out/Release'; -const WORKER_RELEASE_BIN = IS_WINDOWS ? 'mediasoup-worker.exe' : 'mediasoup-worker'; +const WORKER_RELEASE_BIN = IS_WINDOWS + ? 'mediasoup-worker.exe' + : 'mediasoup-worker'; const WORKER_RELEASE_BIN_PATH = `${WORKER_RELEASE_DIR}/${WORKER_RELEASE_BIN}`; const WORKER_PREBUILD_DIR = 'worker/prebuild'; const WORKER_PREBUILD_TAR = getWorkerPrebuildTarName(); @@ -26,30 +28,22 @@ const args = process.argv.slice(3).join(' '); // PYTHONPATH env must be updated now so all invoke calls below will find the // pip invoke module. -if (process.env.PYTHONPATH) -{ - if (IS_WINDOWS) - { +if (process.env.PYTHONPATH) { + if (IS_WINDOWS) { process.env.PYTHONPATH = `${PIP_INVOKE_DIR};${process.env.PYTHONPATH}`; - } - else - { + } else { process.env.PYTHONPATH = `${PIP_INVOKE_DIR}:${process.env.PYTHONPATH}`; } -} -else -{ +} else { process.env.PYTHONPATH = PIP_INVOKE_DIR; } run(); -async function run() -{ +async function run() { logInfo(args ? `[args:"${args}"]` : ''); - switch (task) - { + switch (task) { // As per NPM documentation (https://docs.npmjs.com/cli/v9/using-npm/scripts) // `prepare` script: // @@ -61,20 +55,17 @@ async function run() // // So here we generate flatbuffers definitions for TypeScript and compile // TypeScript to JavaScript. - case 'prepare': - { + case 'prepare': { flatcNode(); buildTypescript({ force: false }); break; } - case 'postinstall': - { + case 'postinstall': { // If the user/app provides us with a custom mediasoup-worker binary then // don't do anything. - if (process.env.MEDIASOUP_WORKER_BIN) - { + if (process.env.MEDIASOUP_WORKER_BIN) { logInfo('MEDIASOUP_WORKER_BIN environment variable given, skipping'); break; @@ -84,32 +75,30 @@ async function run() // (instead of via npm), and if MEDIASOUP_FORCE_PREBUILT_WORKER_DOWNLOAD env is // not set, then skip mediasoup-worker prebuilt download. else if ( - ( - process.env.MEDIASOUP_LOCAL_DEV || + (process.env.MEDIASOUP_LOCAL_DEV || process.env.MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD || - process.env.npm_package_resolved?.startsWith('git+ssh://') - ) && + process.env.npm_package_resolved?.startsWith('git+ssh://')) && !process.env.MEDIASOUP_FORCE_WORKER_PREBUILT_DOWNLOAD - ) - { - logInfo('skipping mediasoup-worker prebuilt download, building it locally'); + ) { + logInfo( + 'skipping mediasoup-worker prebuilt download, building it locally', + ); buildWorker(); - if (!process.env.MEDIASOUP_LOCAL_DEV) - { + if (!process.env.MEDIASOUP_LOCAL_DEV) { cleanWorkerArtifacts(); } } // Attempt to download a prebuilt binary. Fallback to building locally. - else if (!(await downloadPrebuiltWorker())) - { - logInfo(`couldn't fetch any mediasoup-worker prebuilt binary, building it locally`); + else if (!(await downloadPrebuiltWorker())) { + logInfo( + `couldn't fetch any mediasoup-worker prebuilt binary, building it locally`, + ); buildWorker(); - if (!process.env.MEDIASOUP_LOCAL_DEV) - { + if (!process.env.MEDIASOUP_LOCAL_DEV) { cleanWorkerArtifacts(); } } @@ -117,52 +106,51 @@ async function run() break; } - case 'typescript:build': - { + case 'typescript:build': { installNodeDeps(); buildTypescript({ force: true }); break; } - case 'typescript:watch': - { + case 'typescript:watch': { deleteNodeLib(); executeCmd(`tsc --project node --watch ${args}`); break; } - case 'worker:build': - { + case 'worker:build': { buildWorker(); break; } - case 'worker:prebuild': - { + case 'worker:prebuild': { await prebuildWorker(); break; } - case 'lint:node': - { + case 'lint:node': { lintNode(); break; } - case 'lint:worker': - { + case 'lint:worker': { lintWorker(); break; } - case 'format:worker': - { + case 'format:node': { + formatNode(); + + break; + } + + case 'format:worker': { installInvoke(); executeCmd(`"${PYTHON}" -m invoke -r worker format`); @@ -170,37 +158,32 @@ async function run() break; } - case 'flatc:node': - { + case 'flatc:node': { flatcNode(); break; } - case 'flatc:worker': - { + case 'flatc:worker': { flatcWorker(); break; } - case 'test:node': - { + case 'test:node': { buildTypescript({ force: false }); testNode(); break; } - case 'test:worker': - { + case 'test:worker': { testWorker(); break; } - case 'coverage:node': - { + case 'coverage:node': { buildTypescript({ force: false }); executeCmd(`jest --coverage ${args}`); executeCmd('open-cli coverage/lcov-report/index.html'); @@ -208,25 +191,20 @@ async function run() break; } - case 'release:check': - { + case 'release:check': { checkRelease(); break; } - case 'release': - { + case 'release': { let octokit; let versionChanges; - try - { + try { octokit = await getOctokit(); versionChanges = await getVersionChanges(); - } - catch (error) - { + } catch (error) { logError(error.message); exitWithError(); @@ -240,22 +218,20 @@ async function run() logInfo('creating release in GitHub'); - await octokit.repos.createRelease( - { - owner : GH_OWNER, - repo : GH_REPO, - name : PKG.version, - body : versionChanges, - // eslint-disable-next-line camelcase - tag_name : PKG.version, - draft : false - }); + await octokit.repos.createRelease({ + owner: GH_OWNER, + repo: GH_REPO, + name: PKG.version, + body: versionChanges, + // eslint-disable-next-line camelcase + tag_name: PKG.version, + draft: false, + }); // GitHub mediasoup-worker-prebuild CI action doesn't create mediasoup-worker // prebuilt binary for macOS ARM. If this is a macOS ARM machine, do it here // and upload it to the release. - if (os.platform() === 'darwin' && os.arch() === 'arm64') - { + if (os.platform() === 'darwin' && os.arch() === 'arm64') { await prebuildWorker(); await uploadMacArmPrebuiltWorker(); } @@ -265,8 +241,7 @@ async function run() break; } - case 'release:upload-mac-arm-prebuilt-worker': - { + case 'release:upload-mac-arm-prebuilt-worker': { checkRelease(); await prebuildWorker(); await uploadMacArmPrebuiltWorker(); @@ -274,8 +249,7 @@ async function run() break; } - default: - { + default: { logError('unknown task'); exitWithError(); @@ -283,19 +257,14 @@ async function run() } } -function getPython() -{ +function getPython() { let python = process.env.PYTHON; - if (!python) - { - try - { - execSync('python3 --version', { stdio: [ 'ignore', 'ignore', 'ignore' ] }); + if (!python) { + try { + execSync('python3 --version', { stdio: ['ignore', 'ignore', 'ignore'] }); python = 'python3'; - } - catch (error) - { + } catch (error) { python = 'python'; } } @@ -303,14 +272,12 @@ function getPython() return python; } -function getWorkerPrebuildTarName() -{ +function getWorkerPrebuildTarName() { let name = `mediasoup-worker-${PKG.version}-${os.platform()}-${os.arch()}`; // In Linux we want to know about kernel version since kernel >= 6 supports // io-uring. - if (os.platform() === 'linux') - { + if (os.platform() === 'linux') { const kernelMajorVersion = Number(os.release().split('.')[0]); name += `-kernel${kernelMajorVersion}`; @@ -319,10 +286,8 @@ function getWorkerPrebuildTarName() return `${name}.tgz`; } -function installInvoke() -{ - if (fs.existsSync(PIP_INVOKE_DIR)) - { +function installInvoke() { + if (fs.existsSync(PIP_INVOKE_DIR)) { return; } @@ -332,14 +297,12 @@ function installInvoke() // installation. executeCmd( `"${PYTHON}" -m pip install --upgrade --no-user --target="${PIP_INVOKE_DIR}" invoke`, - /* exitOnError */ true + /* exitOnError */ true, ); } -function deleteNodeLib() -{ - if (!fs.existsSync('node/lib')) - { +function deleteNodeLib() { + if (!fs.existsSync('node/lib')) { return; } @@ -348,10 +311,8 @@ function deleteNodeLib() fs.rmSync('node/lib', { recursive: true, force: true }); } -function buildTypescript({ force = false } = { force: false }) -{ - if (!force && fs.existsSync('node/lib')) - { +function buildTypescript({ force = false } = { force: false }) { + if (!force && fs.existsSync('node/lib')) { return; } @@ -361,8 +322,7 @@ function buildTypescript({ force = false } = { force: false }) executeCmd('tsc --project node'); } -function buildWorker() -{ +function buildWorker() { logInfo('buildWorker()'); installInvoke(); @@ -370,8 +330,7 @@ function buildWorker() executeCmd(`"${PYTHON}" -m invoke -r worker mediasoup-worker`); } -function cleanWorkerArtifacts() -{ +function cleanWorkerArtifacts() { logInfo('cleanWorkerArtifacts()'); installInvoke(); @@ -384,15 +343,28 @@ function cleanWorkerArtifacts() executeCmd(`"${PYTHON}" -m invoke -r worker clean-pip`); } -function lintNode() -{ +function lintNode() { logInfo('lintNode()'); - executeCmd('eslint -c node/.eslintrc.js --ignore-path node/.eslintignore --max-warnings 0 node/src node/.eslintrc.js npm-scripts.mjs worker/scripts/clang-format.mjs'); + const paths = [ + 'npm-scripts.mjs', + '.eslintrc.js', + 'node/src', + 'worker/scripts/clang-format.mjs', + ]; + + // Ensure there are no rules that are unnecessary or conflict with Prettier + // rules. + executeCmd('eslint-config-prettier .eslintrc.js'); + + executeCmd( + `eslint -c .eslintrc.js --ignore-path .eslintignore --max-warnings 0 ${paths.join( + ' ', + )}`, + ); } -function lintWorker() -{ +function lintWorker() { logInfo('lintWorker()'); installInvoke(); @@ -400,8 +372,20 @@ function lintWorker() executeCmd(`"${PYTHON}" -m invoke -r worker lint`); } -function flatcNode() -{ +function formatNode() { + logInfo('formatNode()'); + + const paths = [ + 'npm-scripts.mjs', + '.eslintrc.js', + 'node/src', + 'worker/scripts/clang-format.mjs', + ]; + + executeCmd(`prettier ${paths.join(' ')} --write`); +} + +function flatcNode() { logInfo('flatcNode()'); installInvoke(); @@ -411,25 +395,35 @@ function flatcNode() const buildType = process.env.MEDIASOUP_BUILDTYPE || 'Release'; const extension = IS_WINDOWS ? '.exe' : ''; - const flatc = path.resolve(path.join( - 'worker', 'out', buildType, 'build', 'subprojects', `flatbuffers-${FLATBUFFERS_VERSION}`, `flatc${extension}`)); + const flatc = path.resolve( + path.join( + 'worker', + 'out', + buildType, + 'build', + 'subprojects', + `flatbuffers-${FLATBUFFERS_VERSION}`, + `flatc${extension}`, + ), + ); const out = path.resolve(path.join('node', 'src')); - for (const dirent of fs.readdirSync(path.join('worker', 'fbs'), { withFileTypes: true })) - { - if (!dirent.isFile() || path.parse(dirent.name).ext !== '.fbs') - { + for (const dirent of fs.readdirSync(path.join('worker', 'fbs'), { + withFileTypes: true, + })) { + if (!dirent.isFile() || path.parse(dirent.name).ext !== '.fbs') { continue; } const filePath = path.resolve(path.join('worker', 'fbs', dirent.name)); - executeCmd(`"${flatc}" --ts --ts-no-import-ext --gen-object-api -o "${out}" "${filePath}"`); + executeCmd( + `"${flatc}" --ts --ts-no-import-ext --gen-object-api -o "${out}" "${filePath}"`, + ); } } -function flatcWorker() -{ +function flatcWorker() { logInfo('flatcWorker()'); installInvoke(); @@ -437,15 +431,13 @@ function flatcWorker() executeCmd(`"${PYTHON}" -m invoke -r worker flatc`); } -function testNode() -{ +function testNode() { logInfo('testNode()'); - executeCmd(`jest ${args}`); + executeCmd(`jest --detectOpenHandles ${args}`); } -function testWorker() -{ +function testWorker() { logInfo('testWorker()'); installInvoke(); @@ -453,8 +445,7 @@ function testWorker() executeCmd(`"${PYTHON}" -m invoke -r worker test`); } -function installNodeDeps() -{ +function installNodeDeps() { logInfo('installNodeDeps()'); // Install/update Node deps. @@ -463,8 +454,7 @@ function installNodeDeps() executeCmd('npm install --package-lock-only --ignore-scripts'); } -function checkRelease() -{ +function checkRelease() { logInfo('checkRelease()'); installNodeDeps(); @@ -477,32 +467,30 @@ function checkRelease() testWorker(); } -function ensureDir(dir) -{ +function ensureDir(dir) { logInfo(`ensureDir() [dir:${dir}]`); - if (!fs.existsSync(dir)) - { + if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } -async function prebuildWorker() -{ +async function prebuildWorker() { logInfo('prebuildWorker()'); ensureDir(WORKER_PREBUILD_DIR); - return new Promise((resolve, reject) => - { + return new Promise((resolve, reject) => { // Generate a gzip file which just contains mediasoup-worker binary without // any folder. - tar.create( - { - cwd : WORKER_RELEASE_DIR, - gzip : true - }, - [ WORKER_RELEASE_BIN ]) + tar + .create( + { + cwd: WORKER_RELEASE_DIR, + gzip: true, + }, + [WORKER_RELEASE_BIN], + ) .pipe(fs.createWriteStream(WORKER_PREBUILD_TAR_PATH)) .on('finish', resolve) .on('error', reject); @@ -511,8 +499,7 @@ async function prebuildWorker() // Returns a Promise resolving to true if a mediasoup-worker prebuilt binary // was downloaded and uncompressed, false otherwise. -async function downloadPrebuiltWorker() -{ +async function downloadPrebuiltWorker() { const releaseBase = process.env.MEDIASOUP_WORKER_PREBUILT_DOWNLOAD_BASE_URL || `${PKG.repository.url.replace(/\.git$/, '')}/releases/download`; @@ -525,31 +512,25 @@ async function downloadPrebuiltWorker() let res; - try - { + try { res = await fetch(tarUrl); - if (res.status === 404) - { + if (res.status === 404) { logInfo( - 'downloadPrebuiltWorker() | no available mediasoup-worker prebuilt binary for current architecture' + 'downloadPrebuiltWorker() | no available mediasoup-worker prebuilt binary for current architecture', ); return false; - } - else if (!res.ok) - { + } else if (!res.ok) { logError( - `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${res.status} ${res.statusText}` + `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${res.status} ${res.statusText}`, ); return false; } - } - catch (error) - { + } catch (error) { logError( - `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${error}` + `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${error}`, ); return false; @@ -557,27 +538,27 @@ async function downloadPrebuiltWorker() ensureDir(WORKER_RELEASE_DIR); - return new Promise((resolve) => - { + return new Promise(resolve => { // Extract mediasoup-worker in the official mediasoup-worker path. res.body - .pipe(tar.extract( - { - newer : false, - cwd : WORKER_RELEASE_DIR - })) - .on('finish', () => - { - logInfo('downloadPrebuiltWorker() | got mediasoup-worker prebuilt binary'); - - try - { + .pipe( + tar.extract({ + newer: false, + cwd: WORKER_RELEASE_DIR, + }), + ) + .on('finish', () => { + logInfo( + 'downloadPrebuiltWorker() | got mediasoup-worker prebuilt binary', + ); + + try { // Give execution permission to the binary. fs.chmodSync(WORKER_RELEASE_BIN_PATH, 0o775); - } - catch (error) - { - logWarn(`downloadPrebuiltWorker() | failed to give execution permissions to the mediasoup-worker prebuilt binary: ${error}`); + } catch (error) { + logWarn( + `downloadPrebuiltWorker() | failed to give execution permissions to the mediasoup-worker prebuilt binary: ${error}`, + ); } // Let's confirm that the fetched mediasoup-worker prebuit binary does @@ -587,55 +568,42 @@ async function downloadPrebuiltWorker() // expect exit code 41 (see main.cpp). logInfo( - 'downloadPrebuiltWorker() | checking fetched mediasoup-worker prebuilt binary in current host' + 'downloadPrebuiltWorker() | checking fetched mediasoup-worker prebuilt binary in current host', ); - try - { + try { const resolvedBinPath = path.resolve(WORKER_RELEASE_BIN_PATH); // This will always fail on purpose, but if status code is 41 then // it's good. - execSync( - `"${resolvedBinPath}"`, - { - stdio : [ 'ignore', 'ignore', 'ignore' ], - // Ensure no env is passed to avoid accidents. - env : {} - } - ); - } - catch (error) - { - if (error.status === 41) - { + execSync(`"${resolvedBinPath}"`, { + stdio: ['ignore', 'ignore', 'ignore'], + // Ensure no env is passed to avoid accidents. + env: {}, + }); + } catch (error) { + if (error.status === 41) { logInfo( - 'downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary is valid for current host' + 'downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary is valid for current host', ); resolve(true); - } - else - { + } else { logError( - `downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary fails to run in this host [status:${error.status}]` + `downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary fails to run in this host [status:${error.status}]`, ); - try - { + try { fs.unlinkSync(WORKER_RELEASE_BIN_PATH); - } - catch (error2) - {} + } catch (error2) {} resolve(false); } } }) - .on('error', (error) => - { + .on('error', error => { logError( - `downloadPrebuiltWorker() | failed to uncompress downloaded mediasoup-worker prebuilt binary: ${error}` + `downloadPrebuiltWorker() | failed to uncompress downloaded mediasoup-worker prebuilt binary: ${error}`, ); resolve(false); @@ -643,10 +611,8 @@ async function downloadPrebuiltWorker() }); } -async function uploadMacArmPrebuiltWorker() -{ - if (os.platform() !== 'darwin' || os.arch() !== 'arm64') - { +async function uploadMacArmPrebuiltWorker() { + if (os.platform() !== 'darwin' || os.arch() !== 'arm64') { logWarn('uploadMacArmPrebuiltWorker() | invalid platform or architecture'); return; @@ -656,46 +622,40 @@ async function uploadMacArmPrebuiltWorker() logInfo('uploadMacArmPrebuiltWorker() | getting release info'); - const release = await octokit.rest.repos.getReleaseByTag( - { - owner : GH_OWNER, - repo : GH_REPO, - tag : PKG.version - }); + const release = await octokit.rest.repos.getReleaseByTag({ + owner: GH_OWNER, + repo: GH_REPO, + tag: PKG.version, + }); logInfo('uploadMacArmPrebuiltWorker() | uploading release asset'); - await octokit.rest.repos.uploadReleaseAsset( - { - owner : GH_OWNER, - repo : GH_REPO, - // eslint-disable-next-line camelcase - release_id : release.data.id, - name : WORKER_PREBUILD_TAR, - data : fs.readFileSync(WORKER_PREBUILD_TAR_PATH) - }); + await octokit.rest.repos.uploadReleaseAsset({ + owner: GH_OWNER, + repo: GH_REPO, + // eslint-disable-next-line camelcase + release_id: release.data.id, + name: WORKER_PREBUILD_TAR, + data: fs.readFileSync(WORKER_PREBUILD_TAR_PATH), + }); } -async function getOctokit() -{ - if (!process.env.GITHUB_TOKEN) - { +async function getOctokit() { + if (!process.env.GITHUB_TOKEN) { throw new Error('missing GITHUB_TOKEN environment variable'); } // NOTE: Load dep on demand since it's a devDependency. const { Octokit } = await import('@octokit/rest'); - const octokit = new Octokit( - { - auth : process.env.GITHUB_TOKEN - }); + const octokit = new Octokit({ + auth: process.env.GITHUB_TOKEN, + }); return octokit; } -async function getVersionChanges() -{ +async function getVersionChanges() { logInfo('getVersionChanges()'); // NOTE: Load dep on demand since it's a devDependency. @@ -704,12 +664,10 @@ async function getVersionChanges() const changelog = fs.readFileSync('./CHANGELOG.md').toString(); const entries = marked.lexer(changelog); - for (let idx = 0; idx < entries.length; ++idx) - { + for (let idx = 0; idx < entries.length; ++idx) { const entry = entries[idx]; - if (entry.type === 'heading' && entry.text === PKG.version) - { + if (entry.type === 'heading' && entry.text === PKG.version) { const changes = entries[idx + 1].raw; return changes; @@ -717,51 +675,42 @@ async function getVersionChanges() } // This should not happen (unless author forgot to update CHANGELOG). - throw new Error(`no entry found in CHANGELOG.md for version '${PKG.version}'`); + throw new Error( + `no entry found in CHANGELOG.md for version '${PKG.version}'`, + ); } -function executeCmd(command, exitOnError = true) -{ +function executeCmd(command, exitOnError = true) { logInfo(`executeCmd(): ${command}`); - try - { - execSync(command, { stdio: [ 'ignore', process.stdout, process.stderr ] }); - } - catch (error) - { - if (exitOnError) - { + try { + execSync(command, { stdio: ['ignore', process.stdout, process.stderr] }); + } catch (error) { + if (exitOnError) { logError(`executeCmd() failed, exiting: ${error}`); exitWithError(); - } - else - { + } else { logInfo(`executeCmd() failed, ignoring: ${error}`); } } } -function logInfo(message) -{ +function logInfo(message) { // eslint-disable-next-line no-console - console.log(`npm-scripts.mjs \x1b[36m[INFO] [${task}]\x1b\[0m`, message); + console.log(`npm-scripts.mjs \x1b[36m[INFO] [${task}]\x1b[0m`, message); } -function logWarn(message) -{ +function logWarn(message) { // eslint-disable-next-line no-console - console.warn(`npm-scripts.mjs \x1b[33m[WARN] [${task}]\x1b\[0m`, message); + console.warn(`npm-scripts.mjs \x1b[33m[WARN] [${task}]\x1b\0m`, message); } -function logError(message) -{ +function logError(message) { // eslint-disable-next-line no-console - console.error(`npm-scripts.mjs \x1b[31m[ERROR] [${task}]\x1b\[0m`, message); + console.error(`npm-scripts.mjs \x1b[31m[ERROR] [${task}]\x1b[0m`, message); } -function exitWithError() -{ +function exitWithError() { process.exit(1); } diff --git a/package-lock.json b/package-lock.json index 6368bf90f8..68c871f6e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,14 +22,17 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.6", - "@typescript-eslint/eslint-plugin": "^6.17.0", - "@typescript-eslint/parser": "^6.17.0", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.6.1", + "eslint-plugin-prettier": "^5.1.2", "jest": "^29.7.0", "marked": "^11.1.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", + "prettier": "^3.1.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", "typescript": "^5.3.3" @@ -1477,6 +1480,18 @@ "@octokit/openapi-types": "^18.0.0" } }, + "node_modules/@pkgr/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", + "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -1659,16 +1674,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.17.0.tgz", - "integrity": "sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", + "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.17.0", - "@typescript-eslint/type-utils": "6.17.0", - "@typescript-eslint/utils": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/type-utils": "6.18.0", + "@typescript-eslint/utils": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1694,13 +1709,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", - "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0" + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1711,9 +1726,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", - "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1724,13 +1739,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", - "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1752,17 +1767,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", - "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", + "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.17.0", - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", "semver": "^7.5.4" }, "engines": { @@ -1777,12 +1792,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", - "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/types": "6.18.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1818,15 +1833,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.17.0.tgz", - "integrity": "sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", + "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.17.0", - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/typescript-estree": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4" }, "engines": { @@ -1846,13 +1861,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", - "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0" + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1863,9 +1878,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", - "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1876,13 +1891,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", - "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1904,12 +1919,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", - "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/types": "6.18.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1962,13 +1977,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.17.0.tgz", - "integrity": "sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", + "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.17.0", - "@typescript-eslint/utils": "6.17.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/utils": "6.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1989,13 +2004,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", - "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0" + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2006,9 +2021,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", - "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2019,13 +2034,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", - "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2047,17 +2062,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", - "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", + "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.17.0", - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", "semver": "^7.5.4" }, "engines": { @@ -2072,12 +2087,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", - "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/types": "6.18.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3150,6 +3165,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-plugin-jest": { "version": "27.6.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", @@ -3175,6 +3202,36 @@ } } }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", + "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -3369,6 +3426,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-glob": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", @@ -5513,6 +5576,33 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -6274,6 +6364,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/tar": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", @@ -7942,6 +8054,12 @@ "@octokit/openapi-types": "^18.0.0" } }, + "@pkgr/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", + "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "dev": true + }, "@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -8124,16 +8242,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.17.0.tgz", - "integrity": "sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", + "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.17.0", - "@typescript-eslint/type-utils": "6.17.0", - "@typescript-eslint/utils": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/type-utils": "6.18.0", + "@typescript-eslint/utils": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8143,29 +8261,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", - "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0" + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" } }, "@typescript-eslint/types": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", - "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", - "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8175,27 +8293,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", - "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", + "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.17.0", - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", - "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/types": "6.18.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -8220,42 +8338,42 @@ } }, "@typescript-eslint/parser": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.17.0.tgz", - "integrity": "sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", + "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.17.0", - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/typescript-estree": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", - "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0" + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" } }, "@typescript-eslint/types": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", - "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", - "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8265,12 +8383,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", - "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/types": "6.18.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -8305,41 +8423,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.17.0.tgz", - "integrity": "sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", + "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.17.0", - "@typescript-eslint/utils": "6.17.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/utils": "6.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", - "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0" + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" } }, "@typescript-eslint/types": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", - "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", - "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/visitor-keys": "6.17.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8349,27 +8467,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", - "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", + "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.17.0", - "@typescript-eslint/types": "6.17.0", - "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", - "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/types": "6.18.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -9145,6 +9263,13 @@ } } }, + "eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "requires": {} + }, "eslint-plugin-jest": { "version": "27.6.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", @@ -9154,6 +9279,16 @@ "@typescript-eslint/utils": "^5.10.0" } }, + "eslint-plugin-prettier": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", + "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + } + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -9275,6 +9410,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "fast-glob": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", @@ -10826,6 +10967,21 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -11332,6 +11488,24 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "requires": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, "tar": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", diff --git a/package.json b/package.json index 279199fa28..b3772d906d 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,8 @@ "lint": "npm run lint:node && npm run lint:worker", "lint:node": "node npm-scripts.mjs lint:node", "lint:worker": "node npm-scripts.mjs lint:worker", + "format": "npm run format:node && npm run format:worker", + "format:node": "node npm-scripts.mjs format:node", "format:worker": "node npm-scripts.mjs format:worker", "flatc": "npm run flatc:node && npm run flatc:worker", "flatc:node": "node npm-scripts.mjs flatc:node", @@ -113,11 +115,14 @@ "@typescript-eslint/eslint-plugin": "^6.18.0", "@typescript-eslint/parser": "^6.18.0", "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.6.1", + "eslint-plugin-prettier": "^5.1.2", "jest": "^29.7.0", "marked": "^11.1.1", "open-cli": "^7.2.0", "pick-port": "^1.0.1", + "prettier": "^3.1.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", "typescript": "^5.3.3" diff --git a/worker/scripts/clang-format.mjs b/worker/scripts/clang-format.mjs index 13fbd0aaa9..ce48f07d2f 100644 --- a/worker/scripts/clang-format.mjs +++ b/worker/scripts/clang-format.mjs @@ -6,42 +6,37 @@ const task = process.argv.slice(2).join(' '); run(); -async function run() -{ +async function run() { const clangFormatNativeBinary = clangFormat.getNativeBinary(); - const workerFiles = await glob( - [ - '../src/**/*.cpp', - '../include/**/*.hpp', - '../test/src/**/*.cpp', - '../test/include/helpers.hpp', - '../fuzzer/src/**/*.cpp', - '../fuzzer/include/**/*.hpp' - ] - ); + const workerFiles = await glob([ + '../src/**/*.cpp', + '../include/**/*.hpp', + '../test/src/**/*.cpp', + '../test/include/helpers.hpp', + '../fuzzer/src/**/*.cpp', + '../fuzzer/include/**/*.hpp', + ]); - switch (task) - { - case 'lint': - { + switch (task) { + case 'lint': { executeCmd( - `"${clangFormatNativeBinary}" --Werror --dry-run ${workerFiles.join(' ')}` + `"${clangFormatNativeBinary}" --Werror --dry-run ${workerFiles.join( + ' ', + )}`, ); break; } - case 'format': - { + case 'format': { executeCmd( - `"${clangFormatNativeBinary}" --Werror -i ${workerFiles.join(' ')}` + `"${clangFormatNativeBinary}" --Werror -i ${workerFiles.join(' ')}`, ); break; } - default: - { + default: { logError('unknown task'); exitWithError(); @@ -49,14 +44,10 @@ async function run() } } -function executeCmd(command) -{ - try - { - execSync(command, { stdio: [ 'ignore', process.stdout, process.stderr ] }); - } - catch (error) - { +function executeCmd(command) { + try { + execSync(command, { stdio: ['ignore', process.stdout, process.stderr] }); + } catch (error) { logError('executeCmd() failed'); exitWithError(); @@ -64,26 +55,22 @@ function executeCmd(command) } // eslint-disable-next-line no-unused-vars -function logInfo(message) -{ +function logInfo(message) { // eslint-disable-next-line no-console - console.log(`clang-format.mjs \x1b[36m[INFO] [${task}]\x1b\[0m`, message); + console.log(`clang-format.mjs \x1b[36m[INFO] [${task}]\x1b[0m`, message); } // eslint-disable-next-line no-unused-vars -function logWarn(message) -{ +function logWarn(message) { // eslint-disable-next-line no-console - console.warn(`clang-format.mjs \x1b[33m[WARN] [${task}]\x1b\[0m`, message); + console.warn(`clang-format.mjs \x1b[33m[WARN] [${task}]\x1b[0m`, message); } -function logError(message) -{ +function logError(message) { // eslint-disable-next-line no-console - console.error(`clang-format.mjs \x1b[31m[ERROR] [${task}]\x1b\[0m`, message); + console.error(`clang-format.mjs \x1b[31m[ERROR] [${task}]\x1b[0m`, message); } -function exitWithError() -{ +function exitWithError() { process.exit(1); } From 6a573c26aafe09498b7d41cf1da95b5ddf75dca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 8 Jan 2024 13:04:46 +0100 Subject: [PATCH 305/525] C++: tidy up (#1304) C++: tidy up --- worker/.clang-tidy | 24 +++--- worker/include/Channel/ChannelSocket.hpp | 10 +-- worker/include/Logger.hpp | 36 +++++---- worker/include/MediaSoupErrors.hpp | 10 +-- worker/include/RTC/ActiveSpeakerObserver.hpp | 4 +- worker/include/RTC/Consumer.hpp | 4 +- worker/include/RTC/DataConsumer.hpp | 4 +- worker/include/RTC/DataProducer.hpp | 2 +- worker/include/RTC/DtlsTransport.hpp | 8 +- worker/include/RTC/IceCandidate.hpp | 12 +-- worker/include/RTC/KeyFrameRequestManager.hpp | 6 +- worker/include/RTC/PipeTransport.hpp | 4 +- worker/include/RTC/PlainTransport.hpp | 8 +- worker/include/RTC/Producer.hpp | 2 +- .../include/RTC/RTCP/FeedbackRtpTransport.hpp | 6 +- worker/include/RTC/RateCalculator.hpp | 2 +- worker/include/RTC/Router.hpp | 4 +- worker/include/RTC/RtcLogger.hpp | 12 +-- worker/include/RTC/RtpObserver.hpp | 2 +- worker/include/RTC/RtpPacket.hpp | 29 +++----- .../include/RTC/RtpRetransmissionBuffer.hpp | 6 +- worker/include/RTC/RtpStreamRecv.hpp | 2 +- worker/include/RTC/SctpAssociation.hpp | 4 +- worker/include/RTC/StunPacket.hpp | 8 +- worker/include/RTC/Transport.hpp | 4 +- .../RTC/TransportCongestionControlClient.hpp | 2 +- .../RTC/TransportCongestionControlServer.hpp | 2 +- worker/include/RTC/TransportTuple.hpp | 4 +- worker/include/RTC/TrendCalculator.hpp | 2 +- worker/include/RTC/WebRtcServer.hpp | 8 +- .../include/handles/TcpConnectionHandle.hpp | 9 ++- worker/include/handles/TcpServerHandle.hpp | 8 +- worker/include/handles/UdpSocketHandle.hpp | 9 ++- .../handles/UnixStreamSocketHandle.hpp | 5 +- worker/src/Channel/ChannelSocket.cpp | 20 ++--- worker/src/DepLibSRTP.cpp | 16 ++-- worker/src/DepLibWebRTC.cpp | 4 +- worker/src/DepOpenSSL.cpp | 4 +- worker/src/DepUsrSCTP.cpp | 16 ++-- worker/src/Logger.cpp | 4 +- worker/src/MediaSoupErrors.cpp | 2 +- worker/src/RTC/ActiveSpeakerObserver.cpp | 33 ++++----- worker/src/RTC/Consumer.cpp | 5 +- worker/src/RTC/DataConsumer.cpp | 8 +- worker/src/RTC/DataProducer.cpp | 2 +- worker/src/RTC/DirectTransport.cpp | 6 +- worker/src/RTC/DtlsTransport.cpp | 18 ++--- worker/src/RTC/KeyFrameRequestManager.cpp | 6 +- worker/src/RTC/NackGenerator.cpp | 23 ++---- worker/src/RTC/PortManager.cpp | 12 ++- worker/src/RTC/Producer.cpp | 5 +- worker/src/RTC/RtpPacket.cpp | 14 +--- worker/src/RTC/RtpRetransmissionBuffer.cpp | 74 ++++++++++--------- worker/src/RTC/RtpStreamRecv.cpp | 6 +- worker/src/RTC/SctpAssociation.cpp | 54 +++++++++----- worker/src/RTC/SimulcastConsumer.cpp | 2 +- worker/src/RTC/StunPacket.cpp | 28 +++---- worker/src/RTC/Transport.cpp | 8 +- worker/src/RTC/WebRtcServer.cpp | 58 ++++++++------- worker/src/RTC/WebRtcTransport.cpp | 6 +- worker/src/Settings.cpp | 4 +- worker/src/Utils/File.cpp | 4 +- worker/src/Utils/IP.cpp | 2 +- worker/src/Worker.cpp | 4 +- worker/src/handles/TcpConnectionHandle.cpp | 4 +- worker/src/handles/TcpServerHandle.cpp | 26 ++++--- worker/src/handles/TimerHandle.cpp | 3 +- worker/src/handles/UdpSocketHandle.cpp | 28 +++---- worker/src/handles/UnixStreamSocketHandle.cpp | 29 ++++---- worker/src/lib.cpp | 17 +++-- 70 files changed, 420 insertions(+), 397 deletions(-) diff --git a/worker/.clang-tidy b/worker/.clang-tidy index 2394ea1409..14d3b910c0 100644 --- a/worker/.clang-tidy +++ b/worker/.clang-tidy @@ -3,6 +3,8 @@ Checks: "*,\ -altera*,\ -boost-use-to-string,\ -bugprone-easily-swappable-parameters,\ + -bugprone-lambda-function-name,\ + -bugprone-macro-parentheses,\ -cert-*,\ -clang-analyzer-optin.osx.*,\ -clang-analyzer-osx.*,\ @@ -37,11 +39,15 @@ Checks: "*,\ -hicpp-uppercase-literal-suffix,\ -hicpp-vararg,\ -llvm-include-order,\ + -llvm-header-guard,\ + -llvm-else-after-return,\ -llvmlibc-*,\ -misc-non-private-member-variables-in-classes,\ -modernize-avoid-c-arrays,\ + -modernize-concat-nested-namespaces,\ -modernize-make-unique,\ -modernize-pass-by-value,\ + -modernize-use-nodiscard, \ -modernize-use-trailing-return-type,\ -readability-else-after-return,\ -readability-function-cognitive-complexity,\ @@ -49,22 +55,22 @@ Checks: "*,\ -readability-implicit-bool-cast,\ -readability-implicit-bool-conversion,\ -readability-magic-numbers,\ + -readability-redundant-access-specifiers, \ -readability-uppercase-literal-suffix,\ " HeaderFilterRegex: '' AnalyzeTemporaryDtors: false User: mediasoup - -# Old clang-tidy does not support this option which indicates to take the -# format options from .clang-format when applying fixes. -#FormatStyle: file +FormatStyle: file CheckOptions: - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader value: '' - key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle value: '0' + - key: cppcoreguidelines-macro-usage.AllowedRegexp + value: ^MS_* - key: misc-assert-side-effect.AssertMacros value: assert - key: misc-assert-side-effect.CheckFunctionCalls @@ -98,7 +104,7 @@ CheckOptions: - key: readability-identifier-naming.ClassCase value: CamelCase - key: readability-identifier-naming.ClassConstantCase - value: camelBack + value: CamelCase - key: readability-identifier-naming.ClassConstantPrefix value: '' - key: readability-identifier-naming.ClassConstantSuffix @@ -156,9 +162,9 @@ CheckOptions: - key: readability-identifier-naming.ConstexprVariableSuffix value: '' - key: readability-identifier-naming.EnumCase - value: aNy_Case + value: aNy_CasE - key: readability-identifier-naming.EnumConstantCase - value: aNy_Case + value: aNy_CasE - key: readability-identifier-naming.EnumConstantPrefix value: '' - key: readability-identifier-naming.EnumConstantSuffix @@ -194,7 +200,7 @@ CheckOptions: - key: readability-identifier-naming.IgnoreFailedSplit value: '0' - key: readability-identifier-naming.InlineNamespaceCase - value: aNy_Case + value: aNy_CasE - key: readability-identifier-naming.InlineNamespacePrefix value: '' - key: readability-identifier-naming.InlineNamespaceSuffix @@ -224,7 +230,7 @@ CheckOptions: - key: readability-identifier-naming.MethodSuffix value: '' - key: readability-identifier-naming.NamespaceCase - value: aNy_Case + value: aNy_CasE - key: readability-identifier-naming.NamespacePrefix value: '' - key: readability-identifier-naming.NamespaceSuffix diff --git a/worker/include/Channel/ChannelSocket.hpp b/worker/include/Channel/ChannelSocket.hpp index 188ec03abb..83935b8b81 100644 --- a/worker/include/Channel/ChannelSocket.hpp +++ b/worker/include/Channel/ChannelSocket.hpp @@ -24,7 +24,7 @@ namespace Channel public: ConsumerSocket(int fd, size_t bufferSize, Listener* listener); - ~ConsumerSocket(); + ~ConsumerSocket() override; /* Pure virtual methods inherited from ::UnixStreamSocketHandle. */ public: @@ -75,7 +75,7 @@ namespace Channel class Listener : public RequestHandler, public NotificationHandler { public: - virtual ~Listener() = default; + ~Listener() override = default; public: virtual void OnChannelClosed(Channel::ChannelSocket* channel) = 0; @@ -88,13 +88,13 @@ namespace Channel ChannelReadCtx channelReadCtx, ChannelWriteFn channelWriteFn, ChannelWriteCtx channelWriteCtx); - virtual ~ChannelSocket(); + ~ChannelSocket() override; public: void Close(); void SetListener(Listener* listener); - void Send(const uint8_t* message, uint32_t messageLen); - void SendLog(const char* message, uint32_t messageLen); + void Send(const uint8_t* data, uint32_t dataLen); + void SendLog(const char* data, uint32_t dataLen); bool CallbackRead(); private: diff --git a/worker/include/Logger.hpp b/worker/include/Logger.hpp index e3c22bb71f..b10f600a20 100644 --- a/worker/include/Logger.hpp +++ b/worker/include/Logger.hpp @@ -96,8 +96,10 @@ // clang-format off +// NOLINTBEGIN #define _MS_TAG_ENABLED(tag) Settings::configuration.logTags.tag #define _MS_TAG_ENABLED_2(tag1, tag2) (Settings::configuration.logTags.tag1 || Settings::configuration.logTags.tag2) +// NOLINTEND #if !defined(MS_LOG_DEV_LEVEL) #define MS_LOG_DEV_LEVEL 0 @@ -145,14 +147,15 @@ class Logger static void ClassInit(Channel::ChannelSocket* channel); public: - static const uint64_t pid; + static const uint64_t Pid; thread_local static Channel::ChannelSocket* channel; - static const size_t bufferSize {50000}; + static const size_t BufferSize {50000}; thread_local static char buffer[]; }; /* Logging macros. */ +// NOLINTBEGIN #define _MS_LOG_SEPARATOR_CHAR_STD "\n" #ifdef MS_LOG_FILE_LINE @@ -165,6 +168,7 @@ class Logger #define _MS_LOG_STR_DESC _MS_LOG_STR " | " #define _MS_LOG_ARG MS_CLASS, __FUNCTION__ #endif +// NOLINTEND #ifdef MS_LOG_TRACE #define MS_TRACE() \ @@ -172,7 +176,7 @@ class Logger { \ if (Settings::configuration.logLevel == LogLevel::LOG_DEBUG) \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "D(trace) " _MS_LOG_STR, _MS_LOG_ARG); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "D(trace) " _MS_LOG_STR, _MS_LOG_ARG); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ } \ } \ @@ -204,7 +208,7 @@ class Logger { \ if (Settings::configuration.logLevel == LogLevel::LOG_DEBUG && _MS_TAG_ENABLED(tag)) \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "D" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "D" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ } \ } \ @@ -226,7 +230,7 @@ class Logger { \ if (Settings::configuration.logLevel >= LogLevel::LOG_WARN && _MS_TAG_ENABLED(tag)) \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "W" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "W" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ } \ } \ @@ -248,7 +252,7 @@ class Logger { \ if (Settings::configuration.logLevel == LogLevel::LOG_DEBUG && _MS_TAG_ENABLED_2(tag1, tag2)) \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "D" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "D" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ } \ } \ @@ -270,7 +274,7 @@ class Logger { \ if (Settings::configuration.logLevel >= LogLevel::LOG_WARN && _MS_TAG_ENABLED_2(tag1, tag2)) \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "W" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "W" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ } \ } \ @@ -291,7 +295,7 @@ class Logger #define MS_DEBUG_DEV(desc, ...) \ do \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "D" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "D" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ } \ while (false) @@ -313,7 +317,7 @@ class Logger #define MS_WARN_DEV(desc, ...) \ do \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "W" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "W" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ } \ while (false) @@ -333,7 +337,7 @@ class Logger #define MS_DUMP(desc, ...) \ do \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "X" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "X" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ } \ while (false) @@ -349,7 +353,7 @@ class Logger #define MS_DUMP_DATA(data, len) \ do \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "X(data) " _MS_LOG_STR, _MS_LOG_ARG); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "X(data) " _MS_LOG_STR, _MS_LOG_ARG); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ size_t bufferDataLen{ 0 }; \ for (size_t i{0}; i < len; ++i) \ @@ -361,10 +365,10 @@ class Logger Logger::channel->SendLog(Logger::buffer, static_cast(bufferDataLen)); \ bufferDataLen = 0; \ } \ - const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::bufferSize, "X%06X ", static_cast(i)); \ + const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::BufferSize, "X%06X ", static_cast(i)); \ bufferDataLen += loggerWritten; \ } \ - const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::bufferSize, "%02X ", static_cast(data[i])); \ + const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::BufferSize, "%02X ", static_cast(data[i])); \ bufferDataLen += loggerWritten; \ } \ if (bufferDataLen != 0) \ @@ -389,10 +393,10 @@ class Logger std::fprintf(stdout, "%s", Logger::buffer); \ bufferDataLen = 0; \ } \ - const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::bufferSize, "\n%06X ", static_cast(i)); \ + const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::BufferSize, "\n%06X ", static_cast(i)); \ bufferDataLen += loggerWritten; \ } \ - const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::bufferSize, "%02X ", static_cast(data[i])); \ + const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::BufferSize, "%02X ", static_cast(data[i])); \ bufferDataLen += loggerWritten; \ } \ if (bufferDataLen != 0) \ @@ -409,7 +413,7 @@ class Logger { \ if (Settings::configuration.logLevel >= LogLevel::LOG_ERROR || MS_LOG_DEV_LEVEL >= 1) \ { \ - const int loggerWritten = std::snprintf(Logger::buffer, Logger::bufferSize, "E" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ + const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "E" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \ Logger::channel->SendLog(Logger::buffer, static_cast(loggerWritten)); \ } \ } \ diff --git a/worker/include/MediaSoupErrors.hpp b/worker/include/MediaSoupErrors.hpp index 22697992cf..90d3b07ec8 100644 --- a/worker/include/MediaSoupErrors.hpp +++ b/worker/include/MediaSoupErrors.hpp @@ -13,7 +13,7 @@ class MediaSoupError : public std::runtime_error } public: - static const size_t bufferSize{ 2000 }; + static const size_t BufferSize{ 2000 }; thread_local static char buffer[]; }; @@ -30,7 +30,7 @@ class MediaSoupTypeError : public MediaSoupError do \ { \ MS_ERROR("throwing MediaSoupError: " desc, ##__VA_ARGS__); \ - std::snprintf(MediaSoupError::buffer, MediaSoupError::bufferSize, desc, ##__VA_ARGS__); \ + std::snprintf(MediaSoupError::buffer, MediaSoupError::BufferSize, desc, ##__VA_ARGS__); \ throw MediaSoupError(MediaSoupError::buffer); \ } while (false) @@ -38,7 +38,7 @@ class MediaSoupTypeError : public MediaSoupError do \ { \ MS_ERROR_STD("throwing MediaSoupError: " desc, ##__VA_ARGS__); \ - std::snprintf(MediaSoupError::buffer, MediaSoupError::bufferSize, desc, ##__VA_ARGS__); \ + std::snprintf(MediaSoupError::buffer, MediaSoupError::BufferSize, desc, ##__VA_ARGS__); \ throw MediaSoupError(MediaSoupError::buffer); \ } while (false) @@ -46,7 +46,7 @@ class MediaSoupTypeError : public MediaSoupError do \ { \ MS_ERROR("throwing MediaSoupTypeError: " desc, ##__VA_ARGS__); \ - std::snprintf(MediaSoupError::buffer, MediaSoupError::bufferSize, desc, ##__VA_ARGS__); \ + std::snprintf(MediaSoupError::buffer, MediaSoupError::BufferSize, desc, ##__VA_ARGS__); \ throw MediaSoupTypeError(MediaSoupError::buffer); \ } while (false) @@ -54,7 +54,7 @@ class MediaSoupTypeError : public MediaSoupError do \ { \ MS_ERROR_STD("throwing MediaSoupTypeError: " desc, ##__VA_ARGS__); \ - std::snprintf(MediaSoupError::buffer, MediaSoupError::bufferSize, desc, ##__VA_ARGS__); \ + std::snprintf(MediaSoupError::buffer, MediaSoupError::BufferSize, desc, ##__VA_ARGS__); \ throw MediaSoupTypeError(MediaSoupError::buffer); \ } while (false) // clang-format on diff --git a/worker/include/RTC/ActiveSpeakerObserver.hpp b/worker/include/RTC/ActiveSpeakerObserver.hpp index 556e6c0e02..293aa3d8d8 100644 --- a/worker/include/RTC/ActiveSpeakerObserver.hpp +++ b/worker/include/RTC/ActiveSpeakerObserver.hpp @@ -23,7 +23,7 @@ namespace RTC public: Speaker(); void EvalActivityScores(); - double GetActivityScore(uint8_t interval); + double GetActivityScore(uint8_t interval) const; void LevelChanged(uint32_t level, uint64_t now); void LevelTimedOut(uint64_t now); @@ -95,7 +95,7 @@ namespace RTC void OnTimer(TimerHandle* timer) override; private: - double relativeSpeachActivities[RelativeSpeachActivitiesLen]; + double relativeSpeachActivities[RelativeSpeachActivitiesLen]{}; std::string dominantId; TimerHandle* periodicTimer{ nullptr }; uint16_t interval{ 300u }; diff --git a/worker/include/RTC/Consumer.hpp b/worker/include/RTC/Consumer.hpp index 8d3a25c95e..28b4239b62 100644 --- a/worker/include/RTC/Consumer.hpp +++ b/worker/include/RTC/Consumer.hpp @@ -66,7 +66,7 @@ namespace RTC RTC::Consumer::Listener* listener, const FBS::Transport::ConsumeRequest* data, RTC::RtpParameters::Type type); - virtual ~Consumer(); + ~Consumer() override; public: flatbuffers::Offset FillBuffer( @@ -74,7 +74,7 @@ namespace RTC virtual flatbuffers::Offset FillBufferStats( flatbuffers::FlatBufferBuilder& builder) = 0; virtual flatbuffers::Offset FillBufferScore( - flatbuffers::FlatBufferBuilder& builder) const + flatbuffers::FlatBufferBuilder& /*builder*/) const { return 0; }; diff --git a/worker/include/RTC/DataConsumer.hpp b/worker/include/RTC/DataConsumer.hpp index f732726c83..994b616ed7 100644 --- a/worker/include/RTC/DataConsumer.hpp +++ b/worker/include/RTC/DataConsumer.hpp @@ -52,7 +52,7 @@ namespace RTC RTC::DataConsumer::Listener* listener, const FBS::Transport::ConsumeDataRequest* data, size_t maxMessageSize); - virtual ~DataConsumer(); + ~DataConsumer() override; public: flatbuffers::Offset FillBuffer( @@ -104,7 +104,7 @@ namespace RTC uint32_t ppid, std::vector& subchannels, std::optional requiredSubchannel, - onQueuedCallback* = nullptr); + onQueuedCallback* cb = nullptr); /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: diff --git a/worker/include/RTC/DataProducer.hpp b/worker/include/RTC/DataProducer.hpp index 474ebb8214..6c0a8d3988 100644 --- a/worker/include/RTC/DataProducer.hpp +++ b/worker/include/RTC/DataProducer.hpp @@ -48,7 +48,7 @@ namespace RTC size_t maxMessageSize, RTC::DataProducer::Listener* listener, const FBS::Transport::ProduceDataRequest* data); - virtual ~DataProducer(); + ~DataProducer() override; public: flatbuffers::Offset FillBuffer( diff --git a/worker/include/RTC/DtlsTransport.hpp b/worker/include/RTC/DtlsTransport.hpp index bb635ea42f..27f4bd847f 100644 --- a/worker/include/RTC/DtlsTransport.hpp +++ b/worker/include/RTC/DtlsTransport.hpp @@ -112,6 +112,10 @@ namespace RTC ); // clang-format on } + static std::vector& GetLocalFingerprints() + { + return DtlsTransport::localFingerprints; + } private: static void GenerateCertificateAndPrivateKey(); @@ -137,10 +141,6 @@ namespace RTC public: void Dump() const; void Run(Role localRole); - std::vector& GetLocalFingerprints() const - { - return DtlsTransport::localFingerprints; - } bool SetRemoteFingerprint(const Fingerprint& fingerprint); void ProcessDtlsData(const uint8_t* data, size_t len); DtlsState GetState() const diff --git a/worker/include/RTC/IceCandidate.hpp b/worker/include/RTC/IceCandidate.hpp index 3993b9bef1..d2349706e0 100644 --- a/worker/include/RTC/IceCandidate.hpp +++ b/worker/include/RTC/IceCandidate.hpp @@ -36,27 +36,27 @@ namespace RTC public: IceCandidate(RTC::UdpSocket* udpSocket, uint32_t priority) : foundation("udpcandidate"), priority(priority), ip(udpSocket->GetLocalIp()), - protocol(Protocol::UDP), port(udpSocket->GetLocalPort()), type(CandidateType::HOST) + protocol(Protocol::UDP), port(udpSocket->GetLocalPort()) { } IceCandidate(RTC::UdpSocket* udpSocket, uint32_t priority, std::string& announcedIp) : foundation("udpcandidate"), priority(priority), ip(announcedIp), protocol(Protocol::UDP), - port(udpSocket->GetLocalPort()), type(CandidateType::HOST) + port(udpSocket->GetLocalPort()) { } IceCandidate(RTC::TcpServer* tcpServer, uint32_t priority) : foundation("tcpcandidate"), priority(priority), ip(tcpServer->GetLocalIp()), - protocol(Protocol::TCP), port(tcpServer->GetLocalPort()), type(CandidateType::HOST), - tcpType(TcpCandidateType::PASSIVE) + protocol(Protocol::TCP), port(tcpServer->GetLocalPort()) + { } IceCandidate(RTC::TcpServer* tcpServer, uint32_t priority, std::string& announcedIp) : foundation("tcpcandidate"), priority(priority), ip(announcedIp), protocol(Protocol::TCP), - port(tcpServer->GetLocalPort()), type(CandidateType::HOST), - tcpType(TcpCandidateType::PASSIVE) + port(tcpServer->GetLocalPort()) + { } diff --git a/worker/include/RTC/KeyFrameRequestManager.hpp b/worker/include/RTC/KeyFrameRequestManager.hpp index e56482c2a6..76aaa6716c 100644 --- a/worker/include/RTC/KeyFrameRequestManager.hpp +++ b/worker/include/RTC/KeyFrameRequestManager.hpp @@ -20,7 +20,7 @@ namespace RTC public: PendingKeyFrameInfo(Listener* listener, uint32_t ssrc); - ~PendingKeyFrameInfo(); + ~PendingKeyFrameInfo() override; uint32_t GetSsrc() const { @@ -64,7 +64,7 @@ namespace RTC public: KeyFrameRequestDelayer(Listener* listener, uint32_t ssrc, uint32_t delay); - ~KeyFrameRequestDelayer(); + ~KeyFrameRequestDelayer() override; uint32_t GetSsrc() const { @@ -105,7 +105,7 @@ namespace RTC public: explicit KeyFrameRequestManager(Listener* listener, uint32_t keyFrameRequestDelay); - virtual ~KeyFrameRequestManager(); + ~KeyFrameRequestManager() override; void KeyFrameNeeded(uint32_t ssrc); void ForceKeyFrameNeeded(uint32_t ssrc); diff --git a/worker/include/RTC/PipeTransport.hpp b/worker/include/RTC/PipeTransport.hpp index 1c08492a42..3a5a38fd93 100644 --- a/worker/include/RTC/PipeTransport.hpp +++ b/worker/include/RTC/PipeTransport.hpp @@ -75,7 +75,9 @@ namespace RTC RTC::SrtpSession* srtpSendSession{ nullptr }; // Others. ListenInfo listenInfo; - struct sockaddr_storage remoteAddrStorage; + struct sockaddr_storage remoteAddrStorage + { + }; bool rtx{ false }; std::string srtpKey; std::string srtpKeyBase64; diff --git a/worker/include/RTC/PlainTransport.hpp b/worker/include/RTC/PlainTransport.hpp index ad9783618f..2c7b5c20d3 100644 --- a/worker/include/RTC/PlainTransport.hpp +++ b/worker/include/RTC/PlainTransport.hpp @@ -76,8 +76,12 @@ namespace RTC ListenInfo rtcpListenInfo; bool rtcpMux{ true }; bool comedia{ false }; - struct sockaddr_storage remoteAddrStorage; - struct sockaddr_storage rtcpRemoteAddrStorage; + struct sockaddr_storage remoteAddrStorage + { + }; + struct sockaddr_storage rtcpRemoteAddrStorage + { + }; RTC::SrtpSession::CryptoSuite srtpCryptoSuite{ RTC::SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_80 }; diff --git a/worker/include/RTC/Producer.hpp b/worker/include/RTC/Producer.hpp index a7c3e14fae..d7562587c3 100644 --- a/worker/include/RTC/Producer.hpp +++ b/worker/include/RTC/Producer.hpp @@ -98,7 +98,7 @@ namespace RTC const std::string& id, RTC::Producer::Listener* listener, const FBS::Transport::ProduceRequest* data); - virtual ~Producer(); + ~Producer() override; public: flatbuffers::Offset FillBuffer( diff --git a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp index 6c4398664d..cfbbf0c276 100644 --- a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp +++ b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp @@ -209,13 +209,13 @@ namespace RTC { } FeedbackRtpTransportPacket(CommonHeader* commonHeader, size_t availableLen); - ~FeedbackRtpTransportPacket(); + ~FeedbackRtpTransportPacket() override; public: AddPacketResult AddPacket(uint16_t sequenceNumber, uint64_t timestamp, size_t maxRtcpPacketLen); // Just for locally generated packets. void Finish(); - bool IsFull() + bool IsFull() const { // NOTE: Since AddPendingChunks() is called at the end, we cannot track // the exact ongoing value of packetStatusCount. Hence, let's reserve 7 @@ -224,7 +224,7 @@ namespace RTC } bool IsSerializable() const { - return this->deltas.size() > 0; + return !this->deltas.empty(); } bool IsCorrect() const // Just for locally generated packets. { diff --git a/worker/include/RTC/RateCalculator.hpp b/worker/include/RTC/RateCalculator.hpp index d4e974e740..871d4e5977 100644 --- a/worker/include/RTC/RateCalculator.hpp +++ b/worker/include/RTC/RateCalculator.hpp @@ -17,7 +17,7 @@ namespace RTC static constexpr uint16_t DefaultWindowItems{ 100u }; public: - RateCalculator( + explicit RateCalculator( size_t windowSizeMs = DefaultWindowSize, float scale = DefaultBpsScale, uint16_t windowItems = DefaultWindowItems) diff --git a/worker/include/RTC/Router.hpp b/worker/include/RTC/Router.hpp index 46b96f7d65..cd9ab24687 100644 --- a/worker/include/RTC/Router.hpp +++ b/worker/include/RTC/Router.hpp @@ -38,7 +38,7 @@ namespace RTC public: explicit Router(RTC::Shared* shared, const std::string& id, Listener* listener); - virtual ~Router(); + ~Router() override; public: flatbuffers::Offset FillBuffer( @@ -111,7 +111,7 @@ namespace RTC /* Pure virtual methods inherited from RTC::RtpObserver::Listener. */ public: - RTC::Producer* RtpObserverGetProducer(RTC::RtpObserver*, const std::string& id) override; + RTC::Producer* RtpObserverGetProducer(RTC::RtpObserver* rtpObserver, const std::string& id) override; void OnRtpObserverAddProducer(RTC::RtpObserver* rtpObserver, RTC::Producer* producer) override; void OnRtpObserverRemoveProducer(RTC::RtpObserver* rtpObserver, RTC::Producer* producer) override; diff --git a/worker/include/RTC/RtcLogger.hpp b/worker/include/RTC/RtcLogger.hpp index 76c1364870..a241d407c2 100644 --- a/worker/include/RTC/RtcLogger.hpp +++ b/worker/include/RTC/RtcLogger.hpp @@ -40,17 +40,17 @@ namespace RTC void Clear(); public: - uint64_t timestamp; + uint64_t timestamp{}; std::string recvTransportId{}; std::string sendTransportId{}; std::string routerId{}; std::string producerId{}; std::string consumerId{}; - uint32_t recvRtpTimestamp; - uint32_t sendRtpTimestamp; - uint16_t recvSeqNumber; - uint16_t sendSeqNumber; - bool dropped; + uint32_t recvRtpTimestamp{}; + uint32_t sendRtpTimestamp{}; + uint16_t recvSeqNumber{}; + uint16_t sendSeqNumber{}; + bool dropped{}; DropReason dropReason{ DropReason::NONE }; }; }; // namespace RtcLogger diff --git a/worker/include/RTC/RtpObserver.hpp b/worker/include/RTC/RtpObserver.hpp index c17efdc5ad..eee22f8cf7 100644 --- a/worker/include/RTC/RtpObserver.hpp +++ b/worker/include/RTC/RtpObserver.hpp @@ -27,7 +27,7 @@ namespace RTC public: RtpObserver(RTC::Shared* shared, const std::string& id, RTC::RtpObserver::Listener* listener); - virtual ~RtpObserver(); + ~RtpObserver() override; public: void Pause(); diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index 81be74fe4f..2058058365 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -217,7 +217,7 @@ namespace RTC bool HasHeaderExtension() const { - return (this->headerExtension ? true : false); + return (this->headerExtension != nullptr); } // After calling this method, all the extension ids are reset to 0. @@ -366,7 +366,7 @@ namespace RTC return true; } - bool UpdateAbsSendTime(uint64_t ms) + bool UpdateAbsSendTime(uint64_t ms) const { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->absSendTimeExtensionId, extenLen); @@ -398,7 +398,7 @@ namespace RTC return true; } - bool UpdateTransportWideCc01(uint16_t wideSeqNumber) + bool UpdateTransportWideCc01(uint16_t wideSeqNumber) const { uint8_t extenLen; uint8_t* extenValue = GetExtension(this->transportWideCc01ExtensionId, extenLen); @@ -446,7 +446,7 @@ namespace RTC } volume = Utils::Byte::Get1Byte(extenValue, 0); - voice = (volume & (1 << 7)) ? true : false; + voice = (volume & (1 << 7)) != 0; volume &= ~(1 << 7); return true; @@ -462,13 +462,13 @@ namespace RTC return false; } - uint8_t cvoByte = Utils::Byte::Get1Byte(extenValue, 0); - uint8_t cameraValue = ((cvoByte & 0b00001000) >> 3); - uint8_t flipValue = ((cvoByte & 0b00000100) >> 2); - uint8_t rotationValue = (cvoByte & 0b00000011); + const uint8_t cvoByte = Utils::Byte::Get1Byte(extenValue, 0); + const uint8_t cameraValue = ((cvoByte & 0b00001000) >> 3); + const uint8_t flipValue = ((cvoByte & 0b00000100) >> 2); + const uint8_t rotationValue = (cvoByte & 0b00000011); - camera = cameraValue ? true : false; - flip = flipValue ? true : false; + camera = cameraValue != 0; + flip = flipValue != 0; // Using counter clockwise values. switch (rotationValue) @@ -517,12 +517,7 @@ namespace RTC auto* extension = it->second; // In Two-Byte extensions value length may be zero. If so, return false. - if (extension->len == 0u) - { - return false; - } - - return true; + return extension->len != 0u; } else { @@ -666,7 +661,7 @@ namespace RTC HeaderExtension* headerExtension{ nullptr }; // There might be up to 14 one-byte header extensions // (https://datatracker.ietf.org/doc/html/rfc5285#section-4.2), use std::array. - std::array oneByteExtensions; + std::array oneByteExtensions{}; absl::flat_hash_map mapTwoBytesExtensions; uint8_t midExtensionId{ 0u }; uint8_t ridExtensionId{ 0u }; diff --git a/worker/include/RTC/RtpRetransmissionBuffer.hpp b/worker/include/RTC/RtpRetransmissionBuffer.hpp index dee6894876..47229d7efe 100644 --- a/worker/include/RTC/RtpRetransmissionBuffer.hpp +++ b/worker/include/RTC/RtpRetransmissionBuffer.hpp @@ -32,6 +32,10 @@ namespace RTC uint8_t sentTimes{ 0u }; }; + private: + static Item* FillItem( + Item* item, RTC::RtpPacket* packet, std::shared_ptr& sharedPacket); + public: RtpRetransmissionBuffer(uint16_t maxItems, uint32_t maxRetransmissionDelayMs, uint32_t clockRate); ~RtpRetransmissionBuffer(); @@ -48,8 +52,6 @@ namespace RTC void RemoveOldest(uint16_t numItems); bool ClearTooOldByTimestamp(uint32_t newestTimestamp); bool IsTooOldTimestamp(uint32_t timestamp, uint32_t newestTimestamp) const; - Item* FillItem( - Item* item, RTC::RtpPacket* packet, std::shared_ptr& sharedPacket) const; protected: // Make buffer protected for testing purposes. diff --git a/worker/include/RTC/RtpStreamRecv.hpp b/worker/include/RTC/RtpStreamRecv.hpp index 19b25fa8df..932f52cbae 100644 --- a/worker/include/RTC/RtpStreamRecv.hpp +++ b/worker/include/RTC/RtpStreamRecv.hpp @@ -47,7 +47,7 @@ namespace RTC RTC::RtpStream::Params& params, unsigned int sendNackDelayMs, bool useRtpInactivityCheck); - ~RtpStreamRecv(); + ~RtpStreamRecv() override; flatbuffers::Offset FillBufferStats( flatbuffers::FlatBufferBuilder& builder) override; diff --git a/worker/include/RTC/SctpAssociation.hpp b/worker/include/RTC/SctpAssociation.hpp index 146aca32bd..e2f3fe7922 100644 --- a/worker/include/RTC/SctpAssociation.hpp +++ b/worker/include/RTC/SctpAssociation.hpp @@ -89,7 +89,7 @@ namespace RTC { return this->sctpBufferedAmount; } - void ProcessSctpData(const uint8_t* data, size_t len); + void ProcessSctpData(const uint8_t* data, size_t len) const; void SendSctpMessage( RTC::DataConsumer* dataConsumer, const uint8_t* msg, @@ -101,7 +101,7 @@ namespace RTC void DataConsumerClosed(RTC::DataConsumer* dataConsumer); private: - void ResetSctpStream(uint16_t streamId, StreamDirection); + void ResetSctpStream(uint16_t streamId, StreamDirection direction); void AddOutgoingStreams(bool force = false); /* Callbacks fired by usrsctp events. */ diff --git a/worker/include/RTC/StunPacket.hpp b/worker/include/RTC/StunPacket.hpp index 98e1f527eb..ab4846e237 100644 --- a/worker/include/RTC/StunPacket.hpp +++ b/worker/include/RTC/StunPacket.hpp @@ -63,15 +63,15 @@ namespace RTC // DOC: https://tools.ietf.org/html/draft-ietf-avtcore-rfc5764-mux-fixes (data[0] < 3) && // Magic cookie must match. - (data[4] == StunPacket::magicCookie[0]) && (data[5] == StunPacket::magicCookie[1]) && - (data[6] == StunPacket::magicCookie[2]) && (data[7] == StunPacket::magicCookie[3]) + (data[4] == StunPacket::MagicCookie[0]) && (data[5] == StunPacket::MagicCookie[1]) && + (data[6] == StunPacket::MagicCookie[2]) && (data[7] == StunPacket::MagicCookie[3]) ); // clang-format on } static StunPacket* Parse(const uint8_t* data, size_t len); private: - static const uint8_t magicCookie[]; + static const uint8_t MagicCookie[]; public: StunPacket( @@ -173,7 +173,7 @@ namespace RTC } bool HasMessageIntegrity() const { - return (this->messageIntegrity ? true : false); + return (this->messageIntegrity != nullptr); } bool HasFingerprint() const { diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index 95814a4920..8d0eed1615 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -148,7 +148,7 @@ namespace RTC const std::string& id, RTC::Transport::Listener* listener, const FBS::Transport::Options* options); - virtual ~Transport(); + ~Transport() override; public: void CloseProducersAndConsumers(); @@ -271,7 +271,7 @@ namespace RTC const uint8_t* msg, size_t len, uint32_t ppid, - onQueuedCallback* = nullptr) override; + onQueuedCallback* cb = nullptr) override; void OnDataConsumerDataProducerClosed(RTC::DataConsumer* dataConsumer) override; /* Pure virtual methods inherited from RTC::SctpAssociation::Listener. */ diff --git a/worker/include/RTC/TransportCongestionControlClient.hpp b/worker/include/RTC/TransportCongestionControlClient.hpp index 4bd3796284..50df900b58 100644 --- a/worker/include/RTC/TransportCongestionControlClient.hpp +++ b/worker/include/RTC/TransportCongestionControlClient.hpp @@ -58,7 +58,7 @@ namespace RTC uint32_t initialAvailableBitrate, uint32_t maxOutgoingBitrate, uint32_t minOutgoingBitrate); - virtual ~TransportCongestionControlClient(); + ~TransportCongestionControlClient() override; public: RTC::BweType GetBweType() const diff --git a/worker/include/RTC/TransportCongestionControlServer.hpp b/worker/include/RTC/TransportCongestionControlServer.hpp index ae1e307707..d25483c90e 100644 --- a/worker/include/RTC/TransportCongestionControlServer.hpp +++ b/worker/include/RTC/TransportCongestionControlServer.hpp @@ -31,7 +31,7 @@ namespace RTC RTC::TransportCongestionControlServer::Listener* listener, RTC::BweType bweType, size_t maxRtcpPacketLen); - virtual ~TransportCongestionControlServer(); + ~TransportCongestionControlServer() override; public: RTC::BweType GetBweType() const diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index d282de036b..d23545051a 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -245,7 +245,9 @@ namespace RTC RTC::TcpConnection* tcpConnection{ nullptr }; std::string localAnnouncedIp; // Others. - struct sockaddr_storage udpRemoteAddrStorage; + struct sockaddr_storage udpRemoteAddrStorage + { + }; Protocol protocol; }; } // namespace RTC diff --git a/worker/include/RTC/TrendCalculator.hpp b/worker/include/RTC/TrendCalculator.hpp index 1e082a862a..a9150d8724 100644 --- a/worker/include/RTC/TrendCalculator.hpp +++ b/worker/include/RTC/TrendCalculator.hpp @@ -11,7 +11,7 @@ namespace RTC static constexpr float DecreaseFactor{ 0.05f }; // per second. public: - TrendCalculator(float decreaseFactor = DecreaseFactor); + explicit TrendCalculator(float decreaseFactor = DecreaseFactor); public: uint32_t GetValue() const diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index 49803dd6ec..ea8fe12e71 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -38,17 +38,20 @@ namespace RTC std::string announcedIp; }; + private: + static std::string GetLocalIceUsernameFragmentFromReceivedStunPacket(RTC::StunPacket* packet); + public: WebRtcServer( RTC::Shared* shared, const std::string& id, const flatbuffers::Vector>* listenInfos); - ~WebRtcServer(); + ~WebRtcServer() override; public: flatbuffers::Offset FillBuffer( flatbuffers::FlatBufferBuilder& builder) const; - const std::vector GetIceCandidates( + std::vector GetIceCandidates( bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ @@ -56,7 +59,6 @@ namespace RTC void HandleRequest(Channel::ChannelRequest* request) override; private: - std::string GetLocalIceUsernameFragmentFromReceivedStunPacket(RTC::StunPacket* packet) const; void OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnNonStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); diff --git a/worker/include/handles/TcpConnectionHandle.hpp b/worker/include/handles/TcpConnectionHandle.hpp index 4fff59319a..073602d305 100644 --- a/worker/include/handles/TcpConnectionHandle.hpp +++ b/worker/include/handles/TcpConnectionHandle.hpp @@ -24,9 +24,8 @@ class TcpConnectionHandle /* Struct for the data field of uv_req_t when writing into the connection. */ struct UvWriteData { - explicit UvWriteData(size_t storeSize) + explicit UvWriteData(size_t storeSize) : store(new uint8_t[storeSize]) { - this->store = new uint8_t[storeSize]; } // Disable copy constructor because of the dynamically allocated data (store). @@ -38,7 +37,7 @@ class TcpConnectionHandle delete this->cb; } - uv_write_t req; + uv_write_t req{}; uint8_t* store{ nullptr }; TcpConnectionHandle::onSendCallback* cb{ nullptr }; }; @@ -132,7 +131,9 @@ class TcpConnectionHandle size_t bufferDataLen{ 0u }; std::string localIp; uint16_t localPort{ 0u }; - struct sockaddr_storage peerAddr; + struct sockaddr_storage peerAddr + { + }; std::string peerIp; uint16_t peerPort{ 0u }; diff --git a/worker/include/handles/TcpServerHandle.hpp b/worker/include/handles/TcpServerHandle.hpp index 3d7608d88d..6d0fa9d1f9 100644 --- a/worker/include/handles/TcpServerHandle.hpp +++ b/worker/include/handles/TcpServerHandle.hpp @@ -13,8 +13,8 @@ class TcpServerHandle : public TcpConnectionHandle::Listener /** * uvHandle must be an already initialized and binded uv_tcp_t pointer. */ - TcpServerHandle(uv_tcp_t* uvHandle); - virtual ~TcpServerHandle() override; + explicit TcpServerHandle(uv_tcp_t* uvHandle); + ~TcpServerHandle() override; public: void Close(); @@ -64,7 +64,9 @@ class TcpServerHandle : public TcpConnectionHandle::Listener void OnTcpConnectionClosed(TcpConnectionHandle* connection) override; protected: - struct sockaddr_storage localAddr; + struct sockaddr_storage localAddr + { + }; std::string localIp; uint16_t localPort{ 0u }; diff --git a/worker/include/handles/UdpSocketHandle.hpp b/worker/include/handles/UdpSocketHandle.hpp index 37ed5fd5dc..2b7a708105 100644 --- a/worker/include/handles/UdpSocketHandle.hpp +++ b/worker/include/handles/UdpSocketHandle.hpp @@ -14,9 +14,8 @@ class UdpSocketHandle /* Struct for the data field of uv_req_t when sending a datagram. */ struct UvSendData { - explicit UvSendData(size_t storeSize) + explicit UvSendData(size_t storeSize) : store(new uint8_t[storeSize]) { - this->store = new uint8_t[storeSize]; } // Disable copy constructor because of the dynamically allocated data (store). @@ -28,7 +27,7 @@ class UdpSocketHandle delete this->cb; } - uv_udp_send_t req; + uv_udp_send_t req{}; uint8_t* store{ nullptr }; UdpSocketHandle::onSendCallback* cb{ nullptr }; }; @@ -95,7 +94,9 @@ class UdpSocketHandle const uint8_t* data, size_t len, const struct sockaddr* addr) = 0; protected: - struct sockaddr_storage localAddr; + struct sockaddr_storage localAddr + { + }; std::string localIp; uint16_t localPort{ 0u }; diff --git a/worker/include/handles/UnixStreamSocketHandle.hpp b/worker/include/handles/UnixStreamSocketHandle.hpp index 164ab02ec6..e7dc9be5e4 100644 --- a/worker/include/handles/UnixStreamSocketHandle.hpp +++ b/worker/include/handles/UnixStreamSocketHandle.hpp @@ -11,9 +11,8 @@ class UnixStreamSocketHandle /* Struct for the data field of uv_req_t when writing data. */ struct UvWriteData { - explicit UvWriteData(size_t storeSize) + explicit UvWriteData(size_t storeSize) : store(new uint8_t[storeSize]) { - this->store = new uint8_t[storeSize]; } // Disable copy constructor because of the dynamically allocated data (store). @@ -24,7 +23,7 @@ class UnixStreamSocketHandle delete[] this->store; } - uv_write_t req; + uv_write_t req{}; uint8_t* store{ nullptr }; }; diff --git a/worker/src/Channel/ChannelSocket.cpp b/worker/src/Channel/ChannelSocket.cpp index d9310692f8..556072df7b 100644 --- a/worker/src/Channel/ChannelSocket.cpp +++ b/worker/src/Channel/ChannelSocket.cpp @@ -43,13 +43,12 @@ namespace Channel ChannelWriteFn channelWriteFn, ChannelWriteCtx channelWriteCtx) : channelReadFn(channelReadFn), channelReadCtx(channelReadCtx), channelWriteFn(channelWriteFn), - channelWriteCtx(channelWriteCtx) + channelWriteCtx(channelWriteCtx), uvReadHandle(new uv_async_t) { MS_TRACE_STD(); int err; - this->uvReadHandle = new uv_async_t; this->uvReadHandle->data = static_cast(this); err = @@ -122,7 +121,7 @@ namespace Channel this->listener = listener; } - void ChannelSocket::Send(const uint8_t* message, uint32_t messageLen) + void ChannelSocket::Send(const uint8_t* data, uint32_t dataLen) { MS_TRACE_STD(); @@ -131,17 +130,17 @@ namespace Channel return; } - if (messageLen > PayloadMaxLen) + if (dataLen > PayloadMaxLen) { MS_ERROR_STD("message too big"); return; } - SendImpl(reinterpret_cast(message), messageLen); + SendImpl(reinterpret_cast(data), dataLen); } - void ChannelSocket::SendLog(const char* msg, uint32_t messageLen) + void ChannelSocket::SendLog(const char* data, uint32_t dataLen) { MS_TRACE_STD(); @@ -150,14 +149,14 @@ namespace Channel return; } - if (messageLen > PayloadMaxLen) + if (dataLen > PayloadMaxLen) { MS_ERROR_STD("message too big"); return; } - auto log = FBS::Log::CreateLogDirect(this->bufferBuilder, msg); + auto log = FBS::Log::CreateLogDirect(this->bufferBuilder, data); auto message = FBS::Message::CreateMessage(this->bufferBuilder, FBS::Message::Body::Log, log.Union()); @@ -263,7 +262,8 @@ namespace Channel } } - void ChannelSocket::OnConsumerSocketMessage(ConsumerSocket* /*consumerSocket*/, char* msg, size_t msgLen) + void ChannelSocket::OnConsumerSocketMessage( + ConsumerSocket* /*consumerSocket*/, char* msg, size_t /*msgLen*/) { MS_TRACE(); @@ -356,7 +356,7 @@ namespace Channel return; } - size_t readLen = this->bufferDataLen - msgStart; + const size_t readLen = this->bufferDataLen - msgStart; if (readLen < sizeof(uint32_t)) { diff --git a/worker/src/DepLibSRTP.cpp b/worker/src/DepLibSRTP.cpp index e3c8c4be3f..bb9fdde4d6 100644 --- a/worker/src/DepLibSRTP.cpp +++ b/worker/src/DepLibSRTP.cpp @@ -8,8 +8,8 @@ /* Static variables. */ -static std::mutex globalSyncMutex; -static size_t globalInstances = 0; +static std::mutex GlobalSyncMutex; +static size_t GlobalInstances = 0; // clang-format off std::vector DepLibSRTP::errors = @@ -50,9 +50,9 @@ void DepLibSRTP::ClassInit() MS_TRACE(); { - std::lock_guard lock(globalSyncMutex); + const std::lock_guard lock(GlobalSyncMutex); - if (globalInstances == 0) + if (GlobalInstances == 0) { MS_DEBUG_TAG(info, "libsrtp version: \"%s\"", srtp_get_version_string()); @@ -64,7 +64,7 @@ void DepLibSRTP::ClassInit() } } - ++globalInstances; + ++GlobalInstances; } } @@ -73,10 +73,10 @@ void DepLibSRTP::ClassDestroy() MS_TRACE(); { - std::lock_guard lock(globalSyncMutex); - --globalInstances; + const std::lock_guard lock(GlobalSyncMutex); + --GlobalInstances; - if (globalInstances == 0) + if (GlobalInstances == 0) { srtp_shutdown(); } diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index c5edfa2999..dda51cc403 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -9,7 +9,7 @@ /* Static. */ -static std::once_flag globalInitOnce; +static std::once_flag GlobalInitOnce; /* Static methods. */ @@ -21,7 +21,7 @@ void DepLibWebRTC::ClassInit() info, "libwebrtc field trials: \"%s\"", Settings::configuration.libwebrtcFieldTrials.c_str()); std::call_once( - globalInitOnce, + GlobalInitOnce, [] { webrtc::field_trial::InitFieldTrialsFromString( diff --git a/worker/src/DepOpenSSL.cpp b/worker/src/DepOpenSSL.cpp index f38be5fe67..1f75d46d6c 100644 --- a/worker/src/DepOpenSSL.cpp +++ b/worker/src/DepOpenSSL.cpp @@ -9,7 +9,7 @@ /* Static. */ -static std::once_flag globalInitOnce; +static std::once_flag GlobalInitOnce; /* Static methods. */ @@ -18,7 +18,7 @@ void DepOpenSSL::ClassInit() MS_TRACE(); std::call_once( - globalInitOnce, + GlobalInitOnce, [] { MS_DEBUG_TAG(info, "openssl version: \"%s\"", OpenSSL_version(OPENSSL_VERSION)); diff --git a/worker/src/DepUsrSCTP.cpp b/worker/src/DepUsrSCTP.cpp index 4eb0e40713..700bac3348 100644 --- a/worker/src/DepUsrSCTP.cpp +++ b/worker/src/DepUsrSCTP.cpp @@ -69,7 +69,7 @@ void DepUsrSCTP::ClassInit() MS_DEBUG_TAG(info, "usrsctp"); - std::lock_guard lock(GlobalSyncMutex); + const std::lock_guard lock(GlobalSyncMutex); if (GlobalInstances == 0) { @@ -90,7 +90,7 @@ void DepUsrSCTP::ClassDestroy() { MS_TRACE(); - std::lock_guard lock(GlobalSyncMutex); + const std::lock_guard lock(GlobalSyncMutex); --GlobalInstances; if (GlobalInstances == 0) @@ -126,7 +126,7 @@ uintptr_t DepUsrSCTP::GetNextSctpAssociationId() { MS_TRACE(); - std::lock_guard lock(GlobalSyncMutex); + const std::lock_guard lock(GlobalSyncMutex); // NOTE: usrsctp_connect() fails with a value of 0. if (DepUsrSCTP::nextSctpAssociationId == 0u) @@ -154,7 +154,7 @@ void DepUsrSCTP::RegisterSctpAssociation(RTC::SctpAssociation* sctpAssociation) { MS_TRACE(); - std::lock_guard lock(GlobalSyncMutex); + const std::lock_guard lock(GlobalSyncMutex); MS_ASSERT(DepUsrSCTP::checker != nullptr, "Checker not created"); @@ -176,7 +176,7 @@ void DepUsrSCTP::DeregisterSctpAssociation(RTC::SctpAssociation* sctpAssociation { MS_TRACE(); - std::lock_guard lock(GlobalSyncMutex); + const std::lock_guard lock(GlobalSyncMutex); MS_ASSERT(DepUsrSCTP::checker != nullptr, "Checker not created"); @@ -195,7 +195,7 @@ RTC::SctpAssociation* DepUsrSCTP::RetrieveSctpAssociation(uintptr_t id) { MS_TRACE(); - std::lock_guard lock(GlobalSyncMutex); + const std::lock_guard lock(GlobalSyncMutex); auto it = DepUsrSCTP::mapIdSctpAssociation.find(id); @@ -209,11 +209,9 @@ RTC::SctpAssociation* DepUsrSCTP::RetrieveSctpAssociation(uintptr_t id) /* DepUsrSCTP::Checker instance methods. */ -DepUsrSCTP::Checker::Checker() +DepUsrSCTP::Checker::Checker() : timer(new TimerHandle(this)) { MS_TRACE(); - - this->timer = new TimerHandle(this); } DepUsrSCTP::Checker::~Checker() diff --git a/worker/src/Logger.cpp b/worker/src/Logger.cpp index d7d972c9d7..6ec0c4181f 100644 --- a/worker/src/Logger.cpp +++ b/worker/src/Logger.cpp @@ -6,9 +6,9 @@ /* Class variables. */ -const uint64_t Logger::pid{ static_cast(uv_os_getpid()) }; +const uint64_t Logger::Pid{ static_cast(uv_os_getpid()) }; thread_local Channel::ChannelSocket* Logger::channel{ nullptr }; -thread_local char Logger::buffer[Logger::bufferSize]; +thread_local char Logger::buffer[Logger::BufferSize]; /* Class methods. */ diff --git a/worker/src/MediaSoupErrors.cpp b/worker/src/MediaSoupErrors.cpp index 29e3492f4a..d40b6d225b 100644 --- a/worker/src/MediaSoupErrors.cpp +++ b/worker/src/MediaSoupErrors.cpp @@ -2,4 +2,4 @@ #include "MediaSoupErrors.hpp" -thread_local char MediaSoupError::buffer[MediaSoupError::bufferSize]; +thread_local char MediaSoupError::buffer[MediaSoupError::BufferSize]; diff --git a/worker/src/RTC/ActiveSpeakerObserver.cpp b/worker/src/RTC/ActiveSpeakerObserver.cpp index b0f15ae037..ff27d63d67 100644 --- a/worker/src/RTC/ActiveSpeakerObserver.cpp +++ b/worker/src/RTC/ActiveSpeakerObserver.cpp @@ -67,8 +67,8 @@ namespace RTC inline bool ComputeBigs( const std::vector& littles, std::vector& bigs, uint8_t threashold) { - uint32_t littleLen = littles.size(); - uint32_t bigLen = bigs.size(); + const uint32_t littleLen = littles.size(); + const uint32_t bigLen = bigs.size(); const uint32_t littleLenPerBig = littleLen / bigLen; bool changed{ false }; @@ -99,12 +99,10 @@ namespace RTC const std::string& id, RTC::RtpObserver::Listener* listener, const FBS::ActiveSpeakerObserver::ActiveSpeakerObserverOptions* options) - : RTC::RtpObserver(shared, id, listener) + : RTC::RtpObserver(shared, id, listener), interval(options->interval()) { MS_TRACE(); - this->interval = options->interval(); - if (this->interval < 100) { this->interval = 100; @@ -231,14 +229,14 @@ namespace RTC return; } - uint8_t volume = 127 - level; + const uint8_t volume = 127 - level; auto it = this->mapProducerSpeakers.find(producer->id); if (it != this->mapProducerSpeakers.end()) { auto* producerSpeaker = it->second; - uint64_t now = DepLibUV::GetTimeMs(); + const uint64_t now = DepLibUV::GetTimeMs(); producerSpeaker->speaker->LevelChanged(volume, now); } @@ -258,7 +256,7 @@ namespace RTC this->periodicTimer->Restart(); } - void ActiveSpeakerObserver::OnTimer(TimerHandle* timer) + void ActiveSpeakerObserver::OnTimer(TimerHandle* /*timer*/) { MS_TRACE(); @@ -299,7 +297,7 @@ namespace RTC MS_TRACE(); std::string newDominantId; - int32_t speakerCount = this->mapProducerSpeakers.size(); + const int32_t speakerCount = this->mapProducerSpeakers.size(); if (speakerCount == 0) { @@ -352,9 +350,9 @@ namespace RTC speaker->GetActivityScore(interval) / dominantSpeaker->GetActivityScore(interval)); } - double c1 = this->relativeSpeachActivities[0]; - double c2 = this->relativeSpeachActivities[1]; - double c3 = this->relativeSpeachActivities[2]; + const double c1 = this->relativeSpeachActivities[0]; + const double c2 = this->relativeSpeachActivities[1]; + const double c3 = this->relativeSpeachActivities[2]; if ((c1 > C1) && (c2 > C2) && (c3 > C3) && (c2 > newDominantC2)) { @@ -383,7 +381,7 @@ namespace RTC auto* producerSpeaker = kv.second; auto* speaker = producerSpeaker->speaker; const auto& id = producerSpeaker->producer->id; - uint64_t idle = now - speaker->lastLevelChangeTime; + const uint64_t idle = now - speaker->lastLevelChangeTime; if (SpeakerIdleTimeout < idle && (this->dominantId.empty() || id != this->dominantId)) { @@ -397,11 +395,10 @@ namespace RTC } ActiveSpeakerObserver::ProducerSpeaker::ProducerSpeaker(RTC::Producer* producer) - : producer(producer) + : producer(producer), speaker(new Speaker()) { MS_TRACE(); - this->speaker = new Speaker(); this->speaker->paused = producer->IsPaused(); } @@ -416,7 +413,7 @@ namespace RTC : immediateActivityScore(MinActivityScore), mediumActivityScore(MinActivityScore), longActivityScore(MinActivityScore), lastLevelChangeTime(DepLibUV::GetTimeMs()), minLevel(MinLevel), nextMinLevel(MinLevel), immediates(ImmediateBuffLen, 0), - mediums(MediumsBuffLen, 0), longs(LongsBuffLen, 0), levels(LevelsBuffLen, 0), nextLevelIndex(0) + mediums(MediumsBuffLen, 0), longs(LongsBuffLen, 0), levels(LevelsBuffLen, 0) { MS_TRACE(); } @@ -441,7 +438,7 @@ namespace RTC } } - double ActiveSpeakerObserver::Speaker::GetActivityScore(uint8_t interval) + double ActiveSpeakerObserver::Speaker::GetActivityScore(uint8_t interval) const { MS_TRACE(); @@ -486,7 +483,7 @@ namespace RTC // The algorithm expect to have an update every 20 milliseconds. If the // Producer is paused, using a different packetization time or using DTX // we need to update more than one sample when receiving an audio packet. - uint32_t intervalsUpdated = + const uint32_t intervalsUpdated = std::min(std::max(static_cast(elapsed / 20), 1U), LevelsBuffLen); for (uint32_t i{ 0u }; i < intervalsUpdated; ++i) diff --git a/worker/src/RTC/Consumer.cpp b/worker/src/RTC/Consumer.cpp index 796924f795..84cda670ec 100644 --- a/worker/src/RTC/Consumer.cpp +++ b/worker/src/RTC/Consumer.cpp @@ -19,12 +19,11 @@ namespace RTC Listener* listener, const FBS::Transport::ConsumeRequest* data, RTC::RtpParameters::Type type) - : id(id), producerId(producerId), shared(shared), listener(listener), type(type) + : id(id), producerId(producerId), shared(shared), listener(listener), + kind(RTC::Media::Kind(data->kind())), type(type) { MS_TRACE(); - this->kind = RTC::Media::Kind(data->kind()); - // This may throw. this->rtpParameters = RTC::RtpParameters(data->rtpParameters()); diff --git a/worker/src/RTC/DataConsumer.cpp b/worker/src/RTC/DataConsumer.cpp index fdabc812a5..b54ce8c5cc 100644 --- a/worker/src/RTC/DataConsumer.cpp +++ b/worker/src/RTC/DataConsumer.cpp @@ -280,7 +280,7 @@ namespace RTC const auto* body = request->data->body_as(); const uint8_t* data = body->data()->Data(); - size_t len = body->data()->size(); + const size_t len = body->data()->size(); if (len > this->maxMessageSize) { @@ -303,9 +303,9 @@ namespace RTC } }); - static std::vector EmptySubchannels; + static std::vector emptySubchannels; - SendMessage(data, len, body->ppid(), EmptySubchannels, std::nullopt, cb); + SendMessage(data, len, body->ppid(), emptySubchannels, std::nullopt, cb); break; } @@ -543,7 +543,7 @@ namespace RTC // If subchannels are given, verify that this data consumer is subscribed // to at least one of them. - if (subchannels.size() > 0) + if (!subchannels.empty()) { bool subchannelMatched{ false }; diff --git a/worker/src/RTC/DataProducer.cpp b/worker/src/RTC/DataProducer.cpp index 2bb16ecab6..136f0bdbf9 100644 --- a/worker/src/RTC/DataProducer.cpp +++ b/worker/src/RTC/DataProducer.cpp @@ -202,7 +202,7 @@ namespace RTC { const auto* body = notification->data->body_as(); const uint8_t* data = body->data()->Data(); - size_t len = body->data()->size(); + const size_t len = body->data()->size(); if (len > this->maxMessageSize) { diff --git a/worker/src/RTC/DirectTransport.cpp b/worker/src/RTC/DirectTransport.cpp index d11d5a3acd..d0f0b9d118 100644 --- a/worker/src/RTC/DirectTransport.cpp +++ b/worker/src/RTC/DirectTransport.cpp @@ -213,7 +213,11 @@ namespace RTC } void DirectTransport::SendMessage( - RTC::DataConsumer* dataConsumer, const uint8_t* msg, size_t len, uint32_t ppid, onQueuedCallback* cb) + RTC::DataConsumer* dataConsumer, + const uint8_t* msg, + size_t len, + uint32_t ppid, + onQueuedCallback* /*cb*/) { MS_TRACE(); diff --git a/worker/src/RTC/DtlsTransport.cpp b/worker/src/RTC/DtlsTransport.cpp index adada495d3..3199c6aed4 100644 --- a/worker/src/RTC/DtlsTransport.cpp +++ b/worker/src/RTC/DtlsTransport.cpp @@ -71,14 +71,13 @@ inline static long onSslBioOut( int ret, size_t* /*processed*/) { - long resultOfcallback = (operationType == BIO_CB_RETURN) ? static_cast(ret) : 1; + const long resultOfcallback = (operationType == BIO_CB_RETURN) ? static_cast(ret) : 1; if (operationType == BIO_CB_WRITE && argp && len > 0) { MS_DEBUG_DEV("%zu bytes of DTLS data ready to be sent", len); - RTC::DtlsTransport* dtlsTransport = - reinterpret_cast(BIO_get_callback_arg(bio)); + auto* dtlsTransport = reinterpret_cast(BIO_get_callback_arg(bio)); dtlsTransport->SendDtlsData(reinterpret_cast(argp), len); } @@ -333,7 +332,7 @@ namespace RTC int ret{ 0 }; X509_NAME* certName{ nullptr }; - std::string subject = + const std::string subject = std::string("mediasoup") + std::to_string(Utils::Crypto::GetRandomUInt(100000, 999999)); // Create key with curve. @@ -618,8 +617,8 @@ namespace RTC for (auto& kv : DtlsTransport::string2FingerprintAlgorithm) { - const std::string& algorithmString = kv.first; - FingerprintAlgorithm algorithm = kv.second; + const std::string& algorithmString = kv.first; + const FingerprintAlgorithm algorithm = kv.second; uint8_t binaryFingerprint[EVP_MAX_MD_SIZE]; unsigned int size{ 0 }; char hexFingerprint[(EVP_MAX_MD_SIZE * 3) + 1]; @@ -693,14 +692,11 @@ namespace RTC /* Instance methods. */ - DtlsTransport::DtlsTransport(Listener* listener) : listener(listener) + DtlsTransport::DtlsTransport(Listener* listener) + : listener(listener), ssl(SSL_new(DtlsTransport::sslCtx)) { MS_TRACE(); - /* Set SSL. */ - - this->ssl = SSL_new(DtlsTransport::sslCtx); - if (!this->ssl) { LOG_OPENSSL_ERROR("SSL_new() failed"); diff --git a/worker/src/RTC/KeyFrameRequestManager.cpp b/worker/src/RTC/KeyFrameRequestManager.cpp index f3b1e7ed67..1112901b49 100644 --- a/worker/src/RTC/KeyFrameRequestManager.cpp +++ b/worker/src/RTC/KeyFrameRequestManager.cpp @@ -9,11 +9,10 @@ static constexpr uint32_t KeyFrameRetransmissionWaitTime{ 1000 }; /* PendingKeyFrameInfo methods. */ RTC::PendingKeyFrameInfo::PendingKeyFrameInfo(PendingKeyFrameInfo::Listener* listener, uint32_t ssrc) - : listener(listener), ssrc(ssrc) + : listener(listener), ssrc(ssrc), timer(new TimerHandle(this)) { MS_TRACE(); - this->timer = new TimerHandle(this); this->timer->Start(KeyFrameRetransmissionWaitTime); } @@ -39,11 +38,10 @@ inline void RTC::PendingKeyFrameInfo::OnTimer(TimerHandle* timer) RTC::KeyFrameRequestDelayer::KeyFrameRequestDelayer( KeyFrameRequestDelayer::Listener* listener, uint32_t ssrc, uint32_t delay) - : listener(listener), ssrc(ssrc) + : listener(listener), ssrc(ssrc), timer(new TimerHandle(this)) { MS_TRACE(); - this->timer = new TimerHandle(this); this->timer->Start(delay); } diff --git a/worker/src/RTC/NackGenerator.cpp b/worker/src/RTC/NackGenerator.cpp index 7eb168df40..f77c1f3c6b 100644 --- a/worker/src/RTC/NackGenerator.cpp +++ b/worker/src/RTC/NackGenerator.cpp @@ -21,12 +21,10 @@ namespace RTC /* Instance methods. */ NackGenerator::NackGenerator(Listener* listener, unsigned int sendNackDelayMs) - : listener(listener), sendNackDelayMs(sendNackDelayMs), rtt(DefaultRtt) + : listener(listener), sendNackDelayMs(sendNackDelayMs), timer(new TimerHandle(this)), + rtt(DefaultRtt) { MS_TRACE(); - - // Set the timer. - this->timer = new TimerHandle(this); } NackGenerator::~NackGenerator() @@ -42,7 +40,7 @@ namespace RTC { MS_TRACE(); - uint16_t seq = packet->GetSequenceNumber(); + const uint16_t seq = packet->GetSequenceNumber(); const bool isKeyFrame = packet->IsKeyFrame(); if (!this->started) @@ -83,14 +81,7 @@ namespace RTC this->nackList.erase(it); - if (retries != 0) - { - return true; - } - else - { - return false; - } + return retries != 0; } // Out of order packet or already handled NACKed packet. @@ -145,7 +136,7 @@ namespace RTC this->lastSeq = seq; // Check if there are any nacks that are waiting for this seq number. - std::vector nackBatch = GetNackBatch(NackFilter::SEQ); + const std::vector nackBatch = GetNackBatch(NackFilter::SEQ); if (!nackBatch.empty()) { @@ -256,7 +247,7 @@ namespace RTC while (it != this->nackList.end()) { NackInfo& nackInfo = it->second; - uint16_t seq = nackInfo.seq; + const uint16_t seq = nackInfo.seq; if (this->sendNackDelayMs > 0 && nowMs - nackInfo.createdAtMs < this->sendNackDelayMs) { @@ -376,7 +367,7 @@ namespace RTC { MS_TRACE(); - std::vector nackBatch = GetNackBatch(NackFilter::TIME); + const std::vector nackBatch = GetNackBatch(NackFilter::TIME); if (!nackBatch.empty()) { diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index eea8dbb97c..a2247bf256 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -47,7 +47,9 @@ namespace RTC int err; const int family = Utils::IP::GetFamily(ip); - struct sockaddr_storage bindAddr; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sockaddr_storage bindAddr + { + }; size_t portIdx; std::vector& ports = PortManager::GetPorts(transport, ip); size_t attempt{ 0u }; @@ -55,7 +57,7 @@ namespace RTC uv_handle_t* uvHandle{ nullptr }; uint16_t port; std::string transportStr; - uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); + const uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); switch (transport) { @@ -375,10 +377,12 @@ namespace RTC int err; const int family = Utils::IP::GetFamily(ip); - struct sockaddr_storage bindAddr; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sockaddr_storage bindAddr + { + }; uv_handle_t* uvHandle{ nullptr }; std::string transportStr; - uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); + const uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); switch (transport) { diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index 5e2f195675..c465152d6c 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -32,13 +32,10 @@ namespace RTC const std::string& id, RTC::Producer::Listener* listener, const FBS::Transport::ProduceRequest* data) - : id(id), shared(shared), listener(listener) + : id(id), shared(shared), listener(listener), kind(RTC::Media::Kind(data->kind())) { MS_TRACE(); - // This may throw. - this->kind = RTC::Media::Kind(data->kind()); - // This may throw. this->rtpParameters = RTC::RtpParameters(data->rtpParameters()); diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index 8ebe9cce96..ef05d24a41 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -158,10 +158,7 @@ namespace RTC { MS_TRACE(); - if (this->buffer) - { - delete[] this->buffer; - } + delete[] this->buffer; } void RtpPacket::Dump() const @@ -840,14 +837,7 @@ namespace RTC return true; } - if (this->payloadDescriptorHandler->Process(context, this->payload, marker)) - { - return true; - } - else - { - return false; - } + return this->payloadDescriptorHandler->Process(context, this->payload, marker); } void RtpPacket::RestorePayload() diff --git a/worker/src/RTC/RtpRetransmissionBuffer.cpp b/worker/src/RTC/RtpRetransmissionBuffer.cpp index 78e57d0c77..284d5e3c51 100644 --- a/worker/src/RTC/RtpRetransmissionBuffer.cpp +++ b/worker/src/RTC/RtpRetransmissionBuffer.cpp @@ -7,6 +7,37 @@ namespace RTC { + /* Class methods. */ + + RtpRetransmissionBuffer::Item* RtpRetransmissionBuffer::FillItem( + RtpRetransmissionBuffer::Item* item, + RTC::RtpPacket* packet, + std::shared_ptr& sharedPacket) + { + MS_TRACE(); + + // Store original packet into the item. Only clone once and only if + // necessary. + // + // NOTE: This must be done BEFORE assigning item->packet = sharedPacket, + // otherwise the value being copied in item->packet will remain nullptr. + // This is because we are copying an **empty** shared_ptr into another + // shared_ptr (item->packet), so future value assigned via reset() in the + // former doesn't update the value in the copy. + if (!sharedPacket) + { + sharedPacket.reset(packet->Clone()); + } + + // Store original packet and some extra info into the item. + item->packet = sharedPacket; + item->ssrc = packet->GetSsrc(); + item->sequenceNumber = packet->GetSequenceNumber(); + item->timestamp = packet->GetTimestamp(); + + return item; + } + /* Instance methods. */ RtpRetransmissionBuffer::RtpRetransmissionBuffer( @@ -76,7 +107,7 @@ namespace RTC auto* item = new Item(); - this->buffer.push_back(FillItem(item, packet, sharedPacket)); + this->buffer.push_back(RtpRetransmissionBuffer::FillItem(item, packet, sharedPacket)); return; } @@ -102,7 +133,7 @@ namespace RTC auto* item = new Item(); - this->buffer.push_back(FillItem(item, packet, sharedPacket)); + this->buffer.push_back(RtpRetransmissionBuffer::FillItem(item, packet, sharedPacket)); return; } @@ -132,7 +163,7 @@ namespace RTC auto* item = new Item(); - this->buffer.push_back(FillItem(item, packet, sharedPacket)); + this->buffer.push_back(RtpRetransmissionBuffer::FillItem(item, packet, sharedPacket)); return; } @@ -215,7 +246,7 @@ namespace RTC // Push the packet, which becomes the newest one in the buffer. auto* item = new Item(); - this->buffer.push_back(FillItem(item, packet, sharedPacket)); + this->buffer.push_back(RtpRetransmissionBuffer::FillItem(item, packet, sharedPacket)); } // Packet arrived out order and its seq is less than seq of the oldest // stored packet, so will become the oldest one in the buffer. @@ -281,7 +312,7 @@ namespace RTC // Insert the packet, which becomes the oldest one in the buffer. auto* item = new Item(); - this->buffer.push_front(FillItem(item, packet, sharedPacket)); + this->buffer.push_front(RtpRetransmissionBuffer::FillItem(item, packet, sharedPacket)); } // Otherwise packet must be inserted between oldest and newest stored items // so there is already an allocated slot for it. @@ -375,7 +406,7 @@ namespace RTC // Store the packet. item = new Item(); - this->buffer[idx] = FillItem(item, packet, sharedPacket); + this->buffer[idx] = RtpRetransmissionBuffer::FillItem(item, packet, sharedPacket); } MS_ASSERT( @@ -411,7 +442,7 @@ namespace RTC MS_DUMP(""); MS_DUMP(" buffer [size:%zu, maxSize:%" PRIu16 "]", this->buffer.size(), this->maxItems); - if (this->buffer.size() > 0) + if (!this->buffer.empty()) { const auto* oldestItem = GetOldest(); const auto* newestItem = GetNewest(); @@ -554,35 +585,6 @@ namespace RTC return static_cast(diffTs * 1000 / this->clockRate) > this->maxRetransmissionDelayMs; } - RtpRetransmissionBuffer::Item* RtpRetransmissionBuffer::FillItem( - RtpRetransmissionBuffer::Item* item, - RTC::RtpPacket* packet, - std::shared_ptr& sharedPacket) const - { - MS_TRACE(); - - // Store original packet into the item. Only clone once and only if - // necessary. - // - // NOTE: This must be done BEFORE assigning item->packet = sharedPacket, - // otherwise the value being copied in item->packet will remain nullptr. - // This is because we are copying an **empty** shared_ptr into another - // shared_ptr (item->packet), so future value assigned via reset() in the - // former doesn't update the value in the copy. - if (!sharedPacket.get()) - { - sharedPacket.reset(packet->Clone()); - } - - // Store original packet and some extra info into the item. - item->packet = sharedPacket; - item->ssrc = packet->GetSsrc(); - item->sequenceNumber = packet->GetSequenceNumber(); - item->timestamp = packet->GetTimestamp(); - - return item; - } - void RtpRetransmissionBuffer::Item::Reset() { MS_TRACE(); diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index fd55c94618..ba9e50c6d8 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -27,7 +27,7 @@ namespace RTC { for (uint8_t tIdx{ 0u }; tIdx < temporalLayers; ++tIdx) { - spatialLayerCounter.emplace_back(RTC::RtpDataCounter(windowSize)); + spatialLayerCounter.emplace_back(windowSize); } } } @@ -561,7 +561,7 @@ namespace RTC this->lastSrTimestamp += report->GetNtpFrac() >> 16; // Update info about last Sender Report. - Utils::Time::Ntp ntp; // NOLINT(cppcoreguidelines-pro-type-member-init) + Utils::Time::Ntp ntp{}; // NOLINT(cppcoreguidelines-pro-type-member-init) ntp.seconds = report->GetNtpSec(); ntp.fractions = report->GetNtpFrac(); @@ -900,7 +900,7 @@ namespace RTC while (it != end) { - uint16_t shift = *it - seq - 1; + const uint16_t shift = *it - seq - 1; if (shift > 15) { diff --git a/worker/src/RTC/SctpAssociation.cpp b/worker/src/RTC/SctpAssociation.cpp index b83c740a69..2c2da971f1 100644 --- a/worker/src/RTC/SctpAssociation.cpp +++ b/worker/src/RTC/SctpAssociation.cpp @@ -115,14 +115,12 @@ namespace RTC size_t maxSctpMessageSize, size_t sctpSendBufferSize, bool isDataChannel) - : listener(listener), os(os), mis(mis), maxSctpMessageSize(maxSctpMessageSize), - sctpSendBufferSize(sctpSendBufferSize), isDataChannel(isDataChannel) + : id(DepUsrSCTP::GetNextSctpAssociationId()), listener(listener), os(os), mis(mis), + maxSctpMessageSize(maxSctpMessageSize), sctpSendBufferSize(sctpSendBufferSize), + isDataChannel(isDataChannel) { MS_TRACE(); - // Get a id for this SctpAssociation. - this->id = DepUsrSCTP::GetNextSctpAssociationId(); - // Register ourselves in usrsctp. // NOTE: This must be done before calling usrsctp_bind(). usrsctp_register_address(reinterpret_cast(this->id)); @@ -161,7 +159,9 @@ namespace RTC // This ensures that the usrsctp close call deletes the association. This // prevents usrsctp from calling the global send callback with references to // this class as the address. - struct linger lingerOpt; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct linger lingerOpt + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) lingerOpt.l_onoff = 1; lingerOpt.l_linger = 0; @@ -176,7 +176,9 @@ namespace RTC } // Set SCTP_ENABLE_STREAM_RESET. - struct sctp_assoc_value av; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sctp_assoc_value av + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) av.assoc_value = SCTP_ENABLE_RESET_STREAM_REQ | SCTP_ENABLE_RESET_ASSOC_REQ | SCTP_ENABLE_CHANGE_ASSOC_REQ; @@ -203,7 +205,9 @@ namespace RTC } // Enable events. - struct sctp_event event; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sctp_event event + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) std::memset(&event, 0, sizeof(event)); event.se_on = 1; @@ -223,7 +227,9 @@ namespace RTC } // Init message. - struct sctp_initmsg initmsg; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sctp_initmsg initmsg + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) std::memset(&initmsg, 0, sizeof(initmsg)); initmsg.sinit_num_ostreams = this->os; @@ -239,7 +245,9 @@ namespace RTC } // Server side. - struct sockaddr_conn sconn; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sockaddr_conn sconn + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) std::memset(&sconn, 0, sizeof(sconn)); sconn.sconn_family = AF_CONN; @@ -300,7 +308,9 @@ namespace RTC try { int ret; - struct sockaddr_conn rconn; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sockaddr_conn rconn + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) std::memset(&rconn, 0, sizeof(rconn)); rconn.sconn_family = AF_CONN; @@ -318,7 +328,7 @@ namespace RTC } // Disable MTU discovery. - sctp_paddrparams peerAddrParams; // NOLINT(cppcoreguidelines-pro-type-member-init) + sctp_paddrparams peerAddrParams{}; // NOLINT(cppcoreguidelines-pro-type-member-init) std::memset(&peerAddrParams, 0, sizeof(peerAddrParams)); std::memcpy(&peerAddrParams.spp_address, &rconn, sizeof(rconn)); @@ -370,7 +380,7 @@ namespace RTC this->isDataChannel); } - void SctpAssociation::ProcessSctpData(const uint8_t* data, size_t len) + void SctpAssociation::ProcessSctpData(const uint8_t* data, size_t len) const { MS_TRACE(); @@ -396,7 +406,9 @@ namespace RTC const auto& parameters = dataConsumer->GetSctpStreamParameters(); // Fill sctp_sendv_spa. - struct sctp_sendv_spa spa; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sctp_sendv_spa spa + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) std::memset(&spa, 0, sizeof(spa)); spa.sendv_flags = SCTP_SEND_SNDINFO_VALID; @@ -436,12 +448,12 @@ namespace RTC // via onSendSctpData. this->listener->OnSctpAssociationBufferedAmount(this, this->sctpBufferedAmount); - int ret = usrsctp_sendv( + const int ret = usrsctp_sendv( this->socket, msg, len, nullptr, 0, &spa, static_cast(sizeof(spa)), SCTP_SENDV_SPA, 0); if (ret < 0) { - bool sctpSendBufferFull = errno == EWOULDBLOCK || errno == EAGAIN; + const bool sctpSendBufferFull = errno == EWOULDBLOCK || errno == EAGAIN; // SCTP send buffer being full is legit, not an error. if (sctpSendBufferFull) @@ -535,7 +547,9 @@ namespace RTC } int ret; - struct sctp_assoc_value av; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sctp_assoc_value av + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) socklen_t len = sizeof(av); ret = usrsctp_getsockopt(this->socket, IPPROTO_SCTP, SCTP_RECONFIG_SUPPORTED, &av, &len); @@ -633,7 +647,9 @@ namespace RTC return; } - struct sctp_add_streams sas; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sctp_add_streams sas + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) std::memset(&sas, 0, sizeof(sas)); sas.sas_instrms = 0; @@ -641,7 +657,7 @@ namespace RTC MS_DEBUG_TAG(sctp, "adding %" PRIu16 " outgoing streams", additionalOs); - int ret = usrsctp_setsockopt( + const int ret = usrsctp_setsockopt( this->socket, IPPROTO_SCTP, SCTP_ADD_STREAMS, &sas, static_cast(sizeof(sas))); if (ret < 0) diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index c17c15dde4..66c7a75c23 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -1713,7 +1713,7 @@ namespace RTC } inline void SimulcastConsumer::OnRtpStreamScore( - RTC::RtpStream* /*rtpStream*/, uint8_t score, uint8_t /*previousScore*/) + RTC::RtpStream* /*rtpStream*/, uint8_t /*score*/, uint8_t /*previousScore*/) { MS_TRACE(); diff --git a/worker/src/RTC/StunPacket.cpp b/worker/src/RTC/StunPacket.cpp index e420871595..518ca8ff97 100644 --- a/worker/src/RTC/StunPacket.cpp +++ b/worker/src/RTC/StunPacket.cpp @@ -11,7 +11,7 @@ namespace RTC { /* Class variables. */ - const uint8_t StunPacket::magicCookie[] = { 0x21, 0x12, 0xA4, 0x42 }; + const uint8_t StunPacket::MagicCookie[] = { 0x21, 0x12, 0xA4, 0x42 }; /* Class methods. */ @@ -651,7 +651,7 @@ namespace RTC // Set length field. Utils::Byte::Set2Bytes(buffer, 2, static_cast(this->size) - 20); // Set magic cookie. - std::memcpy(buffer + 4, StunPacket::magicCookie, 4); + std::memcpy(buffer + 4, StunPacket::MagicCookie, 4); // Set TransactionId field. std::memcpy(buffer + 8, this->transactionId, 12); // Update the transaction ID pointer. @@ -724,17 +724,17 @@ namespace RTC attrValue + 2, &(reinterpret_cast(this->xorMappedAddress))->sin_port, 2); - attrValue[2] ^= StunPacket::magicCookie[0]; - attrValue[3] ^= StunPacket::magicCookie[1]; + attrValue[2] ^= StunPacket::MagicCookie[0]; + attrValue[3] ^= StunPacket::MagicCookie[1]; // Set address and XOR it. std::memcpy( attrValue + 4, &(reinterpret_cast(this->xorMappedAddress))->sin_addr.s_addr, 4); - attrValue[4] ^= StunPacket::magicCookie[0]; - attrValue[5] ^= StunPacket::magicCookie[1]; - attrValue[6] ^= StunPacket::magicCookie[2]; - attrValue[7] ^= StunPacket::magicCookie[3]; + attrValue[4] ^= StunPacket::MagicCookie[0]; + attrValue[5] ^= StunPacket::MagicCookie[1]; + attrValue[6] ^= StunPacket::MagicCookie[2]; + attrValue[7] ^= StunPacket::MagicCookie[3]; pos += 4 + 8; @@ -752,17 +752,17 @@ namespace RTC attrValue + 2, &(reinterpret_cast(this->xorMappedAddress))->sin6_port, 2); - attrValue[2] ^= StunPacket::magicCookie[0]; - attrValue[3] ^= StunPacket::magicCookie[1]; + attrValue[2] ^= StunPacket::MagicCookie[0]; + attrValue[3] ^= StunPacket::MagicCookie[1]; // Set address and XOR it. std::memcpy( attrValue + 4, &(reinterpret_cast(this->xorMappedAddress))->sin6_addr.s6_addr, 16); - attrValue[4] ^= StunPacket::magicCookie[0]; - attrValue[5] ^= StunPacket::magicCookie[1]; - attrValue[6] ^= StunPacket::magicCookie[2]; - attrValue[7] ^= StunPacket::magicCookie[3]; + attrValue[4] ^= StunPacket::MagicCookie[0]; + attrValue[5] ^= StunPacket::MagicCookie[1]; + attrValue[6] ^= StunPacket::MagicCookie[2]; + attrValue[7] ^= StunPacket::MagicCookie[3]; attrValue[8] ^= this->transactionId[0]; attrValue[9] ^= this->transactionId[1]; attrValue[10] ^= this->transactionId[2]; diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 2d1da9e623..487343e29f 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -2320,7 +2320,7 @@ namespace RTC this->tccClient->SetDesiredBitrate(totalDesiredBitrate, forceBitrate); } - inline void Transport::EmitTraceEventProbationType(RTC::RtpPacket* packet) const + inline void Transport::EmitTraceEventProbationType(RTC::RtpPacket* /*packet*/) const { MS_TRACE(); @@ -2893,10 +2893,10 @@ namespace RTC // Pass the SCTP message to the corresponding DataProducer. try { - static std::vector EmptySubchannels; + static std::vector emptySubchannels; dataProducer->ReceiveMessage( - msg, len, ppid, EmptySubchannels, /*requiredSubchannel*/ std::nullopt); + msg, len, ppid, emptySubchannels, /*requiredSubchannel*/ std::nullopt); } catch (std::exception& error) { @@ -2936,7 +2936,7 @@ namespace RTC } inline void Transport::OnTransportCongestionControlClientSendRtpPacket( - RTC::TransportCongestionControlClient* tccClient, + RTC::TransportCongestionControlClient* /*tccClient*/, RTC::RtpPacket* packet, const webrtc::PacedPacketInfo& pacingInfo) { diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 94801fe5a2..0a4c027d40 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -25,6 +25,30 @@ namespace RTC std::pow(2, 0) * (256 - IceComponent); } + /* Class methods. */ + + inline std::string WebRtcServer::GetLocalIceUsernameFragmentFromReceivedStunPacket( + RTC::StunPacket* packet) + { + MS_TRACE(); + + // Here we inspect the USERNAME attribute of a received STUN request and + // extract its remote usernameFragment (the one given to our IceServer as + // local usernameFragment) which is the first value in the attribute value + // before the ":" symbol. + + const auto& username = packet->GetUsername(); + const size_t colonPos = username.find(':'); + + // If no colon is found just return the whole USERNAME attribute anyway. + if (colonPos == std::string::npos) + { + return username; + } + + return username.substr(0, colonPos); + } + /* Instance methods. */ WebRtcServer::WebRtcServer( @@ -265,7 +289,7 @@ namespace RTC } } - const std::vector WebRtcServer::GetIceCandidates( + std::vector WebRtcServer::GetIceCandidates( bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp) const { MS_TRACE(); @@ -284,7 +308,7 @@ namespace RTC iceLocalPreference += 1000; } - uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); + const uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); if (item.announcedIp.empty()) { @@ -305,7 +329,7 @@ namespace RTC iceLocalPreference += 1000; } - uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); + const uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); if (item.announcedIp.empty()) { @@ -325,28 +349,6 @@ namespace RTC return iceCandidates; } - inline std::string WebRtcServer::GetLocalIceUsernameFragmentFromReceivedStunPacket( - RTC::StunPacket* packet) const - { - MS_TRACE(); - - // Here we inspect the USERNAME attribute of a received STUN request and - // extract its remote usernameFragment (the one given to our IceServer as - // local usernameFragment) which is the first value in the attribute value - // before the ":" symbol. - - const auto& username = packet->GetUsername(); - const size_t colonPos = username.find(':'); - - // If no colon is found just return the whole USERNAME attribute anyway. - if (colonPos == std::string::npos) - { - return username; - } - - return username.substr(0, colonPos); - } - inline void WebRtcServer::OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len) { MS_TRACE(); @@ -389,7 +391,7 @@ namespace RTC } // Otherwise try to match the local ICE username fragment. - auto key = GetLocalIceUsernameFragmentFromReceivedStunPacket(packet); + auto key = WebRtcServer::GetLocalIceUsernameFragmentFromReceivedStunPacket(packet); auto it2 = this->mapLocalIceUsernameFragmentWebRtcTransport.find(key); if (it2 == this->mapLocalIceUsernameFragmentWebRtcTransport.end()) @@ -463,7 +465,7 @@ namespace RTC } inline void WebRtcServer::OnWebRtcTransportLocalIceUsernameFragmentRemoved( - RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) + RTC::WebRtcTransport* /*webRtcTransport*/, const std::string& usernameFragment) { MS_TRACE(); @@ -491,7 +493,7 @@ namespace RTC } inline void WebRtcServer::OnWebRtcTransportTransportTupleRemoved( - RTC::WebRtcTransport* webRtcTransport, RTC::TransportTuple* tuple) + RTC::WebRtcTransport* /*webRtcTransport*/, RTC::TransportTuple* tuple) { MS_TRACE(); diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 6eb1f9717d..a795fef798 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -86,7 +86,7 @@ namespace RTC this->udpSockets[udpSocket] = announcedIp; - if (announcedIp.size() == 0) + if (announcedIp.empty()) { this->iceCandidates.emplace_back(udpSocket, icePriority); } @@ -128,7 +128,7 @@ namespace RTC this->tcpServers[tcpServer] = announcedIp; - if (announcedIp.size() == 0) + if (announcedIp.empty()) { this->iceCandidates.emplace_back(tcpServer, icePriority); } @@ -341,7 +341,7 @@ namespace RTC // Add dtlsParameters.fingerprints. std::vector> fingerprints; - for (const auto& fingerprint : this->dtlsTransport->GetLocalFingerprints()) + for (const auto& fingerprint : RTC::DtlsTransport::GetLocalFingerprints()) { auto algorithm = DtlsTransport::AlgorithmToFbs(fingerprint.algorithm); const auto& value = fingerprint.value; diff --git a/worker/src/Settings.cpp b/worker/src/Settings.cpp index 655e1b2b1e..7aa0006d85 100644 --- a/worker/src/Settings.cpp +++ b/worker/src/Settings.cpp @@ -18,7 +18,7 @@ extern "C" /* Static. */ -static std::mutex globalSyncMutex; +static std::mutex GlobalSyncMutex; /* Class variables. */ @@ -69,7 +69,7 @@ void Settings::SetConfiguration(int argc, char* argv[]) /* Parse command line options. */ // getopt_long_only() is not thread-safe - std::lock_guard lock(globalSyncMutex); + const std::lock_guard lock(GlobalSyncMutex); optind = 1; // Set explicitly, otherwise subsequent runs will fail. opterr = 0; // Don't allow getopt to print error messages. diff --git a/worker/src/Utils/File.cpp b/worker/src/Utils/File.cpp index 196eddca7c..58155d0862 100644 --- a/worker/src/Utils/File.cpp +++ b/worker/src/Utils/File.cpp @@ -20,7 +20,9 @@ namespace Utils { MS_TRACE(); - struct stat fileStat; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct stat fileStat + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) int err; // Ensure the given file exists. diff --git a/worker/src/Utils/IP.cpp b/worker/src/Utils/IP.cpp index 0ba2416fbf..349f141862 100644 --- a/worker/src/Utils/IP.cpp +++ b/worker/src/Utils/IP.cpp @@ -118,7 +118,7 @@ namespace Utils { MS_TRACE(); - sockaddr_storage addrStorage; + sockaddr_storage addrStorage{}; char ipBuffer[INET6_ADDRSTRLEN] = { 0 }; int err; diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 04ccee6c31..faef45fbf3 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -50,7 +50,7 @@ Worker::Worker(::Channel::ChannelSocket* channel) : channel(channel) // Tell the Node process that we are running. this->shared->channelNotifier->Emit( - std::to_string(Logger::pid), FBS::Notification::Event::WORKER_RUNNING); + std::to_string(Logger::Pid), FBS::Notification::Event::WORKER_RUNNING); MS_DEBUG_DEV("starting libuv loop"); DepLibUV::RunLoop(); @@ -143,7 +143,7 @@ flatbuffers::Offset Worker::FillBuffer( return FBS::Worker::CreateDumpResponseDirect( builder, - Logger::pid, + Logger::Pid, &webRtcServerIds, &routerIds, channelMessageHandlers diff --git a/worker/src/handles/TcpConnectionHandle.cpp b/worker/src/handles/TcpConnectionHandle.cpp index 6a3799becd..a35c7f9b79 100644 --- a/worker/src/handles/TcpConnectionHandle.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -74,11 +74,11 @@ inline static void onShutdown(uv_shutdown_t* req, int /*status*/) /* Instance methods. */ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -TcpConnectionHandle::TcpConnectionHandle(size_t bufferSize) : bufferSize(bufferSize) +TcpConnectionHandle::TcpConnectionHandle(size_t bufferSize) + : bufferSize(bufferSize), uvHandle(new uv_tcp_t) { MS_TRACE(); - this->uvHandle = new uv_tcp_t; this->uvHandle->data = static_cast(this); // NOTE: Don't allocate the buffer here. Instead wait for the first uv_alloc_cb(). diff --git a/worker/src/handles/TcpServerHandle.cpp b/worker/src/handles/TcpServerHandle.cpp index fff1c9e3e2..217f0aee90 100644 --- a/worker/src/handles/TcpServerHandle.cpp +++ b/worker/src/handles/TcpServerHandle.cpp @@ -110,7 +110,8 @@ uint32_t TcpServerHandle::GetSendBufferSize() const MS_TRACE(); int size{ 0 }; - int err = uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + const int err = + uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); if (err) { @@ -124,15 +125,15 @@ void TcpServerHandle::SetSendBufferSize(uint32_t size) { MS_TRACE(); - auto size_int = static_cast(size); + auto sizeInt = static_cast(size); - if (size_int <= 0) + if (sizeInt <= 0) { - MS_THROW_TYPE_ERROR("invalid size: %d", size_int); + MS_THROW_TYPE_ERROR("invalid size: %d", sizeInt); } - int err = - uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + const int err = + uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(sizeInt)); if (err) { @@ -145,7 +146,8 @@ uint32_t TcpServerHandle::GetRecvBufferSize() const MS_TRACE(); int size{ 0 }; - int err = uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + const int err = + uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); if (err) { @@ -159,15 +161,15 @@ void TcpServerHandle::SetRecvBufferSize(uint32_t size) { MS_TRACE(); - auto size_int = static_cast(size); + auto sizeInt = static_cast(size); - if (size_int <= 0) + if (sizeInt <= 0) { - MS_THROW_TYPE_ERROR("invalid size: %d", size_int); + MS_THROW_TYPE_ERROR("invalid size: %d", sizeInt); } - int err = - uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + const int err = + uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(sizeInt)); if (err) { diff --git a/worker/src/handles/TimerHandle.cpp b/worker/src/handles/TimerHandle.cpp index 1b85ce929c..e40ae8efb1 100644 --- a/worker/src/handles/TimerHandle.cpp +++ b/worker/src/handles/TimerHandle.cpp @@ -20,11 +20,10 @@ inline static void onCloseTimer(uv_handle_t* handle) /* Instance methods. */ -TimerHandle::TimerHandle(Listener* listener) : listener(listener) +TimerHandle::TimerHandle(Listener* listener) : listener(listener), uvHandle(new uv_timer_t) { MS_TRACE(); - this->uvHandle = new uv_timer_t; this->uvHandle->data = static_cast(this); const int err = uv_timer_init(DepLibUV::GetLoop(), this->uvHandle); diff --git a/worker/src/handles/UdpSocketHandle.cpp b/worker/src/handles/UdpSocketHandle.cpp index 2f30180a0e..60a0041d66 100644 --- a/worker/src/handles/UdpSocketHandle.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -243,7 +243,7 @@ void UdpSocketHandle::Send( buffer = uv_buf_init(reinterpret_cast(sendData->store), len); - int err = uv_udp_send( + const int err = uv_udp_send( &sendData->req, this->uvHandle, &buffer, 1, addr, static_cast(onSend)); if (err != 0) @@ -272,7 +272,8 @@ uint32_t UdpSocketHandle::GetSendBufferSize() const MS_TRACE(); int size{ 0 }; - int err = uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + const int err = + uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); if (err) { @@ -286,15 +287,15 @@ void UdpSocketHandle::SetSendBufferSize(uint32_t size) { MS_TRACE(); - auto size_int = static_cast(size); + auto sizeInt = static_cast(size); - if (size_int <= 0) + if (sizeInt <= 0) { - MS_THROW_TYPE_ERROR("invalid size: %d", size_int); + MS_THROW_TYPE_ERROR("invalid size: %d", sizeInt); } - int err = - uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + const int err = + uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(sizeInt)); if (err) { @@ -307,7 +308,8 @@ uint32_t UdpSocketHandle::GetRecvBufferSize() const MS_TRACE(); int size{ 0 }; - int err = uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + const int err = + uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); if (err) { @@ -321,15 +323,15 @@ void UdpSocketHandle::SetRecvBufferSize(uint32_t size) { MS_TRACE(); - auto size_int = static_cast(size); + auto sizeInt = static_cast(size); - if (size_int <= 0) + if (sizeInt <= 0) { - MS_THROW_TYPE_ERROR("invalid size: %d", size_int); + MS_THROW_TYPE_ERROR("invalid size: %d", sizeInt); } - int err = - uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + const int err = + uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(sizeInt)); if (err) { diff --git a/worker/src/handles/UnixStreamSocketHandle.cpp b/worker/src/handles/UnixStreamSocketHandle.cpp index 15afe5ead8..bf024d1d8e 100644 --- a/worker/src/handles/UnixStreamSocketHandle.cpp +++ b/worker/src/handles/UnixStreamSocketHandle.cpp @@ -76,13 +76,12 @@ inline static void onShutdown(uv_shutdown_t* req, int /*status*/) UnixStreamSocketHandle::UnixStreamSocketHandle( int fd, size_t bufferSize, UnixStreamSocketHandle::Role role) - : bufferSize(bufferSize), role(role) + : uvHandle(new uv_pipe_t), bufferSize(bufferSize), role(role) { MS_TRACE_STD(); int err; - this->uvHandle = new uv_pipe_t; this->uvHandle->data = static_cast(this); err = uv_pipe_init(DepLibUV::GetLoop(), this->uvHandle, 0); @@ -252,7 +251,8 @@ uint32_t UnixStreamSocketHandle::GetSendBufferSize() const MS_TRACE(); int size{ 0 }; - int err = uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + const int err = + uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); if (err) { @@ -266,15 +266,15 @@ void UnixStreamSocketHandle::SetSendBufferSize(uint32_t size) { MS_TRACE(); - auto size_int = static_cast(size); + auto sizeInt = static_cast(size); - if (size_int <= 0) + if (sizeInt <= 0) { - MS_THROW_TYPE_ERROR_STD("invalid size: %d", size_int); + MS_THROW_TYPE_ERROR_STD("invalid size: %d", sizeInt); } - int err = - uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + const int err = + uv_send_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(sizeInt)); if (err) { @@ -287,7 +287,8 @@ uint32_t UnixStreamSocketHandle::GetRecvBufferSize() const MS_TRACE(); int size{ 0 }; - int err = uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); + const int err = + uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size)); if (err) { @@ -301,15 +302,15 @@ void UnixStreamSocketHandle::SetRecvBufferSize(uint32_t size) { MS_TRACE(); - auto size_int = static_cast(size); + auto sizeInt = static_cast(size); - if (size_int <= 0) + if (sizeInt <= 0) { - MS_THROW_TYPE_ERROR_STD("invalid size: %d", size_int); + MS_THROW_TYPE_ERROR_STD("invalid size: %d", sizeInt); } - int err = - uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(size_int)); + const int err = + uv_recv_buffer_size(reinterpret_cast(this->uvHandle), std::addressof(sizeInt)); if (err) { diff --git a/worker/src/lib.cpp b/worker/src/lib.cpp index 7d427db63d..8ea2572b6a 100644 --- a/worker/src/lib.cpp +++ b/worker/src/lib.cpp @@ -26,14 +26,15 @@ void IgnoreSignals(); +// NOLINTNEXTLINE extern "C" int mediasoup_worker_run( int argc, char* argv[], const char* version, int consumerChannelFd, int producerChannelFd, - int payloadConsumeChannelFd, - int payloadProduceChannelFd, + int /*payloadConsumeChannelFd*/, + int /*payloadProduceChannelFd*/, ChannelReadFn channelReadFn, ChannelReadCtx channelReadCtx, ChannelWriteFn channelWriteFn, @@ -141,7 +142,7 @@ extern "C" int mediasoup_worker_run( #endif // Run the Worker. - Worker worker(channel.get()); + const Worker worker(channel.get()); // Free static stuff. DepLibSRTP::ClassDestroy(); @@ -177,10 +178,12 @@ void IgnoreSignals() MS_TRACE(); int err; - struct sigaction act; // NOLINT(cppcoreguidelines-pro-type-member-init) + struct sigaction act + { + }; // NOLINT(cppcoreguidelines-pro-type-member-init) // clang-format off - absl::flat_hash_map ignoredSignals = + absl::flat_hash_map const ignoredSignals = { { "PIPE", SIGPIPE }, { "HUP", SIGHUP }, @@ -199,10 +202,10 @@ void IgnoreSignals() MS_THROW_ERROR("sigfillset() failed: %s", std::strerror(errno)); } - for (auto& kv : ignoredSignals) + for (const auto& kv : ignoredSignals) { const auto& sigName = kv.first; - int sigId = kv.second; + const int sigId = kv.second; err = sigaction(sigId, &act, nullptr); From f563ace7781b6a8f8f9ea79adb96a251f7fbac5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Jan 2024 13:33:45 +0100 Subject: [PATCH 306/525] Update types/node dep --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 68c871f6e8..c57faca3b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.6", + "@types/node": "^20.10.7", "@typescript-eslint/eslint-plugin": "^6.18.0", "@typescript-eslint/parser": "^6.18.0", "eslint": "^8.56.0", @@ -1632,9 +1632,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.10.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", - "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", + "version": "20.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", + "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -8200,9 +8200,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.10.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", - "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", + "version": "20.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", + "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", "dev": true, "requires": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index b3772d906d..9d0806c54f 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.6", + "@types/node": "^20.10.7", "@typescript-eslint/eslint-plugin": "^6.18.0", "@typescript-eslint/parser": "^6.18.0", "eslint": "^8.56.0", From eb5e204ac17aa841dfa275bcccaf227e6e8a51e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Jan 2024 13:46:04 +0100 Subject: [PATCH 307/525] npm-scripts.mjs: cosmetic --- npm-scripts.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 741eec7236..e463c53fb6 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -613,9 +613,9 @@ async function downloadPrebuiltWorker() { async function uploadMacArmPrebuiltWorker() { if (os.platform() !== 'darwin' || os.arch() !== 'arm64') { - logWarn('uploadMacArmPrebuiltWorker() | invalid platform or architecture'); + logError('uploadMacArmPrebuiltWorker() | invalid platform or architecture'); - return; + exitWithError(); } const octokit = await getOctokit(); From 82017d1dc040b11ffa88b60b318ba2dff46b4689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Jan 2024 16:16:17 +0100 Subject: [PATCH 308/525] Improvements ro Prettier and ESLint (#1305) --- .eslintignore | 21 + .github/CONTRIBUTING.md | 73 - .github/ISSUE_TEMPLATE/Bug_Report.md | 2 - .github/ISSUE_TEMPLATE/Support_Question.md | 2 +- .github/workflows/codeql.yaml | 76 +- .github/workflows/mediasoup-rust.yaml | 1 - .prettierignore | 3 + CHANGELOG.md | 1342 +- CONTRIBUTING.md | 74 + README.md | 68 +- node/tsconfig.json | 15 +- npm-scripts.mjs | 20 +- package-lock.json | 23774 +++++++++---------- package.json | 256 +- worker/.clang-format | 10 +- worker/.clang-tidy | 693 +- worker/scripts/package-lock.json | 5650 ++--- worker/scripts/package.json | 24 +- 18 files changed, 15903 insertions(+), 16201 deletions(-) delete mode 100644 .github/CONTRIBUTING.md create mode 100644 CONTRIBUTING.md diff --git a/.eslintignore b/.eslintignore index 7eadde52eb..0ff585b6fc 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,22 @@ +# NOTE: This file and .eslintignore must contain same paths. + +/.cache +/art +/coverage +/doc +/node/lib /node/src/fbs +/rust +/target +/worker/deps +/worker/fbs +/worker/fuzzer +/worker/include +/worker/prebuild +/worker/pip_invoke +/worker/src +/worker/subprojects +/worker/test +/worker/out +/NO_GIT + diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index c9aa7e2bfe..0000000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,73 +0,0 @@ -# Contributing to mediasoup - -Thanks for taking the time to contribute to mediasoup! 🎉👍 - - -## License - -By contributing to mediasoup, you agree that your contributions will be licensed under its ISC License. - - -## Reporting Bugs - -We primarily use GitHub as an issue tracker. Just open an issue in GitHub if you have encountered a bug in mediasoup. - -If you have questions or doubts about mediasoup or need support, please use the mediasoup Discourse Group instead: - -* https://mediasoup.discourse.group - -If you got a crash in mediasoup, please try to provide a core dump into the issue report: - -* https://mediasoup.org/support/#crashes-in-mediasoup-get-a-core-dump - - -## Pull Request Process - -When creating a Pull Request for mediasoup, ensure that you run the following commands to verify that the code in your PR conforms to the code syntax of the project and does not break existing funtionality: - -* `npm run lint`: Check JavaScript and C++ linting rules. -* `npm run typescript:build`: Compile TypeScript code (under `src/` folder) into JavaScript code (under `lib/` folder). -* `npm run test`: Run JavaScript and C++ test units. - -The full list of `npm` scripts (and `make` tasks) is available in the [doc/Building.md](/doc/Building.md) file. - -Once all these commands succeed, wait for the Travis CI checks to complete and verify they run successfully (otherwise the PR won't be accepted). - - -## Coding Style - -In adition to automatic checks performed by commands above, we also enforce other minor things related to coding style: - -### Comments in JavaScript and C++ - -We use `//` for inline comments in both JavaScript and C++ source files. - -* Comments must start with upercase letter. -* Comments must not exceed 80 columns (split into different lines if necessary). -* Comments must end with a dot. - -Example (good): - -```js -// Calculate foo based on bar value. -const foo = bar / 2; -``` - -Example (bad): - -```js -// calculate foo based on bar value -const foo = bar / 2; -``` - -When adding inline documentation for methods or functions, we use `/** */` syntax. Example: - -```js -/** - * Calculates current score for foo and bar. - */ -function calculateScore(): number -{ - // [...] -} -``` diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.md b/.github/ISSUE_TEMPLATE/Bug_Report.md index 590d6de3eb..1abdb77562 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.md +++ b/.github/ISSUE_TEMPLATE/Bug_Report.md @@ -16,7 +16,6 @@ If you got a crash in mediasoup, please try to provide a core dump into the issu https://mediasoup.org/support/#crashes-in-mediasoup-get-a-core-dump - ### Your environment - Operating system: @@ -26,5 +25,4 @@ https://mediasoup.org/support/#crashes-in-mediasoup-get-a-core-dump - mediasoup version: - mediasoup-client version: - ### Issue description diff --git a/.github/ISSUE_TEMPLATE/Support_Question.md b/.github/ISSUE_TEMPLATE/Support_Question.md index fe989f59fd..2ea1f7895f 100644 --- a/.github/ISSUE_TEMPLATE/Support_Question.md +++ b/.github/ISSUE_TEMPLATE/Support_Question.md @@ -9,4 +9,4 @@ https://mediasoup.discourse.group Before asking any questions, please check the mediasoup official documentation: -https://mediasoup.org/documentation/ +https://mediasoup.org/documentation diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 0c297c1cb2..3e65363d6e 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -32,51 +32,55 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'c-cpp', 'javascript-typescript', 'python' ] + language: ['c-cpp', 'javascript-typescript', 'python'] # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] - # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both. + # Use only 'javascript-typescript' to analyze code written in JavaScript, + # TypeScript or both. + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support. env: MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a + # config file. By default, queries listed here will override any + # specified in a config file. Prefix the list here with "+" to use + # these queries and those in the config file. + # + # Details on CodeQL's query packs refer to: + # https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality - # We need to install pip invoke library. - - name: pip3 install invoke - run: pip3 install invoke - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v3 + # We need to install pip invoke library. + - name: pip3 install invoke + run: pip3 install invoke - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + # If the Autobuild fails above, remove it and uncomment the following + # three lines. Modify them (or add more) to build your code if your + # project, please refer to the EXAMPLE below for guidance. - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: '/language:${{matrix.language}}' + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: '/language:${{matrix.language}}' diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index f9d77fef18..f77892891d 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -52,4 +52,3 @@ jobs: env: DOCS_RS: '1' RUSTDOCFLAGS: '-D rustdoc::broken-intra-doc-links -D rustdoc::private_intra_doc_links' - diff --git a/.prettierignore b/.prettierignore index a9b8d7020d..d4f6347eb3 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,5 @@ +# NOTE: This file and .prettierignore must contain same paths. + /.cache /art /coverage @@ -16,3 +18,4 @@ /worker/subprojects /worker/test /worker/out +/NO_GIT diff --git a/CHANGELOG.md b/CHANGELOG.md index 693b5bea6e..751d876192 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,1756 +1,1462 @@ # Changelog - ### 3.13.15 -* Add worker prebuild binary for Linux kernel 6 ([PR #1300](https://github.com/versatica/mediasoup/pull/1300)). - +- Add worker prebuild binary for Linux kernel 6 ([PR #1300](https://github.com/versatica/mediasoup/pull/1300)). ### 3.13.14 -* Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). -* `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). -* `ListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). -* Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). -* Add RTCP Sender Report trace event ([PR #1267](https://github.com/versatica/mediasoup/pull/1267) by @GithubUser8080). - +- Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). +- `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). +- `ListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). +- Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). +- Add RTCP Sender Report trace event ([PR #1267](https://github.com/versatica/mediasoup/pull/1267) by @GithubUser8080). ### 3.13.13 -* worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). -* liburing: Enable zero copy ([PR #1273](https://github.com/versatica/mediasoup/pull/1273)). -* Fix build on musl based systems (such as Alpine Linux) ([PR #1279](https://github.com/versatica/mediasoup/pull/1279)). - +- worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). +- liburing: Enable zero copy ([PR #1273](https://github.com/versatica/mediasoup/pull/1273)). +- Fix build on musl based systems (such as Alpine Linux) ([PR #1279](https://github.com/versatica/mediasoup/pull/1279)). ### 3.13.12 -* worker: Disable `RtcLogger` usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). -* npm installation: Don't require Python if valid worker prebuilt binary is fetched ([PR #1265](https://github.com/versatica/mediasoup/pull/1265)). -* Update h264-profile-level-id NPM dependency to 1.1.0. - +- worker: Disable `RtcLogger` usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). +- npm installation: Don't require Python if valid worker prebuilt binary is fetched ([PR #1265](https://github.com/versatica/mediasoup/pull/1265)). +- Update h264-profile-level-id NPM dependency to 1.1.0. ### 3.13.11 -* liburing: Avoid extra memcpy on RTP ([PR #1258](https://github.com/versatica/mediasoup/pull/1258)). -* libsrtp: Use our own fork with performance gain ([PR #1260](https://github.com/versatica/mediasoup/pull/1260)). -* `DataConsumer`: Add `addSubchannel()` and `removeSubchannel()` methods ([PR #1263](https://github.com/versatica/mediasoup/pull/1263)). -* Fix Rust `DataConsumer` ([PR #1262](https://github.com/versatica/mediasoup/pull/1262)). - +- liburing: Avoid extra memcpy on RTP ([PR #1258](https://github.com/versatica/mediasoup/pull/1258)). +- libsrtp: Use our own fork with performance gain ([PR #1260](https://github.com/versatica/mediasoup/pull/1260)). +- `DataConsumer`: Add `addSubchannel()` and `removeSubchannel()` methods ([PR #1263](https://github.com/versatica/mediasoup/pull/1263)). +- Fix Rust `DataConsumer` ([PR #1262](https://github.com/versatica/mediasoup/pull/1262)). ### 3.13.10 -* `tasks.py`: Always include `--no-user` in `pip install` commands to avoid the "can not combine --user and --target" error in Windows ([PR #1257](https://github.com/versatica/mediasoup/pull/1257)). - +- `tasks.py`: Always include `--no-user` in `pip install` commands to avoid the "can not combine --user and --target" error in Windows ([PR #1257](https://github.com/versatica/mediasoup/pull/1257)). ### 3.13.9 -* Update worker liburing dependency to 2.4-2 ([PR #1254](https://github.com/versatica/mediasoup/pull/1254)). -* liburing: Enable by default ([PR 1255](https://github.com/versatica/mediasoup/pull/1255)). - +- Update worker liburing dependency to 2.4-2 ([PR #1254](https://github.com/versatica/mediasoup/pull/1254)). +- liburing: Enable by default ([PR 1255](https://github.com/versatica/mediasoup/pull/1255)). ### 3.13.8 -* liburing: Enable liburing usage for SCTP data delivery ([PR 1249](https://github.com/versatica/mediasoup/pull/1249)). -* liburing: Disable by default ([PR 1253](https://github.com/versatica/mediasoup/pull/1253)). - +- liburing: Enable liburing usage for SCTP data delivery ([PR 1249](https://github.com/versatica/mediasoup/pull/1249)). +- liburing: Disable by default ([PR 1253](https://github.com/versatica/mediasoup/pull/1253)). ### 3.13.7 -* Update worker dependencies ([PR #1201](https://github.com/versatica/mediasoup/pull/1201)): - * abseil-cpp 20230802.0-2 - * libuv 1.47.0-1 - * OpenSSL 3.0.8-2 - * usrsctp snapshot ebb18adac6501bad4501b1f6dccb67a1c85cc299 -* Enable `liburing` usage for Linux (kernel versions >= 6) ([PR #1218](https://github.com/versatica/mediasoup/pull/1218)). - +- Update worker dependencies ([PR #1201](https://github.com/versatica/mediasoup/pull/1201)): + - abseil-cpp 20230802.0-2 + - libuv 1.47.0-1 + - OpenSSL 3.0.8-2 + - usrsctp snapshot ebb18adac6501bad4501b1f6dccb67a1c85cc299 +- Enable `liburing` usage for Linux (kernel versions >= 6) ([PR #1218](https://github.com/versatica/mediasoup/pull/1218)). ### 3.13.6 -* Replace make + Makefile with Python Invoke library + tasks.py (also fix installation under path with whitespaces) ([PR #1239](https://github.com/versatica/mediasoup/pull/1239)). - +- Replace make + Makefile with Python Invoke library + tasks.py (also fix installation under path with whitespaces) ([PR #1239](https://github.com/versatica/mediasoup/pull/1239)). ### 3.13.5 -* Fix RTCP SDES packet size calculation ([PR #1236](https://github.com/versatica/mediasoup/pull/1236) based on PR [PR #1234](https://github.com/versatica/mediasoup/pull/1234) by @ybybwdwd). -* RTCP Compound Packet: Use a single DLRR report to hold all ssrc info sub-blocks ([PR #1237](https://github.com/versatica/mediasoup/pull/1237)). - +- Fix RTCP SDES packet size calculation ([PR #1236](https://github.com/versatica/mediasoup/pull/1236) based on PR [PR #1234](https://github.com/versatica/mediasoup/pull/1234) by @ybybwdwd). +- RTCP Compound Packet: Use a single DLRR report to hold all ssrc info sub-blocks ([PR #1237](https://github.com/versatica/mediasoup/pull/1237)). ### 3.13.4 -* Fix RTCP DLRR (Delay Since Last Receiver Report) block parsing ([PR #1234](https://github.com/versatica/mediasoup/pull/1234)). - +- Fix RTCP DLRR (Delay Since Last Receiver Report) block parsing ([PR #1234](https://github.com/versatica/mediasoup/pull/1234)). ### 3.13.3 -* Node: Fix issue when 'pause'/'resume' events are not emitted ([PR #1231](https://github.com/versatica/mediasoup/pull/1231) by @douglaseel). - +- Node: Fix issue when 'pause'/'resume' events are not emitted ([PR #1231](https://github.com/versatica/mediasoup/pull/1231) by @douglaseel). ### 3.13.2 -* FBS: `LayersChangeNotification` body must be optional (fixes a crash) ([PR #1227](https://github.com/versatica/mediasoup/pull/1227)). - +- FBS: `LayersChangeNotification` body must be optional (fixes a crash) ([PR #1227](https://github.com/versatica/mediasoup/pull/1227)). ### 3.13.1 -* Node: Extract version from `package.json` using `require()` ([PR #1217](https://github.com/versatica/mediasoup/pull/1217) by @arcinston). - +- Node: Extract version from `package.json` using `require()` ([PR #1217](https://github.com/versatica/mediasoup/pull/1217) by @arcinston). ### 3.13.0 -* Switch from JSON based messages to `flatbuffers` ([PR #1064](https://github.com/versatica/mediasoup/pull/1064)). -* Add `ListenInfo` in all transports and send/recv buffer size options ([PR #1084](https://github.com/versatica/mediasoup/pull/1084)). -* Add optional `rtcpListenInfo` in `PlainTransportOptions` ([PR #1099](https://github.com/versatica/mediasoup/pull/1099)). -* Add pause/resume API in `DataProducer` and `DataConsumer` ([PR #1104](https://github.com/versatica/mediasoup/pull/1104)). -* DataChannel subchannels feature ([PR #1152](https://github.com/versatica/mediasoup/pull/1152)). -* `Worker`: Make DTLS fragment stay within MTU size range ([PR #1156](https://github.com/versatica/mediasoup/pull/1156), based on [PR #1143](https://github.com/versatica/mediasoup/pull/1143) by @vpnts-se). - +- Switch from JSON based messages to `flatbuffers` ([PR #1064](https://github.com/versatica/mediasoup/pull/1064)). +- Add `ListenInfo` in all transports and send/recv buffer size options ([PR #1084](https://github.com/versatica/mediasoup/pull/1084)). +- Add optional `rtcpListenInfo` in `PlainTransportOptions` ([PR #1099](https://github.com/versatica/mediasoup/pull/1099)). +- Add pause/resume API in `DataProducer` and `DataConsumer` ([PR #1104](https://github.com/versatica/mediasoup/pull/1104)). +- DataChannel subchannels feature ([PR #1152](https://github.com/versatica/mediasoup/pull/1152)). +- `Worker`: Make DTLS fragment stay within MTU size range ([PR #1156](https://github.com/versatica/mediasoup/pull/1156), based on [PR #1143](https://github.com/versatica/mediasoup/pull/1143) by @vpnts-se). ### 3.12.16 -* Fix `IceServer` crash when client uses ICE renomination ([PR #1182](https://github.com/versatica/mediasoup/pull/1182)). - +- Fix `IceServer` crash when client uses ICE renomination ([PR #1182](https://github.com/versatica/mediasoup/pull/1182)). ### 3.12.15 -* Fix NPM "postinstall" task in Windows ([PR #1187](https://github.com/versatica/mediasoup/pull/1187)). - +- Fix NPM "postinstall" task in Windows ([PR #1187](https://github.com/versatica/mediasoup/pull/1187)). ### 3.12.14 -* CI: Use Node.js version 20 ([PR #1177](https://github.com/versatica/mediasoup/pull/1177)). -* Use given `PYTHON` environment variable (if given) when running `worker/scripts/getmake.py` ([PR #1186](https://github.com/versatica/mediasoup/pull/1186)). - +- CI: Use Node.js version 20 ([PR #1177](https://github.com/versatica/mediasoup/pull/1177)). +- Use given `PYTHON` environment variable (if given) when running `worker/scripts/getmake.py` ([PR #1186](https://github.com/versatica/mediasoup/pull/1186)). ### 3.12.13 -* Bump up Meson from 1.1.0 to 1.2.1 (fixes Xcode 15 build issues) ([PR #1163](https://github.com/versatica/mediasoup/pull/1163) by @arcinston). - +- Bump up Meson from 1.1.0 to 1.2.1 (fixes Xcode 15 build issues) ([PR #1163](https://github.com/versatica/mediasoup/pull/1163) by @arcinston). ### 3.12.12 -* Support C++20 ([PR #1150](https://github.com/versatica/mediasoup/pull/1150) by @o-u-p). - +- Support C++20 ([PR #1150](https://github.com/versatica/mediasoup/pull/1150) by @o-u-p). ### 3.12.11 -* Google Transport Feedback: Read Reference Time field as 24bits signed as per spec ([PR #1145](https://github.com/versatica/mediasoup/pull/1145)). - +- Google Transport Feedback: Read Reference Time field as 24bits signed as per spec ([PR #1145](https://github.com/versatica/mediasoup/pull/1145)). ### 3.12.10 -* Node: Rename `WebRtcTransport.webRtcServerClosed()` to `listenServerClosed()` ([PR #1141](https://github.com/versatica/mediasoup/pull/1141) by @piranna). - +- Node: Rename `WebRtcTransport.webRtcServerClosed()` to `listenServerClosed()` ([PR #1141](https://github.com/versatica/mediasoup/pull/1141) by @piranna). ### 3.12.9 -* Fix RTCP SDES ([PR #1139](https://github.com/versatica/mediasoup/pull/1139)). - +- Fix RTCP SDES ([PR #1139](https://github.com/versatica/mediasoup/pull/1139)). ### 3.12.8 -* Export `workerBin` absolute path ([PR #1123](https://github.com/versatica/mediasoup/pull/1123)). - +- Export `workerBin` absolute path ([PR #1123](https://github.com/versatica/mediasoup/pull/1123)). ### 3.12.7 -* `SimulcastConsumer`: Fix lack of "layerschange" event when all streams in the producer die ([PR #1122](https://github.com/versatica/mediasoup/pull/1122)). - +- `SimulcastConsumer`: Fix lack of "layerschange" event when all streams in the producer die ([PR #1122](https://github.com/versatica/mediasoup/pull/1122)). ### 3.12.6 -* `Worker`: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). -* `RtpStreamRecv`: Fix jitter calculation ([PR #1117](https://github.com/versatica/mediasoup/pull/1117), thanks to @penguinol). -* Revert "Node: make types.ts only export types rather than the entire class/code" ([PR #1109](https://github.com/versatica/mediasoup/pull/1109)) because it requires `typescript` >= 5 in the apps that import mediasoup and we don't want to be that strict yet. - +- `Worker`: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). +- `RtpStreamRecv`: Fix jitter calculation ([PR #1117](https://github.com/versatica/mediasoup/pull/1117), thanks to @penguinol). +- Revert "Node: make types.ts only export types rather than the entire class/code" ([PR #1109](https://github.com/versatica/mediasoup/pull/1109)) because it requires `typescript` >= 5 in the apps that import mediasoup and we don't want to be that strict yet. ### 3.12.5 -* `DataConsumer`: Fix removed 'bufferedamountlow' notification ([PR #1113](https://github.com/versatica/mediasoup/pull/1113)). - +- `DataConsumer`: Fix removed 'bufferedamountlow' notification ([PR #1113](https://github.com/versatica/mediasoup/pull/1113)). ### 3.12.4 -* Fix downloaded prebuilt binary check on Windows ([PR #1105](https://github.com/versatica/mediasoup/pull/1105) by @woodfe). - +- Fix downloaded prebuilt binary check on Windows ([PR #1105](https://github.com/versatica/mediasoup/pull/1105) by @woodfe). ### 3.12.3 Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://github.com/versatica/mediasoup/pull/1093)). - ### 3.12.2 -* CI: Use `ubuntu-20.04` to build mediasoup-worker prebuilt on Linux ([PR #1092](https://github.com/versatica/mediasoup/pull/1092)). - +- CI: Use `ubuntu-20.04` to build mediasoup-worker prebuilt on Linux ([PR #1092](https://github.com/versatica/mediasoup/pull/1092)). ### 3.12.1 -* mediasoup-worker prebuild: Fallback to local building if fetched binary doesn't run on current host ([PR #1090](https://github.com/versatica/mediasoup/pull/1090)). - +- mediasoup-worker prebuild: Fallback to local building if fetched binary doesn't run on current host ([PR #1090](https://github.com/versatica/mediasoup/pull/1090)). ### 3.12.0 -* Automate and publish prebuilt `mediasoup-worker` binaries ([PR #1087](https://github.com/versatica/mediasoup/pull/1087), thanks to @barlock for his work in ([PR #1083](https://github.com/versatica/mediasoup/pull/1083)). - +- Automate and publish prebuilt `mediasoup-worker` binaries ([PR #1087](https://github.com/versatica/mediasoup/pull/1087), thanks to @barlock for his work in ([PR #1083](https://github.com/versatica/mediasoup/pull/1083)). ### 3.11.26 -* `Worker`: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to @o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). - +- `Worker`: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to @o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). ### 3.11.25 -* `Worker`: Require C++17, Meson >= 1.1.0 and update subprojects ([PR #1081](https://github.com/versatica/mediasoup/pull/1081)). - +- `Worker`: Require C++17, Meson >= 1.1.0 and update subprojects ([PR #1081](https://github.com/versatica/mediasoup/pull/1081)). ### 3.11.24 -* `SeqManager`: Fix performance regression ([PR #1068](https://github.com/versatica/mediasoup/pull/1068), thanks to @vpalmisano for properly reporting). - +- `SeqManager`: Fix performance regression ([PR #1068](https://github.com/versatica/mediasoup/pull/1068), thanks to @vpalmisano for properly reporting). ### 3.11.23 -* Node: Fix `appData` for `Transport` and `RtpObserver` parent classes ([PR #1066](https://github.com/versatica/mediasoup/pull/1066)). - +- Node: Fix `appData` for `Transport` and `RtpObserver` parent classes ([PR #1066](https://github.com/versatica/mediasoup/pull/1066)). ### 3.11.22 -* `RtpStreamRecv`: Only perform RTP inactivity check on simulcast streams ([PR #1061](https://github.com/versatica/mediasoup/pull/1061)). -* `SeqManager`: Properly remove old dropped entries ([PR #1054](https://github.com/versatica/mediasoup/pull/1054)). -* libwebrtc: Upgrade trendline estimator to improve low bandwidth conditions ([PR #1055](https://github.com/versatica/mediasoup/pull/1055) by @ggarber). -* libwebrtc: Fix bandwidth probation dead state ([PR #1031](https://github.com/versatica/mediasoup/pull/1031) by @vpalmisano). - +- `RtpStreamRecv`: Only perform RTP inactivity check on simulcast streams ([PR #1061](https://github.com/versatica/mediasoup/pull/1061)). +- `SeqManager`: Properly remove old dropped entries ([PR #1054](https://github.com/versatica/mediasoup/pull/1054)). +- libwebrtc: Upgrade trendline estimator to improve low bandwidth conditions ([PR #1055](https://github.com/versatica/mediasoup/pull/1055) by @ggarber). +- libwebrtc: Fix bandwidth probation dead state ([PR #1031](https://github.com/versatica/mediasoup/pull/1031) by @vpalmisano). ### 3.11.21 -* Fix check division by zero in transport congestion control ([PR #1049](https://github.com/versatica/mediasoup/pull/1049) by @ggarber). -* Fix lost pending statuses in transport CC feedback ([PR #1050](https://github.com/versatica/mediasoup/pull/1050) by @ggarber). - +- Fix check division by zero in transport congestion control ([PR #1049](https://github.com/versatica/mediasoup/pull/1049) by @ggarber). +- Fix lost pending statuses in transport CC feedback ([PR #1050](https://github.com/versatica/mediasoup/pull/1050) by @ggarber). ### 3.11.20 -* `RtpStreamSend`: Reset RTP retransmission buffer upon RTP sequence number reset ([PR #1041](https://github.com/versatica/mediasoup/pull/1041)). -* `RtpRetransmissionBuffer`: Handle corner case in which received packet has lower seq than newest packet in the buffer but higher timestamp ([PR #1044](https://github.com/versatica/mediasoup/pull/1044)). -* `SeqManager`: Fix crash and add fuzzer ([PR #1045](https://github.com/versatica/mediasoup/pull/1045)). -* Node: Make `appData` TS typed and writable ([PR #1046](https://github.com/versatica/mediasoup/pull/1046), credits to @mango-martin). - +- `RtpStreamSend`: Reset RTP retransmission buffer upon RTP sequence number reset ([PR #1041](https://github.com/versatica/mediasoup/pull/1041)). +- `RtpRetransmissionBuffer`: Handle corner case in which received packet has lower seq than newest packet in the buffer but higher timestamp ([PR #1044](https://github.com/versatica/mediasoup/pull/1044)). +- `SeqManager`: Fix crash and add fuzzer ([PR #1045](https://github.com/versatica/mediasoup/pull/1045)). +- Node: Make `appData` TS typed and writable ([PR #1046](https://github.com/versatica/mediasoup/pull/1046), credits to @mango-martin). ### 3.11.19 -* `SvcConsumer`: Properly handle VP9 K-SVC bandwidth allocation ([PR #1036](https://github.com/versatica/mediasoup/pull/1036) by @vpalmisano). - +- `SvcConsumer`: Properly handle VP9 K-SVC bandwidth allocation ([PR #1036](https://github.com/versatica/mediasoup/pull/1036) by @vpalmisano). ### 3.11.18 -* `RtpRetransmissionBuffer`: Consider the case of packet with newest timestamp but "old" seq number ([PR #1039](https://github.com/versatica/mediasoup/pull/1039)). - +- `RtpRetransmissionBuffer`: Consider the case of packet with newest timestamp but "old" seq number ([PR #1039](https://github.com/versatica/mediasoup/pull/1039)). ### 3.11.17 -* Add `transport.setMinOutgoingBitrate()` method ([PR #1038](https://github.com/versatica/mediasoup/pull/1038), credits to @ jcague). -* `RTC::RetransmissionBuffer`: Increase `RetransmissionBufferMaxItems` from 2500 to 5000. - +- Add `transport.setMinOutgoingBitrate()` method ([PR #1038](https://github.com/versatica/mediasoup/pull/1038), credits to @ jcague). +- `RTC::RetransmissionBuffer`: Increase `RetransmissionBufferMaxItems` from 2500 to 5000. ### 3.11.16 -* Fix `SeqManager`: Properly consider previous cycle dropped inputs ([PR #1032](https://github.com/versatica/mediasoup/pull/1032)). -* `RtpRetransmissionBuffer`: Get rid of not necessary `startSeq` private member ([PR #1029](https://github.com/versatica/mediasoup/pull/1029)). -* Node: Upgrade TypeScript to 5.0.2. - +- Fix `SeqManager`: Properly consider previous cycle dropped inputs ([PR #1032](https://github.com/versatica/mediasoup/pull/1032)). +- `RtpRetransmissionBuffer`: Get rid of not necessary `startSeq` private member ([PR #1029](https://github.com/versatica/mediasoup/pull/1029)). +- Node: Upgrade TypeScript to 5.0.2. ### 3.11.15 -* `RtpRetransmissionBuffer`: Fix crash and add fuzzer ([PR #1028](https://github.com/versatica/mediasoup/pull/1028)). - +- `RtpRetransmissionBuffer`: Fix crash and add fuzzer ([PR #1028](https://github.com/versatica/mediasoup/pull/1028)). ### 3.11.14 -* Refactor RTP retransmission buffer in a separate and testable `RTC::RetransmissionBuffer` class ([PR #1023](https://github.com/versatica/mediasoup/pull/1023)). - +- Refactor RTP retransmission buffer in a separate and testable `RTC::RetransmissionBuffer` class ([PR #1023](https://github.com/versatica/mediasoup/pull/1023)). ### 3.11.13 -* `AudioLevelObserver`: Use multimap rather than map to avoid conflict if various Producers generate same audio level ([PR #1021](https://github.com/versatica/mediasoup/pull/1021), issue reported by @buptlsp). - +- `AudioLevelObserver`: Use multimap rather than map to avoid conflict if various Producers generate same audio level ([PR #1021](https://github.com/versatica/mediasoup/pull/1021), issue reported by @buptlsp). ### 3.11.12 -* Fix jitter calculation ([PR #1019](https://github.com/versatica/mediasoup/pull/1019), credits to @alexciarlillo and @snnz). - +- Fix jitter calculation ([PR #1019](https://github.com/versatica/mediasoup/pull/1019), credits to @alexciarlillo and @snnz). ### 3.11.11 -* Add support for RTCP NACK in OPUS ([PR #1015](https://github.com/versatica/mediasoup/pull/1015)). - +- Add support for RTCP NACK in OPUS ([PR #1015](https://github.com/versatica/mediasoup/pull/1015)). ### 3.11.10 -* Download and use MSYS/make locally for Windows postinstall ([PR #792](https://github.com/versatica/mediasoup/pull/792) by @snnz). - +- Download and use MSYS/make locally for Windows postinstall ([PR #792](https://github.com/versatica/mediasoup/pull/792) by @snnz). ### 3.11.9 -* Allow simulcast with a single encoding (and N temporal layers) ([PR #1013](https://github.com/versatica/mediasoup/pull/1013)). -* Update libsrtp to 2.5.0. - +- Allow simulcast with a single encoding (and N temporal layers) ([PR #1013](https://github.com/versatica/mediasoup/pull/1013)). +- Update libsrtp to 2.5.0. ### 3.11.8 -* `SimulcastConsumer::GetDesiredBitrate()`: Choose the highest bitrate among all Producer streams ([PR #992](https://github.com/versatica/mediasoup/pull/992)). -* `SimulcastConsumer`: Fix frozen video when syncing keyframe is discarded due to too high RTP timestamp extra offset needed ([PR #999](https://github.com/versatica/mediasoup/pull/999), thanks to @satoren for properly reporting the issue and helping with the solution). - +- `SimulcastConsumer::GetDesiredBitrate()`: Choose the highest bitrate among all Producer streams ([PR #992](https://github.com/versatica/mediasoup/pull/992)). +- `SimulcastConsumer`: Fix frozen video when syncing keyframe is discarded due to too high RTP timestamp extra offset needed ([PR #999](https://github.com/versatica/mediasoup/pull/999), thanks to @satoren for properly reporting the issue and helping with the solution). ### 3.11.7 -* libwebrtc: Fix crash due to invalid `arrival_time` value ([PR #985](https://github.com/versatica/mediasoup/pull/985) by @ggarber). -* libwebrtc: Replace `MS_ASSERT()` with `MS_ERROR()` ([PR #988](https://github.com/versatica/mediasoup/pull/988)). - +- libwebrtc: Fix crash due to invalid `arrival_time` value ([PR #985](https://github.com/versatica/mediasoup/pull/985) by @ggarber). +- libwebrtc: Replace `MS_ASSERT()` with `MS_ERROR()` ([PR #988](https://github.com/versatica/mediasoup/pull/988)). ### 3.11.6 -* Fix wrong `PictureID` rolling over in VP9 and VP8 ([PR #984](https://github.com/versatica/mediasoup/pull/984) by @jcague). - +- Fix wrong `PictureID` rolling over in VP9 and VP8 ([PR #984](https://github.com/versatica/mediasoup/pull/984) by @jcague). ### 3.11.5 -* Require Node.js >= 16 ([PR #973](https://github.com/versatica/mediasoup/pull/973)). -* Fix wrong `Consumer` bandwidth estimation under `Producer` packet loss ([PR #962](https://github.com/versatica/mediasoup/pull/962) by @ggarber). - +- Require Node.js >= 16 ([PR #973](https://github.com/versatica/mediasoup/pull/973)). +- Fix wrong `Consumer` bandwidth estimation under `Producer` packet loss ([PR #962](https://github.com/versatica/mediasoup/pull/962) by @ggarber). ### 3.11.4 -* Node: Migrate tests to TypeScript ([PR #958](https://github.com/versatica/mediasoup/pull/958)). -* Node: Remove compiled JavaScript from repository and compile TypeScript code on NPM `prepare` script on demand when installed via git ([PR #954](https://github.com/versatica/mediasoup/pull/954)). -* `Worker`: Add `RTC::Shared` singleton for RTC entities ([PR #953](https://github.com/versatica/mediasoup/pull/953)). -* Update OpenSSL to 3.0.7. - +- Node: Migrate tests to TypeScript ([PR #958](https://github.com/versatica/mediasoup/pull/958)). +- Node: Remove compiled JavaScript from repository and compile TypeScript code on NPM `prepare` script on demand when installed via git ([PR #954](https://github.com/versatica/mediasoup/pull/954)). +- `Worker`: Add `RTC::Shared` singleton for RTC entities ([PR #953](https://github.com/versatica/mediasoup/pull/953)). +- Update OpenSSL to 3.0.7. ### 3.11.3 -* `ChannelMessageHandlers`: Make `RegisterHandler()` not remove the existing handler if another one with same `id` is given ([PR #952](https://github.com/versatica/mediasoup/pull/952)). - +- `ChannelMessageHandlers`: Make `RegisterHandler()` not remove the existing handler if another one with same `id` is given ([PR #952](https://github.com/versatica/mediasoup/pull/952)). ### 3.11.2 -* Fix installation issue in Linux due to a bug in ninja latest version 1.11.1 ([PR #948](https://github.com/versatica/mediasoup/pull/948)). - +- Fix installation issue in Linux due to a bug in ninja latest version 1.11.1 ([PR #948](https://github.com/versatica/mediasoup/pull/948)). ### 3.11.1 -* `ActiveSpeakerObserver`: Revert 'dominantspeaker' event changes in [PR #941](https://github.com/versatica/mediasoup/pull/941) to avoid breaking changes ([PR #947](https://github.com/versatica/mediasoup/pull/947)). - +- `ActiveSpeakerObserver`: Revert 'dominantspeaker' event changes in [PR #941](https://github.com/versatica/mediasoup/pull/941) to avoid breaking changes ([PR #947](https://github.com/versatica/mediasoup/pull/947)). ### 3.11.0 -* `Transport`: Remove duplicate call to method ([PR #931](https://github.com/versatica/mediasoup/pull/931)). -* RTCP: Adjust maximum compound packet size ([PR #934](https://github.com/versatica/mediasoup/pull/934)). -* `DataConsumer`: Fix `bufferedAmount` type to be a number again ([PR #936](https://github.com/versatica/mediasoup/pull/936)). -* `ActiveSpeakerObserver`: Fix 'dominantspeaker' event by having a single `Producer` as argument rather than an array with a single `Producer` into it ([PR #941](https://github.com/versatica/mediasoup/pull/941)). -* `ActiveSpeakerObserver`: Fix memory leak ([PR #942](https://github.com/versatica/mediasoup/pull/942)). -* Fix some libwebrtc issues ([PR #944](https://github.com/versatica/mediasoup/pull/944)). -* Tests: Normalize hexadecimal data representation ([PR #945](https://github.com/versatica/mediasoup/pull/945)). -* `SctpAssociation`: Fix memory violation ([PR #943](https://github.com/versatica/mediasoup/pull/943)). - +- `Transport`: Remove duplicate call to method ([PR #931](https://github.com/versatica/mediasoup/pull/931)). +- RTCP: Adjust maximum compound packet size ([PR #934](https://github.com/versatica/mediasoup/pull/934)). +- `DataConsumer`: Fix `bufferedAmount` type to be a number again ([PR #936](https://github.com/versatica/mediasoup/pull/936)). +- `ActiveSpeakerObserver`: Fix 'dominantspeaker' event by having a single `Producer` as argument rather than an array with a single `Producer` into it ([PR #941](https://github.com/versatica/mediasoup/pull/941)). +- `ActiveSpeakerObserver`: Fix memory leak ([PR #942](https://github.com/versatica/mediasoup/pull/942)). +- Fix some libwebrtc issues ([PR #944](https://github.com/versatica/mediasoup/pull/944)). +- Tests: Normalize hexadecimal data representation ([PR #945](https://github.com/versatica/mediasoup/pull/945)). +- `SctpAssociation`: Fix memory violation ([PR #943](https://github.com/versatica/mediasoup/pull/943)). ### 3.10.12 -* Fix worker crash due to `std::out_of_range` exception ([PR #933](https://github.com/versatica/mediasoup/pull/933)). - +- Fix worker crash due to `std::out_of_range` exception ([PR #933](https://github.com/versatica/mediasoup/pull/933)). ### 3.10.11 -* RTCP: Fix trailing space needed by `srtp_protect_rtcp()` ([PR #929](https://github.com/versatica/mediasoup/pull/929)). - +- RTCP: Fix trailing space needed by `srtp_protect_rtcp()` ([PR #929](https://github.com/versatica/mediasoup/pull/929)). ### 3.10.10 -* Fix the JSON serialization for the payload channel `rtp` event ([PR #926](https://github.com/versatica/mediasoup/pull/926) by @mhammo). - +- Fix the JSON serialization for the payload channel `rtp` event ([PR #926](https://github.com/versatica/mediasoup/pull/926) by @mhammo). ### 3.10.9 -* RTCP enhancements ([PR #914](https://github.com/versatica/mediasoup/pull/914)). - +- RTCP enhancements ([PR #914](https://github.com/versatica/mediasoup/pull/914)). ### 3.10.8 -* `Consumer`: use a bitset instead of a set for supported payload types ([PR #919](https://github.com/versatica/mediasoup/pull/919)). -* RtpPacket: optimize UpdateMid() ([PR #920](https://github.com/versatica/mediasoup/pull/920)). -* Little optimizations and modernization ([PR #916](https://github.com/versatica/mediasoup/pull/916)). -* Fix SIGSEGV at `RTC::WebRtcTransport::OnIceServerTupleRemoved()` ([PR #915](https://github.com/versatica/mediasoup/pull/915), credits to @ybybwdwd). -* `WebRtcServer`: Make `port` optional (if not given, a random available port from the `Worker` port range is used) ([PR #908](https://github.com/versatica/mediasoup/pull/908) by @satoren). - +- `Consumer`: use a bitset instead of a set for supported payload types ([PR #919](https://github.com/versatica/mediasoup/pull/919)). +- RtpPacket: optimize UpdateMid() ([PR #920](https://github.com/versatica/mediasoup/pull/920)). +- Little optimizations and modernization ([PR #916](https://github.com/versatica/mediasoup/pull/916)). +- Fix SIGSEGV at `RTC::WebRtcTransport::OnIceServerTupleRemoved()` ([PR #915](https://github.com/versatica/mediasoup/pull/915), credits to @ybybwdwd). +- `WebRtcServer`: Make `port` optional (if not given, a random available port from the `Worker` port range is used) ([PR #908](https://github.com/versatica/mediasoup/pull/908) by @satoren). ### 3.10.7 -* Forward `abs-capture-time` RTP extension also for audio packets ([PR #911](https://github.com/versatica/mediasoup/pull/911)). - +- Forward `abs-capture-time` RTP extension also for audio packets ([PR #911](https://github.com/versatica/mediasoup/pull/911)). ### 3.10.6 -* Node: Define TypeScript types for `internal` and `data` objects ([PR #891](https://github.com/versatica/mediasoup/pull/891)). -* `Channel` and `PayloadChannel`: Refactor `internal` with a single `handlerId` ([PR #889](https://github.com/versatica/mediasoup/pull/889)). -* `Channel` and `PayloadChannel`: Optimize message format and JSON generation ([PR #893](https://github.com/versatica/mediasoup/pull/893)). -* New C++ `ChannelMessageHandlers` class ([PR #894](https://github.com/versatica/mediasoup/pull/894)). -* Fix Rust support after recent changes ([PR #898](https://github.com/versatica/mediasoup/pull/898)). -* Modify `FeedbackRtpTransport` and tests to be compliant with latest libwebrtc code, make reference time to be unsigned ([PR #899](https://github.com/versatica/mediasoup/pull/899) by @penguinol and @sarumjanuch). - +- Node: Define TypeScript types for `internal` and `data` objects ([PR #891](https://github.com/versatica/mediasoup/pull/891)). +- `Channel` and `PayloadChannel`: Refactor `internal` with a single `handlerId` ([PR #889](https://github.com/versatica/mediasoup/pull/889)). +- `Channel` and `PayloadChannel`: Optimize message format and JSON generation ([PR #893](https://github.com/versatica/mediasoup/pull/893)). +- New C++ `ChannelMessageHandlers` class ([PR #894](https://github.com/versatica/mediasoup/pull/894)). +- Fix Rust support after recent changes ([PR #898](https://github.com/versatica/mediasoup/pull/898)). +- Modify `FeedbackRtpTransport` and tests to be compliant with latest libwebrtc code, make reference time to be unsigned ([PR #899](https://github.com/versatica/mediasoup/pull/899) by @penguinol and @sarumjanuch). ### 3.10.5 -* `RtpStreamSend`: Do not store too old RTP packets ([PR #885](https://github.com/versatica/mediasoup/pull/885)). -* Log error details in channel socket. ([PR #875](https://github.com/versatica/mediasoup/pull/875) by @mstyura). +- `RtpStreamSend`: Do not store too old RTP packets ([PR #885](https://github.com/versatica/mediasoup/pull/885)). +- Log error details in channel socket. ([PR #875](https://github.com/versatica/mediasoup/pull/875) by @mstyura). ### 3.10.4 -* Do not clone RTP packets if not needed ([PR #850](https://github.com/versatica/mediasoup/pull/850)). -* Fix DTLS related crash ([PR #867](https://github.com/versatica/mediasoup/pull/867)). - +- Do not clone RTP packets if not needed ([PR #850](https://github.com/versatica/mediasoup/pull/850)). +- Fix DTLS related crash ([PR #867](https://github.com/versatica/mediasoup/pull/867)). ### 3.10.3 -* `SimpleConsumer`: Fix. Only process Opus codec ([PR #865](https://github.com/versatica/mediasoup/pull/865)). -* TypeScript: Improve `WebRtcTransportOptions` type to not allow `webRtcServer` and `listenIps`options at the same time ([PR #852](https://github.com/versatica/mediasoup/pull/852)). - +- `SimpleConsumer`: Fix. Only process Opus codec ([PR #865](https://github.com/versatica/mediasoup/pull/865)). +- TypeScript: Improve `WebRtcTransportOptions` type to not allow `webRtcServer` and `listenIps`options at the same time ([PR #852](https://github.com/versatica/mediasoup/pull/852)). ### 3.10.2 -* Fix release contents by including meson_options.txt ([PR #863](https://github.com/versatica/mediasoup/pull/863)). - +- Fix release contents by including meson_options.txt ([PR #863](https://github.com/versatica/mediasoup/pull/863)). ### 3.10.1 -* `RtpStreamSend`: Memory optimizations ([PR #840](https://github.com/versatica/mediasoup/pull/840)). Extracted from #675, by @nazar-pc. -* `SimpleConsumer`: Opus DTX ignore capabilities ([PR #846](https://github.com/versatica/mediasoup/pull/846)). -* Update `libuv` to 1.44.1: Fixes `libuv` build ([PR #857](https://github.com/versatica/mediasoup/pull/857)). - +- `RtpStreamSend`: Memory optimizations ([PR #840](https://github.com/versatica/mediasoup/pull/840)). Extracted from #675, by @nazar-pc. +- `SimpleConsumer`: Opus DTX ignore capabilities ([PR #846](https://github.com/versatica/mediasoup/pull/846)). +- Update `libuv` to 1.44.1: Fixes `libuv` build ([PR #857](https://github.com/versatica/mediasoup/pull/857)). ### 3.10.0 -* `WebRtcServer`: A new class that brings to `WebRtcTransports` the ability to listen on a single UDP/TCP port ([PR #834](https://github.com/versatica/mediasoup/pull/834)). -* More SRTP crypto suites ([PR #837](https://github.com/versatica/mediasoup/pull/837)). -* Improve `EnhancedEventEmitter` ([PR #836](https://github.com/versatica/mediasoup/pull/836)). -* `TransportCongestionControlClient`: Allow setting max outgoing bitrate before `tccClient` is created ([PR #833](https://github.com/versatica/mediasoup/pull/833)). -* Update TypeScript version. - +- `WebRtcServer`: A new class that brings to `WebRtcTransports` the ability to listen on a single UDP/TCP port ([PR #834](https://github.com/versatica/mediasoup/pull/834)). +- More SRTP crypto suites ([PR #837](https://github.com/versatica/mediasoup/pull/837)). +- Improve `EnhancedEventEmitter` ([PR #836](https://github.com/versatica/mediasoup/pull/836)). +- `TransportCongestionControlClient`: Allow setting max outgoing bitrate before `tccClient` is created ([PR #833](https://github.com/versatica/mediasoup/pull/833)). +- Update TypeScript version. ### 3.9.17 -* `RateCalculator`: Fix old buffer items cleanup ([PR #830](https://github.com/versatica/mediasoup/pull/830) by @dsdolzhenko). -* Update TypeScript version. - +- `RateCalculator`: Fix old buffer items cleanup ([PR #830](https://github.com/versatica/mediasoup/pull/830) by @dsdolzhenko). +- Update TypeScript version. ### 3.9.16 -* `SimulcastConsumer`: Fix spatial layer switch with unordered packets ([PR #823](https://github.com/versatica/mediasoup/pull/823) by @jcague). -* Update TypeScript version. - +- `SimulcastConsumer`: Fix spatial layer switch with unordered packets ([PR #823](https://github.com/versatica/mediasoup/pull/823) by @jcague). +- Update TypeScript version. ### 3.9.15 -* `RateCalculator`: Revert Fix old buffer items cleanup ([PR #819](https://github.com/versatica/mediasoup/pull/819) by @dsdolzhenko). - +- `RateCalculator`: Revert Fix old buffer items cleanup ([PR #819](https://github.com/versatica/mediasoup/pull/819) by @dsdolzhenko). ### 3.9.14 -* `NackGenerator`: Add a configurable delay before sending NACK ([PR #827](https://github.com/versatica/mediasoup/pull/827), credits to @penguinol). -* `SimulcastConsumer`: Fix a race condition in SimulcastConsumer ([PR #825](https://github.com/versatica/mediasoup/pull/825) by @dsdolzhenko). -* Add support for H264 SVC (#798 by @prtmD). -* `RtpStreamSend`: Support receive RTCP-XR RRT and send RTCP-XR DLRR ([PR #781](https://github.com/versatica/mediasoup/pull/781) by @aggresss). -* `RateCalculator`: Fix old buffer items cleanup ([PR #819](https://github.com/versatica/mediasoup/pull/819) by @dsdolzhenko). -* `DirectTransport`: Create a buffer to process RTP packets ([PR #730](https://github.com/versatica/mediasoup/pull/730) by @rtctt). -* Node: Improve `appData` TypeScript syntax and initialization. -* Allow setting max outgoing bitrate below the initial value ([PR #826](https://github.com/versatica/mediasoup/pull/826) by @ggarber). -* Update TypeScript version. - +- `NackGenerator`: Add a configurable delay before sending NACK ([PR #827](https://github.com/versatica/mediasoup/pull/827), credits to @penguinol). +- `SimulcastConsumer`: Fix a race condition in SimulcastConsumer ([PR #825](https://github.com/versatica/mediasoup/pull/825) by @dsdolzhenko). +- Add support for H264 SVC (#798 by @prtmD). +- `RtpStreamSend`: Support receive RTCP-XR RRT and send RTCP-XR DLRR ([PR #781](https://github.com/versatica/mediasoup/pull/781) by @aggresss). +- `RateCalculator`: Fix old buffer items cleanup ([PR #819](https://github.com/versatica/mediasoup/pull/819) by @dsdolzhenko). +- `DirectTransport`: Create a buffer to process RTP packets ([PR #730](https://github.com/versatica/mediasoup/pull/730) by @rtctt). +- Node: Improve `appData` TypeScript syntax and initialization. +- Allow setting max outgoing bitrate below the initial value ([PR #826](https://github.com/versatica/mediasoup/pull/826) by @ggarber). +- Update TypeScript version. ### 3.9.13 -* `VP8`: Do not discard `TL0PICIDX` from Temporal Layers higher than 0 (PR @817 by @jcague). -* Update TypeScript version. - +- `VP8`: Do not discard `TL0PICIDX` from Temporal Layers higher than 0 (PR @817 by @jcague). +- Update TypeScript version. ### 3.9.12 -* `DtlsTransport`: Make DTLS negotiation run immediately ([PR #815](https://github.com/versatica/mediasoup/pull/815)). -* Update TypeScript version. - +- `DtlsTransport`: Make DTLS negotiation run immediately ([PR #815](https://github.com/versatica/mediasoup/pull/815)). +- Update TypeScript version. ### 3.9.11 -* Modify `SimulcastConsumer` to keep using layers without good scores ([PR #804](https://github.com/versatica/mediasoup/pull/804) by @ggarber). - +- Modify `SimulcastConsumer` to keep using layers without good scores ([PR #804](https://github.com/versatica/mediasoup/pull/804) by @ggarber). ### 3.9.10 -* Update worker dependencies: - * OpenSSL 3.0.2. - * abseil-cpp 20211102.0. - * nlohmann_json 3.10.5. - * usrsctp snapshot 4e06feb01cadcd127d119486b98a4bd3d64aa1e7. - * wingetopt 1.00. -* Update TypeScript version. -* Fix RTP marker bit not being reseted after mangling in each `Consumer` ([PR #811](https://github.com/versatica/mediasoup/pull/811) by @ggarber). - +- Update worker dependencies: + - OpenSSL 3.0.2. + - abseil-cpp 20211102.0. + - nlohmann_json 3.10.5. + - usrsctp snapshot 4e06feb01cadcd127d119486b98a4bd3d64aa1e7. + - wingetopt 1.00. +- Update TypeScript version. +- Fix RTP marker bit not being reseted after mangling in each `Consumer` ([PR #811](https://github.com/versatica/mediasoup/pull/811) by @ggarber). ### 3.9.9 -* Optimize RTP header extension handling ([PR #786](https://github.com/versatica/mediasoup/pull/786)). -* `RateCalculator`: Reset optimization ([PR #785](https://github.com/versatica/mediasoup/pull/785)). -* Fix frozen video due to double call to `Consumer::UserOnTransportDisconnected()` ([PR #788](https://github.com/versatica/mediasoup/pull/788), thanks to @ggarber for exposing this issue in [PR #787](https://github.com/versatica/mediasoup/pull/787)). - +- Optimize RTP header extension handling ([PR #786](https://github.com/versatica/mediasoup/pull/786)). +- `RateCalculator`: Reset optimization ([PR #785](https://github.com/versatica/mediasoup/pull/785)). +- Fix frozen video due to double call to `Consumer::UserOnTransportDisconnected()` ([PR #788](https://github.com/versatica/mediasoup/pull/788), thanks to @ggarber for exposing this issue in [PR #787](https://github.com/versatica/mediasoup/pull/787)). ### 3.9.8 -* Fix VP9 kSVC forwarding logic to not forward lower unneded layers ([PR #778](https://github.com/versatica/mediasoup/pull/778) by @ggarber). -* Fix update bandwidth estimation configuration and available bitrate when updating max outgoing bitrate ([PR #779](https://github.com/versatica/mediasoup/pull/779) by @ggarber). -* Replace outdated `random-numbers` package by native `crypto.randomInt()` ([PR #776](https://github.com/versatica/mediasoup/pull/776) by @piranna). -* Update TypeScript version. - +- Fix VP9 kSVC forwarding logic to not forward lower unneded layers ([PR #778](https://github.com/versatica/mediasoup/pull/778) by @ggarber). +- Fix update bandwidth estimation configuration and available bitrate when updating max outgoing bitrate ([PR #779](https://github.com/versatica/mediasoup/pull/779) by @ggarber). +- Replace outdated `random-numbers` package by native `crypto.randomInt()` ([PR #776](https://github.com/versatica/mediasoup/pull/776) by @piranna). +- Update TypeScript version. ### 3.9.7 -* Typing event emitters in mediasoup Node ([PR #764](https://github.com/versatica/mediasoup/pull/764) by @unao). - +- Typing event emitters in mediasoup Node ([PR #764](https://github.com/versatica/mediasoup/pull/764) by @unao). ### 3.9.6 -* TCC client optimizations for faster and more stable BWE ([PR #712](https://github.com/versatica/mediasoup/pull/712) by @ggarber). -* Added support for RTP abs-capture-time header ([PR #761](https://github.com/versatica/mediasoup/pull/761) by @oto313). - +- TCC client optimizations for faster and more stable BWE ([PR #712](https://github.com/versatica/mediasoup/pull/712) by @ggarber). +- Added support for RTP abs-capture-time header ([PR #761](https://github.com/versatica/mediasoup/pull/761) by @oto313). ### 3.9.5 -* ICE renomination support ([PR #756](https://github.com/versatica/mediasoup/pull/756)). -* Update `libuv` to 1.43.0. - +- ICE renomination support ([PR #756](https://github.com/versatica/mediasoup/pull/756)). +- Update `libuv` to 1.43.0. ### 3.9.4 -* `Worker`: Fix bad printing of error messages from Worker ([PR #750](https://github.com/versatica/mediasoup/pull/750) by @j1elo). - +- `Worker`: Fix bad printing of error messages from Worker ([PR #750](https://github.com/versatica/mediasoup/pull/750) by @j1elo). ### 3.9.3 -* Single H264/H265 codec configuration in `supportedRtpCapabilities` ([PR #718](https://github.com/versatica/mediasoup/pull/718)). -* Improve Windows support by not requiring MSVC configuration ([PR #741](https://github.com/versatica/mediasoup/pull/741)). - +- Single H264/H265 codec configuration in `supportedRtpCapabilities` ([PR #718](https://github.com/versatica/mediasoup/pull/718)). +- Improve Windows support by not requiring MSVC configuration ([PR #741](https://github.com/versatica/mediasoup/pull/741)). ### 3.9.2 -* `pipeToRouter()`: Reuse same `PipeTransport` when possible ([PR #697](https://github.com/versatica/mediasoup/pull/697)). -* Add `worker.died` boolean getter. -* Update TypeScript version to 4.X.X and use `target: "esnext"` so transpilation of ECMAScript private fields (`#xxxxx`) don't use `WeakMaps` tricks but use standard syntax instead. -* Use more than one core for compilation on Windows ([PR #709](https://github.com/versatica/mediasoup/pull/709)). -* `Consumer`: Modification of bitrate allocation algorithm ([PR #708](https://github.com/versatica/mediasoup/pull/708)). - +- `pipeToRouter()`: Reuse same `PipeTransport` when possible ([PR #697](https://github.com/versatica/mediasoup/pull/697)). +- Add `worker.died` boolean getter. +- Update TypeScript version to 4.X.X and use `target: "esnext"` so transpilation of ECMAScript private fields (`#xxxxx`) don't use `WeakMaps` tricks but use standard syntax instead. +- Use more than one core for compilation on Windows ([PR #709](https://github.com/versatica/mediasoup/pull/709)). +- `Consumer`: Modification of bitrate allocation algorithm ([PR #708](https://github.com/versatica/mediasoup/pull/708)). ### 3.9.1 -* NixOS friendly build process ([PR #683](https://github.com/versatica/mediasoup/pull/683)). -* `Worker`: Emit "died" event before observer "close" ([PR #684](https://github.com/versatica/mediasoup/pull/684)). -* Transport: Hide debug message for RTX RTCP-RR packets ([PR #688](https://github.com/versatica/mediasoup/pull/688)). -* Update `libuv` to 1.42.0. -* Improve Windows support ([PR #692](https://github.com/versatica/mediasoup/pull/692)). -* Avoid build commands when MEDIASOUP_WORKER_BIN is set ([PR #695](https://github.com/versatica/mediasoup/pull/695)). - +- NixOS friendly build process ([PR #683](https://github.com/versatica/mediasoup/pull/683)). +- `Worker`: Emit "died" event before observer "close" ([PR #684](https://github.com/versatica/mediasoup/pull/684)). +- Transport: Hide debug message for RTX RTCP-RR packets ([PR #688](https://github.com/versatica/mediasoup/pull/688)). +- Update `libuv` to 1.42.0. +- Improve Windows support ([PR #692](https://github.com/versatica/mediasoup/pull/692)). +- Avoid build commands when MEDIASOUP_WORKER_BIN is set ([PR #695](https://github.com/versatica/mediasoup/pull/695)). ### 3.9.0 -* Replaces GYP build system with fully-functional Meson build system ([PR #622](https://github.com/versatica/mediasoup/pull/622)). -* Worker communication optimization (aka removing netstring dependency) ([PR #644](https://github.com/versatica/mediasoup/pull/644)). -* Move TypeScript and compiled JavaScript code to a new `node` folder. -* Use ES6 private fields. -* Require Node.js version >= 12. - +- Replaces GYP build system with fully-functional Meson build system ([PR #622](https://github.com/versatica/mediasoup/pull/622)). +- Worker communication optimization (aka removing netstring dependency) ([PR #644](https://github.com/versatica/mediasoup/pull/644)). +- Move TypeScript and compiled JavaScript code to a new `node` folder. +- Use ES6 private fields. +- Require Node.js version >= 12. ### 3.8.4 -* OPUS multi-channel (Surround sound) support ([PR #647](https://github.com/versatica/mediasoup/pull/647)). -* Add `packetLoss` stats to transport ([PR #648](https://github.com/versatica/mediasoup/pull/648) by @ggarber). -* Fixes for active speaker observer ([PR #655](https://github.com/versatica/mediasoup/pull/655) by @ggarber). -* Fix big endian issues ([PR #639](https://github.com/versatica/mediasoup/pull/639)). - +- OPUS multi-channel (Surround sound) support ([PR #647](https://github.com/versatica/mediasoup/pull/647)). +- Add `packetLoss` stats to transport ([PR #648](https://github.com/versatica/mediasoup/pull/648) by @ggarber). +- Fixes for active speaker observer ([PR #655](https://github.com/versatica/mediasoup/pull/655) by @ggarber). +- Fix big endian issues ([PR #639](https://github.com/versatica/mediasoup/pull/639)). ### 3.8.3 -* Fix wrong `size_t*` to `int*` conversion in 64bit Big-Endian hosts ([PR #637](https://github.com/versatica/mediasoup/pull/637)). - +- Fix wrong `size_t*` to `int*` conversion in 64bit Big-Endian hosts ([PR #637](https://github.com/versatica/mediasoup/pull/637)). ### 3.8.2 -* `ActiveSpeakerObserver`: Fix crash due to a `nullptr` ([PR #634](https://github.com/versatica/mediasoup/pull/634)). - +- `ActiveSpeakerObserver`: Fix crash due to a `nullptr` ([PR #634](https://github.com/versatica/mediasoup/pull/634)). ### 3.8.1 -* `SimulcastConsumer`: Fix RTP timestamp when switching layers ([PR #626](https://github.com/versatica/mediasoup/pull/626) by @penguinol). - +- `SimulcastConsumer`: Fix RTP timestamp when switching layers ([PR #626](https://github.com/versatica/mediasoup/pull/626) by @penguinol). ### 3.8.0 -* Update `libuv` to 1.42.0. -* Use non-ASM OpenSSL on Windows ([PR #614](https://github.com/versatica/mediasoup/pull/614)). -* Fix minor memory leak caused by non-virtual destructor ([PR #625](https://github.com/versatica/mediasoup/pull/625)). -* Dominant Speaker Event ([PR #603](https://github.com/versatica/mediasoup/pull/603) by @SteveMcFarlin). - +- Update `libuv` to 1.42.0. +- Use non-ASM OpenSSL on Windows ([PR #614](https://github.com/versatica/mediasoup/pull/614)). +- Fix minor memory leak caused by non-virtual destructor ([PR #625](https://github.com/versatica/mediasoup/pull/625)). +- Dominant Speaker Event ([PR #603](https://github.com/versatica/mediasoup/pull/603) by @SteveMcFarlin). ### 3.7.19 -* Update `libuv` to 1.41.0. -* C++: +- Update `libuv` to 1.41.0. +- C++: - Move header includes ([PR #608](https://github.com/versatica/mediasoup/pull/608)). - Enhance debugging on channel request/notification error ([PR #607](https://github.com/versatica/mediasoup/pull/607)). - ### 3.7.18 -* Support for optional fixed port on transports ([PR #593](https://github.com/versatica/mediasoup/pull/593) by @nazar-pc). -* Upgrade and optimize OpenSSL dependency ([PR #598](https://github.com/versatica/mediasoup/pull/598) by @vpalmisano): +- Support for optional fixed port on transports ([PR #593](https://github.com/versatica/mediasoup/pull/593) by @nazar-pc). +- Upgrade and optimize OpenSSL dependency ([PR #598](https://github.com/versatica/mediasoup/pull/598) by @vpalmisano): - OpenSSL upgraded to version 1.1.1k. - Enable the compilation of assembly extensions for OpenSSL. - Optimize the worker build (`-O3`) and disable the debug flag (`-g`). - ### 3.7.17 -* Introduce `PipeConsumerOptions` to avoid incorrect type information on `PipeTransport.consume()` arguments. -* Make `ConsumerOptions.rtpCapabilities` field required as it should have always been. - +- Introduce `PipeConsumerOptions` to avoid incorrect type information on `PipeTransport.consume()` arguments. +- Make `ConsumerOptions.rtpCapabilities` field required as it should have always been. ### 3.7.16 -* Add `mid` option in `ConsumerOptions` to provide way to override MID ([PR #586](https://github.com/versatica/mediasoup/pull/586) by @mstyura). - +- Add `mid` option in `ConsumerOptions` to provide way to override MID ([PR #586](https://github.com/versatica/mediasoup/pull/586) by @mstyura). ### 3.7.15 -* `kind` field of `RtpHeaderExtension` is no longer optional. It must be 'audio' or 'video'. -* Refactor API inconsistency in internal RTP Observer communication with worker. - +- `kind` field of `RtpHeaderExtension` is no longer optional. It must be 'audio' or 'video'. +- Refactor API inconsistency in internal RTP Observer communication with worker. ### 3.7.14 -* Update `usrsctp` to include a "possible use after free bug" fix (commit [here](https://github.com/sctplab/usrsctp/commit/0f8d58300b1fdcd943b4a9dd3fbd830825390d4d)). - +- Update `usrsctp` to include a "possible use after free bug" fix (commit [here](https://github.com/sctplab/usrsctp/commit/0f8d58300b1fdcd943b4a9dd3fbd830825390d4d)). ### 3.7.13 -* Fix build on FreeBSD ([PR #585](https://github.com/versatica/mediasoup/pull/585) by @smortex). - +- Fix build on FreeBSD ([PR #585](https://github.com/versatica/mediasoup/pull/585) by @smortex). ### 3.7.12 -* `mediasoup-worker`: Fix memory leaks on error exit ([PR #581](https://github.com/versatica/mediasoup/pull/581)). - +- `mediasoup-worker`: Fix memory leaks on error exit ([PR #581](https://github.com/versatica/mediasoup/pull/581)). ### 3.7.11 -* Fix `DepUsrSCTP::Checker::timer` not being freed on `Worker` close ([PR #576](https://github.com/versatica/mediasoup/pull/576)). Thanks @nazar-pc for discovering this. - +- Fix `DepUsrSCTP::Checker::timer` not being freed on `Worker` close ([PR #576](https://github.com/versatica/mediasoup/pull/576)). Thanks @nazar-pc for discovering this. ### 3.7.10 -* Remove clang tools binaries from regular installation. - +- Remove clang tools binaries from regular installation. ### 3.7.9 -* Code clean up. - +- Code clean up. ### 3.7.8 -* `PayloadChannel`: Copy received messages into a separate buffer to avoid memory corruption if the message is later modified ([PR #570](https://github.com/versatica/mediasoup/pull/570) by @aggresss). - +- `PayloadChannel`: Copy received messages into a separate buffer to avoid memory corruption if the message is later modified ([PR #570](https://github.com/versatica/mediasoup/pull/570) by @aggresss). ### 3.7.7 -* Thread and memory safety fixes needed for mediasoup-rust ([PR #562](https://github.com/versatica/mediasoup/pull/562) by @nazar-pc). -* mediasoup-rust support on macOS ([PR #567](https://github.com/versatica/mediasoup/pull/567) by @nazar-pc). -* mediasoup-rust release 0.7.2. - +- Thread and memory safety fixes needed for mediasoup-rust ([PR #562](https://github.com/versatica/mediasoup/pull/562) by @nazar-pc). +- mediasoup-rust support on macOS ([PR #567](https://github.com/versatica/mediasoup/pull/567) by @nazar-pc). +- mediasoup-rust release 0.7.2. ### 3.7.6 -* `Transport`: Implement new `setMaxOutgoingBitrate()` method ([PR #555](https://github.com/versatica/mediasoup/pull/555) by @t-mullen). -* `SctpAssociation`: Don't warn if SCTP send buffer is full. -* Rust: Update modules structure and other minor improvements for Rust version ([PR #558](https://github.com/versatica/mediasoup/pull/558)). -* `mediasoup-worker`: Avoid duplicated basenames so that libmediasoup-worker is compilable on macOS ([PR #557](https://github.com/versatica/mediasoup/pull/557)). - +- `Transport`: Implement new `setMaxOutgoingBitrate()` method ([PR #555](https://github.com/versatica/mediasoup/pull/555) by @t-mullen). +- `SctpAssociation`: Don't warn if SCTP send buffer is full. +- Rust: Update modules structure and other minor improvements for Rust version ([PR #558](https://github.com/versatica/mediasoup/pull/558)). +- `mediasoup-worker`: Avoid duplicated basenames so that libmediasoup-worker is compilable on macOS ([PR #557](https://github.com/versatica/mediasoup/pull/557)). ### 3.7.5 -* SctpAssociation: provide 'sctpsendbufferfull' reason on send error (#552). - +- SctpAssociation: provide 'sctpsendbufferfull' reason on send error (#552). ### 3.7.4 -* Improve `RateCalculator` ([PR #547](https://github.com/versatica/mediasoup/pull/547) by @vpalmisano). - +- Improve `RateCalculator` ([PR #547](https://github.com/versatica/mediasoup/pull/547) by @vpalmisano). ### 3.7.3 -* Make worker M1 compilable. - +- Make worker M1 compilable. ### 3.7.2 -* `RateCalculator` optimization ([PR #538](https://github.com/versatica/mediasoup/pull/538) by @vpalmisano). - +- `RateCalculator` optimization ([PR #538](https://github.com/versatica/mediasoup/pull/538) by @vpalmisano). ### 3.7.1 -* `SimulcastConsumer`: Fix miscalculation when increasing layer ([PR #541](https://github.com/versatica/mediasoup/pull/541) by @penguinol). -* Rust version with thread-based worker ([PR #540](https://github.com/versatica/mediasoup/pull/540)). - +- `SimulcastConsumer`: Fix miscalculation when increasing layer ([PR #541](https://github.com/versatica/mediasoup/pull/541) by @penguinol). +- Rust version with thread-based worker ([PR #540](https://github.com/versatica/mediasoup/pull/540)). ### 3.7.0 -* Welcome to `mediasoup-rust`! Authored by @nazar-pc (PRs #518 and #533). -* Update `usrsctp`. - +- Welcome to `mediasoup-rust`! Authored by @nazar-pc (PRs #518 and #533). +- Update `usrsctp`. ### 3.6.37 -* Fix crash if empty `fingerprints` array is given in `webrtcTransport.connect()` (issue #537). +- Fix crash if empty `fingerprints` array is given in `webrtcTransport.connect()` (issue #537). ### 3.6.36 -* `Producer`: Add new stats field 'rtxPacketsDiscarded' ([PR #536](https://github.com/versatica/mediasoup/pull/536)). - +- `Producer`: Add new stats field 'rtxPacketsDiscarded' ([PR #536](https://github.com/versatica/mediasoup/pull/536)). ### 3.6.35 -* `XxxxConsumer.hpp`: make `IsActive()` return `true` (even if `Producer`'s score is 0) when DTX is enabled ([PR #534](https://github.com/versatica/mediasoup/pull/534) due to issue #532). - +- `XxxxConsumer.hpp`: make `IsActive()` return `true` (even if `Producer`'s score is 0) when DTX is enabled ([PR #534](https://github.com/versatica/mediasoup/pull/534) due to issue #532). ### 3.6.34 -* Fix crash (regression, issue #529). - +- Fix crash (regression, issue #529). ### 3.6.33 -* Add missing `delete cb` that otherwise would leak ([PR #527](https://github.com/versatica/mediasoup/pull/527) based on [PR #526](https://github.com/versatica/mediasoup/pull/526) by @vpalmisano). -* `router.pipeToRouter()`: Fix possible inconsistency in `pipeProducer.paused` status (as discussed in this [thread](https://mediasoup.discourse.group/t/concurrency-architecture/2515/) in the mediasoup forum). -* Update `nlohmann/json` to 3.9.1. -* Update `usrsctp`. -* Enhance Jitter calculation. - +- Add missing `delete cb` that otherwise would leak ([PR #527](https://github.com/versatica/mediasoup/pull/527) based on [PR #526](https://github.com/versatica/mediasoup/pull/526) by @vpalmisano). +- `router.pipeToRouter()`: Fix possible inconsistency in `pipeProducer.paused` status (as discussed in this [thread](https://mediasoup.discourse.group/t/concurrency-architecture/2515/) in the mediasoup forum). +- Update `nlohmann/json` to 3.9.1. +- Update `usrsctp`. +- Enhance Jitter calculation. ### 3.6.32 -* Fix notifications from `mediasoup-worker` being processed before responses received before them (issue #501). - +- Fix notifications from `mediasoup-worker` being processed before responses received before them (issue #501). ### 3.6.31 -* Move `bufferedAmount` from `dataConsumer.dump()` to `dataConsumer.getStats()`. - +- Move `bufferedAmount` from `dataConsumer.dump()` to `dataConsumer.getStats()`. ### 3.6.30 -* Add `pipe` option to `transport.consume()`([PR #494](https://github.com/versatica/mediasoup/pull/494)). +- Add `pipe` option to `transport.consume()`([PR #494](https://github.com/versatica/mediasoup/pull/494)). - So the receiver will get all streams from the `Producer`. - It works for any kind of transport (but `PipeTransport` which is always like this). -* Add `LICENSE` and `PATENTS` files in `libwebrtc` dependency (issue #495). -* Added `worker/src/Utils/README_BASE64_UTILS` (issue #497). -* Update `usrsctp`. - +- Add `LICENSE` and `PATENTS` files in `libwebrtc` dependency (issue #495). +- Added `worker/src/Utils/README_BASE64_UTILS` (issue #497). +- Update `usrsctp`. ### 3.6.29 -* Fix wrong message about `rtcMinPort` and `rtcMaxPort`. -* Update deps. -* Improve `EnhancedEventEmitter.safeAsPromise()` (although not used). - +- Fix wrong message about `rtcMinPort` and `rtcMaxPort`. +- Update deps. +- Improve `EnhancedEventEmitter.safeAsPromise()` (although not used). ### 3.6.28 -* Fix replacement of `__MEDIASOUP_VERSION__` in `lib/index.d.ts` (issue #483). -* `worker/scripts/configure.py`: Handle 'mips64' ([PR #485](https://github.com/versatica/mediasoup/pull/485)). - +- Fix replacement of `__MEDIASOUP_VERSION__` in `lib/index.d.ts` (issue #483). +- `worker/scripts/configure.py`: Handle 'mips64' ([PR #485](https://github.com/versatica/mediasoup/pull/485)). ### 3.6.27 -* Allow the `mediasoup-worker` process to inherit all environment variables (issue #480). - +- Allow the `mediasoup-worker` process to inherit all environment variables (issue #480). ### 3.6.26 -* BWE tweaks and debug logs. - +- BWE tweaks and debug logs. ### 3.6.25 -* SCTP fixes ([PR #479](https://github.com/versatica/mediasoup/pull/479)). - +- SCTP fixes ([PR #479](https://github.com/versatica/mediasoup/pull/479)). ### 3.6.24 -* Update `awaitqueue` dependency. - +- Update `awaitqueue` dependency. ### 3.6.23 -* Fix yet another memory leak in Node.js layer due to `PayloadChannel` event listener not being removed. - +- Fix yet another memory leak in Node.js layer due to `PayloadChannel` event listener not being removed. ### 3.6.22 -* `Transport.cpp`: Provide transport congestion client with RTCP Receiver Reports (#464). -* Update `libuv` to 1.40.0. -* Update Node deps. -* `SctpAssociation.cpp`: increase `sctpBufferedAmount` before sending any data (#472). - +- `Transport.cpp`: Provide transport congestion client with RTCP Receiver Reports (#464). +- Update `libuv` to 1.40.0. +- Update Node deps. +- `SctpAssociation.cpp`: increase `sctpBufferedAmount` before sending any data (#472). ### 3.6.21 -* Fix memory leak in Node.js layer due to `PayloadChannel` event listener not being removed (related to #463). - +- Fix memory leak in Node.js layer due to `PayloadChannel` event listener not being removed (related to #463). ### 3.6.20 -* Remove `-fwrapv` when building mediasoup-worker in `Debug` mode (issue #460). -* Add `MEDIASOUP_MAX_CORES` to limit `NUM_CORES` during mediasoup-worker build ([PR #462](https://github.com/versatica/mediasoup/pull/462)). - +- Remove `-fwrapv` when building mediasoup-worker in `Debug` mode (issue #460). +- Add `MEDIASOUP_MAX_CORES` to limit `NUM_CORES` during mediasoup-worker build ([PR #462](https://github.com/versatica/mediasoup/pull/462)). ### 3.6.19 -* Update `usrsctp` dependency. -* Update `typescript-eslint` deps. -* Update Node deps. - +- Update `usrsctp` dependency. +- Update `typescript-eslint` deps. +- Update Node deps. ### 3.6.18 -* Fix `ortc.getConsumerRtpParameters()` RTX codec comparison issue ([PR #453](https://github.com/versatica/mediasoup/pull/453)). -* RtpObserver: expose `RtpObserverAddRemoveProducerOptions` for `addProducer()` and `removeProducer()` methods. - +- Fix `ortc.getConsumerRtpParameters()` RTX codec comparison issue ([PR #453](https://github.com/versatica/mediasoup/pull/453)). +- RtpObserver: expose `RtpObserverAddRemoveProducerOptions` for `addProducer()` and `removeProducer()` methods. ### 3.6.17 -* Update `libuv` to 1.39.0. -* Update Node deps. -* SimulcastConsumer: Prefer the highest spatial layer initially ([PR #450](https://github.com/versatica/mediasoup/pull/450)). -* RtpStreamRecv: Set RtpDataCounter window size to 6 secs if DTX (#451) - +- Update `libuv` to 1.39.0. +- Update Node deps. +- SimulcastConsumer: Prefer the highest spatial layer initially ([PR #450](https://github.com/versatica/mediasoup/pull/450)). +- RtpStreamRecv: Set RtpDataCounter window size to 6 secs if DTX (#451) ### 3.6.16 -* `SctpAssociation.cpp`: Fix `OnSctpAssociationBufferedAmount()` call. -* Update deps. -* New API to send data from Node throught SCTP DataConsumer. - +- `SctpAssociation.cpp`: Fix `OnSctpAssociationBufferedAmount()` call. +- Update deps. +- New API to send data from Node throught SCTP DataConsumer. ### 3.6.15 -* Avoid SRTP leak by deleting invalid SSRCs after STRP decryption (issue #437, thanks to @penguinol for reporting). -* Update `usrsctp` dep. -* DataConsumer 'bufferedAmount' implementation ([PR #442](https://github.com/versatica/mediasoup/pull/442)). +- Avoid SRTP leak by deleting invalid SSRCs after STRP decryption (issue #437, thanks to @penguinol for reporting). +- Update `usrsctp` dep. +- DataConsumer 'bufferedAmount' implementation ([PR #442](https://github.com/versatica/mediasoup/pull/442)). ### 3.6.14 -* Fix `usrsctp` vulnerability ([PR #439](https://github.com/versatica/mediasoup/pull/439)). -* Fix issue #435 (thanks to @penguinol for reporting). -* `TransportCongestionControlClient.cpp`: Enable periodic ALR probing to recover faster from network issues. - -* Update `nlohmann::json` C++ dep to 3.9.0. +- Fix `usrsctp` vulnerability ([PR #439](https://github.com/versatica/mediasoup/pull/439)). +- Fix issue #435 (thanks to @penguinol for reporting). +- `TransportCongestionControlClient.cpp`: Enable periodic ALR probing to recover faster from network issues. +- Update `nlohmann::json` C++ dep to 3.9.0. ### 3.6.13 -* RTP on `DirectTransport` (issue #433, [PR #434](https://github.com/versatica/mediasoup/pull/434)): +- RTP on `DirectTransport` (issue #433, [PR #434](https://github.com/versatica/mediasoup/pull/434)): - New API `producer.send(rtpPacket: Buffer)`. - New API `consumer.on('rtp', (rtpPacket: Buffer)`. - New API `directTransport.sendRtcp(rtcpPacket: Buffer)`. - New API `directTransport.on('rtcp', (rtpPacket: Buffer)`. - ### 3.6.12 -* Release script. - +- Release script. ### 3.6.11 -* `Transport`: rename `maxSctpSendBufferSize` to `sctpSendBufferSize`. - +- `Transport`: rename `maxSctpSendBufferSize` to `sctpSendBufferSize`. ### 3.6.10 -* `Transport`: Implement `maxSctpSendBufferSize`. -* Update `libuv` to 1.38.1. - +- `Transport`: Implement `maxSctpSendBufferSize`. +- Update `libuv` to 1.38.1. ### 3.6.9 -* `Transport::ReceiveRtpPacket()`: Call `RecvStreamClosed(packet->GetSsrc())` if received RTP packet does not match any `Producer`. -* `Transport::HandleRtcpPacket()`: Ensure `Consumer` is found for received NACK Feedback packets. -* Fix issue #408. - +- `Transport::ReceiveRtpPacket()`: Call `RecvStreamClosed(packet->GetSsrc())` if received RTP packet does not match any `Producer`. +- `Transport::HandleRtcpPacket()`: Ensure `Consumer` is found for received NACK Feedback packets. +- Fix issue #408. ### 3.6.8 -* Fix SRTP leak due to streams not being removed when a `Producer` or `Consumer` is closed. - - [PR #428](https://github.com/versatica/mediasoup/pull/428) (fixes issues #426). +- Fix SRTP leak due to streams not being removed when a `Producer` or `Consumer` is closed. + - [PR #428](https://github.com/versatica/mediasoup/pull/428) (fixes issues #426). - Credits to credits to @penguinol for reporting and initial work at [PR #427](https://github.com/versatica/mediasoup/pull/427). -* Update `nlohmann::json` C++ dep to 3.8.0. -* C++: Enhance `const` correctness. - +- Update `nlohmann::json` C++ dep to 3.8.0. +- C++: Enhance `const` correctness. ### 3.6.7 -* `ConsumerScore`: Add `producerScores`, scores of all RTP streams in the producer ordered by encoding (just useful when the producer uses simulcast). +- `ConsumerScore`: Add `producerScores`, scores of all RTP streams in the producer ordered by encoding (just useful when the producer uses simulcast). - [PR #421](https://github.com/versatica/mediasoup/pull/421) (fixes issues #420). -* Hide worker executable console in Windows. +- Hide worker executable console in Windows. - [PR #419](https://github.com/versatica/mediasoup/pull/419) (credits to @BlueMagnificent). -* `RtpStream.cpp`: Fix wrong `std::round()` usage. +- `RtpStream.cpp`: Fix wrong `std::round()` usage. - Issue #423. - ### 3.6.6 -* Update `usrsctp` library. -* Update ESlint and TypeScript related dependencies. - +- Update `usrsctp` library. +- Update ESlint and TypeScript related dependencies. ### 3.6.5 -* Set `score:0` when `dtx:true` is set in an `encoding` and there is no RTP for some seconds for that RTP stream. +- Set `score:0` when `dtx:true` is set in an `encoding` and there is no RTP for some seconds for that RTP stream. - Fixes #415. - ### 3.6.4 -* `gyp`: Fix CLT version detection in OSX Catalina when XCode app is not installed. +- `gyp`: Fix CLT version detection in OSX Catalina when XCode app is not installed. - [PR #413](https://github.com/versatica/mediasoup/pull/413) (credits to @enimo). - ### 3.6.3 -* Modernize TypeScript. - +- Modernize TypeScript. ### 3.6.2 -* Fix crash in `Transport.ts` when closing a `DataConsumer` created on a `DirectTransport`. - +- Fix crash in `Transport.ts` when closing a `DataConsumer` created on a `DirectTransport`. ### 3.6.1 -* Export new `DirectTransport` in `types`. -* Make `DataProducerOptions` optional (not needed when in a `DirectTransport`). - +- Export new `DirectTransport` in `types`. +- Make `DataProducerOptions` optional (not needed when in a `DirectTransport`). ### 3.6.0 -* SCTP/DataChannel termination: +- SCTP/DataChannel termination: - [PR #409](https://github.com/versatica/mediasoup/pull/409) - Allow the Node application to directly send text/binary messages to mediasoup-worker C++ process so others can consume them using `DataConsumers`. - And vice-versa: allow the Node application to directly consume in Node messages send by `DataProducers`. -* Add `WorkerLogTag` TypeScript enum and also add a new 'message' tag into it. - +- Add `WorkerLogTag` TypeScript enum and also add a new 'message' tag into it. ### 3.5.15 -* Simulcast and SVC: Better computation of desired bitrate based on `maxBitrate` field in the `producer.rtpParameters.encodings`. - +- Simulcast and SVC: Better computation of desired bitrate based on `maxBitrate` field in the `producer.rtpParameters.encodings`. ### 3.5.14 -* Update deps, specially `uuid` and `@types/uuid` that had a TypeScript related bug. -* `TransportCongestionClient.cpp`: Improve sender side bandwidth estimation by do not reporting `this->initialAvailableBitrate` as available bitrate due to strange behavior in the algorithm. - +- Update deps, specially `uuid` and `@types/uuid` that had a TypeScript related bug. +- `TransportCongestionClient.cpp`: Improve sender side bandwidth estimation by do not reporting `this->initialAvailableBitrate` as available bitrate due to strange behavior in the algorithm. ### 3.5.13 -* Simplify `GetDesiredBitrate()` in `SimulcastConsumer` and `SvcConsumer`. -* Update `libuv` to 1.38.0. - +- Simplify `GetDesiredBitrate()` in `SimulcastConsumer` and `SvcConsumer`. +- Update `libuv` to 1.38.0. ### 3.5.12 -* `SeqManager.cpp`: Improve performance. +- `SeqManager.cpp`: Improve performance. - [PR #398](https://github.com/versatica/mediasoup/pull/398) (credits to @penguinol). - ### 3.5.11 -* `SeqManager.cpp`: Fix a bug and improve performance. +- `SeqManager.cpp`: Fix a bug and improve performance. - Fixes issue #395 via [PR #396](https://github.com/versatica/mediasoup/pull/396) (credits to @penguinol). -* Drop Node.js 8 support. Minimum supported Node.js version is now 10. -* Upgrade `eslint` and `jest` major versions. - +- Drop Node.js 8 support. Minimum supported Node.js version is now 10. +- Upgrade `eslint` and `jest` major versions. ### 3.5.10 -* `SimulcastConsumer.cpp`: Fix `IncreaseLayer()` method (fixes #394). -* Udpate Node deps. - +- `SimulcastConsumer.cpp`: Fix `IncreaseLayer()` method (fixes #394). +- Udpate Node deps. ### 3.5.9 -* `libwebrtc`: Apply patch by @sspanak and @Ivaka to avoid crash. Related issue: #357. -* `PortManager.cpp`: Do not use `UV_UDP_RECVMMSG` in Windows due to a bug in `libuv` 1.37.0. -* Update Node deps. - +- `libwebrtc`: Apply patch by @sspanak and @Ivaka to avoid crash. Related issue: #357. +- `PortManager.cpp`: Do not use `UV_UDP_RECVMMSG` in Windows due to a bug in `libuv` 1.37.0. +- Update Node deps. ### 3.5.8 -* Enable `UV_UDP_RECVMMSG`: +- Enable `UV_UDP_RECVMMSG`: - Upgrade `libuv` to 1.37.0. - Use `uv_udp_init_ex()` with `UV_UDP_RECVMMSG` flag. - Add our own `uv.gyp` now that `libuv` has removed support for GYP (fixes #384). - ### 3.5.7 -* Fix crash in mediasoup-worker due to conversion from `uint64_t` to `int64_t` (used within `libwebrtc` code. Fixes #357. -* Update `usrsctp` library. -* Update Node deps. - +- Fix crash in mediasoup-worker due to conversion from `uint64_t` to `int64_t` (used within `libwebrtc` code. Fixes #357. +- Update `usrsctp` library. +- Update Node deps. ### 3.5.6 -* `SeqManager.cpp`: Fix video lag after a long time. +- `SeqManager.cpp`: Fix video lag after a long time. - Fixes #372 (thanks @penguinol for reporting it and giving the solution). - ### 3.5.5 -* `UdpSocket.cpp`: Revert `uv__udp_recvmmsg()` usage since it notifies about received UDP packets in reverse order. Feature on hold until fixed. - +- `UdpSocket.cpp`: Revert `uv__udp_recvmmsg()` usage since it notifies about received UDP packets in reverse order. Feature on hold until fixed. ### 3.5.4 -* `Transport.cpp`: Enable transport congestion client for the first video Consumer, no matter it's uses simulcast, SVC or a single stream. -* Update `libuv` to 1.35.0. -* `UdpSocket.cpp`: Ensure the new libuv's `uv__udp_recvmmsg()` is used, which is more efficient. - +- `Transport.cpp`: Enable transport congestion client for the first video Consumer, no matter it's uses simulcast, SVC or a single stream. +- Update `libuv` to 1.35.0. +- `UdpSocket.cpp`: Ensure the new libuv's `uv__udp_recvmmsg()` is used, which is more efficient. ### 3.5.3 -* `PlainTransport`: Remove `multiSource` option. It was a hack nobody should use. - +- `PlainTransport`: Remove `multiSource` option. It was a hack nobody should use. ### 3.5.2 -* Enable MID RTP extension in mediasoup to receivers direction (for consumers). +- Enable MID RTP extension in mediasoup to receivers direction (for consumers). - This **requires** mediasoup-client 3.5.2 to work. - ### 3.5.1 -* `PlainTransport`: Fix event name: 'rtcpTuple' => 'rtcptuple'. - +- `PlainTransport`: Fix event name: 'rtcpTuple' => 'rtcptuple'. ### 3.5.0 -* `PipeTransport`: Add support for SRTP and RTP retransmission (RTX + NACK). Useful when connecting two mediasoup servers running in different hosts via pipe transports. -* `PlainTransport`: Add support for SRTP. -* Rename `PlainRtpTransport` to `PlainTransport` everywhere (classes, methods, TypeScript types, etc). Keep previous names and mark them as DEPRECATED. -* Fix vulnarability in IPv6 parser. - +- `PipeTransport`: Add support for SRTP and RTP retransmission (RTX + NACK). Useful when connecting two mediasoup servers running in different hosts via pipe transports. +- `PlainTransport`: Add support for SRTP. +- Rename `PlainRtpTransport` to `PlainTransport` everywhere (classes, methods, TypeScript types, etc). Keep previous names and mark them as DEPRECATED. +- Fix vulnarability in IPv6 parser. ### 3.4.13 -* Update `uuid` dep to 7.0.X (new API). -* Fix crash due wrong array index in `PipeConsumer::FillJson()`. +- Update `uuid` dep to 7.0.X (new API). +- Fix crash due wrong array index in `PipeConsumer::FillJson()`. - Fixes #364 - ### 3.4.12 -* TypeScript: generate `es2020` instead of `es6`. -* Update `usrsctp` library. +- TypeScript: generate `es2020` instead of `es6`. +- Update `usrsctp` library. - Fixes #362 (thanks @chvarlam for reporting it). - ### 3.4.11 -* `IceServer.cpp`: Reject received STUN Binding request with 487 if remote peer indicates ICE-CONTROLLED into it. - +- `IceServer.cpp`: Reject received STUN Binding request with 487 if remote peer indicates ICE-CONTROLLED into it. ### 3.4.10 -* `ProducerOptions`: Rename `keyFrameWaitTime` option to `keyFrameRequestDelay` and make it work as expected. - +- `ProducerOptions`: Rename `keyFrameWaitTime` option to `keyFrameRequestDelay` and make it work as expected. ### 3.4.9 -* Add `Utils::Json::IsPositiveInteger()` to not rely on `is_number_unsigned()` of json lib, which is unreliable due to its design. -* Avoid ES6 `export default` and always use named `export`. -* `router.pipeToRouter()`: Ensure a single `PipeTransport` pair is created between `router1` and `router2`. - - Since the operation is async, it may happen that two simultaneous calls to `router1.pipeToRouter({ producerId: xxx, router: router2 })` would end up generating two pairs of `PipeTranports`. To prevent that, let's use an async queue. -* Add `keyFrameWaitTime` option to `ProducerOptions`. -* Update Node and C++ deps. - +- Add `Utils::Json::IsPositiveInteger()` to not rely on `is_number_unsigned()` of json lib, which is unreliable due to its design. +- Avoid ES6 `export default` and always use named `export`. +- `router.pipeToRouter()`: Ensure a single `PipeTransport` pair is created between `router1` and `router2`. + - Since the operation is async, it may happen that two simultaneous calls to `router1.pipeToRouter({ producerId: xxx, router: router2 })` would end up generating two pairs of `PipeTranports`. To prevent that, let's use an async queue. +- Add `keyFrameWaitTime` option to `ProducerOptions`. +- Update Node and C++ deps. ### 3.4.8 -* `libsrtp.gyp`: Fix regression in mediasoup for Windows. +- `libsrtp.gyp`: Fix regression in mediasoup for Windows. - `libsrtp.gyp`: Modernize it based on the new `BUILD.gn` in Chromium. - `libsrtp.gyp`: Don't include "test" and other targets. - Assume `HAVE_INTTYPES_H`, `HAVE_INT8_T`, etc. in Windows. - Issue details: https://github.com/sctplab/usrsctp/issues/353 -* `gyp` dependency: Add support for Microsoft Visual Studio 2019. +- `gyp` dependency: Add support for Microsoft Visual Studio 2019. - Modify our own `gyp` sources to fix the issue. - CL uploaded to GYP project with the fix. - Issue details: https://github.com/sctplab/usrsctp/issues/347 - ### 3.4.7 -* `PortManager.cpp`: Do not limit the number of failed `bind()` attempts to 20 since it does not work well in scenarios that launch tons of `Workers` with same port range. Instead iterate all ports in the range given to the Worker. -* Do not copy `catch.hpp` into `test/include/` but make the GYP `mediasoup-worker-test` target include the corresponding folder in `deps/catch`. - +- `PortManager.cpp`: Do not limit the number of failed `bind()` attempts to 20 since it does not work well in scenarios that launch tons of `Workers` with same port range. Instead iterate all ports in the range given to the Worker. +- Do not copy `catch.hpp` into `test/include/` but make the GYP `mediasoup-worker-test` target include the corresponding folder in `deps/catch`. ### 3.4.6 -* Update libsrtp to 2.3.0. -* Update ESLint and TypeScript deps. - +- Update libsrtp to 2.3.0. +- Update ESLint and TypeScript deps. ### 3.4.5 -* Update deps. -* Fix text in `./github/Bug_Report.md` so it no longer references the deprecated mailing list. - +- Update deps. +- Fix text in `./github/Bug_Report.md` so it no longer references the deprecated mailing list. ### 3.4.4 -* `Transport.cpp`: Ignore RTCP SDES packets (we don't do anything with them anyway). -* `Producer` and `Consumer` stats: Always show `roundTripTime` (even if calculated value is 0) after a `roundTripTime` > 0 has been seen. - +- `Transport.cpp`: Ignore RTCP SDES packets (we don't do anything with them anyway). +- `Producer` and `Consumer` stats: Always show `roundTripTime` (even if calculated value is 0) after a `roundTripTime` > 0 has been seen. ### 3.4.3 -* `Transport.cpp`: Fix RTCP FIR processing: +- `Transport.cpp`: Fix RTCP FIR processing: - Instead of looking at the media ssrc in the common header, iterate FIR items and look for associated `Consumers` based on ssrcs in each FIR item. - Fixes #350 (thanks @j1elo for reporting and documenting the issue). - ### 3.4.2 -* `SctpAssociation.cpp`: Improve/fix logs. -* Improve Node `EventEmitter` events inline documentation. -* `test-node-sctp.js`: Wait for SCTP association to be open before sending data. - +- `SctpAssociation.cpp`: Improve/fix logs. +- Improve Node `EventEmitter` events inline documentation. +- `test-node-sctp.js`: Wait for SCTP association to be open before sending data. ### 3.4.1 -* Improve mediasoup-worker build system by using `sh` instead of `bash` and default to 4 cores (thanks @smoke, [PR #349](https://github.com/versatica/mediasoup/pull/349)). - +- Improve mediasoup-worker build system by using `sh` instead of `bash` and default to 4 cores (thanks @smoke, [PR #349](https://github.com/versatica/mediasoup/pull/349)). ### 3.4.0 -* Add `worker.getResourceUsage()` API. -* Update OpenSSL to 1.1.1d. -* Update `libuv` to 1.34.0. -* Update TypeScript version. - +- Add `worker.getResourceUsage()` API. +- Update OpenSSL to 1.1.1d. +- Update `libuv` to 1.34.0. +- Update TypeScript version. ### 3.3.8 -* Update usrsctp dependency (it fixes a potential wrong memory access). +- Update usrsctp dependency (it fixes a potential wrong memory access). - More details in the reported issue: https://github.com/sctplab/usrsctp/issues/408 - ### 3.3.7 -* Fix `version` getter. - +- Fix `version` getter. ### 3.3.6 -* `SctpAssociation.cpp`: Initialize the `usrsctp` socket in the class constructor. Fixes #348. - +- `SctpAssociation.cpp`: Initialize the `usrsctp` socket in the class constructor. Fixes #348. ### 3.3.5 -* Fix usage of a deallocated `RTC::TcpConnection` instance under heavy CPU usage due to mediasoup deleting the instance in the middle of a receiving iteration. Fixes #333. +- Fix usage of a deallocated `RTC::TcpConnection` instance under heavy CPU usage due to mediasoup deleting the instance in the middle of a receiving iteration. Fixes #333. - More details in the commit: https://github.com/versatica/mediasoup/commit/49824baf102ab6d2b01e5bca565c29b8ac0fec22 - ### 3.3.4 -* IPv6 fix: Use `INET6_ADDRSTRLEN` instead of `INET_ADDRSTRLEN`. - +- IPv6 fix: Use `INET6_ADDRSTRLEN` instead of `INET_ADDRSTRLEN`. ### 3.3.3 -* Add `consumer.setPriority()` and `consumer.priority` API to prioritize how the estimated outgoing bitrate in a transport is distributed among all video consumers (in case there is not enough bitrate to satisfy them). -* Make video `SimpleConsumers` play the BWE game by helping in probation generation and bitrate distribution. -* Add `consumer.preferredLayers` getter. -* Rename `enablePacketEvent()` and "packet" event to `enableTraceEvent()` and "trace" event (sorry SEMVER). -* Transport: Add a new "trace" event of type "bwe" with detailed information about bitrates. - +- Add `consumer.setPriority()` and `consumer.priority` API to prioritize how the estimated outgoing bitrate in a transport is distributed among all video consumers (in case there is not enough bitrate to satisfy them). +- Make video `SimpleConsumers` play the BWE game by helping in probation generation and bitrate distribution. +- Add `consumer.preferredLayers` getter. +- Rename `enablePacketEvent()` and "packet" event to `enableTraceEvent()` and "trace" event (sorry SEMVER). +- Transport: Add a new "trace" event of type "bwe" with detailed information about bitrates. ### 3.3.2 -* Improve "packet" event by not firing both "keyframe" and "rtp" types for the same RTP packet. - +- Improve "packet" event by not firing both "keyframe" and "rtp" types for the same RTP packet. ### 3.3.1 - -* Add type "keyframe" as a valid type for "packet" event in `Producers` and `Consumers`. - +- Add type "keyframe" as a valid type for "packet" event in `Producers` and `Consumers`. ### 3.3.0 -* Add transport-cc bandwidth estimation and congestion control in sender and receiver side. -* Run in Windows. -* Rewrite to TypeScript. -* Tons of improvements. - +- Add transport-cc bandwidth estimation and congestion control in sender and receiver side. +- Run in Windows. +- Rewrite to TypeScript. +- Tons of improvements. ### 3.2.5 -* Fix TCP leak (#325). - +- Fix TCP leak (#325). ### 3.2.4 -* `PlainRtpTransport`: Fix comedia mode. - +- `PlainRtpTransport`: Fix comedia mode. ### 3.2.3 -* `RateCalculator`: improve efficiency in `GetRate()` method (#324). - +- `RateCalculator`: improve efficiency in `GetRate()` method (#324). ### 3.2.2 -* `RtpDataCounter`: use window size of 2500 ms instead of 1000 ms. +- `RtpDataCounter`: use window size of 2500 ms instead of 1000 ms. - Fixes false "lack of RTP" detection in some screen sharing usages with simulcast. - Fixes #312. - ### 3.2.1 -* Add RTCP Extended Reports for RTT calculation on receiver RTP stream (thanks @yangjinechofor for initial pull request #314). -* Make mediasoup-worker compile in Armbian Debian Buster (thanks @krishisola, fixes #321). - +- Add RTCP Extended Reports for RTT calculation on receiver RTP stream (thanks @yangjinechofor for initial pull request #314). +- Make mediasoup-worker compile in Armbian Debian Buster (thanks @krishisola, fixes #321). ### 3.2.0 -* Add DataChannel support via DataProducers and DataConsumers (#10). -* SRTP: Add support for AEAD GCM (#320). - +- Add DataChannel support via DataProducers and DataConsumers (#10). +- SRTP: Add support for AEAD GCM (#320). ### 3.1.7 -* `PipeConsumer.cpp`: Fix RTCP generation (thanks @vpalmisano). - +- `PipeConsumer.cpp`: Fix RTCP generation (thanks @vpalmisano). ### 3.1.6 -* VP8 and H264: Fix regression in 3.1.5 that produces lot of changes in current temporal layer detection. - +- VP8 and H264: Fix regression in 3.1.5 that produces lot of changes in current temporal layer detection. ### 3.1.5 -* VP8 and H264: Allow packets without temporal layer information even if N temporal layers were announced. - +- VP8 and H264: Allow packets without temporal layer information even if N temporal layers were announced. ### 3.1.4 -* Add `-fPIC` in `cflags` to compile in x86-64. Fixes #315. - +- Add `-fPIC` in `cflags` to compile in x86-64. Fixes #315. ### 3.1.3 -* Set the sender SSRC on PLI and FIR requests [related thread](https://mediasoup.discourse.group/t/broadcasting-a-vp8-rtp-stream-from-gstreamer/93). - +- Set the sender SSRC on PLI and FIR requests [related thread](https://mediasoup.discourse.group/t/broadcasting-a-vp8-rtp-stream-from-gstreamer/93). ### 3.1.2 -* Workaround to detect H264 key frames when Chrome uses external encoder (related [issue](https://bugs.chromium.org/p/webrtc/issues/detail?id=10746)). Fixes #313. - +- Workaround to detect H264 key frames when Chrome uses external encoder (related [issue](https://bugs.chromium.org/p/webrtc/issues/detail?id=10746)). Fixes #313. ### 3.1.1 -* Improve `GetBitratePriority()` method in `SimulcastConsumer` and `SvcConsumer` by checking the total bitrate of all temporal layers in a given producer stream or spatial layer. - +- Improve `GetBitratePriority()` method in `SimulcastConsumer` and `SvcConsumer` by checking the total bitrate of all temporal layers in a given producer stream or spatial layer. ### 3.1.0 -* Add SVC support. It includes VP9 full SVC and VP9 K-SVC as implemented by libwebrtc. -* Prefer Python 2 (if available) over Python 3. This is because there are yet pending issues with gyp + Python 3. - +- Add SVC support. It includes VP9 full SVC and VP9 K-SVC as implemented by libwebrtc. +- Prefer Python 2 (if available) over Python 3. This is because there are yet pending issues with gyp + Python 3. ### 3.0.12 -* Do not require Python 2 to compile mediasoup worker (#207). Both Python 2 and 3 can now be used. - +- Do not require Python 2 to compile mediasoup worker (#207). Both Python 2 and 3 can now be used. ### 3.0.11 -* Codecs: Improve temporal layer switching in VP8 and H264. -* Skip worker compilation if `MEDIASOUP_WORKER_BIN` environment variable is given (#309). This makes it possible to install mediasoup in platforms in which, somehow, gcc > 4.8 is not available during `npm install mediasoup` but it's available later. -* Fix `RtpStreamRecv::TransmissionCounter::GetBitrate()`. - +- Codecs: Improve temporal layer switching in VP8 and H264. +- Skip worker compilation if `MEDIASOUP_WORKER_BIN` environment variable is given (#309). This makes it possible to install mediasoup in platforms in which, somehow, gcc > 4.8 is not available during `npm install mediasoup` but it's available later. +- Fix `RtpStreamRecv::TransmissionCounter::GetBitrate()`. ### 3.0.10 -* `parseScalabilityMode()`: allow "S" as spatial layer (and not just "L"). "L" means "dependent spatial layer" while "S" means "independent spatial layer", which is used in K-SVC (VP9, AV1, etc). - +- `parseScalabilityMode()`: allow "S" as spatial layer (and not just "L"). "L" means "dependent spatial layer" while "S" means "independent spatial layer", which is used in K-SVC (VP9, AV1, etc). ### 3.0.9 -* `RtpStreamSend::ReceiveRtcpReceiverReport()`: improve `rtt` calculation if no Sender Report info is reported in received Received Report. -* Update `libuv` to version 1.29.1. - +- `RtpStreamSend::ReceiveRtcpReceiverReport()`: improve `rtt` calculation if no Sender Report info is reported in received Received Report. +- Update `libuv` to version 1.29.1. ### 3.0.8 -* VP8 & H264: Improve temporal layer switching. - +- VP8 & H264: Improve temporal layer switching. ### 3.0.7 -* RTP frame-marking: Add some missing checks. - +- RTP frame-marking: Add some missing checks. ### 3.0.6 -* Fix regression in proxied RTP header extensions. - +- Fix regression in proxied RTP header extensions. ### 3.0.5 -* Add support for frame-marking RTP extensions and use it to enable temporal layers switching in H264 codec (#305). - +- Add support for frame-marking RTP extensions and use it to enable temporal layers switching in H264 codec (#305). ### 3.0.4 -* Improve RTP probation for simulcast/svc consumers by using proper RTP retransmission with increasing sequence number. - +- Improve RTP probation for simulcast/svc consumers by using proper RTP retransmission with increasing sequence number. ### 3.0.3 -* Simulcast: Improve timestamps extra offset handling by having a map of extra offsets indexed by received timestamps. This helps in case of packet retransmission. - +- Simulcast: Improve timestamps extra offset handling by having a map of extra offsets indexed by received timestamps. This helps in case of packet retransmission. ### 3.0.2 -* Simulcast: proper RTP stream switching by rewriting packet timestamp with a new timestamp calculated from the SenderReports' NTP relationship. - +- Simulcast: proper RTP stream switching by rewriting packet timestamp with a new timestamp calculated from the SenderReports' NTP relationship. ### 3.0.1 -* Fix crash in `SimulcastConsumer::IncreaseLayer()` with Safari and H264 (#300). - +- Fix crash in `SimulcastConsumer::IncreaseLayer()` with Safari and H264 (#300). ### 3.0.0 -* v3 is here! - +- v3 is here! ### 2.6.19 -* `RtpStreamSend.cpp`: Fix a crash in `StorePacket()` when it receives an old packet and there is no space left in the storage buffer (thanks to zkfun for reporting it and providing us with the solution). -* Update deps. - +- `RtpStreamSend.cpp`: Fix a crash in `StorePacket()` when it receives an old packet and there is no space left in the storage buffer (thanks to zkfun for reporting it and providing us with the solution). +- Update deps. ### 2.6.18 -* Fix usage of a deallocated `RTC::TcpConnection` instance under heavy CPU usage due to mediasoup deleting the instance in the middle of a receiving iteration. - +- Fix usage of a deallocated `RTC::TcpConnection` instance under heavy CPU usage due to mediasoup deleting the instance in the middle of a receiving iteration. ### 2.6.17 -* Improve build system by using all available CPU cores in parallel. - +- Improve build system by using all available CPU cores in parallel. ### 2.6.16 -* Don't mandate server port range to be >= 99. - +- Don't mandate server port range to be >= 99. ### 2.6.15 -* Fix NACK retransmissions. - +- Fix NACK retransmissions. ### 2.6.14 -* Fix TCP leak (#325). - +- Fix TCP leak (#325). ### 2.6.13 -* Make mediasoup-worker compile in Armbian Debian Buster (thanks @krishisola, fixes #321). -* Update deps. - +- Make mediasoup-worker compile in Armbian Debian Buster (thanks @krishisola, fixes #321). +- Update deps. ### 2.6.12 -* Fix RTCP Receiver Report handling. - +- Fix RTCP Receiver Report handling. ### 2.6.11 -* Update deps. -* Simulcast: Increase profiles one by one unless explicitly forced (fixes #188). - +- Update deps. +- Simulcast: Increase profiles one by one unless explicitly forced (fixes #188). ### 2.6.10 -* `PlainRtpTransport.js`: Add missing methods and events. - +- `PlainRtpTransport.js`: Add missing methods and events. ### 2.6.9 -* Remove a potential crash if a single `encoding` is given in the Producer `rtpParameters` and it has a `profile` value. - +- Remove a potential crash if a single `encoding` is given in the Producer `rtpParameters` and it has a `profile` value. ### 2.6.8 -* C++: Verify in libuv static callbacks that the associated C++ instance has not been deallocated (thanks @artushin and @mariat-atg for reporting and providing valuable help in #258). - +- C++: Verify in libuv static callbacks that the associated C++ instance has not been deallocated (thanks @artushin and @mariat-atg for reporting and providing valuable help in #258). ### 2.6.7 -* Fix wrong destruction of Transports in Router.cpp that generates 100% CPU usage in mediasoup-worker processes. - +- Fix wrong destruction of Transports in Router.cpp that generates 100% CPU usage in mediasoup-worker processes. ### 2.6.6 -* Fix a port leak when a WebRtcTransport is remotely closed due to a DTLS close alert (thanks @artushin for reporting it in #259). - +- Fix a port leak when a WebRtcTransport is remotely closed due to a DTLS close alert (thanks @artushin for reporting it in #259). ### 2.6.5 -* RtpPacket: Fix Two-Byte header extensions parsing. - +- RtpPacket: Fix Two-Byte header extensions parsing. ### 2.6.4 -* Upgrade again to OpenSSL 1.1.0j (20 Nov 2018) after adding a workaround for issue [#257](https://github.com/versatica/mediasoup/issues/257). - +- Upgrade again to OpenSSL 1.1.0j (20 Nov 2018) after adding a workaround for issue [#257](https://github.com/versatica/mediasoup/issues/257). ### 2.6.3 -* Downgrade OpenSSL to version 1.1.0h (27 Mar 2018) until issue [#257](https://github.com/versatica/mediasoup/issues/257) is fixed. - +- Downgrade OpenSSL to version 1.1.0h (27 Mar 2018) until issue [#257](https://github.com/versatica/mediasoup/issues/257) is fixed. ### 2.6.2 -* C++: Remove all `Destroy()` class methods and no longer do `delete this`. -* Update libuv to 1.24.1. -* Update OpenSSL to 1.1.0g. - +- C++: Remove all `Destroy()` class methods and no longer do `delete this`. +- Update libuv to 1.24.1. +- Update OpenSSL to 1.1.0g. ### 2.6.1 -* worker: Internal refactor and code cleanup. -* Remove announced support for certain RTCP feedback types that mediasoup does nothing with (and avoid forwarding them to the remote RTP sender). -* fuzzer: fix some wrong memory access in `RtpPacket::Dump()` and `StunMessage::Dump()` (just used during development). +- worker: Internal refactor and code cleanup. +- Remove announced support for certain RTCP feedback types that mediasoup does nothing with (and avoid forwarding them to the remote RTP sender). +- fuzzer: fix some wrong memory access in `RtpPacket::Dump()` and `StunMessage::Dump()` (just used during development). ### 2.6.0 -* Integrate [libFuzzer](http://llvm.org/docs/LibFuzzer.html) into mediasoup (documentation in the `doc` folder). Extensive testing done. Several heap-buffer-overflow and memory leaks fixed. - +- Integrate [libFuzzer](http://llvm.org/docs/LibFuzzer.html) into mediasoup (documentation in the `doc` folder). Extensive testing done. Several heap-buffer-overflow and memory leaks fixed. ### 2.5.6 -* `Producer.cpp`: Remove `UpdateRtpParameters()`. It was broken since Consumers +- `Producer.cpp`: Remove `UpdateRtpParameters()`. It was broken since Consumers were not notified about profile removed and so on, so they may crash. -* `Producer.cpp: Remove some maps and simplify streams handling by having a - single `mapSsrcRtpStreamInfo`. Just keep `mapActiveProfiles` because - `GetActiveProfiles()` method needs it. -* `Producer::MayNeedNewStream()`: Ignore new media streams with new SSRC if +- `Producer.cpp: Remove some maps and simplify streams handling by having a +single `mapSsrcRtpStreamInfo`. Just keep `mapActiveProfiles`because`GetActiveProfiles()` method needs it. +- `Producer::MayNeedNewStream()`: Ignore new media streams with new SSRC if its RID is already in use by other media stream (fixes #235). -* Fix a bad memory access when using two byte RTP header extensions. - +- Fix a bad memory access when using two byte RTP header extensions. ### 2.5.5 -* `Server.js`: If a worker crashes make sure `_latestWorkerIdx` becomes 0. - +- `Server.js`: If a worker crashes make sure `_latestWorkerIdx` becomes 0. ### 2.5.4 -* `server.Room()`: Assign workers incrementally or explicitly via new `workerIdx` argument. -* Add `server.numWorkers` getter. - +- `server.Room()`: Assign workers incrementally or explicitly via new `workerIdx` argument. +- Add `server.numWorkers` getter. ### 2.5.3 -* Don't announce `muxId` nor RTP MID extension support in `Consumer` RTP parameters. - +- Don't announce `muxId` nor RTP MID extension support in `Consumer` RTP parameters. ### 2.5.2 -* Enable RTP MID extension again. - +- Enable RTP MID extension again. ### 2.5.1 -* Disable RTP MID extension until [#230](https://github.com/versatica/mediasoup/issues/230) is fixed. - +- Disable RTP MID extension until [#230](https://github.com/versatica/mediasoup/issues/230) is fixed. ### 2.5.0 -* Add RTP MID extension support. +- Add RTP MID extension support. ### 2.4.6 -* Do not close `Transport` on ICE disconnected (as it would prevent ICE restart on "recv" TCP transports). - +- Do not close `Transport` on ICE disconnected (as it would prevent ICE restart on "recv" TCP transports). ### 2.4.5 -* Improve codec matching. - +- Improve codec matching. ### 2.4.4 -* Fix audio codec matching when `channels` parameter is not given. - +- Fix audio codec matching when `channels` parameter is not given. ### 2.4.3 -* Make `PlainRtpTransport` not leak if port allocation fails (related issue [#224](https://github.com/versatica/mediasoup/issues/224)). - +- Make `PlainRtpTransport` not leak if port allocation fails (related issue [#224](https://github.com/versatica/mediasoup/issues/224)). ### 2.4.2 -* Fix a crash in when no more RTP ports were available (see related issue [#222](https://github.com/versatica/mediasoup/issues/222)). - +- Fix a crash in when no more RTP ports were available (see related issue [#222](https://github.com/versatica/mediasoup/issues/222)). ### 2.4.1 -* Update dependencies. - +- Update dependencies. ### 2.4.0 -* Allow non WebRTC peers to create plain RTP transports (no ICE/DTLS/SRTP but just plain RTP and RTCP) for sending and receiving media. - +- Allow non WebRTC peers to create plain RTP transports (no ICE/DTLS/SRTP but just plain RTP and RTCP) for sending and receiving media. ### 2.3.3 -* Fix C++ syntax to avoid an error when building the worker with clang 8.0.0 (OSX 10.11.6). - +- Fix C++ syntax to avoid an error when building the worker with clang 8.0.0 (OSX 10.11.6). ### 2.3.2 -* `Channel.js`: Upgrade `REQUEST_TIMEOUT` to 20 seconds to avoid timeout errors when the Node or worker thread usage is too high (related to this [issue](https://github.com/versatica/mediasoup-client/issues/48)). - +- `Channel.js`: Upgrade `REQUEST_TIMEOUT` to 20 seconds to avoid timeout errors when the Node or worker thread usage is too high (related to this [issue](https://github.com/versatica/mediasoup-client/issues/48)). ### 2.3.1 -* H264: Check if there is room for the indicated NAL unit size (thanks @ggarber). -* H264: Code cleanup. - +- H264: Check if there is room for the indicated NAL unit size (thanks @ggarber). +- H264: Code cleanup. ### 2.3.0 -* Add new "spy" feature. A "spy" peer cannot produce media and is invisible for other peers in the room. - +- Add new "spy" feature. A "spy" peer cannot produce media and is invisible for other peers in the room. ### 2.2.7 -* Fix H264 simulcast by properly detecting when the profile switching should be done. -* Fix a crash in `Consumer::GetStats()` (see related issue [#196](https://github.com/versatica/mediasoup/issues/196)). - +- Fix H264 simulcast by properly detecting when the profile switching should be done. +- Fix a crash in `Consumer::GetStats()` (see related issue [#196](https://github.com/versatica/mediasoup/issues/196)). ### 2.2.6 -* Add H264 simulcast capability. - +- Add H264 simulcast capability. ### 2.2.5 -* Avoid calling deprecated (NOOP) `SSL_CTX_set_ecdh_auto()` function in OpenSSL >= 1.1.0. - +- Avoid calling deprecated (NOOP) `SSL_CTX_set_ecdh_auto()` function in OpenSSL >= 1.1.0. ### 2.2.4 -* [Fix #4](https://github.com/versatica/mediasoup/issues/4): Avoid DTLS handshake fragmentation. - +- [Fix #4](https://github.com/versatica/mediasoup/issues/4): Avoid DTLS handshake fragmentation. ### 2.2.3 -* [Fix #196](https://github.com/versatica/mediasoup/issues/196): Crash in `Consumer::getStats()` due to wrong `targetProfile`. - +- [Fix #196](https://github.com/versatica/mediasoup/issues/196): Crash in `Consumer::getStats()` due to wrong `targetProfile`. ### 2.2.2 -* Improve [issue #209](https://github.com/versatica/mediasoup/issues/209). - +- Improve [issue #209](https://github.com/versatica/mediasoup/issues/209). ### 2.2.1 -* [Fix #209](https://github.com/versatica/mediasoup/issues/209): `DtlsTransport`: don't crash when signaled fingerprint and DTLS fingerprint do not match (thanks @yangjinecho for reporting it). - +- [Fix #209](https://github.com/versatica/mediasoup/issues/209): `DtlsTransport`: don't crash when signaled fingerprint and DTLS fingerprint do not match (thanks @yangjinecho for reporting it). ### 2.2.0 -* Update Node and C/C++ dependencies. - +- Update Node and C/C++ dependencies. ### 2.1.0 -* Add `localIP` option for `room.createRtpStreamer()` and `transport.startMirroring()` [[PR #199](https://github.com/versatica/mediasoup/pull/199)](https://github.com/versatica/mediasoup/pull/199). - +- Add `localIP` option for `room.createRtpStreamer()` and `transport.startMirroring()` [[PR #199](https://github.com/versatica/mediasoup/pull/199)](https://github.com/versatica/mediasoup/pull/199). ### 2.0.16 -* Improve C++ usage (remove "warning: missing initializer for member" [-Wmissing-field-initializers]). -* Update Travis-CI settings. - +- Improve C++ usage (remove "warning: missing initializer for member" [-Wmissing-field-initializers]). +- Update Travis-CI settings. ### 2.0.15 -* Make `PlainRtpTransport` also send RTCP SR/RR reports (thanks @artushin for reporting). - +- Make `PlainRtpTransport` also send RTCP SR/RR reports (thanks @artushin for reporting). ### 2.0.14 -* [Fix #193](https://github.com/versatica/mediasoup/issues/193): `preferTcp` not honored (thanks @artushin). - +- [Fix #193](https://github.com/versatica/mediasoup/issues/193): `preferTcp` not honored (thanks @artushin). ### 2.0.13 -* Avoid crash when no remote IP/port is given. - +- Avoid crash when no remote IP/port is given. ### 2.0.12 -* Add `handled` and `unhandled` events to `Consumer`. - +- Add `handled` and `unhandled` events to `Consumer`. ### 2.0.11 -* [Fix #185](https://github.com/versatica/mediasoup/issues/185): Consumer: initialize effective profile to 'NONE' (thanks @artushin). -* [Fix #186](https://github.com/versatica/mediasoup/issues/186): NackGenerator code being executed after instance deletion (thanks @baiyufei). - +- [Fix #185](https://github.com/versatica/mediasoup/issues/185): Consumer: initialize effective profile to 'NONE' (thanks @artushin). +- [Fix #186](https://github.com/versatica/mediasoup/issues/186): NackGenerator code being executed after instance deletion (thanks @baiyufei). ### 2.0.10 -* [Fix #183](https://github.com/versatica/mediasoup/issues/183): Always reset the effective `Consumer` profile when removed (thanks @thehappycoder). - +- [Fix #183](https://github.com/versatica/mediasoup/issues/183): Always reset the effective `Consumer` profile when removed (thanks @thehappycoder). ### 2.0.9 -* Make ICE+DTLS more flexible by allowing sending DTLS handshake when ICE is just connected. - +- Make ICE+DTLS more flexible by allowing sending DTLS handshake when ICE is just connected. ### 2.0.8 -* Disable stats periodic retrieval also on remote closure of `Producer` and `WebRtcTransport`. - +- Disable stats periodic retrieval also on remote closure of `Producer` and `WebRtcTransport`. ### 2.0.7 -* [Fix #180](https://github.com/versatica/mediasoup/issues/180): Added missing include `cmath` so that `std::round` can be used (thanks @jacobEAdamson). - +- [Fix #180](https://github.com/versatica/mediasoup/issues/180): Added missing include `cmath` so that `std::round` can be used (thanks @jacobEAdamson). ### 2.0.6 -* [Fix #173](https://github.com/versatica/mediasoup/issues/173): Avoid buffer overflow in `()` (thanks @lightmare). -* Improve stream layers management in `Consumer` by using the new `RtpMonitor` class. - +- [Fix #173](https://github.com/versatica/mediasoup/issues/173): Avoid buffer overflow in `()` (thanks @lightmare). +- Improve stream layers management in `Consumer` by using the new `RtpMonitor` class. ### 2.0.5 -* [Fix #164](https://github.com/versatica/mediasoup/issues/164): Sometimes video freezes forever (no RTP received in browser at all). -* [Fix #160](https://github.com/versatica/mediasoup/issues/160): Assert error in `RTC::Consumer::GetStats()`. - +- [Fix #164](https://github.com/versatica/mediasoup/issues/164): Sometimes video freezes forever (no RTP received in browser at all). +- [Fix #160](https://github.com/versatica/mediasoup/issues/160): Assert error in `RTC::Consumer::GetStats()`. ### 2.0.4 -* [Fix #159](https://github.com/versatica/mediasoup/issues/159): Don’t rely on VP8 payload descriptor flags to assure the existence of data. -* [Fix #160](https://github.com/versatica/mediasoup/issues/160): Reset `targetProfile` when the corresponding profile is removed. - +- [Fix #159](https://github.com/versatica/mediasoup/issues/159): Don’t rely on VP8 payload descriptor flags to assure the existence of data. +- [Fix #160](https://github.com/versatica/mediasoup/issues/160): Reset `targetProfile` when the corresponding profile is removed. ### 2.0.3 -* worker: Fix crash when VP8 payload has no `PictureId`. - +- worker: Fix crash when VP8 payload has no `PictureId`. ### 2.0.2 -* worker: Remove wrong `assert` on `Producer::DeactivateStreamProfiles()`. - +- worker: Remove wrong `assert` on `Producer::DeactivateStreamProfiles()`. ### 2.0.1 -* Update README file. - +- Update README file. ### 2.0.0 -* New design based on `Producers` and `Consumer` plus a mediasoup protocol and the **mediasoup-client** client side SDK. - +- New design based on `Producers` and `Consumer` plus a mediasoup protocol and the **mediasoup-client** client side SDK. ### 1.2.8 -* Fix a crash due to RTX packet processing while the associated `NackGenerator` is not yet created. - +- Fix a crash due to RTX packet processing while the associated `NackGenerator` is not yet created. ### 1.2.7 -* Habemus RTX ([RFC 4588](https://tools.ietf.org/html/rfc4588)) for proper RTP retransmission. - +- Habemus RTX ([RFC 4588](https://tools.ietf.org/html/rfc4588)) for proper RTP retransmission. ### 1.2.6 -* Fix an issue in `buffer.toString()` that makes mediasoup fail in Node 8. -* Update libuv to version 1.12.0. - +- Fix an issue in `buffer.toString()` that makes mediasoup fail in Node 8. +- Update libuv to version 1.12.0. ### 1.2.5 -* Add support for [ICE renomination](https://tools.ietf.org/html/draft-thatcher-ice-renomination). - +- Add support for [ICE renomination](https://tools.ietf.org/html/draft-thatcher-ice-renomination). ### 1.2.4 -* Fix a SDP negotiation issue when the remote peer does not have compatible codecs. - +- Fix a SDP negotiation issue when the remote peer does not have compatible codecs. ### 1.2.3 -* Add video codecs supported by Microsoft Edge. - +- Add video codecs supported by Microsoft Edge. ### 1.2.2 -* `RtpReceiver`: generate RTCP PLI when "rtpraw" or "rtpobject" event listener is set. - +- `RtpReceiver`: generate RTCP PLI when "rtpraw" or "rtpobject" event listener is set. ### 1.2.1 -* `RtpReceiver`: fix an error producing packets when "rtpobject" event is set. - +- `RtpReceiver`: fix an error producing packets when "rtpobject" event is set. ### 1.2.0 -* `RtpSender`: allow `disable()`/`enable()` without forcing SDP renegotiation (#114). - +- `RtpSender`: allow `disable()`/`enable()` without forcing SDP renegotiation (#114). ### 1.1.0 -* Add `Room.on('audiolevels')` event. - +- Add `Room.on('audiolevels')` event. ### 1.0.2 -* Set a maximum value of 1500 bytes for packet storage in `RtpStreamSend`. - +- Set a maximum value of 1500 bytes for packet storage in `RtpStreamSend`. ### 1.0.1 -* Avoid possible segfault if `RemoteBitrateEstimator` generates a bandwidth estimation with zero SSRCs. - +- Avoid possible segfault if `RemoteBitrateEstimator` generates a bandwidth estimation with zero SSRCs. ### 1.0.0 -* First stable release. +- First stable release. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..d6daf18d34 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# Contributing to mediasoup + +Thanks for taking the time to contribute to mediasoup! 🎉👍 + +## License + +By contributing to mediasoup, you agree that your contributions will be licensed under its ISC License. + +## Reporting Bugs + +We primarily use GitHub as an issue tracker. Just open an issue in GitHub if you have encountered a bug in mediasoup. + +If you have questions or doubts about mediasoup or need support, please use the mediasoup Discourse Group instead: + +- https://mediasoup.discourse.group + +If you got a crash in mediasoup, please try to provide a core dump into the issue report: + +- https://mediasoup.org/support/#crashes-in-mediasoup-get-a-core-dump + +## Pull Request Process + +When creating a Pull Request for mediasoup: + +- Ensure that changes/additions done in TypeScript files (in `node/src` folder) are also applied to the Rust layer (in `rust` folder), and vice-versa. +- Test units must be added for both Node.js and Rust. +- Changes/additions in C++ code may need tests in `worker/test` folder. + +Once all changes are done, run the following commands to verify that the code in your PR conforms to the code syntax of the project, it does not break existing funtionality and tests pass: + +- `npm run lint`: Check TypeScript and C++ linting rules. Formating errors can be automatically fixed by running `npm run format`. +- `npm run typescript:build`: Compile TypeScript code (under `src` folder) into JavaScript code (under `lib` folder). +- `npm run test`: Run JavaScript and C++ test units. +- Instead, you can run `npm run release:check` which will run all those steps. +- `cargo fmt`, `cargo clippy` and `cargo test` to ensure that everything is good in Rust side. + +The full list of `npm` scripts, `invoke` tasks and `cargo` commands is available in the [doc/Building.md](/doc/Building.md) file. + +## Coding Style + +In adition to automatic checks performed by commands above, we also enforce other minor things related to coding style: + +### Comments in TypeScript and C++ + +We use `//` for inline comments in both JavaScript and C++ source files. + +- Comments must start with upercase letter. +- Comments must not exceed 80 columns (split into different lines if necessary). +- Comments must end with a dot. + +Example (good): + +```ts +// Calculate foo based on bar value. +const foo = bar / 2; +``` + +Example (bad): + +```ts +// calculate foo based on bar value +const foo = bar / 2; +``` + +When adding inline documentation for methods or functions, we use `/** */` syntax. Example: + +```ts +/** + * Calculates current score for foo and bar. + */ +function calculateScore(): number { + // [...] +} +``` diff --git a/README.md b/README.md index aa709787ab..28b1204556 100644 --- a/README.md +++ b/README.md @@ -10,58 +10,51 @@ [![][codeql-shield-mediasoup]][codeql-mediasoup] [![][opencollective-shield-mediasoup]][opencollective-mediasoup] - ## Website and Documentation -* [mediasoup.org][mediasoup-website] - +- [mediasoup.org][mediasoup-website] ## Support Forum -* [mediasoup.discourse.group][mediasoup-discourse] - +- [mediasoup.discourse.group][mediasoup-discourse] ## Design Goals mediasoup and its client side libraries are designed to accomplish with the following goals: -* Be a [SFU](https://webrtcglossary.com/sfu/) (Selective Forwarding Unit). -* Support both WebRTC and plain RTP input and output. -* Be a Node.js module/Rust crate in server side. -* Be a tiny JavaScript and C++ libraries in client side. -* Be minimalist: just handle the media layer. -* Be signaling agnostic: do not mandate any signaling protocol. -* Be super low level API. -* Support all existing WebRTC endpoints. -* Enable integration with well known multimedia libraries/tools. - +- Be a [SFU](https://webrtcglossary.com/sfu) (Selective Forwarding Unit). +- Support both WebRTC and plain RTP input and output. +- Be a Node.js module or Rust crate in server side. +- Be a tiny TypeScript and C++ libraries in client side. +- Be minimalist: just handle the media layer. +- Be signaling agnostic: do not mandate any signaling protocol. +- Be super low level API. +- Support all existing WebRTC endpoints. +- Enable integration with well known multimedia libraries/tools. ## Architecture ![][mediasoup-architecture] - ## Use Cases mediasoup and its client side libraries provide a super low level API. They are intended to enable different use cases and scenarios, without any constraint or assumption. Some of these use cases are: -* Group video chat applications. -* One-to-many (or few-to-many) broadcasting applications in real-time. -* RTP streaming. - +- Group video chat applications. +- One-to-many (or few-to-many) broadcasting applications in real-time. +- RTP streaming. ## Features -* ECMAScript 6/Idiomatic Rust low level API. -* Multi-stream: multiple audio/video streams over a single ICE + DTLS transport. -* IPv6 ready. -* ICE / DTLS / RTP / RTCP over UDP and TCP. -* Simulcast and SVC support. -* Congestion control. -* Sender and receiver bandwidth estimation with spatial/temporal layers distribution algorithm. -* Data message exchange (via WebRTC DataChannels, SCTP over plain UDP, and direct termination in Node.js/Rust). -* Extremely powerful (media worker thread/subprocess coded in C++ on top of [libuv](https://libuv.org)). - +- ECMAScript 6/Idiomatic Rust low level API. +- Multi-stream: multiple audio/video streams over a single ICE + DTLS transport. +- IPv6 ready. +- ICE / DTLS / RTP / RTCP over UDP and TCP. +- Simulcast and SVC support. +- Congestion control. +- Sender and receiver bandwidth estimation with spatial/temporal layers distribution algorithm. +- Data message exchange (via WebRTC DataChannels, SCTP over plain UDP, and direct termination in Node.js/Rust). +- Extremely powerful (media worker thread/subprocess coded in C++ on top of [libuv](https://libuv.org)). ## Demo Online @@ -69,31 +62,24 @@ mediasoup and its client side libraries provide a super low level API. They are Try it at [v3demo.mediasoup.org](https://v3demo.mediasoup.org) ([source code](https://github.com/versatica/mediasoup-demo)). - ## Authors -* Iñaki Baz Castillo [[website](https://inakibaz.me)|[github](https://github.com/ibc/)] -* José Luis Millán [[github](https://github.com/jmillan/)] -* Nazar Mokynskyi [[github](https://github.com/nazar-pc/)] - +- Iñaki Baz Castillo [[website](https://inakibaz.me)|[github](https://github.com/ibc/)] +- José Luis Millán [[github](https://github.com/jmillan/)] +- Nazar Mokynskyi [[github](https://github.com/nazar-pc/)] ## Social -* Twitter: [@mediasoup_sfu](https://twitter.com/mediasoup_sfu) - +- Twitter: [@mediasoup_sfu](https://twitter.com/mediasoup_sfu) ## Sponsor You can support mediasoup by [sponsoring][sponsor] it. Thanks! - ## License [ISC](./LICENSE) - - - [mediasoup-banner]: /art/mediasoup-banner.png [mediasoup-website]: https://mediasoup.org [mediasoup-discourse]: https://mediasoup.discourse.group diff --git a/node/tsconfig.json b/node/tsconfig.json index bcdc2139c1..87394576c7 100644 --- a/node/tsconfig.json +++ b/node/tsconfig.json @@ -1,8 +1,7 @@ { "compileOnSave": true, - "compilerOptions": - { - "lib": [ "es2021" ], + "compilerOptions": { + "lib": ["es2021"], "target": "esnext", "module": "commonjs", "moduleResolution": "node", @@ -11,11 +10,11 @@ "declaration": true, "declarationMap": true }, - "include": [ "src" ], + "include": ["src"], "watchOptions": { - "watchFile": "useFsEvents", - "watchDirectory": "useFsEvents", - "fallbackPolling": "dynamicPriority", - "synchronousWatchDirectory": true + "watchFile": "useFsEvents", + "watchDirectory": "useFsEvents", + "fallbackPolling": "dynamicPriority", + "synchronousWatchDirectory": true } } diff --git a/npm-scripts.mjs b/npm-scripts.mjs index e463c53fb6..e044c38077 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -346,21 +346,14 @@ function cleanWorkerArtifacts() { function lintNode() { logInfo('lintNode()'); - const paths = [ - 'npm-scripts.mjs', - '.eslintrc.js', - 'node/src', - 'worker/scripts/clang-format.mjs', - ]; + executeCmd('prettier . --check'); // Ensure there are no rules that are unnecessary or conflict with Prettier // rules. executeCmd('eslint-config-prettier .eslintrc.js'); executeCmd( - `eslint -c .eslintrc.js --ignore-path .eslintignore --max-warnings 0 ${paths.join( - ' ', - )}`, + 'eslint -c .eslintrc.js --ignore-path .eslintignore --max-warnings 0 .', ); } @@ -375,14 +368,7 @@ function lintWorker() { function formatNode() { logInfo('formatNode()'); - const paths = [ - 'npm-scripts.mjs', - '.eslintrc.js', - 'node/src', - 'worker/scripts/clang-format.mjs', - ]; - - executeCmd(`prettier ${paths.join(' ')} --write`); + executeCmd('prettier . --write'); } function flatcNode() { diff --git a/package-lock.json b/package-lock.json index c57faca3b8..c079ed111e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11889 +1,11889 @@ { - "name": "mediasoup", - "version": "3.13.15", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "mediasoup", - "version": "3.13.15", - "hasInstallScript": true, - "license": "ISC", - "dependencies": { - "debug": "^4.3.4", - "flatbuffers": "^23.5.26", - "h264-profile-level-id": "^2.0.0", - "node-fetch": "^3.3.2", - "supports-color": "^9.4.0", - "tar": "^6.2.0" - }, - "devDependencies": { - "@octokit/rest": "^20.0.2", - "@types/debug": "^4.1.12", - "@types/jest": "^29.5.11", - "@types/node": "^20.10.7", - "@typescript-eslint/eslint-plugin": "^6.18.0", - "@typescript-eslint/parser": "^6.18.0", - "eslint": "^8.56.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.6.1", - "eslint-plugin-prettier": "^5.1.2", - "jest": "^29.7.0", - "marked": "^11.1.1", - "open-cli": "^7.2.0", - "pick-port": "^1.0.1", - "prettier": "^3.1.1", - "sctp": "^1.0.0", - "ts-jest": "^29.1.1", - "typescript": "^5.3.3" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mediasoup" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.1.tgz", - "integrity": "sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.2.tgz", - "integrity": "sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.2", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.1", - "@babel/parser": "^7.20.2", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz", - "integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.0", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz", - "integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.1.tgz", - "integrity": "sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", - "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@octokit/auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", - "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", - "dev": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/core": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", - "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", - "dev": true, - "dependencies": { - "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.0.0", - "@octokit/request": "^8.0.2", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/endpoint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", - "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", - "dev": true, - "dependencies": { - "@octokit/types": "^11.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/graphql": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", - "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", - "dev": true, - "dependencies": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^11.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", - "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", - "dev": true - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", - "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", - "dev": true, - "dependencies": { - "@octokit/types": "^12.0.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=5" - } - }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", - "dev": true - }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^19.0.0" - } - }, - "node_modules/@octokit/plugin-request-log": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", - "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", - "dev": true, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=5" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", - "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", - "dev": true, - "dependencies": { - "@octokit/types": "^12.0.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=5" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", - "dev": true - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^19.0.0" - } - }, - "node_modules/@octokit/request": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", - "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", - "dev": true, - "dependencies": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.1.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/request-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", - "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", - "dev": true, - "dependencies": { - "@octokit/types": "^11.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/rest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", - "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", - "dev": true, - "dependencies": { - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/types": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", - "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^18.0.0" - } - }, - "node_modules/@pkgr/core": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", - "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "29.5.11", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", - "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", - "dev": true, - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, - "node_modules/@types/node": { - "version": "20.10.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", - "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/yargs": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", - "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", - "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/type-utils": "6.18.0", - "@typescript-eslint/utils": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.18.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", - "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.18.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", - "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/utils": "6.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.18.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-8.0.2.tgz", - "integrity": "sha512-qMKdlOfsjlezMqxkUGGMaWWs17i2HoL15tM+wtx8ld4nLrUwU58TFdvyGOz/piNP842KeO8yXvggVQSdQ828NA==", - "dev": true, - "dependencies": { - "camelcase": "^7.0.0", - "map-obj": "^4.3.0", - "quick-lru": "^6.1.1", - "type-fest": "^2.13.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001431", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz", - "integrity": "sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", - "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", - "deprecated": "cross-spawn no longer requires a build toolchain, use it instead", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.0", - "which": "^1.2.8" - } - }, - "node_modules/cross-spawn-async/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/cross-spawn-async/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/cross-spawn-async/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "dev": true, - "dependencies": { - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/crypto-random-string/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-browser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", - "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", - "dev": true, - "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^5.0.0", - "xdg-default-browser": "^2.1.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-jest": { - "version": "27.6.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", - "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^5.10.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", - "eslint": "^7.0.0 || ^8.0.0", - "jest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", - "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-type": { - "version": "18.2.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", - "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", - "dev": true, - "dependencies": { - "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0", - "token-types": "^5.0.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatbuffers": { - "version": "23.5.26", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.5.26.tgz", - "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==" - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/h264-profile-level-id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-2.0.0.tgz", - "integrity": "sha512-X4CLryVbVA0CtjTExS4G5U1gb2Z4wa32AF8ukVmFuLdw2JRq2aHisor7SY5SYTUUrUSqq0KdPIO18sql6IWIQw==", - "dependencies": { - "@types/debug": "^4.1.12", - "debug": "^4.3.4" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mediasoup" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/hosted-git-info": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", - "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", - "dev": true, - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", - "dev": true - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-wsl/node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/marked": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", - "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/meow": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", - "integrity": "sha512-Cl0yeeIrko6d94KpUo1M+0X1sB14ikoaqlIGuTH1fW4I+E3+YljL54/hb/BWmVfrV9tTV9zU04+xjw08Fh2WkA==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^8.0.2", - "decamelize": "^6.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^4.0.1", - "read-pkg-up": "^9.1.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^3.1.0", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.1.tgz", - "integrity": "sha512-htXWckxlT6U4+ilVgweNliPqlsVSSucbxVexRYllyMVJDtf5rTjv6kF/s+qAd4QSL1BZcnJPEJavYBPQiWuZDA==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", - "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", - "dev": true, - "dependencies": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", - "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", - "dev": true, - "dependencies": { - "default-browser": "^3.1.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open-cli": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.2.0.tgz", - "integrity": "sha512-1ANJc8oJ92FiaNZ0o2Hw4WBvDJoXs1P74aFMtpAvlbkIPV4uPcQvDz7V6kMOrsZkmB4tglrHVMlLQaafuUuxXg==", - "dev": true, - "dependencies": { - "file-type": "^18.2.1", - "get-stdin": "^9.0.0", - "meow": "^11.0.0", - "open": "^9.0.0", - "tempy": "^3.0.0" - }, - "bin": { - "open-cli": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/peek-readable": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", - "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/pick-port": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-1.0.1.tgz", - "integrity": "sha512-JzjRIkfG/4pG3tYLl1LwdmFtnlW+Rsxe200DevHZzZLYDUgfnx8LuOFnLwy5Dt59JY1HIN3JXyMXRbUvERkh/g==", - "dev": true, - "dependencies": { - "debug": "^4.3.1" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/polycrc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/polycrc/-/polycrc-0.1.0.tgz", - "integrity": "sha512-pBjdz8Gj0ixRkR80acjWl6bxiHf23MTI6chIKbQqphF2SrXXtYSPlftCSL31bD3veSWJCaTsM1QhT6zlIebqlg==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", - "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pure-rand": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", - "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ] - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.1.tgz", - "integrity": "sha512-S27GBT+F0NTRiehtbrgaSE1idUAJ5bX8dPAQTdylEyNlrdcH5X4Lz7Edz3DYzecbsCluD5zO8ZNEe04z3D3u6Q==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "node_modules/read-pkg": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", - "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.1", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^2.0.0" - }, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", - "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", - "dev": true, - "dependencies": { - "find-up": "^6.3.0", - "read-pkg": "^7.1.0", - "type-fest": "^2.5.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "dev": true, - "dependencies": { - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/redent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "dependencies": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/sctp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sctp/-/sctp-1.0.0.tgz", - "integrity": "sha512-wceaBrz55a0dbYG3c2zfJ1adUASLJhntQYZNVZKlGfKH1ExMckZB0sOxroWgpJLflcAB/k6wMOAPOrmylsRU4A==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "ip": "^1.1.5", - "polycrc": "^0.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strtok3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", - "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", - "dev": true, - "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^5.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/synckit/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tempy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz", - "integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==", - "dev": true, - "dependencies": { - "is-stream": "^3.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^2.12.2", - "unique-string": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/titleize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", - "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/token-types": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", - "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", - "dev": true, - "dependencies": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/trim-newlines": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", - "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ts-api-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", - "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", - "dev": true, - "engines": { - "node": ">=16.13.0" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", - "dev": true, - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dev": true, - "dependencies": { - "crypto-random-string": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/xdg-default-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", - "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", - "dev": true, - "dependencies": { - "execa": "^0.2.2", - "titleize": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/xdg-default-browser/node_modules/execa": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", - "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", - "dev": true, - "dependencies": { - "cross-spawn-async": "^2.1.1", - "npm-run-path": "^1.0.0", - "object-assign": "^4.0.1", - "path-key": "^1.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/xdg-default-browser/node_modules/npm-run-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", - "dev": true, - "dependencies": { - "path-key": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/xdg-default-browser/node_modules/path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/compat-data": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.1.tgz", - "integrity": "sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==", - "dev": true - }, - "@babel/core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.2.tgz", - "integrity": "sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.2", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.1", - "@babel/parser": "^7.20.2", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "requires": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz", - "integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.20.0", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz", - "integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dev": true, - "requires": { - "@babel/types": "^7.20.2" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true - }, - "@babel/helpers": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.1.tgz", - "integrity": "sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==", - "dev": true, - "requires": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.0" - } - }, - "@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - }, - "@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - } - }, - "@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "requires": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - } - }, - "@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "requires": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - } - }, - "@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "requires": { - "jest-get-type": "^29.6.3" - } - }, - "@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - } - }, - "@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "dependencies": { - "istanbul-lib-instrument": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", - "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - } - } - } - }, - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "requires": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - } - }, - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@octokit/auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", - "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", - "dev": true - }, - "@octokit/core": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", - "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", - "dev": true, - "requires": { - "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.0.0", - "@octokit/request": "^8.0.2", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", - "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", - "dev": true, - "requires": { - "@octokit/types": "^11.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", - "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", - "dev": true, - "requires": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^11.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", - "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", - "dev": true - }, - "@octokit/plugin-paginate-rest": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", - "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", - "dev": true, - "requires": { - "@octokit/types": "^12.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", - "dev": true - }, - "@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^19.0.0" - } - } - } - }, - "@octokit/plugin-request-log": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", - "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", - "dev": true, - "requires": {} - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", - "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", - "dev": true, - "requires": { - "@octokit/types": "^12.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", - "dev": true - }, - "@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^19.0.0" - } - } - } - }, - "@octokit/request": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", - "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", - "dev": true, - "requires": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.1.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", - "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", - "dev": true, - "requires": { - "@octokit/types": "^11.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/rest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", - "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", - "dev": true, - "requires": { - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" - } - }, - "@octokit/types": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", - "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^18.0.0" - } - }, - "@pkgr/core": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", - "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", - "dev": true - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.0" - } - }, - "@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", - "dev": true, - "requires": { - "@babel/types": "^7.20.7" - } - }, - "@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "requires": { - "@types/ms": "*" - } - }, - "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "29.5.11", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", - "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", - "dev": true, - "requires": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, - "@types/node": { - "version": "20.10.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", - "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", - "dev": true, - "requires": { - "undici-types": "~5.26.4" - } - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/yargs": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", - "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", - "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/type-utils": "6.18.0", - "@typescript-eslint/utils": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" - } - }, - "@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "semver": "^7.5.4" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.18.0", - "eslint-visitor-keys": "^3.4.1" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", - "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" - } - }, - "@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.18.0", - "eslint-visitor-keys": "^3.4.1" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", - "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/utils": "6.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" - } - }, - "@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "semver": "^7.5.4" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.18.0", - "eslint-visitor-keys": "^3.4.1" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true - }, - "babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "requires": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true - }, - "big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true - }, - "bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "requires": { - "big-integer": "^1.6.44" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "requires": { - "run-applescript": "^5.0.0" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "camelcase-keys": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-8.0.2.tgz", - "integrity": "sha512-qMKdlOfsjlezMqxkUGGMaWWs17i2HoL15tM+wtx8ld4nLrUwU58TFdvyGOz/piNP842KeO8yXvggVQSdQ828NA==", - "dev": true, - "requires": { - "camelcase": "^7.0.0", - "map-obj": "^4.3.0", - "quick-lru": "^6.1.1", - "type-fest": "^2.13.0" - }, - "dependencies": { - "camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "dev": true - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - } - } - }, - "caniuse-lite": { - "version": "1.0.30001431", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz", - "integrity": "sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "ci-info": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", - "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", - "dev": true, - "requires": { - "lru-cache": "^4.0.0", - "which": "^1.2.8" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - } - } - }, - "crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "dev": true, - "requires": { - "type-fest": "^1.0.1" - }, - "dependencies": { - "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true - } - } - }, - "data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true - } - } - }, - "dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "requires": {} - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true - }, - "default-browser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", - "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", - "dev": true, - "requires": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^5.0.0", - "xdg-default-browser": "^2.1.0" - } - }, - "default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, - "requires": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - } - }, - "define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true - }, - "emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "requires": {} - }, - "eslint-plugin-jest": { - "version": "27.6.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", - "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "^5.10.0" - } - }, - "eslint-plugin-prettier": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", - "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true - }, - "expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "requires": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-type": { - "version": "18.2.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", - "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", - "dev": true, - "requires": { - "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0", - "token-types": "^5.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatbuffers": { - "version": "23.5.26", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.5.26.tgz", - "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==" - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "requires": { - "fetch-blob": "^3.1.2" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "h264-profile-level-id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-2.0.0.tgz", - "integrity": "sha512-X4CLryVbVA0CtjTExS4G5U1gb2Z4wa32AF8ukVmFuLdw2JRq2aHisor7SY5SYTUUrUSqq0KdPIO18sql6IWIQw==", - "requires": { - "@types/debug": "^4.1.12", - "debug": "^4.3.4" - } - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "hosted-git-info": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", - "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - } - } - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "requires": { - "is-docker": "^3.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - }, - "dependencies": { - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - } - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "requires": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - } - }, - "jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - } - }, - "jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "requires": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - } - }, - "jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - } - }, - "jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "requires": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - } - }, - "jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "requires": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - } - }, - "jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - } - }, - "jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - }, - "jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - } - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - } - } - }, - "jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "requires": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "requires": { - "semver": "^7.5.3" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true - }, - "marked": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", - "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==", - "dev": true - }, - "meow": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", - "integrity": "sha512-Cl0yeeIrko6d94KpUo1M+0X1sB14ikoaqlIGuTH1fW4I+E3+YljL54/hb/BWmVfrV9tTV9zU04+xjw08Fh2WkA==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^8.0.2", - "decamelize": "^6.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^4.0.1", - "read-pkg-up": "^9.1.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^3.1.0", - "yargs-parser": "^21.1.1" - }, - "dependencies": { - "type-fest": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.1.tgz", - "integrity": "sha512-htXWckxlT6U4+ilVgweNliPqlsVSSucbxVexRYllyMVJDtf5rTjv6kF/s+qAd4QSL1BZcnJPEJavYBPQiWuZDA==", - "dev": true - } - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" - }, - "node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - } - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true - }, - "normalize-package-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", - "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", - "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", - "dev": true, - "requires": { - "default-browser": "^3.1.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - } - }, - "open-cli": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.2.0.tgz", - "integrity": "sha512-1ANJc8oJ92FiaNZ0o2Hw4WBvDJoXs1P74aFMtpAvlbkIPV4uPcQvDz7V6kMOrsZkmB4tglrHVMlLQaafuUuxXg==", - "dev": true, - "requires": { - "file-type": "^18.2.1", - "get-stdin": "^9.0.0", - "meow": "^11.0.0", - "open": "^9.0.0", - "tempy": "^3.0.0" - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "peek-readable": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", - "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", - "dev": true - }, - "pick-port": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-1.0.1.tgz", - "integrity": "sha512-JzjRIkfG/4pG3tYLl1LwdmFtnlW+Rsxe200DevHZzZLYDUgfnx8LuOFnLwy5Dt59JY1HIN3JXyMXRbUvERkh/g==", - "dev": true, - "requires": { - "debug": "^4.3.1" - } - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } - } - }, - "polycrc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/polycrc/-/polycrc-0.1.0.tgz", - "integrity": "sha512-pBjdz8Gj0ixRkR80acjWl6bxiHf23MTI6chIKbQqphF2SrXXtYSPlftCSL31bD3veSWJCaTsM1QhT6zlIebqlg==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", - "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "pure-rand": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", - "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "quick-lru": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.1.tgz", - "integrity": "sha512-S27GBT+F0NTRiehtbrgaSE1idUAJ5bX8dPAQTdylEyNlrdcH5X4Lz7Edz3DYzecbsCluD5zO8ZNEe04z3D3u6Q==", - "dev": true - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "read-pkg": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", - "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.1", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^2.0.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", - "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", - "dev": true, - "requires": { - "find-up": "^6.3.0", - "read-pkg": "^7.1.0", - "type-fest": "^2.5.0" - }, - "dependencies": { - "find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "requires": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - } - }, - "locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "requires": { - "p-locate": "^6.0.0" - } - }, - "p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "requires": { - "yocto-queue": "^1.0.0" - } - }, - "p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "requires": { - "p-limit": "^4.0.0" - } - }, - "path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - }, - "yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "dev": true, - "requires": { - "readable-stream": "^3.6.0" - } - }, - "redent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "requires": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "sctp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sctp/-/sctp-1.0.0.tgz", - "integrity": "sha512-wceaBrz55a0dbYG3c2zfJ1adUASLJhntQYZNVZKlGfKH1ExMckZB0sOxroWgpJLflcAB/k6wMOAPOrmylsRU4A==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "ip": "^1.1.5", - "polycrc": "^0.1.0" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "requires": { - "min-indent": "^1.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "strtok3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", - "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", - "dev": true, - "requires": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^5.0.0" - } - }, - "supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==" - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dev": true, - "requires": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - } - } - }, - "tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true - }, - "tempy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz", - "integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==", - "dev": true, - "requires": { - "is-stream": "^3.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^2.12.2", - "unique-string": "^3.0.0" - }, - "dependencies": { - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "titleize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", - "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", - "dev": true - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "token-types": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", - "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", - "dev": true, - "requires": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - } - }, - "trim-newlines": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", - "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", - "dev": true - }, - "ts-api-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", - "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", - "dev": true, - "requires": {} - }, - "ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true - }, - "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dev": true, - "requires": { - "crypto-random-string": "^4.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - }, - "untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - } - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - }, - "xdg-default-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", - "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", - "dev": true, - "requires": { - "execa": "^0.2.2", - "titleize": "^1.0.0" - }, - "dependencies": { - "execa": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", - "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", - "dev": true, - "requires": { - "cross-spawn-async": "^2.1.1", - "npm-run-path": "^1.0.0", - "object-assign": "^4.0.1", - "path-key": "^1.0.0", - "strip-eof": "^1.0.0" - } - }, - "npm-run-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", - "dev": true, - "requires": { - "path-key": "^1.0.0" - } - }, - "path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", - "dev": true - } - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } + "name": "mediasoup", + "version": "3.13.15", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "mediasoup", + "version": "3.13.15", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "debug": "^4.3.4", + "flatbuffers": "^23.5.26", + "h264-profile-level-id": "^2.0.0", + "node-fetch": "^3.3.2", + "supports-color": "^9.4.0", + "tar": "^6.2.0" + }, + "devDependencies": { + "@octokit/rest": "^20.0.2", + "@types/debug": "^4.1.12", + "@types/jest": "^29.5.11", + "@types/node": "^20.10.7", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-jest": "^27.6.1", + "eslint-plugin-prettier": "^5.1.2", + "jest": "^29.7.0", + "marked": "^11.1.1", + "open-cli": "^7.2.0", + "pick-port": "^1.0.1", + "prettier": "^3.1.1", + "sctp": "^1.0.0", + "ts-jest": "^29.1.1", + "typescript": "^5.3.3" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mediasoup" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.1.tgz", + "integrity": "sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.2.tgz", + "integrity": "sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.20.2", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-module-transforms": "^7.20.2", + "@babel/helpers": "^7.20.1", + "@babel/parser": "^7.20.2", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz", + "integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.20.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz", + "integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.1.tgz", + "integrity": "sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", + "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.0.0", + "@octokit/request": "^8.0.2", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", + "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", + "dev": true, + "dependencies": { + "@octokit/types": "^11.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", + "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", + "dev": true, + "dependencies": { + "@octokit/request": "^8.0.1", + "@octokit/types": "^11.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", + "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", + "dev": true, + "dependencies": { + "@octokit/types": "^12.0.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", + "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^19.0.0" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", + "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", + "dev": true, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", + "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", + "dev": true, + "dependencies": { + "@octokit/types": "^12.0.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", + "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "dev": true + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^19.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", + "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.1.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", + "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", + "dev": true, + "dependencies": { + "@octokit/types": "^11.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest": { + "version": "20.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", + "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", + "dev": true, + "dependencies": { + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", + "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", + "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, + "node_modules/@types/node": { + "version": "20.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", + "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", + "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/type-utils": "6.18.0", + "@typescript-eslint/utils": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", + "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.18.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", + "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.18.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", + "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/utils": "6.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", + "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.18.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true + }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-8.0.2.tgz", + "integrity": "sha512-qMKdlOfsjlezMqxkUGGMaWWs17i2HoL15tM+wtx8ld4nLrUwU58TFdvyGOz/piNP842KeO8yXvggVQSdQ828NA==", + "dev": true, + "dependencies": { + "camelcase": "^7.0.0", + "map-obj": "^4.3.0", + "quick-lru": "^6.1.1", + "type-fest": "^2.13.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001431", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz", + "integrity": "sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", + "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn-async": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", + "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", + "deprecated": "cross-spawn no longer requires a build toolchain, use it instead", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.0", + "which": "^1.2.8" + } + }, + "node_modules/cross-spawn-async/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/cross-spawn-async/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/cross-spawn-async/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", + "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^5.0.0", + "xdg-default-browser": "^2.1.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "27.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", + "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", + "eslint": "^7.0.0 || ^8.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", + "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-type": { + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", + "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", + "dev": true, + "dependencies": { + "readable-web-to-node-stream": "^3.0.2", + "strtok3": "^7.0.0", + "token-types": "^5.0.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatbuffers": { + "version": "23.5.26", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.5.26.tgz", + "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==" + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/h264-profile-level-id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-2.0.0.tgz", + "integrity": "sha512-X4CLryVbVA0CtjTExS4G5U1gb2Z4wa32AF8ukVmFuLdw2JRq2aHisor7SY5SYTUUrUSqq0KdPIO18sql6IWIQw==", + "dependencies": { + "@types/debug": "^4.1.12", + "debug": "^4.3.4" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mediasoup" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hosted-git-info": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", + "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", + "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/meow": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", + "integrity": "sha512-Cl0yeeIrko6d94KpUo1M+0X1sB14ikoaqlIGuTH1fW4I+E3+YljL54/hb/BWmVfrV9tTV9zU04+xjw08Fh2WkA==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^8.0.2", + "decamelize": "^6.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^4.0.1", + "read-pkg-up": "^9.1.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^3.1.0", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.1.tgz", + "integrity": "sha512-htXWckxlT6U4+ilVgweNliPqlsVSSucbxVexRYllyMVJDtf5rTjv6kF/s+qAd4QSL1BZcnJPEJavYBPQiWuZDA==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", + "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", + "dev": true, + "dependencies": { + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", + "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", + "dev": true, + "dependencies": { + "default-browser": "^3.1.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open-cli": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.2.0.tgz", + "integrity": "sha512-1ANJc8oJ92FiaNZ0o2Hw4WBvDJoXs1P74aFMtpAvlbkIPV4uPcQvDz7V6kMOrsZkmB4tglrHVMlLQaafuUuxXg==", + "dev": true, + "dependencies": { + "file-type": "^18.2.1", + "get-stdin": "^9.0.0", + "meow": "^11.0.0", + "open": "^9.0.0", + "tempy": "^3.0.0" + }, + "bin": { + "open-cli": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/peek-readable": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", + "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/pick-port": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-1.0.1.tgz", + "integrity": "sha512-JzjRIkfG/4pG3tYLl1LwdmFtnlW+Rsxe200DevHZzZLYDUgfnx8LuOFnLwy5Dt59JY1HIN3JXyMXRbUvERkh/g==", + "dev": true, + "dependencies": { + "debug": "^4.3.1" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/polycrc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/polycrc/-/polycrc-0.1.0.tgz", + "integrity": "sha512-pBjdz8Gj0ixRkR80acjWl6bxiHf23MTI6chIKbQqphF2SrXXtYSPlftCSL31bD3veSWJCaTsM1QhT6zlIebqlg==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.1.tgz", + "integrity": "sha512-S27GBT+F0NTRiehtbrgaSE1idUAJ5bX8dPAQTdylEyNlrdcH5X4Lz7Edz3DYzecbsCluD5zO8ZNEe04z3D3u6Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/read-pkg": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", + "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^2.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", + "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", + "dev": true, + "dependencies": { + "find-up": "^6.3.0", + "read-pkg": "^7.1.0", + "type-fest": "^2.5.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dev": true, + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "dependencies": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/sctp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sctp/-/sctp-1.0.0.tgz", + "integrity": "sha512-wceaBrz55a0dbYG3c2zfJ1adUASLJhntQYZNVZKlGfKH1ExMckZB0sOxroWgpJLflcAB/k6wMOAPOrmylsRU4A==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "ip": "^1.1.5", + "polycrc": "^0.1.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strtok3": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", + "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", + "dev": true, + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz", + "integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==", + "dev": true, + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/titleize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", + "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/token-types": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", + "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", + "dev": true, + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/trim-newlines": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", + "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/xdg-default-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", + "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", + "dev": true, + "dependencies": { + "execa": "^0.2.2", + "titleize": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/xdg-default-browser/node_modules/execa": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", + "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", + "dev": true, + "dependencies": { + "cross-spawn-async": "^2.1.1", + "npm-run-path": "^1.0.0", + "object-assign": "^4.0.1", + "path-key": "^1.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/xdg-default-browser/node_modules/npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", + "dev": true, + "dependencies": { + "path-key": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xdg-default-browser/node_modules/path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/compat-data": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.1.tgz", + "integrity": "sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==", + "dev": true + }, + "@babel/core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.2.tgz", + "integrity": "sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.20.2", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-module-transforms": "^7.20.2", + "@babel/helpers": "^7.20.1", + "@babel/parser": "^7.20.2", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "dependencies": { + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz", + "integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.20.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz", + "integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dev": true, + "requires": { + "@babel/types": "^7.20.2" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.1.tgz", + "integrity": "sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.0" + } + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + } + }, + "@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "requires": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + } + }, + "@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3" + } + }, + "@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + } + }, + "@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + } + } + } + }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true + }, + "@octokit/core": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", + "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", + "dev": true, + "requires": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.0.0", + "@octokit/request": "^8.0.2", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", + "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", + "dev": true, + "requires": { + "@octokit/types": "^11.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", + "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", + "dev": true, + "requires": { + "@octokit/request": "^8.0.1", + "@octokit/types": "^11.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", + "dev": true + }, + "@octokit/plugin-paginate-rest": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", + "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", + "dev": true, + "requires": { + "@octokit/types": "^12.0.0" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", + "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "dev": true + }, + "@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dev": true, + "requires": { + "@octokit/openapi-types": "^19.0.0" + } + } + } + }, + "@octokit/plugin-request-log": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", + "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", + "dev": true, + "requires": {} + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", + "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", + "dev": true, + "requires": { + "@octokit/types": "^12.0.0" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", + "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "dev": true + }, + "@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dev": true, + "requires": { + "@octokit/openapi-types": "^19.0.0" + } + } + } + }, + "@octokit/request": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", + "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", + "dev": true, + "requires": { + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.1.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", + "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", + "dev": true, + "requires": { + "@octokit/types": "^11.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "20.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", + "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", + "dev": true, + "requires": { + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + } + }, + "@octokit/types": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", + "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", + "dev": true, + "requires": { + "@octokit/openapi-types": "^18.0.0" + } + }, + "@pkgr/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", + "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "dev": true + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "dev": true + }, + "@types/babel__core": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "requires": { + "@types/ms": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", + "dev": true, + "requires": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, + "@types/node": { + "version": "20.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", + "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", + "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/type-utils": "6.18.0", + "@typescript-eslint/utils": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" + } + }, + "@typescript-eslint/types": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", + "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.18.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", + "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" + } + }, + "@typescript-eslint/types": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.18.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", + "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/utils": "6.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" + } + }, + "@typescript-eslint/types": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", + "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.18.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true + }, + "babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "requires": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true + }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true + }, + "bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "requires": { + "big-integer": "^1.6.44" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "requires": { + "run-applescript": "^5.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-keys": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-8.0.2.tgz", + "integrity": "sha512-qMKdlOfsjlezMqxkUGGMaWWs17i2HoL15tM+wtx8ld4nLrUwU58TFdvyGOz/piNP842KeO8yXvggVQSdQ828NA==", + "dev": true, + "requires": { + "camelcase": "^7.0.0", + "map-obj": "^4.3.0", + "quick-lru": "^6.1.1", + "type-fest": "^2.13.0" + }, + "dependencies": { + "camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "dev": true + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + } + } + }, + "caniuse-lite": { + "version": "1.0.30001431", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz", + "integrity": "sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "ci-info": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", + "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", + "dev": true + }, + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "cross-spawn-async": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", + "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", + "dev": true, + "requires": { + "lru-cache": "^4.0.0", + "which": "^1.2.8" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + } + } + }, + "crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "requires": { + "type-fest": "^1.0.1" + }, + "dependencies": { + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + } + } + }, + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true + } + } + }, + "dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "requires": {} + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, + "default-browser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", + "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", + "dev": true, + "requires": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^5.0.0", + "xdg-default-browser": "^2.1.0" + } + }, + "default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "requires": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + } + }, + "define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true + }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "electron-to-chromium": { + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true + }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "requires": {} + }, + "eslint-plugin-jest": { + "version": "27.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", + "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "^5.10.0" + } + }, + "eslint-plugin-prettier": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", + "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "requires": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-type": { + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", + "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", + "dev": true, + "requires": { + "readable-web-to-node-stream": "^3.0.2", + "strtok3": "^7.0.0", + "token-types": "^5.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatbuffers": { + "version": "23.5.26", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.5.26.tgz", + "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==" + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "h264-profile-level-id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/h264-profile-level-id/-/h264-profile-level-id-2.0.0.tgz", + "integrity": "sha512-X4CLryVbVA0CtjTExS4G5U1gb2Z4wa32AF8ukVmFuLdw2JRq2aHisor7SY5SYTUUrUSqq0KdPIO18sql6IWIQw==", + "requires": { + "@types/debug": "^4.1.12", + "debug": "^4.3.4" + } + }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "hosted-git-info": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", + "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, + "requires": { + "lru-cache": "^7.5.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + } + } + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "requires": { + "is-docker": "^3.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + }, + "dependencies": { + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + } + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + } + }, + "jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "requires": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + } + }, + "jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + } + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + } + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + } + }, + "jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "requires": {} + }, + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true + }, + "jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "requires": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + } + }, + "jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + } + }, + "jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + } + }, + "jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + } + }, + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + } + } + }, + "jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true + }, + "marked": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", + "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==", + "dev": true + }, + "meow": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", + "integrity": "sha512-Cl0yeeIrko6d94KpUo1M+0X1sB14ikoaqlIGuTH1fW4I+E3+YljL54/hb/BWmVfrV9tTV9zU04+xjw08Fh2WkA==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^8.0.2", + "decamelize": "^6.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^4.0.1", + "read-pkg-up": "^9.1.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^3.1.0", + "yargs-parser": "^21.1.1" + }, + "dependencies": { + "type-fest": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.1.tgz", + "integrity": "sha512-htXWckxlT6U4+ilVgweNliPqlsVSSucbxVexRYllyMVJDtf5rTjv6kF/s+qAd4QSL1BZcnJPEJavYBPQiWuZDA==", + "dev": true + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "normalize-package-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", + "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", + "dev": true, + "requires": { + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", + "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", + "dev": true, + "requires": { + "default-browser": "^3.1.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + } + }, + "open-cli": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.2.0.tgz", + "integrity": "sha512-1ANJc8oJ92FiaNZ0o2Hw4WBvDJoXs1P74aFMtpAvlbkIPV4uPcQvDz7V6kMOrsZkmB4tglrHVMlLQaafuUuxXg==", + "dev": true, + "requires": { + "file-type": "^18.2.1", + "get-stdin": "^9.0.0", + "meow": "^11.0.0", + "open": "^9.0.0", + "tempy": "^3.0.0" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "peek-readable": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", + "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", + "dev": true + }, + "pick-port": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-1.0.1.tgz", + "integrity": "sha512-JzjRIkfG/4pG3tYLl1LwdmFtnlW+Rsxe200DevHZzZLYDUgfnx8LuOFnLwy5Dt59JY1HIN3JXyMXRbUvERkh/g==", + "dev": true, + "requires": { + "debug": "^4.3.1" + } + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, + "polycrc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/polycrc/-/polycrc-0.1.0.tgz", + "integrity": "sha512-pBjdz8Gj0ixRkR80acjWl6bxiHf23MTI6chIKbQqphF2SrXXtYSPlftCSL31bD3veSWJCaTsM1QhT6zlIebqlg==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "pure-rand": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "quick-lru": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.1.tgz", + "integrity": "sha512-S27GBT+F0NTRiehtbrgaSE1idUAJ5bX8dPAQTdylEyNlrdcH5X4Lz7Edz3DYzecbsCluD5zO8ZNEe04z3D3u6Q==", + "dev": true + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "read-pkg": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", + "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^2.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", + "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", + "dev": true, + "requires": { + "find-up": "^6.3.0", + "read-pkg": "^7.1.0", + "type-fest": "^2.5.0" + }, + "dependencies": { + "find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "requires": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + } + }, + "locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "requires": { + "p-locate": "^6.0.0" + } + }, + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "requires": { + "p-limit": "^4.0.0" + } + }, + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true + } + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dev": true, + "requires": { + "readable-stream": "^3.6.0" + } + }, + "redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "requires": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "requires": { + "execa": "^5.0.0" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "sctp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sctp/-/sctp-1.0.0.tgz", + "integrity": "sha512-wceaBrz55a0dbYG3c2zfJ1adUASLJhntQYZNVZKlGfKH1ExMckZB0sOxroWgpJLflcAB/k6wMOAPOrmylsRU4A==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "ip": "^1.1.5", + "polycrc": "^0.1.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "requires": { + "min-indent": "^1.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "strtok3": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", + "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", + "dev": true, + "requires": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^5.0.0" + } + }, + "supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==" + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "requires": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, + "tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true + }, + "tempy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz", + "integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==", + "dev": true, + "requires": { + "is-stream": "^3.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "dependencies": { + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "titleize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", + "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", + "dev": true + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "token-types": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", + "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", + "dev": true, + "requires": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + } + }, + "trim-newlines": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", + "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", + "dev": true + }, + "ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "requires": {} + }, + "ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "requires": { + "crypto-random-string": "^4.0.0" + } + }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "dependencies": { + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + } + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "xdg-default-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", + "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", + "dev": true, + "requires": { + "execa": "^0.2.2", + "titleize": "^1.0.0" + }, + "dependencies": { + "execa": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", + "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", + "dev": true, + "requires": { + "cross-spawn-async": "^2.1.1", + "npm-run-path": "^1.0.0", + "object-assign": "^4.0.1", + "path-key": "^1.0.0", + "strip-eof": "^1.0.0" + } + }, + "npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", + "dev": true, + "requires": { + "path-key": "^1.0.0" + } + }, + "path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", + "dev": true + } + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } } diff --git a/package.json b/package.json index 9d0806c54f..fd2e0fe4ca 100644 --- a/package.json +++ b/package.json @@ -1,130 +1,130 @@ { - "name": "mediasoup", - "version": "3.13.15", - "description": "Cutting Edge WebRTC Video Conferencing", - "contributors": [ - "Iñaki Baz Castillo (https://inakibaz.me)", - "José Luis Millán (https://github.com/jmillan)", - "Nazar Mokynskyi (https://github.com/nazar-pc)" - ], - "license": "ISC", - "homepage": "https://mediasoup.org", - "repository": { - "type": "git", - "url": "https://github.com/versatica/mediasoup.git" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mediasoup" - }, - "main": "node/lib/index.js", - "types": "node/lib/index.d.ts", - "files": [ - "node/lib", - "worker/deps/libwebrtc", - "worker/fbs", - "worker/fuzzer/include", - "worker/fuzzer/src", - "worker/include", - "worker/src", - "worker/scripts/*.json", - "worker/scripts/*.mjs", - "worker/scripts/*.py", - "worker/scripts/*.sh", - "worker/subprojects/*.wrap", - "worker/test/include", - "worker/test/src", - "worker/meson.build", - "worker/meson_options.txt", - "worker/tasks.py", - "npm-scripts.mjs" - ], - "engines": { - "node": ">=16" - }, - "keywords": [ - "webrtc", - "ortc", - "sfu", - "nodejs" - ], - "scripts": { - "prepare": "node npm-scripts.mjs prepare", - "postinstall": "node npm-scripts.mjs postinstall", - "typescript:build": "node npm-scripts.mjs typescript:build", - "typescript:watch": "node npm-scripts.mjs typescript:watch", - "worker:build": "node npm-scripts.mjs worker:build", - "worker:prebuild": "node npm-scripts.mjs worker:prebuild", - "lint": "npm run lint:node && npm run lint:worker", - "lint:node": "node npm-scripts.mjs lint:node", - "lint:worker": "node npm-scripts.mjs lint:worker", - "format": "npm run format:node && npm run format:worker", - "format:node": "node npm-scripts.mjs format:node", - "format:worker": "node npm-scripts.mjs format:worker", - "flatc": "npm run flatc:node && npm run flatc:worker", - "flatc:node": "node npm-scripts.mjs flatc:node", - "flatc:worker": "node npm-scripts.mjs flatc:worker", - "test": "npm run test:node && npm run test:worker", - "test:node": "node npm-scripts.mjs test:node", - "test:worker": "node npm-scripts.mjs test:worker", - "coverage:node": "node npm-scripts.mjs coverage:node", - "release:check": "node npm-scripts.mjs release:check", - "release": "node npm-scripts.mjs release", - "release:upload-mac-arm-prebuilt-worker": "node npm-scripts.mjs release:upload-mac-arm-prebuilt-worker" - }, - "jest": { - "verbose": true, - "testEnvironment": "node", - "testRegex": "node/src/test/test-.*\\.ts", - "transform": { - "^.*\\.ts$": [ - "ts-jest", - { - "diagnostics": { - "ignoreCodes": [ - "TS151001" - ] - } - } - ] - }, - "coveragePathIgnorePatterns": [ - "node/src/fbs", - "node/src/test" - ], - "cacheDirectory": ".cache/jest", - "modulePathIgnorePatterns": [ - "worker", - "rust", - "target" - ] - }, - "dependencies": { - "debug": "^4.3.4", - "flatbuffers": "^23.5.26", - "h264-profile-level-id": "^2.0.0", - "node-fetch": "^3.3.2", - "supports-color": "^9.4.0", - "tar": "^6.2.0" - }, - "devDependencies": { - "@octokit/rest": "^20.0.2", - "@types/debug": "^4.1.12", - "@types/jest": "^29.5.11", - "@types/node": "^20.10.7", - "@typescript-eslint/eslint-plugin": "^6.18.0", - "@typescript-eslint/parser": "^6.18.0", - "eslint": "^8.56.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.6.1", - "eslint-plugin-prettier": "^5.1.2", - "jest": "^29.7.0", - "marked": "^11.1.1", - "open-cli": "^7.2.0", - "pick-port": "^1.0.1", - "prettier": "^3.1.1", - "sctp": "^1.0.0", - "ts-jest": "^29.1.1", - "typescript": "^5.3.3" - } + "name": "mediasoup", + "version": "3.13.15", + "description": "Cutting Edge WebRTC Video Conferencing", + "contributors": [ + "Iñaki Baz Castillo (https://inakibaz.me)", + "José Luis Millán (https://github.com/jmillan)", + "Nazar Mokynskyi (https://github.com/nazar-pc)" + ], + "license": "ISC", + "homepage": "https://mediasoup.org", + "repository": { + "type": "git", + "url": "https://github.com/versatica/mediasoup.git" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mediasoup" + }, + "main": "node/lib/index.js", + "types": "node/lib/index.d.ts", + "files": [ + "node/lib", + "worker/deps/libwebrtc", + "worker/fbs", + "worker/fuzzer/include", + "worker/fuzzer/src", + "worker/include", + "worker/src", + "worker/scripts/*.json", + "worker/scripts/*.mjs", + "worker/scripts/*.py", + "worker/scripts/*.sh", + "worker/subprojects/*.wrap", + "worker/test/include", + "worker/test/src", + "worker/meson.build", + "worker/meson_options.txt", + "worker/tasks.py", + "npm-scripts.mjs" + ], + "engines": { + "node": ">=16" + }, + "keywords": [ + "webrtc", + "ortc", + "sfu", + "nodejs" + ], + "scripts": { + "prepare": "node npm-scripts.mjs prepare", + "postinstall": "node npm-scripts.mjs postinstall", + "typescript:build": "node npm-scripts.mjs typescript:build", + "typescript:watch": "node npm-scripts.mjs typescript:watch", + "worker:build": "node npm-scripts.mjs worker:build", + "worker:prebuild": "node npm-scripts.mjs worker:prebuild", + "lint": "npm run lint:node && npm run lint:worker", + "lint:node": "node npm-scripts.mjs lint:node", + "lint:worker": "node npm-scripts.mjs lint:worker", + "format": "npm run format:node && npm run format:worker", + "format:node": "node npm-scripts.mjs format:node", + "format:worker": "node npm-scripts.mjs format:worker", + "flatc": "npm run flatc:node && npm run flatc:worker", + "flatc:node": "node npm-scripts.mjs flatc:node", + "flatc:worker": "node npm-scripts.mjs flatc:worker", + "test": "npm run test:node && npm run test:worker", + "test:node": "node npm-scripts.mjs test:node", + "test:worker": "node npm-scripts.mjs test:worker", + "coverage:node": "node npm-scripts.mjs coverage:node", + "release:check": "node npm-scripts.mjs release:check", + "release": "node npm-scripts.mjs release", + "release:upload-mac-arm-prebuilt-worker": "node npm-scripts.mjs release:upload-mac-arm-prebuilt-worker" + }, + "jest": { + "verbose": true, + "testEnvironment": "node", + "testRegex": "node/src/test/test-.*\\.ts", + "transform": { + "^.*\\.ts$": [ + "ts-jest", + { + "diagnostics": { + "ignoreCodes": [ + "TS151001" + ] + } + } + ] + }, + "coveragePathIgnorePatterns": [ + "node/src/fbs", + "node/src/test" + ], + "cacheDirectory": ".cache/jest", + "modulePathIgnorePatterns": [ + "worker", + "rust", + "target" + ] + }, + "dependencies": { + "debug": "^4.3.4", + "flatbuffers": "^23.5.26", + "h264-profile-level-id": "^2.0.0", + "node-fetch": "^3.3.2", + "supports-color": "^9.4.0", + "tar": "^6.2.0" + }, + "devDependencies": { + "@octokit/rest": "^20.0.2", + "@types/debug": "^4.1.12", + "@types/jest": "^29.5.11", + "@types/node": "^20.10.7", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-jest": "^27.6.1", + "eslint-plugin-prettier": "^5.1.2", + "jest": "^29.7.0", + "marked": "^11.1.1", + "open-cli": "^7.2.0", + "pick-port": "^1.0.1", + "prettier": "^3.1.1", + "sctp": "^1.0.0", + "ts-jest": "^29.1.1", + "typescript": "^5.3.3" + } } diff --git a/worker/.clang-format b/worker/.clang-format index 2217415190..953a0fdc73 100644 --- a/worker/.clang-format +++ b/worker/.clang-format @@ -47,15 +47,15 @@ DisableFormat: false ExperimentalAutoDetectBinPacking: true FixNamespaceComments: true IncludeCategories: - - Regex: '"common.hpp"' + - Regex: '"common.hpp"' Priority: 1 - - Regex: '^"(Channel|PayloadChannel|FBS|RTC|Utils|handles)/' + - Regex: '^"(Channel|PayloadChannel|FBS|RTC|Utils|handles)/' Priority: 3 - - Regex: '"*"' + - Regex: '"*"' Priority: 2 - - Regex: '^<(flatbuffers|uv|openssl|srtp|usrsctp|libwebrtc)(.|/)' + - Regex: '^<(flatbuffers|uv|openssl|srtp|usrsctp|libwebrtc)(.|/)' Priority: 4 - - Regex: '<*>' + - Regex: '<*>' Priority: 5 IncludeIsMainRegex: '$' IndentCaseLabels: true diff --git a/worker/.clang-tidy b/worker/.clang-tidy index 14d3b910c0..0f4b9c0273 100644 --- a/worker/.clang-tidy +++ b/worker/.clang-tidy @@ -1,63 +1,63 @@ --- Checks: "*,\ - -altera*,\ - -boost-use-to-string,\ - -bugprone-easily-swappable-parameters,\ - -bugprone-lambda-function-name,\ - -bugprone-macro-parentheses,\ - -cert-*,\ - -clang-analyzer-optin.osx.*,\ - -clang-analyzer-osx.*,\ - -cppcoreguidelines-avoid-c-arrays,\ - -cppcoreguidelines-avoid-do-while,\ - -cppcoreguidelines-avoid-goto,\ - -cppcoreguidelines-avoid-magic-numbers,\ - -cppcoreguidelines-init-variables,\ - -cppcoreguidelines-no-malloc,\ - -cppcoreguidelines-non-private-member-variables-in-classes,\ - -cppcoreguidelines-owning-memory,\ - -cppcoreguidelines-pro-bounds-array-to-pointer-decay,\ - -cppcoreguidelines-pro-bounds-constant-array-index,\ - -cppcoreguidelines-pro-bounds-pointer-arithmetic,\ - -cppcoreguidelines-pro-type-const-cast,\ - -cppcoreguidelines-pro-type-reinterpret-cast,\ - -cppcoreguidelines-pro-type-static-cast-downcast,\ - -cppcoreguidelines-pro-type-union-access,\ - -cppcoreguidelines-pro-type-vararg,\ - -cppcoreguidelines-special-member-functions,\ - -fuchsia-default-arguments-calls,\ - -fuchsia-default-arguments-declarations,\ - -google-default-arguments,\ - -google-readability-*,\ - -google-runtime-references,\ - -hicpp-avoid-c-arrays,\ - -hicpp-avoid-goto,\ - -hicpp-braces-around-statements,\ - -hicpp-no-array-decay,\ - -hicpp-signed-bitwise,\ - -hicpp-special-member-functions,\ - -hicpp-uppercase-literal-suffix,\ - -hicpp-vararg,\ - -llvm-include-order,\ - -llvm-header-guard,\ - -llvm-else-after-return,\ - -llvmlibc-*,\ - -misc-non-private-member-variables-in-classes,\ - -modernize-avoid-c-arrays,\ - -modernize-concat-nested-namespaces,\ - -modernize-make-unique,\ - -modernize-pass-by-value,\ - -modernize-use-nodiscard, \ - -modernize-use-trailing-return-type,\ - -readability-else-after-return,\ - -readability-function-cognitive-complexity,\ - -readability-identifier-length,\ - -readability-implicit-bool-cast,\ - -readability-implicit-bool-conversion,\ - -readability-magic-numbers,\ - -readability-redundant-access-specifiers, \ - -readability-uppercase-literal-suffix,\ - " + -altera*,\ + -boost-use-to-string,\ + -bugprone-easily-swappable-parameters,\ + -bugprone-lambda-function-name,\ + -bugprone-macro-parentheses,\ + -cert-*,\ + -clang-analyzer-optin.osx.*,\ + -clang-analyzer-osx.*,\ + -cppcoreguidelines-avoid-c-arrays,\ + -cppcoreguidelines-avoid-do-while,\ + -cppcoreguidelines-avoid-goto,\ + -cppcoreguidelines-avoid-magic-numbers,\ + -cppcoreguidelines-init-variables,\ + -cppcoreguidelines-no-malloc,\ + -cppcoreguidelines-non-private-member-variables-in-classes,\ + -cppcoreguidelines-owning-memory,\ + -cppcoreguidelines-pro-bounds-array-to-pointer-decay,\ + -cppcoreguidelines-pro-bounds-constant-array-index,\ + -cppcoreguidelines-pro-bounds-pointer-arithmetic,\ + -cppcoreguidelines-pro-type-const-cast,\ + -cppcoreguidelines-pro-type-reinterpret-cast,\ + -cppcoreguidelines-pro-type-static-cast-downcast,\ + -cppcoreguidelines-pro-type-union-access,\ + -cppcoreguidelines-pro-type-vararg,\ + -cppcoreguidelines-special-member-functions,\ + -fuchsia-default-arguments-calls,\ + -fuchsia-default-arguments-declarations,\ + -google-default-arguments,\ + -google-readability-*,\ + -google-runtime-references,\ + -hicpp-avoid-c-arrays,\ + -hicpp-avoid-goto,\ + -hicpp-braces-around-statements,\ + -hicpp-no-array-decay,\ + -hicpp-signed-bitwise,\ + -hicpp-special-member-functions,\ + -hicpp-uppercase-literal-suffix,\ + -hicpp-vararg,\ + -llvm-include-order,\ + -llvm-header-guard,\ + -llvm-else-after-return,\ + -llvmlibc-*,\ + -misc-non-private-member-variables-in-classes,\ + -modernize-avoid-c-arrays,\ + -modernize-concat-nested-namespaces,\ + -modernize-make-unique,\ + -modernize-pass-by-value,\ + -modernize-use-nodiscard, \ + -modernize-use-trailing-return-type,\ + -readability-else-after-return,\ + -readability-function-cognitive-complexity,\ + -readability-identifier-length,\ + -readability-implicit-bool-cast,\ + -readability-implicit-bool-conversion,\ + -readability-magic-numbers,\ + -readability-redundant-access-specifiers, \ + -readability-uppercase-literal-suffix,\ + " HeaderFilterRegex: '' AnalyzeTemporaryDtors: false @@ -65,292 +65,291 @@ User: mediasoup FormatStyle: file CheckOptions: - - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader - value: '' - - key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle - value: '0' - - key: cppcoreguidelines-macro-usage.AllowedRegexp - value: ^MS_* - - key: misc-assert-side-effect.AssertMacros - value: assert - - key: misc-assert-side-effect.CheckFunctionCalls - value: '0' - - key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries - value: '1' - - key: modernize-loop-convert.MaxCopySize - value: '16' - - key: modernize-loop-convert.MinConfidence - value: reasonable - - key: modernize-loop-convert.NamingStyle - value: CamelCase - - key: modernize-replace-auto-ptr.IncludeStyle - value: llvm - - key: modernize-use-nullptr.NullMacros - value: 'NULL' - - key: readability-braces-around-statements.ShortStatementLines - value: '3' - - key: readability-function-size.BranchThreshold - value: '4294967295' - - key: readability-function-size.LineThreshold - value: '4294967295' - - key: readability-function-size.StatementThreshold - value: '800' - - key: readability-identifier-naming.AbstractClassCase - value: CamelCase - - key: readability-identifier-naming.AbstractClassPrefix - value: '' - - key: readability-identifier-naming.AbstractClassSuffix - value: '' - - key: readability-identifier-naming.ClassCase - value: CamelCase - - key: readability-identifier-naming.ClassConstantCase - value: CamelCase - - key: readability-identifier-naming.ClassConstantPrefix - value: '' - - key: readability-identifier-naming.ClassConstantSuffix - value: '' - - key: readability-identifier-naming.ClassMemberCase - value: camelBack - - key: readability-identifier-naming.ClassMemberPrefix - value: '' - - key: readability-identifier-naming.ClassMemberSuffix - value: '' - - key: readability-identifier-naming.ClassMethodCase - value: CamelCase - - key: readability-identifier-naming.ClassMethodPrefix - value: '' - - key: readability-identifier-naming.ClassMethodSuffix - value: '' - - key: readability-identifier-naming.ClassPrefix - value: '' - - key: readability-identifier-naming.ClassSuffix - value: '' - - key: readability-identifier-naming.ConstantCase - value: UPPER_CASE - - key: readability-identifier-naming.ConstantMemberCase - value: camelBack - - key: readability-identifier-naming.ConstantMemberPrefix - value: '' - - key: readability-identifier-naming.ConstantMemberSuffix - value: '' - - key: readability-identifier-naming.ConstantParameterCase - value: camelBack - - key: readability-identifier-naming.ConstantParameterPrefix - value: '' - - key: readability-identifier-naming.ConstantParameterSuffix - value: '' - - key: readability-identifier-naming.ConstantPrefix - value: '' - - key: readability-identifier-naming.ConstantSuffix - value: '' - - key: readability-identifier-naming.ConstexprFunctionCase - value: camelBack - - key: readability-identifier-naming.ConstexprFunctionPrefix - value: '' - - key: readability-identifier-naming.ConstexprFunctionSuffix - value: '' - - key: readability-identifier-naming.ConstexprMethodCase - value: camelBack - - key: readability-identifier-naming.ConstexprMethodPrefix - value: '' - - key: readability-identifier-naming.ConstexprMethodSuffix - value: '' - - key: readability-identifier-naming.ConstexprVariableCase - value: CamelCase - - key: readability-identifier-naming.ConstexprVariablePrefix - value: '' - - key: readability-identifier-naming.ConstexprVariableSuffix - value: '' - - key: readability-identifier-naming.EnumCase - value: aNy_CasE - - key: readability-identifier-naming.EnumConstantCase - value: aNy_CasE - - key: readability-identifier-naming.EnumConstantPrefix - value: '' - - key: readability-identifier-naming.EnumConstantSuffix - value: '' - - key: readability-identifier-naming.EnumPrefix - value: '' - - key: readability-identifier-naming.EnumSuffix - value: '' - - key: readability-identifier-naming.FunctionCase - value: camelBack - - key: readability-identifier-naming.FunctionPrefix - value: '' - - key: readability-identifier-naming.FunctionSuffix - value: '' - - key: readability-identifier-naming.GlobalConstantCase - value: CamelCase - - key: readability-identifier-naming.GlobalConstantPrefix - value: '' - - key: readability-identifier-naming.GlobalConstantSuffix - value: '' - - key: readability-identifier-naming.GlobalFunctionCase - value: CamelCase - - key: readability-identifier-naming.GlobalFunctionPrefix - value: '' - - key: readability-identifier-naming.GlobalFunctionSuffix - value: '' - - key: readability-identifier-naming.GlobalVariableCase - value: CamelCase - - key: readability-identifier-naming.GlobalVariablePrefix - value: '' - - key: readability-identifier-naming.GlobalVariableSuffix - value: '' - - key: readability-identifier-naming.IgnoreFailedSplit - value: '0' - - key: readability-identifier-naming.InlineNamespaceCase - value: aNy_CasE - - key: readability-identifier-naming.InlineNamespacePrefix - value: '' - - key: readability-identifier-naming.InlineNamespaceSuffix - value: '' - - key: readability-identifier-naming.LocalConstantCase - value: camelBack - - key: readability-identifier-naming.LocalConstantPrefix - value: '' - - key: readability-identifier-naming.LocalConstantSuffix - value: '' - - key: readability-identifier-naming.LocalVariableCase - value: camelBack - - key: readability-identifier-naming.LocalVariablePrefix - value: '' - - key: readability-identifier-naming.LocalVariableSuffix - value: '' - - key: readability-identifier-naming.MemberCase - value: camelBack - - key: readability-identifier-naming.MemberPrefix - value: '' - - key: readability-identifier-naming.MemberSuffix - value: '' - - key: readability-identifier-naming.MethodCase - value: CamelCase - - key: readability-identifier-naming.MethodPrefix - value: '' - - key: readability-identifier-naming.MethodSuffix - value: '' - - key: readability-identifier-naming.NamespaceCase - value: aNy_CasE - - key: readability-identifier-naming.NamespacePrefix - value: '' - - key: readability-identifier-naming.NamespaceSuffix - value: '' - - key: readability-identifier-naming.ParameterCase - value: camelBack - - key: readability-identifier-naming.ParameterPackCase - value: camelBack - - key: readability-identifier-naming.ParameterPackPrefix - value: '' - - key: readability-identifier-naming.ParameterPackSuffix - value: '' - - key: readability-identifier-naming.ParameterPrefix - value: '' - - key: readability-identifier-naming.ParameterSuffix - value: '' - - key: readability-identifier-naming.PrivateMemberCase - value: camelBack - - key: readability-identifier-naming.PrivateMemberPrefix - value: '' - - key: readability-identifier-naming.PrivateMemberSuffix - value: '' - - key: readability-identifier-naming.PrivateMethodCase - value: CamelCase - - key: readability-identifier-naming.PrivateMethodPrefix - value: '' - - key: readability-identifier-naming.PrivateMethodSuffix - value: '' - - key: readability-identifier-naming.ProtectedMemberCase - value: camelBack - - key: readability-identifier-naming.ProtectedMemberPrefix - value: '' - - key: readability-identifier-naming.ProtectedMemberSuffix - value: '' - - key: readability-identifier-naming.ProtectedMethodCase - value: CamelCase - - key: readability-identifier-naming.ProtectedMethodPrefix - value: '' - - key: readability-identifier-naming.ProtectedMethodSuffix - value: '' - - key: readability-identifier-naming.PublicMemberCase - value: camelBack - - key: readability-identifier-naming.PublicMemberPrefix - value: '' - - key: readability-identifier-naming.PublicMemberSuffix - value: '' - - key: readability-identifier-naming.PublicMethodCase - value: CamelCase - - key: readability-identifier-naming.PublicMethodPrefix - value: '' - - key: readability-identifier-naming.PublicMethodSuffix - value: '' - - key: readability-identifier-naming.StaticConstantCase - value: CamelCase - - key: readability-identifier-naming.StaticConstantPrefix - value: '' - - key: readability-identifier-naming.StaticConstantSuffix - value: '' - - key: readability-identifier-naming.StaticVariableCase - value: camelBack - - key: readability-identifier-naming.StaticVariablePrefix - value: '' - - key: readability-identifier-naming.StaticVariableSuffix - value: '' - - key: readability-identifier-naming.StructCase - value: CamelCase - - key: readability-identifier-naming.StructPrefix - value: '' - - key: readability-identifier-naming.StructSuffix - value: '' - - key: readability-identifier-naming.TemplateParameterCase - value: CamelCase - - key: readability-identifier-naming.TemplateParameterPrefix - value: '' - - key: readability-identifier-naming.TemplateParameterSuffix - value: '' - - key: readability-identifier-naming.TemplateTemplateParameterCase - value: CamelCase - - key: readability-identifier-naming.TemplateTemplateParameterPrefix - value: '' - - key: readability-identifier-naming.TemplateTemplateParameterSuffix - value: '' - - key: readability-identifier-naming.TypeTemplateParameterCase - value: CamelCase - - key: readability-identifier-naming.TypeTemplateParameterPrefix - value: '' - - key: readability-identifier-naming.TypeTemplateParameterSuffix - value: '' - - key: readability-identifier-naming.TypedefCase - value: CamelCase - - key: readability-identifier-naming.TypedefPrefix - value: '' - - key: readability-identifier-naming.TypedefSuffix - value: '' - - key: readability-identifier-naming.UnionCase - value: CamelCase - - key: readability-identifier-naming.UnionPrefix - value: '' - - key: readability-identifier-naming.UnionSuffix - value: '' - - key: readability-identifier-naming.ValueTemplateParameterCase - value: camelBack - - key: readability-identifier-naming.ValueTemplateParameterPrefix - value: '' - - key: readability-identifier-naming.ValueTemplateParameterSuffix - value: '' - - key: readability-identifier-naming.VariableCase - value: camelBack - - key: readability-identifier-naming.VariablePrefix - value: '' - - key: readability-identifier-naming.VariableSuffix - value: '' - - key: readability-identifier-naming.VirtualMethodCase - value: CamelCase - - key: readability-identifier-naming.VirtualMethodPrefix - value: '' - - key: readability-identifier-naming.VirtualMethodSuffix - value: '' - - key: readability-simplify-boolean-expr.ChainedConditionalAssignment - value: '1' - - key: readability-simplify-boolean-expr.ChainedConditionalReturn - value: '1' -... + - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader + value: '' + - key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle + value: '0' + - key: cppcoreguidelines-macro-usage.AllowedRegexp + value: ^MS_* + - key: misc-assert-side-effect.AssertMacros + value: assert + - key: misc-assert-side-effect.CheckFunctionCalls + value: '0' + - key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries + value: '1' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-use-nullptr.NullMacros + value: 'NULL' + - key: readability-braces-around-statements.ShortStatementLines + value: '3' + - key: readability-function-size.BranchThreshold + value: '4294967295' + - key: readability-function-size.LineThreshold + value: '4294967295' + - key: readability-function-size.StatementThreshold + value: '800' + - key: readability-identifier-naming.AbstractClassCase + value: CamelCase + - key: readability-identifier-naming.AbstractClassPrefix + value: '' + - key: readability-identifier-naming.AbstractClassSuffix + value: '' + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.ClassConstantCase + value: CamelCase + - key: readability-identifier-naming.ClassConstantPrefix + value: '' + - key: readability-identifier-naming.ClassConstantSuffix + value: '' + - key: readability-identifier-naming.ClassMemberCase + value: camelBack + - key: readability-identifier-naming.ClassMemberPrefix + value: '' + - key: readability-identifier-naming.ClassMemberSuffix + value: '' + - key: readability-identifier-naming.ClassMethodCase + value: CamelCase + - key: readability-identifier-naming.ClassMethodPrefix + value: '' + - key: readability-identifier-naming.ClassMethodSuffix + value: '' + - key: readability-identifier-naming.ClassPrefix + value: '' + - key: readability-identifier-naming.ClassSuffix + value: '' + - key: readability-identifier-naming.ConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.ConstantMemberCase + value: camelBack + - key: readability-identifier-naming.ConstantMemberPrefix + value: '' + - key: readability-identifier-naming.ConstantMemberSuffix + value: '' + - key: readability-identifier-naming.ConstantParameterCase + value: camelBack + - key: readability-identifier-naming.ConstantParameterPrefix + value: '' + - key: readability-identifier-naming.ConstantParameterSuffix + value: '' + - key: readability-identifier-naming.ConstantPrefix + value: '' + - key: readability-identifier-naming.ConstantSuffix + value: '' + - key: readability-identifier-naming.ConstexprFunctionCase + value: camelBack + - key: readability-identifier-naming.ConstexprFunctionPrefix + value: '' + - key: readability-identifier-naming.ConstexprFunctionSuffix + value: '' + - key: readability-identifier-naming.ConstexprMethodCase + value: camelBack + - key: readability-identifier-naming.ConstexprMethodPrefix + value: '' + - key: readability-identifier-naming.ConstexprMethodSuffix + value: '' + - key: readability-identifier-naming.ConstexprVariableCase + value: CamelCase + - key: readability-identifier-naming.ConstexprVariablePrefix + value: '' + - key: readability-identifier-naming.ConstexprVariableSuffix + value: '' + - key: readability-identifier-naming.EnumCase + value: aNy_CasE + - key: readability-identifier-naming.EnumConstantCase + value: aNy_CasE + - key: readability-identifier-naming.EnumConstantPrefix + value: '' + - key: readability-identifier-naming.EnumConstantSuffix + value: '' + - key: readability-identifier-naming.EnumPrefix + value: '' + - key: readability-identifier-naming.EnumSuffix + value: '' + - key: readability-identifier-naming.FunctionCase + value: camelBack + - key: readability-identifier-naming.FunctionPrefix + value: '' + - key: readability-identifier-naming.FunctionSuffix + value: '' + - key: readability-identifier-naming.GlobalConstantCase + value: CamelCase + - key: readability-identifier-naming.GlobalConstantPrefix + value: '' + - key: readability-identifier-naming.GlobalConstantSuffix + value: '' + - key: readability-identifier-naming.GlobalFunctionCase + value: CamelCase + - key: readability-identifier-naming.GlobalFunctionPrefix + value: '' + - key: readability-identifier-naming.GlobalFunctionSuffix + value: '' + - key: readability-identifier-naming.GlobalVariableCase + value: CamelCase + - key: readability-identifier-naming.GlobalVariablePrefix + value: '' + - key: readability-identifier-naming.GlobalVariableSuffix + value: '' + - key: readability-identifier-naming.IgnoreFailedSplit + value: '0' + - key: readability-identifier-naming.InlineNamespaceCase + value: aNy_CasE + - key: readability-identifier-naming.InlineNamespacePrefix + value: '' + - key: readability-identifier-naming.InlineNamespaceSuffix + value: '' + - key: readability-identifier-naming.LocalConstantCase + value: camelBack + - key: readability-identifier-naming.LocalConstantPrefix + value: '' + - key: readability-identifier-naming.LocalConstantSuffix + value: '' + - key: readability-identifier-naming.LocalVariableCase + value: camelBack + - key: readability-identifier-naming.LocalVariablePrefix + value: '' + - key: readability-identifier-naming.LocalVariableSuffix + value: '' + - key: readability-identifier-naming.MemberCase + value: camelBack + - key: readability-identifier-naming.MemberPrefix + value: '' + - key: readability-identifier-naming.MemberSuffix + value: '' + - key: readability-identifier-naming.MethodCase + value: CamelCase + - key: readability-identifier-naming.MethodPrefix + value: '' + - key: readability-identifier-naming.MethodSuffix + value: '' + - key: readability-identifier-naming.NamespaceCase + value: aNy_CasE + - key: readability-identifier-naming.NamespacePrefix + value: '' + - key: readability-identifier-naming.NamespaceSuffix + value: '' + - key: readability-identifier-naming.ParameterCase + value: camelBack + - key: readability-identifier-naming.ParameterPackCase + value: camelBack + - key: readability-identifier-naming.ParameterPackPrefix + value: '' + - key: readability-identifier-naming.ParameterPackSuffix + value: '' + - key: readability-identifier-naming.ParameterPrefix + value: '' + - key: readability-identifier-naming.ParameterSuffix + value: '' + - key: readability-identifier-naming.PrivateMemberCase + value: camelBack + - key: readability-identifier-naming.PrivateMemberPrefix + value: '' + - key: readability-identifier-naming.PrivateMemberSuffix + value: '' + - key: readability-identifier-naming.PrivateMethodCase + value: CamelCase + - key: readability-identifier-naming.PrivateMethodPrefix + value: '' + - key: readability-identifier-naming.PrivateMethodSuffix + value: '' + - key: readability-identifier-naming.ProtectedMemberCase + value: camelBack + - key: readability-identifier-naming.ProtectedMemberPrefix + value: '' + - key: readability-identifier-naming.ProtectedMemberSuffix + value: '' + - key: readability-identifier-naming.ProtectedMethodCase + value: CamelCase + - key: readability-identifier-naming.ProtectedMethodPrefix + value: '' + - key: readability-identifier-naming.ProtectedMethodSuffix + value: '' + - key: readability-identifier-naming.PublicMemberCase + value: camelBack + - key: readability-identifier-naming.PublicMemberPrefix + value: '' + - key: readability-identifier-naming.PublicMemberSuffix + value: '' + - key: readability-identifier-naming.PublicMethodCase + value: CamelCase + - key: readability-identifier-naming.PublicMethodPrefix + value: '' + - key: readability-identifier-naming.PublicMethodSuffix + value: '' + - key: readability-identifier-naming.StaticConstantCase + value: CamelCase + - key: readability-identifier-naming.StaticConstantPrefix + value: '' + - key: readability-identifier-naming.StaticConstantSuffix + value: '' + - key: readability-identifier-naming.StaticVariableCase + value: camelBack + - key: readability-identifier-naming.StaticVariablePrefix + value: '' + - key: readability-identifier-naming.StaticVariableSuffix + value: '' + - key: readability-identifier-naming.StructCase + value: CamelCase + - key: readability-identifier-naming.StructPrefix + value: '' + - key: readability-identifier-naming.StructSuffix + value: '' + - key: readability-identifier-naming.TemplateParameterCase + value: CamelCase + - key: readability-identifier-naming.TemplateParameterPrefix + value: '' + - key: readability-identifier-naming.TemplateParameterSuffix + value: '' + - key: readability-identifier-naming.TemplateTemplateParameterCase + value: CamelCase + - key: readability-identifier-naming.TemplateTemplateParameterPrefix + value: '' + - key: readability-identifier-naming.TemplateTemplateParameterSuffix + value: '' + - key: readability-identifier-naming.TypeTemplateParameterCase + value: CamelCase + - key: readability-identifier-naming.TypeTemplateParameterPrefix + value: '' + - key: readability-identifier-naming.TypeTemplateParameterSuffix + value: '' + - key: readability-identifier-naming.TypedefCase + value: CamelCase + - key: readability-identifier-naming.TypedefPrefix + value: '' + - key: readability-identifier-naming.TypedefSuffix + value: '' + - key: readability-identifier-naming.UnionCase + value: CamelCase + - key: readability-identifier-naming.UnionPrefix + value: '' + - key: readability-identifier-naming.UnionSuffix + value: '' + - key: readability-identifier-naming.ValueTemplateParameterCase + value: camelBack + - key: readability-identifier-naming.ValueTemplateParameterPrefix + value: '' + - key: readability-identifier-naming.ValueTemplateParameterSuffix + value: '' + - key: readability-identifier-naming.VariableCase + value: camelBack + - key: readability-identifier-naming.VariablePrefix + value: '' + - key: readability-identifier-naming.VariableSuffix + value: '' + - key: readability-identifier-naming.VirtualMethodCase + value: CamelCase + - key: readability-identifier-naming.VirtualMethodPrefix + value: '' + - key: readability-identifier-naming.VirtualMethodSuffix + value: '' + - key: readability-simplify-boolean-expr.ChainedConditionalAssignment + value: '1' + - key: readability-simplify-boolean-expr.ChainedConditionalReturn + value: '1' diff --git a/worker/scripts/package-lock.json b/worker/scripts/package-lock.json index 358ebe9286..7805731de1 100644 --- a/worker/scripts/package-lock.json +++ b/worker/scripts/package-lock.json @@ -1,2827 +1,2827 @@ { - "name": "mediasoup-worker-dev-tools", - "version": "0.0.1", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "mediasoup-worker-dev-tools", - "version": "0.0.1", - "dependencies": { - "clang-format": "^1.8.0", - "clang-tools-prebuilt": "^0.1.4", - "glob": "^10.3.10" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dependencies": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "node_modules/clang-format": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", - "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==", - "dependencies": { - "async": "^3.2.3", - "glob": "^7.0.0", - "resolve": "^1.1.6" - }, - "bin": { - "check-clang-format": "bin/check-clang-format.js", - "clang-format": "index.js", - "git-clang-format": "bin/git-clang-format" - } - }, - "node_modules/clang-format/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/clang-format/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/clang-format/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/clang-tools-prebuilt": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", - "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", - "hasInstallScript": true, - "dependencies": { - "home-path": "^0.1.1", - "mkdirp": "^0.5.0", - "nugget": "^1.5.1", - "path-exists": "^1.0.0" - }, - "bin": { - "clang-apply-replacements": "tools/clang-apply-replacements.js", - "clang-include-fixer": "tools/clang-include-fixer.js", - "clang-rename": "tools/clang-rename.js", - "clang-tidy": "tools/clang-tidy.js", - "find-all-symbols": "tools/find-all-symbols.js" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dependencies": { - "array-find-index": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/home-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/home-path/-/home-path-0.1.2.tgz", - "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=" - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dependencies": { - "repeating": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "node_modules/is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dependencies": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru-cache": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", - "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/lru-cache/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lru-cache/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dependencies": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/meow/node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/nugget": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", - "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", - "dependencies": { - "debug": "^2.1.3", - "minimist": "^1.1.0", - "pretty-bytes": "^1.0.2", - "progress-stream": "^1.1.0", - "request": "^2.45.0", - "single-line-log": "^0.4.1", - "throttleit": "0.0.2" - }, - "bin": { - "nugget": "bin.js" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-exists": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", - "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "dependencies": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - }, - "bin": { - "pretty-bytes": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/progress-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", - "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", - "dependencies": { - "speedometer": "~0.1.2", - "through2": "~0.2.3" - } - }, - "node_modules/progress-stream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/progress-stream/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" - }, - "node_modules/progress-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/progress-stream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "node_modules/progress-stream/node_modules/through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", - "dependencies": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" - } - }, - "node_modules/progress-stream/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dependencies": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dependencies": { - "is-finite": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" - }, - "node_modules/single-line-log": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", - "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==" - }, - "node_modules/speedometer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=" - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dependencies": { - "get-stdin": "^4.0.1" - }, - "bin": { - "strip-indent": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/throttleit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=" - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - }, - "dependencies": { - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "clang-format": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", - "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==", - "requires": { - "async": "^3.2.3", - "glob": "^7.0.0", - "resolve": "^1.1.6" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "clang-tools-prebuilt": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", - "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", - "requires": { - "home-path": "^0.1.1", - "mkdirp": "^0.5.0", - "nugget": "^1.5.1", - "path-exists": "^1.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "requires": { - "array-find-index": "^1.0.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" - } - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "home-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/home-path/-/home-path-0.1.2.tgz", - "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=" - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "requires": { - "repeating": "^2.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", - "requires": { - "has": "^1.0.3" - } - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lru-cache": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", - "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", - "requires": { - "semver": "^7.3.5" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - } - } - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "nugget": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", - "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", - "requires": { - "debug": "^2.1.3", - "minimist": "^1.1.0", - "pretty-bytes": "^1.0.2", - "progress-stream": "^1.1.0", - "request": "^2.45.0", - "single-line-log": "^0.4.1", - "throttleit": "0.0.2" - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", - "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } - }, - "pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - } - }, - "progress-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", - "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", - "requires": { - "speedometer": "~0.1.2", - "through2": "~0.2.3" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", - "requires": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" - } - }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "requires": { - "object-keys": "~0.4.0" - } - } - } - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" - }, - "single-line-log": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", - "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==" - }, - "speedometer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=" - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - } - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "requires": { - "get-stdin": "^4.0.1" - } - }, - "throttleit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=" - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - } - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } + "name": "mediasoup-worker-dev-tools", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "mediasoup-worker-dev-tools", + "version": "0.0.1", + "dependencies": { + "clang-format": "^1.8.0", + "clang-tools-prebuilt": "^0.1.4", + "glob": "^10.3.10" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dependencies": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/clang-format": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", + "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==", + "dependencies": { + "async": "^3.2.3", + "glob": "^7.0.0", + "resolve": "^1.1.6" + }, + "bin": { + "check-clang-format": "bin/check-clang-format.js", + "clang-format": "index.js", + "git-clang-format": "bin/git-clang-format" + } + }, + "node_modules/clang-format/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/clang-format/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/clang-format/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/clang-tools-prebuilt": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", + "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", + "hasInstallScript": true, + "dependencies": { + "home-path": "^0.1.1", + "mkdirp": "^0.5.0", + "nugget": "^1.5.1", + "path-exists": "^1.0.0" + }, + "bin": { + "clang-apply-replacements": "tools/clang-apply-replacements.js", + "clang-include-fixer": "tools/clang-include-fixer.js", + "clang-rename": "tools/clang-rename.js", + "clang-tidy": "tools/clang-tidy.js", + "find-all-symbols": "tools/find-all-symbols.js" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dependencies": { + "array-find-index": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-up/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/home-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/home-path/-/home-path-0.1.2.tgz", + "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=" + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dependencies": { + "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "node_modules/is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dependencies": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", + "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/lru-cache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru-cache/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dependencies": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/meow/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/nugget": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", + "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", + "dependencies": { + "debug": "^2.1.3", + "minimist": "^1.1.0", + "pretty-bytes": "^1.0.2", + "progress-stream": "^1.1.0", + "request": "^2.45.0", + "single-line-log": "^0.4.1", + "throttleit": "0.0.2" + }, + "bin": { + "nugget": "bin.js" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-exists": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "dependencies": { + "get-stdin": "^4.0.1", + "meow": "^3.1.0" + }, + "bin": { + "pretty-bytes": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/progress-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", + "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", + "dependencies": { + "speedometer": "~0.1.2", + "through2": "~0.2.3" + } + }, + "node_modules/progress-stream/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/progress-stream/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "node_modules/progress-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/progress-stream/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "node_modules/progress-stream/node_modules/through2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "dependencies": { + "readable-stream": "~1.1.9", + "xtend": "~2.1.1" + } + }, + "node_modules/progress-stream/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dependencies": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dependencies": { + "is-finite": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", + "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" + }, + "node_modules/single-line-log": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", + "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==" + }, + "node_modules/speedometer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=" + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dependencies": { + "get-stdin": "^4.0.1" + }, + "bin": { + "strip-indent": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=" + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "clang-format": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", + "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==", + "requires": { + "async": "^3.2.3", + "glob": "^7.0.0", + "resolve": "^1.1.6" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "clang-tools-prebuilt": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", + "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", + "requires": { + "home-path": "^0.1.1", + "mkdirp": "^0.5.0", + "nugget": "^1.5.1", + "path-exists": "^1.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + } + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "home-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/home-path/-/home-path-0.1.2.tgz", + "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=" + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "^2.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "requires": { + "has": "^1.0.3" + } + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lru-cache": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", + "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", + "requires": { + "semver": "^7.3.5" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + } + } + }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "requires": { + "mime-db": "1.51.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "nugget": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", + "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", + "requires": { + "debug": "^2.1.3", + "minimist": "^1.1.0", + "pretty-bytes": "^1.0.2", + "progress-stream": "^1.1.0", + "request": "^2.45.0", + "single-line-log": "^0.4.1", + "throttleit": "0.0.2" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.1.0" + } + }, + "progress-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", + "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", + "requires": { + "speedometer": "~0.1.2", + "through2": "~0.2.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "through2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "requires": { + "readable-stream": "~1.1.9", + "xtend": "~2.1.1" + } + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "~0.4.0" + } + } + } + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", + "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" + }, + "single-line-log": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", + "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==" + }, + "speedometer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + } + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "^4.0.1" + } + }, + "throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } } diff --git a/worker/scripts/package.json b/worker/scripts/package.json index 5d58f50481..ba844335b7 100644 --- a/worker/scripts/package.json +++ b/worker/scripts/package.json @@ -1,14 +1,14 @@ { - "name": "mediasoup-worker-dev-tools", - "version": "0.0.1", - "description": "mediasoup worker dev tools", - "scripts": { - "lint": "node clang-format.mjs lint", - "format": "node clang-format.mjs format" - }, - "dependencies": { - "clang-format": "^1.8.0", - "clang-tools-prebuilt": "^0.1.4", - "glob": "^10.3.10" - } + "name": "mediasoup-worker-dev-tools", + "version": "0.0.1", + "description": "mediasoup worker dev tools", + "scripts": { + "lint": "node clang-format.mjs lint", + "format": "node clang-format.mjs format" + }, + "dependencies": { + "clang-format": "^1.8.0", + "clang-tools-prebuilt": "^0.1.4", + "glob": "^10.3.10" + } } From e3ab41fe4d966de23faddfb3fc50e6524fb9ea9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Jan 2024 12:30:49 +0100 Subject: [PATCH 309/525] Node: Add new worker.on('subprocessclose') to fix Node tests (#1307) --- CHANGELOG.md | 4 ++ node/src/Channel.ts | 16 +++-- node/src/Worker.ts | 46 ++++++++++---- node/src/test/test-ActiveSpeakerObserver.ts | 8 ++- node/src/test/test-AudioLevelObserver.ts | 8 ++- node/src/test/test-Consumer.ts | 27 +++++--- node/src/test/test-DataConsumer.ts | 8 ++- node/src/test/test-DataProducer.ts | 8 ++- node/src/test/test-DirectTransport.ts | 10 ++- node/src/test/test-PipeTransport.ts | 14 ++++- node/src/test/test-PlainTransport.ts | 8 ++- node/src/test/test-Producer.ts | 8 ++- node/src/test/test-Router.ts | 8 ++- node/src/test/test-WebRtcServer.ts | 8 ++- node/src/test/test-WebRtcTransport.ts | 8 ++- node/src/test/test-Worker.ts | 30 ++++++++- node/src/test/test-multiopus.ts | 8 ++- node/src/test/test-node-sctp.ts | 8 ++- npm-scripts.mjs | 4 +- worker/Makefile | 48 +++++++-------- worker/tasks.py | 68 ++++++++++----------- 21 files changed, 250 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 751d876192..df1131be4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Node: Add new `worker.on('subprocessclose')` event ([PR #1307](https://github.com/versatica/mediasoup/pull/1307)). + ### 3.13.15 - Add worker prebuild binary for Linux kernel 6 ([PR #1300](https://github.com/versatica/mediasoup/pull/1300)). diff --git a/node/src/Channel.ts b/node/src/Channel.ts index 7e1c719612..1f50bf9489 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -228,15 +228,13 @@ export class Channel extends EnhancedEventEmitter { this.#producerSocket.removeAllListeners('error'); this.#producerSocket.on('error', () => {}); - // Destroy the socket after a while to allow pending incoming messages. - setTimeout(() => { - try { - this.#producerSocket.destroy(); - } catch (error) {} - try { - this.#consumerSocket.destroy(); - } catch (error) {} - }, 200); + // Destroy the sockets. + try { + this.#producerSocket.destroy(); + } catch (error) {} + try { + this.#consumerSocket.destroy(); + } catch (error) {} } /** diff --git a/node/src/Worker.ts b/node/src/Worker.ts index ab05ef7ccb..6e1f5e46c9 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -200,6 +200,7 @@ export type WorkerDump = { export type WorkerEvents = { died: [Error]; + subprocessclose: []; listenererror: [string, Error]; // Private events. '@success': []; @@ -244,7 +245,7 @@ export class Worker< WorkerAppData extends AppData = AppData, > extends EnhancedEventEmitter { // mediasoup-worker child process. - #child?: ChildProcess; + #child: ChildProcess; // Worker process PID. readonly #pid: number; @@ -258,6 +259,9 @@ export class Worker< // Died dlag. #died = false; + // Worker subprocess closed flag. + #subprocessClosed = false; + // Custom app data. #appData: WorkerAppData; @@ -389,7 +393,10 @@ export class Worker< }); this.#child.on('exit', (code, signal) => { - this.#child = undefined; + // If killed by ourselves, do nothing. + if (this.#child.killed) { + return; + } if (!spawnDone) { spawnDone = true; @@ -431,7 +438,10 @@ export class Worker< }); this.#child.on('error', error => { - this.#child = undefined; + // If killed by ourselves, do nothing. + if (this.#child.killed) { + return; + } if (!spawnDone) { spawnDone = true; @@ -455,6 +465,19 @@ export class Worker< } }); + this.#child.on('close', (code, signal) => { + logger.debug( + 'worker subprocess closed [pid:%s, code:%s, signal:%s]', + this.#pid, + code, + signal, + ); + + this.#subprocessClosed = true; + + this.safeEmit('subprocessclose'); + }); + // Be ready for 3rd party worker libraries logging to stdout. this.#child.stdout!.on('data', buffer => { for (const line of buffer.toString('utf8').split('\n')) { @@ -495,6 +518,13 @@ export class Worker< return this.#died; } + /** + * Whether the Worker subprocess is closed. + */ + get subprocessClosed(): boolean { + return this.#subprocessClosed; + } + /** * App custom data. */ @@ -545,15 +575,7 @@ export class Worker< this.#closed = true; // Kill the worker process. - if (this.#child) { - // Remove event listeners but leave a fake 'error' hander to avoid - // propagation. - this.#child.removeAllListeners('exit'); - this.#child.removeAllListeners('error'); - this.#child.on('error', () => {}); - this.#child.kill('SIGTERM'); - this.#child = undefined; - } + this.#child.kill('SIGTERM'); // Close the Channel instance. this.#channel.close(); diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index c42462c553..13eb1014cf 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -27,8 +27,14 @@ beforeEach(async () => { ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('router.createActiveSpeakerObserver() succeeds', async () => { diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index e96537a5c8..21e943099d 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -27,8 +27,14 @@ beforeEach(async () => { ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('router.createAudioLevelObserver() succeeds', async () => { diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index d2d7e8a751..ce4a938197 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -241,8 +241,14 @@ beforeEach(async () => { ); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('transport.consume() succeeds', async () => { @@ -330,7 +336,7 @@ test('transport.consume() succeeds', async () => { ).toBe(true); // Pause videoProducer. - ctx.videoProducer!.pause(); + await ctx.videoProducer!.pause(); const videoConsumer = await ctx.webRtcTransport2!.consume({ producerId: ctx.videoProducer!.id, @@ -987,22 +993,25 @@ test('Consumer emits "producerpause" and "producerresume"', async () => { rtpCapabilities: ctx.consumerDeviceCapabilities, }); - await new Promise(resolve => { + // eslint-disable-next-line no-async-promise-executor + await new Promise(async resolve => { audioConsumer.on('producerpause', resolve); - ctx.audioProducer!.pause().catch(() => {}); + // Let's await for pause() to resolve to avoid aborted channel requests + // due to worker closure. + await ctx.audioProducer!.pause(); }); expect(audioConsumer.paused).toBe(false); expect(audioConsumer.producerPaused).toBe(true); - await new Promise(resolve => { + // eslint-disable-next-line no-async-promise-executor + await new Promise(async resolve => { audioConsumer.on('producerresume', resolve); - // Let's catch rejection since the test will complete before we get the - // response to this channel request, and if we don't handle that rejection - // it will make Jest fail any other random test. - ctx.audioProducer!.resume().catch(() => {}); + // Let's await for resume() to resolve to avoid aborted channel requests + // due to worker closure. + await ctx.audioProducer!.resume(); }); expect(audioConsumer.paused).toBe(false); diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index 230f1d9d77..9bd160563d 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -40,8 +40,14 @@ beforeEach(async () => { ); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('transport.consumeData() succeeds', async () => { diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index 1577e0ed05..de0b4fc7d3 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -44,8 +44,14 @@ beforeEach(async () => { }); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('webRtcTransport1.produceData() succeeds', async () => { diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index 25a39b6411..42c50c9464 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -12,8 +12,14 @@ beforeEach(async () => { ctx.router = await ctx.worker.createRouter(); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('router.createDirectTransport() succeeds', async () => { @@ -138,7 +144,7 @@ test('dataProducer.send() succeeds', async () => { ); }); - sendNextMessage(); + await sendNextMessage(); async function sendNextMessage(): Promise { const id = ++numSentMessages; diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 2249c2bdea..6943aa0cb2 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -195,9 +195,21 @@ beforeEach(async () => { ); }); -afterEach(() => { +afterEach(async () => { ctx.worker1?.close(); ctx.worker2?.close(); + + if (ctx.worker1?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker1?.on('subprocessclose', resolve), + ); + } + + if (ctx.worker2?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker2?.on('subprocessclose', resolve), + ); + } }); test('router.pipeToRouter() succeeds with audio', async () => { diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index ccf85c0720..f8bd9d18bd 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -49,8 +49,14 @@ beforeEach(async () => { ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('router.createPlainTransport() succeeds', async () => { diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index 0533033eb3..5ee64b9e8e 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -144,8 +144,14 @@ beforeEach(async () => { }); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('webRtcTransport1.produce() succeeds', async () => { diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index 877a6e1b32..80e1f263e2 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -42,8 +42,14 @@ beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('worker.createRouter() succeeds', async () => { diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index 0ed13fb9aa..c2f3aac924 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -13,8 +13,14 @@ beforeEach(async () => { ctx.worker = await mediasoup.createWorker(); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('worker.createWebRtcServer() succeeds', async () => { diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 5e37072184..2c13ec5f57 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -54,8 +54,14 @@ beforeEach(async () => { ctx.router = await ctx.worker.createRouter({ mediaCodecs: ctx.mediaCodecs }); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('router.createWebRtcTransport() succeeds', async () => { diff --git a/node/src/test/test-Worker.ts b/node/src/test/test-Worker.ts index 75baec9c4c..3c5314e2ed 100644 --- a/node/src/test/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -48,6 +48,8 @@ test('createWorker() succeeds', async () => { worker1.close(); + await new Promise(resolve => worker1.on('subprocessclose', resolve)); + expect(worker1.closed).toBe(true); expect(worker1.died).toBe(false); @@ -70,6 +72,8 @@ test('createWorker() succeeds', async () => { worker2.close(); + await new Promise(resolve => worker2.on('subprocessclose', resolve)); + expect(worker2.closed).toBe(true); expect(worker2.died).toBe(false); }, 2000); @@ -111,6 +115,8 @@ test('worker.updateSettings() succeeds', async () => { ).resolves.toBeUndefined(); worker.close(); + + await new Promise(resolve => worker.on('subprocessclose', resolve)); }, 2000); test('worker.updateSettings() with wrong settings rejects with TypeError', async () => { @@ -122,6 +128,8 @@ test('worker.updateSettings() with wrong settings rejects with TypeError', async ); worker.close(); + + await new Promise(resolve => worker.on('subprocessclose', resolve)); }, 2000); test('worker.updateSettings() rejects with InvalidStateError if closed', async () => { @@ -129,6 +137,8 @@ test('worker.updateSettings() rejects with InvalidStateError if closed', async ( worker.close(); + await new Promise(resolve => worker.on('subprocessclose', resolve)); + await expect(worker.updateSettings({ logLevel: 'error' })).rejects.toThrow( InvalidStateError, ); @@ -155,6 +165,8 @@ test('worker.dump() rejects with InvalidStateError if closed', async () => { worker.close(); + await new Promise(resolve => worker.on('subprocessclose', resolve)); + await expect(worker.dump()).rejects.toThrow(InvalidStateError); }, 2000); @@ -164,6 +176,8 @@ test('worker.getResourceUsage() succeeds', async () => { await expect(worker.getResourceUsage()).resolves.toMatchObject({}); worker.close(); + + await new Promise(resolve => worker.on('subprocessclose', resolve)); }, 2000); test('worker.close() succeeds', async () => { @@ -173,6 +187,8 @@ test('worker.close() succeeds', async () => { worker.observer.once('close', onObserverClose); worker.close(); + await new Promise(resolve => worker.on('subprocessclose', resolve)); + expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker.closed).toBe(true); expect(worker.died).toBe(false); @@ -209,6 +225,10 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { process.kill(worker1.pid, 'SIGINT'); }); + if (!worker1.subprocessClosed) { + await new Promise(resolve => worker1.on('subprocessclose', resolve)); + } + expect(onDied).toHaveBeenCalledTimes(1); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker1.closed).toBe(true); @@ -241,6 +261,10 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { process.kill(worker2.pid, 'SIGTERM'); }); + if (!worker2.subprocessClosed) { + await new Promise(resolve => worker2.on('subprocessclose', resolve)); + } + expect(onDied).toHaveBeenCalledTimes(1); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker2.closed).toBe(true); @@ -273,6 +297,10 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { process.kill(worker3.pid, 'SIGKILL'); }); + if (!worker3.subprocessClosed) { + await new Promise(resolve => worker3.on('subprocessclose', resolve)); + } + expect(onDied).toHaveBeenCalledTimes(1); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker3.closed).toBe(true); @@ -298,7 +326,7 @@ if (os.platform() !== 'win32') { expect(worker.closed).toBe(false); worker.close(); - resolve(); + worker.on('subprocessclose', resolve); }, 2000); }); }, 3000); diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index 45e328ea82..95f65dcb33 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -103,8 +103,14 @@ beforeEach(async () => { }); }); -afterEach(() => { +afterEach(async () => { ctx.worker?.close(); + + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } }); test('produce() and consume() succeed', async () => { diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index 228cc391e5..fda8c9169c 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -99,10 +99,16 @@ afterEach(async () => { ctx.sctpSocket?.end(); ctx.worker?.close(); + if (ctx.worker?.subprocessClosed === false) { + await new Promise( + resolve => ctx.worker?.on('subprocessclose', resolve), + ); + } + // NOTE: For some reason we have to wait a bit for the SCTP stuff to release // internal things, otherwise Jest reports open handles. We don't care much // honestly. - await new Promise(resolve => setTimeout(resolve, 2000)); + await new Promise(resolve => setTimeout(resolve, 1000)); }); test('ordered DataProducer delivers all SCTP messages to the DataConsumer', async () => { diff --git a/npm-scripts.mjs b/npm-scripts.mjs index e044c38077..91dbed9114 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -296,7 +296,7 @@ function installInvoke() { // Install pip invoke into custom location, so we don't depend on system-wide // installation. executeCmd( - `"${PYTHON}" -m pip install --upgrade --no-user --target="${PIP_INVOKE_DIR}" invoke`, + `"${PYTHON}" -m pip install --upgrade --no-user --target "${PIP_INVOKE_DIR}" invoke`, /* exitOnError */ true, ); } @@ -420,7 +420,7 @@ function flatcWorker() { function testNode() { logInfo('testNode()'); - executeCmd(`jest --detectOpenHandles ${args}`); + executeCmd(`jest --silent false --detectOpenHandles ${args}`); } function testWorker() { diff --git a/worker/Makefile b/worker/Makefile index bf5a2aba3a..0463766e7e 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -47,75 +47,75 @@ invoke: ifeq ($(wildcard $(PIP_INVOKE_DIR)),) # Install pip invoke into custom location, so we don't depend on system-wide # installation. - $(PYTHON) -m pip install --upgrade --no-user --target="$(PIP_INVOKE_DIR)" invoke + "$(PYTHON)" -m pip install --upgrade --no-user --target "$(PIP_INVOKE_DIR)" invoke endif meson-ninja: invoke - $(PYTHON) -m invoke meson-ninja + "$(PYTHON)" -m invoke meson-ninja setup: invoke - $(PYTHON) -m invoke setup + "$(PYTHON)" -m invoke setup clean: invoke - $(PYTHON) -m invoke clean + "$(PYTHON)" -m invoke clean clean-build: invoke - $(PYTHON) -m invoke clean-build + "$(PYTHON)" -m invoke clean-build clean-pip: invoke - $(PYTHON) -m invoke clean-pip + "$(PYTHON)" -m invoke clean-pip clean-subprojects: invoke - $(PYTHON) -m invoke clean-subprojects + "$(PYTHON)" -m invoke clean-subprojects clean-all: invoke - $(PYTHON) -m invoke clean-all + "$(PYTHON)" -m invoke clean-all # It requires the SUBPROJECT environment variable. update-wrap-file: invoke - $(PYTHON) -m invoke subprojects $(SUBPROJECT) + "$(PYTHON)" -m invoke subprojects $(SUBPROJECT) mediasoup-worker: invoke - $(PYTHON) -m invoke mediasoup-worker + "$(PYTHON)" -m invoke mediasoup-worker libmediasoup-worker: invoke - $(PYTHON) -m invoke libmediasoup-worker + "$(PYTHON)" -m invoke libmediasoup-worker flatc: invoke - $(PYTHON) -m invoke flatc + "$(PYTHON)" -m invoke flatc xcode: invoke - $(PYTHON) -m invoke xcode + "$(PYTHON)" -m invoke xcode lint: invoke - $(PYTHON) -m invoke lint + "$(PYTHON)" -m invoke lint format: invoke - $(PYTHON) -m invoke format + "$(PYTHON)" -m invoke format test: invoke - $(PYTHON) -m invoke test + "$(PYTHON)" -m invoke test test-asan: invoke - $(PYTHON) -m invoke test-asan + "$(PYTHON)" -m invoke test-asan tidy: invoke - $(PYTHON) -m invoke tidy + "$(PYTHON)" -m invoke tidy fuzzer: invoke - $(PYTHON) -m invoke fuzzer + "$(PYTHON)" -m invoke fuzzer fuzzer-run-all: invoke - $(PYTHON) -m invoke fuzzer-run-all + "$(PYTHON)" -m invoke fuzzer-run-all docker: invoke - $(PYTHON) -m invoke docker + "$(PYTHON)" -m invoke docker docker-run: invoke - $(PYTHON) -m invoke docker-run + "$(PYTHON)" -m invoke docker-run docker-alpine: invoke - $(PYTHON) -m invoke docker-alpine + "$(PYTHON)" -m invoke docker-alpine docker-alpine-run: invoke - $(PYTHON) -m invoke docker-alpine-run + "$(PYTHON)" -m invoke docker-alpine-run diff --git a/worker/tasks.py b/worker/tasks.py index 64476777de..e0c91b7630 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -107,14 +107,14 @@ def meson_ninja(ctx): # fallback to command without `--system` if the first one fails. try: ctx.run( - f'"{PYTHON}" -m pip install --system --upgrade --no-user --target="{PIP_MESON_NINJA_DIR}" pip setuptools', + f'"{PYTHON}" -m pip install --system --upgrade --no-user --target "{PIP_MESON_NINJA_DIR}" pip setuptools', echo=True, hide=True, shell=SHELL ); except: ctx.run( - f'"{PYTHON}" -m pip install --upgrade --no-user --target="{PIP_MESON_NINJA_DIR}" pip setuptools', + f'"{PYTHON}" -m pip install --upgrade --no-user --target "{PIP_MESON_NINJA_DIR}" pip setuptools', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -127,7 +127,7 @@ def meson_ninja(ctx): # Install meson and ninja using pip into our custom location, so we don't # depend on system-wide installation. ctx.run( - f'"{PYTHON}" -m pip install --upgrade --no-user --target="{PIP_MESON_NINJA_DIR}" {pip_build_binaries} meson=={MESON_VERSION} ninja=={NINJA_VERSION}', + f'"{PYTHON}" -m pip install --upgrade --no-user --target "{PIP_MESON_NINJA_DIR}" {pip_build_binaries} meson=={MESON_VERSION} ninja=={NINJA_VERSION}', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -140,7 +140,7 @@ def setup(ctx): Run meson setup """ if MEDIASOUP_BUILDTYPE == 'Release': - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true {MESON_ARGS} "{BUILD_DIR}"', echo=True, @@ -148,7 +148,7 @@ def setup(ctx): shell=SHELL ); elif MEDIASOUP_BUILDTYPE == 'Debug': - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug {MESON_ARGS} "{BUILD_DIR}"', echo=True, @@ -156,7 +156,7 @@ def setup(ctx): shell=SHELL ); else: - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release {MESON_ARGS} "{BUILD_DIR}"', echo=True, @@ -208,7 +208,7 @@ def clean_subprojects(ctx): """ Clean meson subprojects """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" subprojects purge --include-cache --confirm', echo=True, @@ -222,7 +222,7 @@ def clean_all(ctx): """ Clean meson subprojects and all installed/built artificats """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): try: ctx.run( f'"{MESON}" subprojects purge --include-cache --confirm', @@ -244,7 +244,7 @@ def update_wrap_file(ctx, subproject): """ Update the wrap file of a subproject """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" subprojects update --reset {subproject}', echo=True, @@ -258,7 +258,7 @@ def flatc(ctx): """ Compile FlatBuffers FBS files """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" compile -C "{BUILD_DIR}" flatbuffers-generator', echo=True, @@ -276,14 +276,14 @@ def mediasoup_worker(ctx): print('skipping mediasoup-worker compilation due to the existence of the MEDIASOUP_WORKER_BIN environment variable'); return; - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker', echo=True, pty=PTY_SUPPORTED, shell=SHELL ); - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker', echo=True, @@ -297,14 +297,14 @@ def libmediasoup_worker(ctx): """ Compile libmediasoup-worker library """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} libmediasoup-worker', echo=True, pty=PTY_SUPPORTED, shell=SHELL ); - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags libmediasoup-worker', echo=True, @@ -318,7 +318,7 @@ def xcode(ctx): """ Setup Xcode project """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" setup --buildtype {MEDIASOUP_BUILDTYPE.lower()} --backend xcode "{MEDIASOUP_OUT_DIR}/xcode"', echo=True, @@ -332,7 +332,7 @@ def lint(ctx): """ Lint source code """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{NPM}" run lint --prefix scripts/', echo=True, @@ -349,7 +349,7 @@ def lint(ctx): shell=SHELL ); - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{PYTHON}" -m pylint tasks.py', echo=True, @@ -363,7 +363,7 @@ def format(ctx): """ Format source code according to lint rules """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{NPM}" run format --prefix scripts/', echo=True, @@ -377,14 +377,14 @@ def test(ctx): """ Run worker tests """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test', echo=True, pty=PTY_SUPPORTED, shell=SHELL ); - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test', echo=True, @@ -395,7 +395,7 @@ def test(ctx): mediasoup_worker_test = 'mediasoup-worker-test.exe' if os.name == 'nt' else 'mediasoup-worker-test'; mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or ''; - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{BUILD_DIR}/{mediasoup_worker_test}" --invisibles --colour-mode=ansi {mediasoup_test_tags}', echo=True, @@ -409,14 +409,14 @@ def test_asan(ctx): """ Run worker test with Address Sanitizer """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test-asan', echo=True, pty=PTY_SUPPORTED, shell=SHELL ); - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test-asan', echo=True, @@ -426,7 +426,7 @@ def test_asan(ctx): mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or ''; - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'ASAN_OPTIONS=detect_leaks=1 "{BUILD_DIR}/mediasoup-worker-test-asan" --invisibles --use-colour=yes {mediasoup_test_tags}', echo=True, @@ -442,7 +442,7 @@ def tidy(ctx): """ mediasoup_tidy_checks = os.getenv('MEDIASOUP_TIDY_CHECKS') or ''; - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{PYTHON}" ./scripts/clang-tidy.py -clang-tidy-binary=./scripts/node_modules/.bin/clang-tidy -clang-apply-replacements-binary=./scripts/node_modules/.bin/clang-apply-replacements -header-filter="(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|handles/**/*.hpp)" -p="{BUILD_DIR}" -j={NUM_CORES} -checks={mediasoup_tidy_checks} -quiet', echo=True, @@ -456,14 +456,14 @@ def fuzzer(ctx): """ Build the mediasoup-worker-fuzzer binary (which uses libFuzzer) """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-fuzzer', echo=True, pty=PTY_SUPPORTED, shell=SHELL ); - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-fuzzer', echo=True, @@ -477,7 +477,7 @@ def fuzzer_run_all(ctx): """ Run all fuzzer cases """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'LSAN_OPTIONS=verbosity=1:log_threads=1 "{BUILD_DIR}/mediasoup-worker-fuzzer" -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus', echo=True, @@ -492,7 +492,7 @@ def docker(ctx): Build a Linux Ubuntu Docker image with fuzzer capable clang++ """ if os.getenv('DOCKER_NO_CACHE') == 'true': - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{DOCKER}" build -f Dockerfile --no-cache --tag mediasoup/docker:latest .', echo=True, @@ -500,7 +500,7 @@ def docker(ctx): shell=SHELL ); else: - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{DOCKER}" build -f Dockerfile --tag mediasoup/docker:latest .', echo=True, @@ -514,7 +514,7 @@ def docker_run(ctx): """ Run a container of the Ubuntu Docker image created in the docker task """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{DOCKER}" run --name=mediasoupDocker -it --rm --privileged --cap-add SYS_PTRACE -v "{WORKER_DIR}/../:/mediasoup" mediasoup/docker:latest', echo=True, @@ -529,7 +529,7 @@ def docker_alpine(ctx): Build a Linux Alpine Docker image """ if os.getenv('DOCKER_NO_CACHE') == 'true': - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{DOCKER}" build -f Dockerfile.alpine --no-cache --tag mediasoup/docker-alpine:latest .', echo=True, @@ -537,7 +537,7 @@ def docker_alpine(ctx): shell=SHELL ); else: - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{DOCKER}" build -f Dockerfile.alpine --tag mediasoup/docker-alpine:latest .', echo=True, @@ -551,7 +551,7 @@ def docker_alpine_run(ctx): """ Run a container of the Alpine Docker image created in the docker_alpine task """ - with ctx.cd(WORKER_DIR): + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{DOCKER}" run --name=mediasoupDockerAlpine -it --rm --privileged --cap-add SYS_PTRACE -v "{WORKER_DIR}/../:/mediasoup" mediasoup/docker-alpine:latest', echo=True, From 1e451249a3ac8e6e3c09579473957a3e206ec453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Jan 2024 12:34:29 +0100 Subject: [PATCH 310/525] Update ts eslint deps --- package-lock.json | 332 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 168 insertions(+), 168 deletions(-) diff --git a/package-lock.json b/package-lock.json index c079ed111e..415fbcf5aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,8 +22,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.7", - "@typescript-eslint/eslint-plugin": "^6.18.0", - "@typescript-eslint/parser": "^6.18.0", + "@typescript-eslint/eslint-plugin": "^6.18.1", + "@typescript-eslint/parser": "^6.18.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.6.1", @@ -1674,16 +1674,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", - "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz", + "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/type-utils": "6.18.0", - "@typescript-eslint/utils": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/type-utils": "6.18.1", + "@typescript-eslint/utils": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1709,13 +1709,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", + "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1726,9 +1726,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", + "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1739,13 +1739,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", + "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1767,17 +1767,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", + "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", "semver": "^7.5.4" }, "engines": { @@ -1792,12 +1792,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", + "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/types": "6.18.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1833,15 +1833,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", - "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz", + "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4" }, "engines": { @@ -1861,13 +1861,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", + "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1878,9 +1878,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", + "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1891,13 +1891,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", + "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1919,12 +1919,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", + "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/types": "6.18.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1977,13 +1977,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", - "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz", + "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/utils": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/utils": "6.18.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -2004,13 +2004,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", + "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2021,9 +2021,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", + "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2034,13 +2034,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", + "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2062,17 +2062,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", + "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", "semver": "^7.5.4" }, "engines": { @@ -2087,12 +2087,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", + "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/types": "6.18.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -8242,16 +8242,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", - "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz", + "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/type-utils": "6.18.0", - "@typescript-eslint/utils": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/type-utils": "6.18.1", + "@typescript-eslint/utils": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8261,29 +8261,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", + "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1" } }, "@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", + "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", + "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8293,27 +8293,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", + "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", + "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/types": "6.18.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -8338,42 +8338,42 @@ } }, "@typescript-eslint/parser": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", - "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz", + "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", + "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1" } }, "@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", + "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", + "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8383,12 +8383,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", + "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/types": "6.18.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -8423,41 +8423,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", - "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz", + "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/utils": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/utils": "6.18.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", + "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1" } }, "@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", + "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", + "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8467,27 +8467,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", + "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", + "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/types": "6.18.1", "eslint-visitor-keys": "^3.4.1" } }, diff --git a/package.json b/package.json index fd2e0fe4ca..ef18bb14c8 100644 --- a/package.json +++ b/package.json @@ -112,8 +112,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", "@types/node": "^20.10.7", - "@typescript-eslint/eslint-plugin": "^6.18.0", - "@typescript-eslint/parser": "^6.18.0", + "@typescript-eslint/eslint-plugin": "^6.18.1", + "@typescript-eslint/parser": "^6.18.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.6.1", From 86d79e9f7aa4bd736cab9d729313ad7527e07a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Jan 2024 13:09:51 +0100 Subject: [PATCH 311/525] Fix typos --- .eslintignore | 2 +- .prettierignore | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.eslintignore b/.eslintignore index 0ff585b6fc..6e2bd913cd 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,4 @@ -# NOTE: This file and .eslintignore must contain same paths. +# NOTE: This file and .prettierignore must contain same paths. /.cache /art diff --git a/.prettierignore b/.prettierignore index d4f6347eb3..f154487ec4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,4 @@ -# NOTE: This file and .prettierignore must contain same paths. +# NOTE: This file and .eslintignore must contain same paths. /.cache /art From 310c57239205519d07890504095961756f410dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Jan 2024 15:02:48 +0100 Subject: [PATCH 312/525] mediasoup-node.yaml: no need to specify --silent false (already set in npm-scripts) --- .github/workflows/mediasoup-node.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index aad43a1210..0618603bc7 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -57,4 +57,4 @@ jobs: run: npm run lint:node - name: npm run test:node - run: npm run test:node -- --silent false + run: npm run test:node From e485eaa46edc04f998044f26086a12dba4b63b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Jan 2024 17:58:52 +0100 Subject: [PATCH 313/525] Update pick-port NPM library to 2.0.0 --- node/src/test/test-PipeTransport.ts | 9 +++-- node/src/test/test-PlainTransport.ts | 33 +++++++++++++---- node/src/test/test-WebRtcServer.ts | 51 +++++++++++++++++++++------ node/src/test/test-WebRtcTransport.ts | 3 +- package-lock.json | 35 +++++++++--------- package.json | 4 +-- 6 files changed, 95 insertions(+), 40 deletions(-) diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 6943aa0cb2..fc07859c9f 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -1,5 +1,4 @@ -// @ts-ignore -import * as pickPort from 'pick-port'; +import { pickPort } from 'pick-port'; import * as mediasoup from '../'; import * as utils from '../utils'; @@ -709,7 +708,11 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { }, 2000); test('router.createPipeTransport() with fixed port succeeds', async () => { - const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); const pipeTransport = await ctx.router1!.createPipeTransport({ listenInfo: { protocol: 'udp', ip: '127.0.0.1', port }, }); diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index f8bd9d18bd..8e6413fb47 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -1,6 +1,5 @@ import * as os from 'node:os'; -// @ts-ignore -import * as pickPort from 'pick-port'; +import { pickPort } from 'pick-port'; import * as mediasoup from '../'; import * as utils from '../utils'; @@ -120,8 +119,16 @@ test('router.createPlainTransport() succeeds', async () => { expect(typeof anotherTransport).toBe('object'); - const rtpPort = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const rtcpPort = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const rtpPort = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + const rtcpPort = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); const transport2 = await ctx.router!.createPlainTransport({ listenInfo: { protocol: 'udp', ip: '127.0.0.1', port: rtpPort }, rtcpListenInfo: { protocol: 'udp', ip: '127.0.0.1', port: rtcpPort }, @@ -299,7 +306,11 @@ test('router.createPlainTransport() with non bindable IP rejects with Error', as if (!IS_WINDOWS) { test('two transports binding to the same IP:port with udpReusePort flag succeed', async () => { const multicastIp = '224.0.0.1'; - const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); + const port = await pickPort({ + type: 'udp', + ip: multicastIp, + reserveTimeout: 0, + }); await expect( ctx.router!.createPlainTransport({ @@ -327,7 +338,11 @@ if (!IS_WINDOWS) { test('two transports binding to the same IP:port without udpReusePort flag fail', async () => { const multicastIp = '224.0.0.1'; - const port = await pickPort({ ip: multicastIp, reserveTimeout: 0 }); + const port = await pickPort({ + type: 'udp', + ip: multicastIp, + reserveTimeout: 0, + }); await expect( ctx.router!.createPlainTransport({ @@ -476,7 +491,11 @@ test('PlainTransport methods reject if closed', async () => { }, 2000); test('router.createPlainTransport() with fixed port succeeds', async () => { - const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); const plainTransport = await ctx.router!.createPlainTransport({ listenInfo: { protocol: 'udp', ip: '127.0.0.1', port }, }); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index c2f3aac924..85a83df6a2 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -1,5 +1,4 @@ -// @ts-ignore -import * as pickPort from 'pick-port'; +import { pickPort } from 'pick-port'; import * as mediasoup from '../'; import { InvalidStateError } from '../errors'; @@ -28,7 +27,11 @@ test('worker.createWebRtcServer() succeeds', async () => { ctx.worker!.observer.once('newwebrtcserver', onObserverNewWebRtcServer); - const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port1 = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', @@ -166,8 +169,16 @@ test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', test('worker.createWebRtcServer() with unavailable listenInfos rejects with Error', async () => { const worker2 = await mediasoup.createWorker(); - const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); - const port2 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port1 = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + const port2 = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); // Using an unavailable listen IP. await expect( @@ -235,7 +246,11 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is closed', async () => { ctx.worker!.close(); - const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); await expect( ctx.worker!.createWebRtcServer({ @@ -245,7 +260,11 @@ test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is cl }, 2000); test('webRtcServer.close() succeeds', async () => { - const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); const webRtcServer = await ctx.worker!.createWebRtcServer({ listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', port }], }); @@ -259,7 +278,11 @@ test('webRtcServer.close() succeeds', async () => { }, 2000); test('WebRtcServer emits "workerclose" if Worker is closed', async () => { - const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); const webRtcServer = await ctx.worker!.createWebRtcServer({ listenInfos: [{ protocol: 'tcp', ip: '127.0.0.1', port }], }); @@ -277,7 +300,11 @@ test('WebRtcServer emits "workerclose" if Worker is closed', async () => { }, 2000); test('router.createWebRtcTransport() with webRtcServer succeeds and transport is closed', async () => { - const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port1 = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', @@ -372,7 +399,11 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is }, 2000); test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer is closed', async () => { - const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port1 = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 2c13ec5f57..7e10d17dda 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -1,5 +1,4 @@ -// @ts-ignore -import * as pickPort from 'pick-port'; +import { pickPort } from 'pick-port'; import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import * as utils from '../utils'; diff --git a/package-lock.json b/package-lock.json index 415fbcf5aa..a3f877a0b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.7", + "@types/node": "^20.10.8", "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", "eslint": "^8.56.0", @@ -31,7 +31,7 @@ "jest": "^29.7.0", "marked": "^11.1.1", "open-cli": "^7.2.0", - "pick-port": "^1.0.1", + "pick-port": "^2.0.0", "prettier": "^3.1.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", @@ -1632,9 +1632,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.10.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", - "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", + "version": "20.10.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", + "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -5462,12 +5462,15 @@ } }, "node_modules/pick-port": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-1.0.1.tgz", - "integrity": "sha512-JzjRIkfG/4pG3tYLl1LwdmFtnlW+Rsxe200DevHZzZLYDUgfnx8LuOFnLwy5Dt59JY1HIN3JXyMXRbUvERkh/g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.0.0.tgz", + "integrity": "sha512-J0la9VzIUofUKs4EhWuwbtsEJjkvs7rAOp/JbXE0RlR0ZMI0AhwiCm1roIUhK/gnOGvTE7OJznFW48mmOQyz/A==", "dev": true, "dependencies": { - "debug": "^4.3.1" + "debug": "^4.3.4" + }, + "engines": { + "node": ">=16" } }, "node_modules/picocolors": { @@ -8200,9 +8203,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.10.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", - "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", + "version": "20.10.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", + "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -10881,12 +10884,12 @@ "dev": true }, "pick-port": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-1.0.1.tgz", - "integrity": "sha512-JzjRIkfG/4pG3tYLl1LwdmFtnlW+Rsxe200DevHZzZLYDUgfnx8LuOFnLwy5Dt59JY1HIN3JXyMXRbUvERkh/g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.0.0.tgz", + "integrity": "sha512-J0la9VzIUofUKs4EhWuwbtsEJjkvs7rAOp/JbXE0RlR0ZMI0AhwiCm1roIUhK/gnOGvTE7OJznFW48mmOQyz/A==", "dev": true, "requires": { - "debug": "^4.3.1" + "debug": "^4.3.4" } }, "picocolors": { diff --git a/package.json b/package.json index ef18bb14c8..f1b0da9c75 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.7", + "@types/node": "^20.10.8", "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", "eslint": "^8.56.0", @@ -121,7 +121,7 @@ "jest": "^29.7.0", "marked": "^11.1.1", "open-cli": "^7.2.0", - "pick-port": "^1.0.1", + "pick-port": "^2.0.0", "prettier": "^3.1.1", "sctp": "^1.0.0", "ts-jest": "^29.1.1", From c6517f8e55f681794d84740d8bbe9ea61ab69439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Tue, 9 Jan 2024 18:00:49 +0100 Subject: [PATCH 314/525] clang-tidy C++ (#1308) modernize clang-tidy and fix tasks.py command --- doc/Building.md | 9 +- worker/.clang-tidy | 12 +- worker/include/Channel/ChannelRequest.hpp | 2 +- worker/include/RTC/RtpDictionaries.hpp | 3 +- worker/include/RTC/SeqManager.hpp | 14 +- worker/include/Settings.hpp | 4 +- worker/include/Utils.hpp | 24 +- worker/include/Worker.hpp | 2 +- worker/include/handles/UdpSocketHandle.hpp | 2 + worker/scripts/package-lock.json | 1787 +---------------- worker/scripts/package.json | 1 - worker/src/Channel/ChannelRequest.cpp | 2 +- worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 19 +- worker/src/RTC/RTCP/Packet.cpp | 4 +- worker/src/RTC/RtcLogger.cpp | 10 +- .../RtpHeaderExtensionParameters.cpp | 1 - worker/src/RTC/SctpAssociation.cpp | 1 + .../SctpDictionaries/SctpStreamParameters.cpp | 1 - worker/src/RTC/SeqManager.cpp | 10 +- worker/src/RTC/SimulcastConsumer.cpp | 1 - worker/src/RTC/Transport.cpp | 1 + worker/src/Settings.cpp | 10 +- worker/src/Utils/Crypto.cpp | 2 +- worker/src/Utils/String.cpp | 2 +- worker/src/Worker.cpp | 2 +- worker/src/handles/TcpConnectionHandle.cpp | 1 + worker/src/handles/UdpSocketHandle.cpp | 5 +- worker/tasks.py | 14 +- 28 files changed, 116 insertions(+), 1830 deletions(-) diff --git a/doc/Building.md b/doc/Building.md index 944b3e2502..6d5ab153f2 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -200,8 +200,15 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy) and performs C++ code - `invoke clean` and `invoke mediasoup-worker` must have been called first. - [PyYAML](https://pyyaml.org) is required. - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. +- [clang-tools-extra](https://clang.llvm.org/extra/index.html) is required. + - In OSX install it with `brew install clang-tools-extra`. + - In linux the package name is `clang-tools-extra`. -"MEDIASOUP_TIDY_CHECKS" environment variable with a comma separated list of checks overrides the checks defined in `.clang-tidy` file. +**Environment variables** + +- "MEDIASOUP_TIDY_CHECKS": comma separated list of checks. Overrides the checks defined in `.clang-tidy` file. +- "MEDIASOUP_TIDY_FILES": space separated source files to process, including their path. All .cpp files will be processes by default. +- "MEDIASOUP_CLANG_TIDY_DIR": path to directory containing clang tools (run-clang-tidy, clang-tidy, clang-apply-replacements). ### `invoke fuzzer` diff --git a/worker/.clang-tidy b/worker/.clang-tidy index 0f4b9c0273..f66b8de82c 100644 --- a/worker/.clang-tidy +++ b/worker/.clang-tidy @@ -1,21 +1,26 @@ --- Checks: "*,\ -altera*,\ + -android*,\ -boost-use-to-string,\ -bugprone-easily-swappable-parameters,\ + -bugprone-implicit-widening-of-multiplication-result,\ -bugprone-lambda-function-name,\ -bugprone-macro-parentheses,\ + -bugprone-reserved-identifier,\ -cert-*,\ -clang-analyzer-optin.osx.*,\ -clang-analyzer-osx.*,\ -cppcoreguidelines-avoid-c-arrays,\ -cppcoreguidelines-avoid-do-while,\ -cppcoreguidelines-avoid-goto,\ + -cppcoreguidelines-avoid-non-const-global-variables,\ -cppcoreguidelines-avoid-magic-numbers,\ -cppcoreguidelines-init-variables,\ -cppcoreguidelines-no-malloc,\ -cppcoreguidelines-non-private-member-variables-in-classes,\ -cppcoreguidelines-owning-memory,\ + -cppcoreguidelines-prefer-member-initializer,\ -cppcoreguidelines-pro-bounds-array-to-pointer-decay,\ -cppcoreguidelines-pro-bounds-constant-array-index,\ -cppcoreguidelines-pro-bounds-pointer-arithmetic,\ @@ -27,9 +32,11 @@ Checks: "*,\ -cppcoreguidelines-special-member-functions,\ -fuchsia-default-arguments-calls,\ -fuchsia-default-arguments-declarations,\ + -fuchsia-overloaded-operator,\ -google-default-arguments,\ -google-readability-*,\ -google-runtime-references,\ + -google-upgrade-googletest-case,\ -hicpp-avoid-c-arrays,\ -hicpp-avoid-goto,\ -hicpp-braces-around-statements,\ @@ -42,7 +49,9 @@ Checks: "*,\ -llvm-header-guard,\ -llvm-else-after-return,\ -llvmlibc-*,\ + -misc-confusable-identifiers,\ -misc-non-private-member-variables-in-classes,\ + -misc-use-anonymous-namespace,\ -modernize-avoid-c-arrays,\ -modernize-concat-nested-namespaces,\ -modernize-make-unique,\ @@ -59,7 +68,6 @@ Checks: "*,\ -readability-uppercase-literal-suffix,\ " -HeaderFilterRegex: '' AnalyzeTemporaryDtors: false User: mediasoup FormatStyle: file @@ -332,7 +340,7 @@ CheckOptions: - key: readability-identifier-naming.UnionSuffix value: '' - key: readability-identifier-naming.ValueTemplateParameterCase - value: camelBack + value: CamelCase - key: readability-identifier-naming.ValueTemplateParameterPrefix value: '' - key: readability-identifier-naming.ValueTemplateParameterSuffix diff --git a/worker/include/Channel/ChannelRequest.hpp b/worker/include/Channel/ChannelRequest.hpp index 5ae484798e..1f1b48c242 100644 --- a/worker/include/Channel/ChannelRequest.hpp +++ b/worker/include/Channel/ChannelRequest.hpp @@ -53,7 +53,7 @@ namespace Channel void TypeError(const char* reason = nullptr); private: - void Send(uint8_t* buffer, size_t size); + void Send(uint8_t* buffer, size_t size) const; void SendResponse(const flatbuffers::Offset& response); public: diff --git a/worker/include/RTC/RtpDictionaries.hpp b/worker/include/RTC/RtpDictionaries.hpp index caf3211f1a..e9a266b5a5 100644 --- a/worker/include/RTC/RtpDictionaries.hpp +++ b/worker/include/RTC/RtpDictionaries.hpp @@ -210,8 +210,7 @@ namespace RTC { public: RtpHeaderExtensionParameters() = default; - explicit RtpHeaderExtensionParameters( - const FBS::RtpParameters::RtpHeaderExtensionParameters* const data); + explicit RtpHeaderExtensionParameters(const FBS::RtpParameters::RtpHeaderExtensionParameters* data); flatbuffers::Offset FillBuffer( flatbuffers::FlatBufferBuilder& builder) const; diff --git a/worker/include/RTC/SeqManager.hpp b/worker/include/RTC/SeqManager.hpp index 82409d2a65..3a0fd3cdab 100644 --- a/worker/include/RTC/SeqManager.hpp +++ b/worker/include/RTC/SeqManager.hpp @@ -18,21 +18,21 @@ namespace RTC public: struct SeqLowerThan { - bool operator()(const T lhs, const T rhs) const; + bool operator()(T lhs, T rhs) const; }; struct SeqHigherThan { - bool operator()(const T lhs, const T rhs) const; + bool operator()(T lhs, T rhs) const; }; private: - static const SeqLowerThan isSeqLowerThan; - static const SeqHigherThan isSeqHigherThan; + static const SeqLowerThan isSeqLowerThan; // NOLINT(readability-identifier-naming) + static const SeqHigherThan isSeqHigherThan; // NOLINT(readability-identifier-naming) public: - static bool IsSeqLowerThan(const T lhs, const T rhs); - static bool IsSeqHigherThan(const T lhs, const T rhs); + static bool IsSeqLowerThan(T lhs, T rhs); + static bool IsSeqHigherThan(T lhs, T rhs); public: SeqManager() = default; @@ -40,7 +40,7 @@ namespace RTC public: void Sync(T input); void Drop(T input); - bool Input(const T input, T& output); + bool Input(T input, T& output); T GetMaxInput() const; T GetMaxOutput() const; diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index bd3343546d..06a66f4bf6 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -55,8 +55,8 @@ class Settings thread_local static struct Configuration configuration; private: - static absl::flat_hash_map string2LogLevel; - static absl::flat_hash_map logLevel2String; + static absl::flat_hash_map String2LogLevel; // NOLINT(readability-identifier-naming) + static absl::flat_hash_map LogLevel2String; // NOLINT(readability-identifier-naming) }; #endif diff --git a/worker/include/Utils.hpp b/worker/include/Utils.hpp index 120afb0b62..4e2d0ba15f 100644 --- a/worker/include/Utils.hpp +++ b/worker/include/Utils.hpp @@ -57,9 +57,7 @@ namespace Utils std::memcmp( std::addressof(reinterpret_cast(addr1)->sin6_addr), std::addressof(reinterpret_cast(addr2)->sin6_addr), - 16) == 0 - ? true - : false); + 16) == 0); } default: @@ -71,7 +69,9 @@ namespace Utils static struct sockaddr_storage CopyAddress(const struct sockaddr* addr) { - struct sockaddr_storage copiedAddr; + struct sockaddr_storage copiedAddr + { + }; switch (addr->sa_family) { @@ -125,7 +125,7 @@ namespace Utils auto byte0 = data[i + 2]; // The less significant byte. // Check bit 7 (sign). - uint8_t extension = byte2 & 0b10000000 ? 0b11111111 : 0b00000000; + const uint8_t extension = byte2 & 0b10000000 ? 0b11111111 : 0b00000000; return int32_t{ byte0 } | (int32_t{ byte1 } << 8) | (int32_t{ byte2 } << 16) | (int32_t{ extension } << 24); @@ -252,10 +252,10 @@ namespace Utils return (((Crypto::seed >> 4) & 0x7FFF7FFF) % (max - min + 1)) + min; } - static const std::string GetRandomString(size_t len) + static std::string GetRandomString(size_t len) { char buffer[64]; - static const char chars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', + static const char Chars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; @@ -266,10 +266,10 @@ namespace Utils for (size_t i{ 0 }; i < len; ++i) { - buffer[i] = chars[GetRandomUInt(0, sizeof(chars) - 1)]; + buffer[i] = Chars[GetRandomUInt(0, sizeof(Chars) - 1)]; } - return std::string(buffer, len); + return { buffer, len }; } static uint32_t GetCRC32(const uint8_t* data, size_t size) @@ -279,7 +279,7 @@ namespace Utils while (size--) { - crc = Crypto::crc32Table[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + crc = Crypto::Crc32Table[(crc ^ *p++) & 0xFF] ^ (crc >> 8); } return crc ^ ~0U; @@ -292,7 +292,7 @@ namespace Utils thread_local static EVP_MAC* mac; thread_local static EVP_MAC_CTX* hmacSha1Ctx; thread_local static uint8_t hmacSha1Buffer[]; - static const uint32_t crc32Table[256]; + static const uint32_t Crc32Table[256]; }; class String @@ -328,7 +328,7 @@ namespace Utils static Time::Ntp TimeMs2Ntp(uint64_t ms) { - Time::Ntp ntp; // NOLINT(cppcoreguidelines-pro-type-member-init) + Time::Ntp ntp{}; // NOLINT(cppcoreguidelines-pro-type-member-init) ntp.seconds = ms / 1000; ntp.fractions = diff --git a/worker/include/Worker.hpp b/worker/include/Worker.hpp index 9bb91b8fed..24483766b6 100644 --- a/worker/include/Worker.hpp +++ b/worker/include/Worker.hpp @@ -30,7 +30,7 @@ class Worker : public Channel::ChannelSocket::Listener, RTC::WebRtcServer* GetWebRtcServer(const std::string& webRtcServerId) const; RTC::Router* GetRouter(const std::string& routerId) const; void CheckNoWebRtcServer(const std::string& webRtcServerId) const; - void CheckNoRouter(const std::string& webRtcServerId) const; + void CheckNoRouter(const std::string& routerId) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: diff --git a/worker/include/handles/UdpSocketHandle.hpp b/worker/include/handles/UdpSocketHandle.hpp index 2b7a708105..8a4085c33f 100644 --- a/worker/include/handles/UdpSocketHandle.hpp +++ b/worker/include/handles/UdpSocketHandle.hpp @@ -84,8 +84,10 @@ class UdpSocketHandle /* Callbacks fired by UV events. */ public: + // NOLINTNEXTLINE(readability-convert-member-functions-to-static) void OnUvRecvAlloc(size_t suggestedSize, uv_buf_t* buf); void OnUvRecv(ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned int flags); + // NOLINTNEXTLINE(readability-convert-member-functions-to-static) void OnUvSend(int status, UdpSocketHandle::onSendCallback* cb); /* Pure virtual methods that must be implemented by the subclass. */ diff --git a/worker/scripts/package-lock.json b/worker/scripts/package-lock.json index 7805731de1..9f468b26cc 100644 --- a/worker/scripts/package-lock.json +++ b/worker/scripts/package-lock.json @@ -9,7 +9,6 @@ "version": "0.0.1", "dependencies": { "clang-format": "^1.8.0", - "clang-tools-prebuilt": "^0.1.4", "glob": "^10.3.10" } }, @@ -111,81 +110,16 @@ "node": ">=14" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "engines": { - "node": ">=0.8" - } - }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -194,31 +128,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dependencies": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "node_modules/clang-format": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", @@ -273,25 +182,6 @@ "node": "*" } }, - "node_modules/clang-tools-prebuilt": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", - "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", - "hasInstallScript": true, - "dependencies": { - "home-path": "^0.1.1", - "mkdirp": "^0.5.0", - "nugget": "^1.5.1", - "path-exists": "^1.0.0" - }, - "bin": { - "clang-apply-replacements": "tools/clang-apply-replacements.js", - "clang-include-fixer": "tools/clang-include-fixer.js", - "clang-rename": "tools/clang-rename.js", - "clang-tidy": "tools/clang-tidy.js", - "find-all-symbols": "tools/find-all-symbols.js" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -308,27 +198,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -356,125 +230,16 @@ "node": ">= 8" } }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dependencies": { - "array-find-index": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -501,27 +266,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -532,22 +276,6 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/glob": { "version": "10.3.10", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", @@ -569,32 +297,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -606,41 +308,6 @@ "node": ">= 0.4.0" } }, - "node_modules/home-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/home-path/-/home-path-0.1.2.tgz", - "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=" - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dependencies": { - "repeating": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -655,11 +322,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, "node_modules/is-core-module": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", @@ -671,37 +333,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "node_modules/jackspeak": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", @@ -719,67 +355,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dependencies": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lru-cache": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", @@ -816,61 +391,6 @@ "node": ">=10" } }, - "node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dependencies": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/meow/node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -885,11 +405,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, "node_modules/minipass": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", @@ -898,58 +413,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/nugget": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", - "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", - "dependencies": { - "debug": "^2.1.3", - "minimist": "^1.1.0", - "pretty-bytes": "^1.0.2", - "progress-stream": "^1.1.0", - "request": "^2.45.0", - "single-line-log": "^0.4.1", - "throttleit": "0.0.2" - }, - "bin": { - "nugget": "bin.js" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -958,25 +421,6 @@ "wrappy": "1" } }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-exists": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", - "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1013,221 +457,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "dependencies": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - }, - "bin": { - "pretty-bytes": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/progress-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", - "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", - "dependencies": { - "speedometer": "~0.1.2", - "through2": "~0.2.3" - } - }, - "node_modules/progress-stream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/progress-stream/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" - }, - "node_modules/progress-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/progress-stream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "node_modules/progress-stream/node_modules/through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", - "dependencies": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" - } - }, - "node_modules/progress-stream/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dependencies": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dependencies": { - "is-finite": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -1240,24 +469,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -1277,73 +488,6 @@ "node": ">=8" } }, - "node_modules/signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" - }, - "node_modules/single-line-log": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", - "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==" - }, - "node_modules/speedometer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=" - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", @@ -1375,145 +519,35 @@ } }, "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dependencies": { - "get-stdin": "^4.0.1" - }, - "bin": { - "strip-indent": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/throttleit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=" - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } }, "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", @@ -1662,68 +696,16 @@ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "optional": true }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, "async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -1732,25 +714,6 @@ "balanced-match": "^1.0.0" } }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "clang-format": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", @@ -1793,17 +756,6 @@ } } }, - "clang-tools-prebuilt": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/clang-tools-prebuilt/-/clang-tools-prebuilt-0.1.4.tgz", - "integrity": "sha512-aghHewt9UsAAxUFaycuQxgBHCaTOrebWfG4h3+BXK/rvcoFzGjcSrseUkAvo6TzRa2d81eFc2zeviYuKcLGXVA==", - "requires": { - "home-path": "^0.1.1", - "mkdirp": "^0.5.0", - "nugget": "^1.5.1", - "path-exists": "^1.0.0" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1817,24 +769,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1855,106 +794,16 @@ } } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "requires": { - "array-find-index": "^1.0.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, "foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -1971,21 +820,6 @@ } } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1996,19 +830,6 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "10.3.10", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", @@ -2021,25 +842,6 @@ "path-scurry": "^1.10.1" } }, - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2048,34 +850,6 @@ "function-bind": "^1.1.1" } }, - "home-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/home-path/-/home-path-0.1.2.tgz", - "integrity": "sha1-PbJsojrcFE/uqPHi18j2yJDL/io=" - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "requires": { - "repeating": "^2.0.0" - } - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2090,11 +864,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, "is-core-module": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", @@ -2103,31 +872,11 @@ "has": "^1.0.3" } }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "jackspeak": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", @@ -2137,58 +886,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, "lru-cache": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", @@ -2215,48 +912,6 @@ } } }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - } - } - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - }, "minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -2265,59 +920,11 @@ "brace-expansion": "^2.0.1" } }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, "minipass": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "nugget": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", - "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", - "requires": { - "debug": "^2.1.3", - "minimist": "^1.1.0", - "pretty-bytes": "^1.0.2", - "progress-stream": "^1.1.0", - "request": "^2.45.0", - "single-line-log": "^0.4.1", - "throttleit": "0.0.2" - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2326,19 +933,6 @@ "wrappy": "1" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", - "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=" - }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2363,180 +957,6 @@ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } - }, - "pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - } - }, - "progress-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", - "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", - "requires": { - "speedometer": "~0.1.2", - "through2": "~0.2.3" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", - "requires": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" - } - }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "requires": { - "object-keys": "~0.4.0" - } - } - } - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -2546,21 +966,6 @@ "path-parse": "^1.0.6" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2574,65 +979,6 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, - "signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" - }, - "single-line-log": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", - "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==" - }, - "speedometer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=" - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "string-width-cjs": { "version": "npm:string-width@4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -2678,93 +1024,6 @@ } } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "requires": { - "get-stdin": "^4.0.1" - } - }, - "throttleit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=" - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - } - } - }, "wrap-ansi-cjs": { "version": "npm:wrap-ansi@7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/worker/scripts/package.json b/worker/scripts/package.json index ba844335b7..eb4827cf34 100644 --- a/worker/scripts/package.json +++ b/worker/scripts/package.json @@ -8,7 +8,6 @@ }, "dependencies": { "clang-format": "^1.8.0", - "clang-tools-prebuilt": "^0.1.4", "glob": "^10.3.10" } } diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index ed1ef58395..f268d94f21 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -156,7 +156,7 @@ namespace Channel this->SendResponse(response); } - void ChannelRequest::Send(uint8_t* buffer, size_t size) + void ChannelRequest::Send(uint8_t* buffer, size_t size) const { this->channel->Send(buffer, size); } diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index 0e41548ada..a732cafcfd 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -62,7 +62,7 @@ namespace RTC { MS_TRACE(); - size_t len = static_cast(ntohs(commonHeader->length) + 1) * 4; + const size_t len = static_cast(ntohs(commonHeader->length) + 1) * 4; if (len > availableLen) { @@ -86,8 +86,8 @@ namespace RTC // Make contentData point to the beginning of the chunks. uint8_t* contentData = data + FeedbackRtpTransportPacket::fixedHeaderSize; // Make contentLen be the available length for chunks. - size_t contentLen = len - Packet::CommonHeaderSize - FeedbackPacket::HeaderSize - - FeedbackRtpTransportPacket::fixedHeaderSize; + const size_t contentLen = len - Packet::CommonHeaderSize - FeedbackPacket::HeaderSize - + FeedbackRtpTransportPacket::fixedHeaderSize; size_t offset{ 0u }; uint16_t count{ 0u }; uint16_t receivedPacketStatusCount{ 0u }; @@ -618,8 +618,8 @@ namespace RTC return nullptr; } - auto bytes = Utils::Byte::Get2Bytes(data, 0); - uint8_t chunkType = (bytes >> 15) & 0x01; + auto bytes = Utils::Byte::Get2Bytes(data, 0); + const uint8_t chunkType = (bytes >> 15) & 0x01; // Run length chunk. if (chunkType == 0) @@ -649,7 +649,7 @@ namespace RTC // Vector chunk. else { - uint8_t symbolSize = data[0] & 0x40; + const uint8_t symbolSize = data[0] & 0x40; if (symbolSize == 0) { @@ -750,7 +750,8 @@ namespace RTC { MS_TRACE(); - bool received = (this->status == Status::SmallDelta || this->status == Status::LargeDelta); + const bool received = + (this->status == Status::SmallDelta || this->status == Status::LargeDelta); for (uint16_t count{ 1u }; count <= this->count; ++count) { @@ -875,7 +876,7 @@ namespace RTC for (auto status : this->statuses) { - bool received = (status == Status::SmallDelta || status == Status::LargeDelta); + const bool received = (status == Status::SmallDelta || status == Status::LargeDelta); packetResults.emplace_back(++currentSequenceNumber, received); } @@ -1015,7 +1016,7 @@ namespace RTC for (auto status : this->statuses) { - bool received = (status == Status::SmallDelta || status == Status::LargeDelta); + const bool received = (status == Status::SmallDelta || status == Status::LargeDelta); packetResults.emplace_back(++currentSequenceNumber, received); } diff --git a/worker/src/RTC/RTCP/Packet.cpp b/worker/src/RTC/RTCP/Packet.cpp index bb9a47b949..0cae29f65e 100644 --- a/worker/src/RTC/RTCP/Packet.cpp +++ b/worker/src/RTC/RTCP/Packet.cpp @@ -54,8 +54,8 @@ namespace RTC return first; } - auto* header = const_cast(reinterpret_cast(data)); - size_t packetLen = static_cast(ntohs(header->length) + 1) * 4; + auto* header = const_cast(reinterpret_cast(data)); + const size_t packetLen = static_cast(ntohs(header->length) + 1) * 4; if (len < packetLen) { diff --git a/worker/src/RTC/RtcLogger.cpp b/worker/src/RTC/RtcLogger.cpp index 96f6809246..2b7a72b093 100644 --- a/worker/src/RTC/RtcLogger.cpp +++ b/worker/src/RTC/RtcLogger.cpp @@ -56,23 +56,23 @@ namespace RTC if (!this->recvTransportId.empty()) { - std::cout << ", \"recvTransportId\": \"" << this->recvTransportId << "\""; + std::cout << R"(, "recvTransportId": ")" << this->recvTransportId << "\""; } if (!this->sendTransportId.empty()) { - std::cout << ", \"sendTransportId\": \"" << this->sendTransportId << "\""; + std::cout << R"(, "sendTransportId": ")" << this->sendTransportId << "\""; } if (!this->routerId.empty()) { - std::cout << ", \"routerId\": \"" << this->routerId << "\""; + std::cout << R"(, "routerId": ")" << this->routerId << "\""; } if (!this->producerId.empty()) { - std::cout << ", \"producerId\": \"" << this->producerId << "\""; + std::cout << R"(, "producerId": ")" << this->producerId << "\""; } if (!this->consumerId.empty()) { - std::cout << ", \"consumerId\": \"" << this->consumerId << "\""; + std::cout << R"(, "consumerId": ")" << this->consumerId << "\""; } std::cout << ", \"recvRtpTimestamp\": " << this->recvRtpTimestamp; diff --git a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp index 96e0e3a6a7..636e175b69 100644 --- a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp @@ -3,7 +3,6 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC diff --git a/worker/src/RTC/SctpAssociation.cpp b/worker/src/RTC/SctpAssociation.cpp index 2c2da971f1..499ec2a053 100644 --- a/worker/src/RTC/SctpAssociation.cpp +++ b/worker/src/RTC/SctpAssociation.cpp @@ -127,6 +127,7 @@ namespace RTC int ret; + // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer) this->socket = usrsctp_socket( AF_CONN, SOCK_STREAM, diff --git a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp index c99947c61e..6a2d6fa8d6 100644 --- a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp +++ b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp @@ -3,7 +3,6 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/SctpDictionaries.hpp" namespace RTC diff --git a/worker/src/RTC/SeqManager.cpp b/worker/src/RTC/SeqManager.cpp index 35ebc2db27..2a7bad5cdc 100644 --- a/worker/src/RTC/SeqManager.cpp +++ b/worker/src/RTC/SeqManager.cpp @@ -8,14 +8,14 @@ namespace RTC { template - bool SeqManager::SeqLowerThan::operator()(const T lhs, const T rhs) const + bool SeqManager::SeqLowerThan::operator()(T lhs, T rhs) const { return ((rhs > lhs) && (rhs - lhs <= MaxValue / 2)) || ((lhs > rhs) && (lhs - rhs > MaxValue / 2)); } template - bool SeqManager::SeqHigherThan::operator()(const T lhs, const T rhs) const + bool SeqManager::SeqHigherThan::operator()(T lhs, T rhs) const { return ((lhs > rhs) && (lhs - rhs <= MaxValue / 2)) || ((rhs > lhs) && (rhs - lhs > MaxValue / 2)); @@ -28,13 +28,13 @@ namespace RTC const typename SeqManager::SeqHigherThan SeqManager::isSeqHigherThan{}; template - bool SeqManager::IsSeqLowerThan(const T lhs, const T rhs) + bool SeqManager::IsSeqLowerThan(T lhs, T rhs) { return isSeqLowerThan(lhs, rhs); } template - bool SeqManager::IsSeqHigherThan(const T lhs, const T rhs) + bool SeqManager::IsSeqHigherThan(T lhs, T rhs) { return isSeqHigherThan(lhs, rhs); } @@ -69,7 +69,7 @@ namespace RTC } template - bool SeqManager::Input(const T input, T& output) + bool SeqManager::Input(T input, T& output) { auto base = this->base; diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index 66c7a75c23..6151a1c0b8 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -5,7 +5,6 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/Codecs/Tools.hpp" namespace RTC diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 487343e29f..1e1bbedab3 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -2260,6 +2260,7 @@ namespace RTC auto* consumer = it->second; auto bweType = this->tccClient->GetBweType(); + // NOLINTNEXTLINE(bugprone-too-small-loop-variable) for (uint8_t i{ 1u }; i <= (baseAllocation ? 1u : priority); ++i) { uint32_t usedBitrate{ 0u }; diff --git a/worker/src/Settings.cpp b/worker/src/Settings.cpp index 7aa0006d85..abde2f9c07 100644 --- a/worker/src/Settings.cpp +++ b/worker/src/Settings.cpp @@ -24,14 +24,14 @@ static std::mutex GlobalSyncMutex; thread_local struct Settings::Configuration Settings::configuration; // clang-format off -absl::flat_hash_map Settings::string2LogLevel = +absl::flat_hash_map Settings::String2LogLevel = { { "debug", LogLevel::LOG_DEBUG }, { "warn", LogLevel::LOG_WARN }, { "error", LogLevel::LOG_ERROR }, { "none", LogLevel::LOG_NONE } }; -absl::flat_hash_map Settings::logLevel2String = +absl::flat_hash_map Settings::LogLevel2String = { { LogLevel::LOG_DEBUG, "debug" }, { LogLevel::LOG_WARN, "warn" }, @@ -275,7 +275,7 @@ void Settings::PrintConfiguration() MS_DEBUG_TAG( info, " logLevel : %s", - Settings::logLevel2String[Settings::configuration.logLevel].c_str()); + Settings::LogLevel2String[Settings::configuration.logLevel].c_str()); MS_DEBUG_TAG(info, " logTags : %s", logTagsStream.str().c_str()); MS_DEBUG_TAG(info, " rtcMinPort : %" PRIu16, Settings::configuration.rtcMinPort); MS_DEBUG_TAG(info, " rtcMaxPort : %" PRIu16, Settings::configuration.rtcMaxPort); @@ -348,12 +348,12 @@ void Settings::SetLogLevel(std::string& level) // Lowcase given level. Utils::String::ToLowerCase(level); - if (Settings::string2LogLevel.find(level) == Settings::string2LogLevel.end()) + if (Settings::String2LogLevel.find(level) == Settings::String2LogLevel.end()) { MS_THROW_TYPE_ERROR("invalid value '%s' for logLevel", level.c_str()); } - Settings::configuration.logLevel = Settings::string2LogLevel[level]; + Settings::configuration.logLevel = Settings::String2LogLevel[level]; } void Settings::SetLogTags(const std::vector& tags) diff --git a/worker/src/Utils/Crypto.cpp b/worker/src/Utils/Crypto.cpp index 45dc91a6fa..e5c696efaf 100644 --- a/worker/src/Utils/Crypto.cpp +++ b/worker/src/Utils/Crypto.cpp @@ -14,7 +14,7 @@ namespace Utils thread_local EVP_MAC_CTX* Crypto::hmacSha1Ctx{ nullptr }; thread_local uint8_t Crypto::hmacSha1Buffer[SHA_DIGEST_LENGTH]; // clang-format off - const uint32_t Crypto::crc32Table[] = + const uint32_t Crypto::Crc32Table[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, diff --git a/worker/src/Utils/String.cpp b/worker/src/Utils/String.cpp index 77fe74c0ca..b29042f31e 100644 --- a/worker/src/Utils/String.cpp +++ b/worker/src/Utils/String.cpp @@ -77,7 +77,7 @@ namespace Utils *pos++ = '='; } - return std::string(reinterpret_cast(out), pos - out); + return { reinterpret_cast(out), static_cast(pos - out) }; } std::string Utils::String::Base64Encode(const std::string& str) diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index faef45fbf3..1bd5468f88 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -312,7 +312,7 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) { const auto* const body = request->data->body_as(); - std::string webRtcServerId = body->webRtcServerId()->str(); + const std::string webRtcServerId = body->webRtcServerId()->str(); CheckNoWebRtcServer(webRtcServerId); diff --git a/worker/src/handles/TcpConnectionHandle.cpp b/worker/src/handles/TcpConnectionHandle.cpp index a35c7f9b79..ae2ded0d9c 100644 --- a/worker/src/handles/TcpConnectionHandle.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -187,6 +187,7 @@ void TcpConnectionHandle::Start() return; } + // NOLINTNEXTLINE(misc-const-correctness) int err = uv_read_start( reinterpret_cast(this->uvHandle), static_cast(onAlloc), diff --git a/worker/src/handles/UdpSocketHandle.cpp b/worker/src/handles/UdpSocketHandle.cpp index 60a0041d66..471d28366f 100644 --- a/worker/src/handles/UdpSocketHandle.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -66,11 +66,10 @@ UdpSocketHandle::UdpSocketHandle(uv_udp_t* uvHandle) : uvHandle(uvHandle) { MS_TRACE(); - int err; - this->uvHandle->data = static_cast(this); - err = uv_udp_recv_start( + // NOLINTNEXTLINE(misc-const-correctness) + int err = uv_udp_recv_start( this->uvHandle, static_cast(onAlloc), static_cast(onRecv)); if (err != 0) diff --git a/worker/tasks.py b/worker/tasks.py index e0c91b7630..2db0b2e820 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -441,10 +441,22 @@ def tidy(ctx): Perform C++ checks with clang-tidy """ mediasoup_tidy_checks = os.getenv('MEDIASOUP_TIDY_CHECKS') or ''; + mediasoup_tidy_files = os.getenv('MEDIASOUP_TIDY_FILES') or ''; + mediasoup_clang_tidy_dir = os.getenv('MEDIASOUP_CLANG_TIDY_DIR'); + + if not mediasoup_clang_tidy_dir: + print('missing MEDIASOUP_CLANG_TIDY_DIR env varialbe'); + return; + + if mediasoup_tidy_checks: + mediasoup_tidy_checks = '-*,' + mediasoup_tidy_checks; + + if not mediasoup_tidy_files: + mediasoup_tidy_files = 'src/*.cpp src/**/*.cpp src/**/**.cpp'; with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( - f'"{PYTHON}" ./scripts/clang-tidy.py -clang-tidy-binary=./scripts/node_modules/.bin/clang-tidy -clang-apply-replacements-binary=./scripts/node_modules/.bin/clang-apply-replacements -header-filter="(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|handles/**/*.hpp)" -p="{BUILD_DIR}" -j={NUM_CORES} -checks={mediasoup_tidy_checks} -quiet', + f'"{PYTHON}" "{mediasoup_clang_tidy_dir}/run-clang-tidy" -clang-tidy-binary="{mediasoup_clang_tidy_dir}/clang-tidy" -clang-apply-replacements-binary="{mediasoup_clang_tidy_dir}/clang-apply-replacements" -p=./ -j={NUM_CORES} -fix -checks={mediasoup_tidy_checks} {mediasoup_tidy_files}', echo=True, pty=PTY_SUPPORTED, shell=SHELL From ab358a7997e498ea9aebaf12eeed2226df83ed56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 00:35:11 +0100 Subject: [PATCH 315/525] 3.13.16 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df1131be4e..afa31f1bc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### NEXT +### 3.13.16 - Node: Add new `worker.on('subprocessclose')` event ([PR #1307](https://github.com/versatica/mediasoup/pull/1307)). diff --git a/package-lock.json b/package-lock.json index a3f877a0b1..9ecdf256c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.15", + "version": "3.13.16", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.15", + "version": "3.13.16", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index f1b0da9c75..d475ca9ede 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.15", + "version": "3.13.16", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From b0007e0c71beed8bbc1243301a95002319fb822f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 13:28:30 +0100 Subject: [PATCH 316/525] doc/Building.md: cosmetic --- doc/Building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Building.md b/doc/Building.md index 6d5ab153f2..92d9351e82 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -200,7 +200,7 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy) and performs C++ code - `invoke clean` and `invoke mediasoup-worker` must have been called first. - [PyYAML](https://pyyaml.org) is required. - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. -- [clang-tools-extra](https://clang.llvm.org/extra/index.html) is required. +- [clang-tools-extra](https://clang.llvm.org/extra) is required. - In OSX install it with `brew install clang-tools-extra`. - In linux the package name is `clang-tools-extra`. From fefe6d6ef8a6fe6cf5a518bc5176be7b11f29a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 13:35:32 +0100 Subject: [PATCH 317/525] doc/Building.md: cosmetic --- doc/Building.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/Building.md b/doc/Building.md index 92d9351e82..5f46c5d3c1 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -204,11 +204,11 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy) and performs C++ code - In OSX install it with `brew install clang-tools-extra`. - In linux the package name is `clang-tools-extra`. -**Environment variables** +**Environment variables:** -- "MEDIASOUP_TIDY_CHECKS": comma separated list of checks. Overrides the checks defined in `.clang-tidy` file. -- "MEDIASOUP_TIDY_FILES": space separated source files to process, including their path. All .cpp files will be processes by default. -- "MEDIASOUP_CLANG_TIDY_DIR": path to directory containing clang tools (run-clang-tidy, clang-tidy, clang-apply-replacements). +- "MEDIASOUP_TIDY_CHECKS": Comma separated list of checks. Overrides the checks defined in `worker/.clang-tidy` file. +- "MEDIASOUP_TIDY_FILES": Space separated source files to process, including their path. All `.cpp` files will be processes by default. +- "MEDIASOUP_CLANG_TIDY_DIR": Path to directory containing clang tools (`run-clang-tidy`, `clang-tidy`, `clang-apply-replacements`). ### `invoke fuzzer` From 8f640d0bb686bd1d8205b9f5d3eb3c353526ab6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 15:43:15 +0100 Subject: [PATCH 318/525] doc/Building.md: Fix clang-tools-extra installation in macOS --- doc/Building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Building.md b/doc/Building.md index 5f46c5d3c1..cacf526c53 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -201,7 +201,7 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy) and performs C++ code - [PyYAML](https://pyyaml.org) is required. - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. - [clang-tools-extra](https://clang.llvm.org/extra) is required. - - In OSX install it with `brew install clang-tools-extra`. + - In OSX install it with `brew install llvm`. - In linux the package name is `clang-tools-extra`. **Environment variables:** From cd41008dcd3a21bf0ffcc1992c680db6ef192ba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 16:21:02 +0100 Subject: [PATCH 319/525] doc/Building.md: improve 'invoke tidy' doc --- doc/Building.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/Building.md b/doc/Building.md index cacf526c53..66b8cd17e8 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -153,7 +153,7 @@ Check the meaning of useful macros in the `worker/include/Logger.hpp` header fil Binary is built at `worker/out/MEDIASOUP_BUILDTYPE/build`. -In order to instruct the mediasoup Node.js module to use the "Debug"` `mediasoup-worker` binary, an environment variable must be set before running the Node.js application: +In order to instruct the mediasoup Node.js module to use the "Debug" mediasoup-worker` binary, an environment variable must be set before running the Node.js application: ```bash MEDIASOUP_BUILDTYPE=Debug node myapp.js @@ -198,8 +198,6 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy) and performs C++ code **Requirements:** - `invoke clean` and `invoke mediasoup-worker` must have been called first. -- [PyYAML](https://pyyaml.org) is required. - - In OSX install it with `brew install libyaml` and `sudo easy_install-X.Y pyyaml`. - [clang-tools-extra](https://clang.llvm.org/extra) is required. - In OSX install it with `brew install llvm`. - In linux the package name is `clang-tools-extra`. @@ -210,6 +208,12 @@ Runs [clang-tidy](http://clang.llvm.org/extra/clang-tidy) and performs C++ code - "MEDIASOUP_TIDY_FILES": Space separated source files to process, including their path. All `.cpp` files will be processes by default. - "MEDIASOUP_CLANG_TIDY_DIR": Path to directory containing clang tools (`run-clang-tidy`, `clang-tidy`, `clang-apply-replacements`). +**Usage example in macOS:** + +```bash +MEDIASOUP_CLANG_TIDY_DIR=/usr/local/opt/llvm/bin invoke tidy +``` + ### `invoke fuzzer` Builds the `mediasoup-worker-fuzzer` binary (which uses [libFuzzer](http://llvm.org/docs/LibFuzzer.html)) at `worker/out/Release` (or at `worker/out/Debug/` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"). @@ -217,8 +221,8 @@ Builds the `mediasoup-worker-fuzzer` binary (which uses [libFuzzer](http://llvm. **Requirements:** - Linux with fuzzer capable clang++. -- `CC` environment variable must point to "clang". -- `CXX` environment variable must point to "clang++". +- "CC" environment variable must point to `clang`. +- "CXX" environment variable must point to `clang++`. Read the [Fuzzer](Fuzzer.md) documentation for detailed information. From fc508d67a2470e6382c5b7b4921721a9c4ad6d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 16:21:39 +0100 Subject: [PATCH 320/525] Make 'invoke tidy' read the proper build compile_commands.json file --- worker/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/tasks.py b/worker/tasks.py index 2db0b2e820..1a34589187 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -456,7 +456,7 @@ def tidy(ctx): with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( - f'"{PYTHON}" "{mediasoup_clang_tidy_dir}/run-clang-tidy" -clang-tidy-binary="{mediasoup_clang_tidy_dir}/clang-tidy" -clang-apply-replacements-binary="{mediasoup_clang_tidy_dir}/clang-apply-replacements" -p=./ -j={NUM_CORES} -fix -checks={mediasoup_tidy_checks} {mediasoup_tidy_files}', + f'"{PYTHON}" "{mediasoup_clang_tidy_dir}/run-clang-tidy" -clang-tidy-binary="{mediasoup_clang_tidy_dir}/clang-tidy" -clang-apply-replacements-binary="{mediasoup_clang_tidy_dir}/clang-apply-replacements" -p="{BUILD_DIR}" -j={NUM_CORES} -fix -checks={mediasoup_tidy_checks} {mediasoup_tidy_files}', echo=True, pty=PTY_SUPPORTED, shell=SHELL From 9990d11d00c54a97b7b6554322a4721a543793f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 16:23:16 +0100 Subject: [PATCH 321/525] Update npm ts eslint deps --- package-lock.json | 28 ++++++++++++++-------------- package.json | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9ecdf256c9..71123e5af9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,8 +26,8 @@ "@typescript-eslint/parser": "^6.18.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.6.1", - "eslint-plugin-prettier": "^5.1.2", + "eslint-plugin-jest": "^27.6.2", + "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^11.1.1", "open-cli": "^7.2.0", @@ -3178,9 +3178,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.6.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", - "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", + "version": "27.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.2.tgz", + "integrity": "sha512-CI1AlKrsNhYFoP48VU8BVWOi7+qHTq4bRxyUlGjeU8SfFt8abjXhjOuDzUoMp68DoXIx17KpNpIkMrl4s4ZW0g==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -3203,9 +3203,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", - "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", @@ -9274,18 +9274,18 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "27.6.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", - "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", + "version": "27.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.2.tgz", + "integrity": "sha512-CI1AlKrsNhYFoP48VU8BVWOi7+qHTq4bRxyUlGjeU8SfFt8abjXhjOuDzUoMp68DoXIx17KpNpIkMrl4s4ZW0g==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" } }, "eslint-plugin-prettier": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", - "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0", diff --git a/package.json b/package.json index d475ca9ede..58f1bfc861 100644 --- a/package.json +++ b/package.json @@ -116,8 +116,8 @@ "@typescript-eslint/parser": "^6.18.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.6.1", - "eslint-plugin-prettier": "^5.1.2", + "eslint-plugin-jest": "^27.6.2", + "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^11.1.1", "open-cli": "^7.2.0", From 6b13b8e898f8854acc8fa0e5335139b0ab8d697f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 16:35:02 +0100 Subject: [PATCH 322/525] .clang-tidy: exclude 'misc-include-cleaner' option https://clang.llvm.org/extra/clang-tidy/checks/misc/include-cleaner.html Because it warns when a cpp file uses a symbol exported by an include file not directly included in that cpp file, which is something we do (and want to do) all the time. --- worker/.clang-tidy | 1 + 1 file changed, 1 insertion(+) diff --git a/worker/.clang-tidy b/worker/.clang-tidy index f66b8de82c..036fdac6c5 100644 --- a/worker/.clang-tidy +++ b/worker/.clang-tidy @@ -50,6 +50,7 @@ Checks: "*,\ -llvm-else-after-return,\ -llvmlibc-*,\ -misc-confusable-identifiers,\ + -misc-include-cleaner,\ -misc-non-private-member-variables-in-classes,\ -misc-use-anonymous-namespace,\ -modernize-avoid-c-arrays,\ From 70455fa6da4f74737ff91c51a6b0848153957e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 16:38:19 +0100 Subject: [PATCH 323/525] Remove useless worker/.clang-tidy-ignore file --- worker/.clang-tidy-ignore | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 worker/.clang-tidy-ignore diff --git a/worker/.clang-tidy-ignore b/worker/.clang-tidy-ignore deleted file mode 100644 index 82186c89a4..0000000000 --- a/worker/.clang-tidy-ignore +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore subprojects folder. -/subprojects From e2e7754ba6f59d9740c6a07f36ea42895151eafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 16:40:03 +0100 Subject: [PATCH 324/525] clang-tidy: exclude 'concurrency-mt-unsafe' rule since we don't use threads --- worker/.clang-tidy | 1 + 1 file changed, 1 insertion(+) diff --git a/worker/.clang-tidy b/worker/.clang-tidy index 036fdac6c5..d079f6afe6 100644 --- a/worker/.clang-tidy +++ b/worker/.clang-tidy @@ -11,6 +11,7 @@ Checks: "*,\ -cert-*,\ -clang-analyzer-optin.osx.*,\ -clang-analyzer-osx.*,\ + -concurrency-mt-unsafe,\ -cppcoreguidelines-avoid-c-arrays,\ -cppcoreguidelines-avoid-do-while,\ -cppcoreguidelines-avoid-goto,\ From 5caabfd7116a3287335eeec157d8cca0de3c1394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 16:58:17 +0100 Subject: [PATCH 325/525] invoke tidy: exit with error if MEDIASOUP_CLANG_TIDY_DIR is not given Another alternative is `raise Exception(text)` but produces terrible output --- worker/tasks.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/worker/tasks.py b/worker/tasks.py index 1a34589187..a99f74cf5c 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -444,9 +444,10 @@ def tidy(ctx): mediasoup_tidy_files = os.getenv('MEDIASOUP_TIDY_FILES') or ''; mediasoup_clang_tidy_dir = os.getenv('MEDIASOUP_CLANG_TIDY_DIR'); + # MEDIASOUP_CLANG_TIDY_DIR env variable is mandatory. + # NOTE: sys.exit(text) exists the program with status code 1. if not mediasoup_clang_tidy_dir: - print('missing MEDIASOUP_CLANG_TIDY_DIR env varialbe'); - return; + sys.exit('missing MEDIASOUP_CLANG_TIDY_DIR env variable'); if mediasoup_tidy_checks: mediasoup_tidy_checks = '-*,' + mediasoup_tidy_checks; From f7de6a20c7078c98516e4acd7608686692904609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Wed, 10 Jan 2024 17:18:57 +0100 Subject: [PATCH 326/525] C++: remove unused include directives (#1309) --- worker/src/DepLibUV.cpp | 1 - worker/src/RTC/ActiveSpeakerObserver.cpp | 1 - worker/src/RTC/AudioLevelObserver.cpp | 2 -- worker/src/RTC/Consumer.cpp | 2 -- worker/src/RTC/DataConsumer.cpp | 2 -- worker/src/RTC/DataProducer.cpp | 2 -- worker/src/RTC/DirectTransport.cpp | 1 - worker/src/RTC/IceServer.cpp | 4 +--- worker/src/RTC/PipeConsumer.cpp | 4 +--- worker/src/RTC/Producer.cpp | 7 ++----- worker/src/RTC/RTCP/Feedback.cpp | 1 - worker/src/RTC/RTCP/FeedbackPsFir.cpp | 1 - worker/src/RTC/RTCP/FeedbackPsSli.cpp | 1 - worker/src/RTC/RTCP/FeedbackPsTst.cpp | 2 +- worker/src/RTC/RTCP/FeedbackPsVbcm.cpp | 2 +- worker/src/RTC/RTCP/FeedbackRtpEcn.cpp | 2 +- worker/src/RTC/RTCP/FeedbackRtpNack.cpp | 4 ++-- worker/src/RTC/RTCP/FeedbackRtpTllei.cpp | 2 +- worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp | 1 - worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 3 +-- worker/src/RTC/RTCP/ReceiverReport.cpp | 2 +- worker/src/RTC/RTCP/Sdes.cpp | 2 +- worker/src/RTC/RTCP/SenderReport.cpp | 2 +- worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp | 2 +- worker/src/RTC/RTCP/XrReceiverReferenceTime.cpp | 2 +- worker/src/RTC/Router.cpp | 1 - worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp | 1 - worker/src/RTC/RtpDictionaries/RtcpParameters.cpp | 2 -- worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp | 1 - worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp | 1 - worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp | 1 - worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp | 2 -- worker/src/RTC/RtpProbationGenerator.cpp | 1 - worker/src/RTC/RtpStreamSend.cpp | 1 - worker/src/RTC/SenderBandwidthEstimator.cpp | 1 - worker/src/RTC/SvcConsumer.cpp | 1 - worker/src/RTC/Transport.cpp | 1 - worker/src/RTC/TransportCongestionControlClient.cpp | 1 - worker/src/lib.cpp | 1 - 39 files changed, 16 insertions(+), 55 deletions(-) diff --git a/worker/src/DepLibUV.cpp b/worker/src/DepLibUV.cpp index 2871895033..12af49ba59 100644 --- a/worker/src/DepLibUV.cpp +++ b/worker/src/DepLibUV.cpp @@ -3,7 +3,6 @@ #include "DepLibUV.hpp" #include "Logger.hpp" -#include // std::abort() /* Static variables. */ diff --git a/worker/src/RTC/ActiveSpeakerObserver.cpp b/worker/src/RTC/ActiveSpeakerObserver.cpp index ff27d63d67..a858c84615 100644 --- a/worker/src/RTC/ActiveSpeakerObserver.cpp +++ b/worker/src/RTC/ActiveSpeakerObserver.cpp @@ -3,7 +3,6 @@ #include "RTC/ActiveSpeakerObserver.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC diff --git a/worker/src/RTC/AudioLevelObserver.cpp b/worker/src/RTC/AudioLevelObserver.cpp index 126a3ac72d..0b880d88af 100644 --- a/worker/src/RTC/AudioLevelObserver.cpp +++ b/worker/src/RTC/AudioLevelObserver.cpp @@ -4,10 +4,8 @@ #include "RTC/AudioLevelObserver.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" #include // std::lround() -#include namespace RTC { diff --git a/worker/src/RTC/Consumer.cpp b/worker/src/RTC/Consumer.cpp index 84cda670ec..7ab2699645 100644 --- a/worker/src/RTC/Consumer.cpp +++ b/worker/src/RTC/Consumer.cpp @@ -5,8 +5,6 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include // std::ostream_iterator -#include // std::ostringstream namespace RTC { diff --git a/worker/src/RTC/DataConsumer.cpp b/worker/src/RTC/DataConsumer.cpp index b54ce8c5cc..1aaf97df12 100644 --- a/worker/src/RTC/DataConsumer.cpp +++ b/worker/src/RTC/DataConsumer.cpp @@ -5,9 +5,7 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/SctpAssociation.hpp" -#include namespace RTC { diff --git a/worker/src/RTC/DataProducer.cpp b/worker/src/RTC/DataProducer.cpp index 136f0bdbf9..eebd66ebec 100644 --- a/worker/src/RTC/DataProducer.cpp +++ b/worker/src/RTC/DataProducer.cpp @@ -5,8 +5,6 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" -#include #include namespace RTC diff --git a/worker/src/RTC/DirectTransport.cpp b/worker/src/RTC/DirectTransport.cpp index d0f0b9d118..435c4b406b 100644 --- a/worker/src/RTC/DirectTransport.cpp +++ b/worker/src/RTC/DirectTransport.cpp @@ -3,7 +3,6 @@ #include "RTC/DirectTransport.hpp" #include "Logger.hpp" -#include "MediaSoupErrors.hpp" namespace RTC { diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index 1584f8b54b..88e8b1af20 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -1,10 +1,8 @@ #define MS_CLASS "RTC::IceServer" // #define MS_LOG_DEV_LEVEL 3 -#include - -#include "Logger.hpp" #include "RTC/IceServer.hpp" +#include "Logger.hpp" namespace RTC { diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index 4b43242ce7..2312ed87c9 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -1,12 +1,10 @@ -#include "FBS/consumer.h" #define MS_CLASS "RTC::PipeConsumer" // #define MS_LOG_DEV_LEVEL 3 -#include "DepLibUV.hpp" +#include "RTC/PipeConsumer.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "RTC/Codecs/Tools.hpp" -#include "RTC/PipeConsumer.hpp" namespace RTC { diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index c465152d6c..4e2a4a90b7 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -7,13 +7,10 @@ #include "MediaSoupErrors.hpp" #include "Utils.hpp" #include "RTC/Codecs/Tools.hpp" -#include "RTC/RTCP/FeedbackPs.hpp" -#include "RTC/RTCP/FeedbackRtp.hpp" +#include "RTC/RTCP/Feedback.hpp" #include "RTC/RTCP/XrReceiverReferenceTime.hpp" #include -#include // std::memcpy() -#include // std::ostream_iterator -#include // std::ostringstream +#include // std::memcpy() namespace RTC { diff --git a/worker/src/RTC/RTCP/Feedback.cpp b/worker/src/RTC/RTCP/Feedback.cpp index 0ba7d01a7e..4286556457 100644 --- a/worker/src/RTC/RTCP/Feedback.cpp +++ b/worker/src/RTC/RTCP/Feedback.cpp @@ -3,7 +3,6 @@ #include "RTC/RTCP/Feedback.hpp" #include "Logger.hpp" -#include "Utils.hpp" #include "RTC/RTCP/FeedbackPsAfb.hpp" #include "RTC/RTCP/FeedbackPsFir.hpp" #include "RTC/RTCP/FeedbackPsLei.hpp" diff --git a/worker/src/RTC/RTCP/FeedbackPsFir.cpp b/worker/src/RTC/RTCP/FeedbackPsFir.cpp index 1cc6656c9d..ee69ac635c 100644 --- a/worker/src/RTC/RTCP/FeedbackPsFir.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsFir.cpp @@ -3,7 +3,6 @@ #include "RTC/RTCP/FeedbackPsFir.hpp" #include "Logger.hpp" -#include #include // std::memset() namespace RTC diff --git a/worker/src/RTC/RTCP/FeedbackPsSli.cpp b/worker/src/RTC/RTCP/FeedbackPsSli.cpp index 23516def7c..085b60e330 100644 --- a/worker/src/RTC/RTCP/FeedbackPsSli.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsSli.cpp @@ -3,7 +3,6 @@ #include "RTC/RTCP/FeedbackPsSli.hpp" #include "Logger.hpp" -#include namespace RTC { diff --git a/worker/src/RTC/RTCP/FeedbackPsTst.cpp b/worker/src/RTC/RTCP/FeedbackPsTst.cpp index 4f27b3156a..72160665f6 100644 --- a/worker/src/RTC/RTCP/FeedbackPsTst.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsTst.cpp @@ -3,7 +3,7 @@ #include "RTC/RTCP/FeedbackPsTst.hpp" #include "Logger.hpp" -#include +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp b/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp index d57c86e56a..b40029467c 100644 --- a/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp @@ -3,7 +3,7 @@ #include "RTC/RTCP/FeedbackPsVbcm.hpp" #include "Logger.hpp" -#include +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/RTCP/FeedbackRtpEcn.cpp b/worker/src/RTC/RTCP/FeedbackRtpEcn.cpp index 096d0c9084..a6adc3d91a 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpEcn.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpEcn.cpp @@ -3,7 +3,7 @@ #include "RTC/RTCP/FeedbackRtpEcn.hpp" #include "Logger.hpp" -#include +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/RTCP/FeedbackRtpNack.cpp b/worker/src/RTC/RTCP/FeedbackRtpNack.cpp index f0e153cd15..d119044d8a 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpNack.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpNack.cpp @@ -3,8 +3,8 @@ #include "RTC/RTCP/FeedbackRtpNack.hpp" #include "Logger.hpp" -#include // std::bitset() -#include +#include // std::bitset() +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/RTCP/FeedbackRtpTllei.cpp b/worker/src/RTC/RTCP/FeedbackRtpTllei.cpp index d02b9eed61..4f7087dace 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTllei.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTllei.cpp @@ -3,7 +3,7 @@ #include "RTC/RTCP/FeedbackRtpTllei.hpp" #include "Logger.hpp" -#include +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp b/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp index cd6a0b6e87..fe998f8975 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp @@ -4,7 +4,6 @@ #include "RTC/RTCP/FeedbackRtpTmmb.hpp" #include "Logger.hpp" #include "Utils.hpp" -#include namespace RTC { diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index a732cafcfd..0ec398cf12 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -5,8 +5,7 @@ #include "Logger.hpp" #include "Utils.hpp" #include "RTC/SeqManager.hpp" -#include // std::numeric_limits() -#include +#include // std::ostringstream namespace RTC { diff --git a/worker/src/RTC/RTCP/ReceiverReport.cpp b/worker/src/RTC/RTCP/ReceiverReport.cpp index 4ca41739e5..de873b340c 100644 --- a/worker/src/RTC/RTCP/ReceiverReport.cpp +++ b/worker/src/RTC/RTCP/ReceiverReport.cpp @@ -4,7 +4,7 @@ #include "RTC/RTCP/ReceiverReport.hpp" #include "Logger.hpp" #include "Utils.hpp" -#include +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/RTCP/Sdes.cpp b/worker/src/RTC/RTCP/Sdes.cpp index 222aa1f13d..3d5e9fe373 100644 --- a/worker/src/RTC/RTCP/Sdes.cpp +++ b/worker/src/RTC/RTCP/Sdes.cpp @@ -4,7 +4,7 @@ #include "RTC/RTCP/Sdes.hpp" #include "Logger.hpp" #include "Utils.hpp" -#include +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/RTCP/SenderReport.cpp b/worker/src/RTC/RTCP/SenderReport.cpp index 510ecc06c6..ed51124b88 100644 --- a/worker/src/RTC/RTCP/SenderReport.cpp +++ b/worker/src/RTC/RTCP/SenderReport.cpp @@ -3,7 +3,7 @@ #include "RTC/RTCP/SenderReport.hpp" #include "Logger.hpp" -#include +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp b/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp index a626e6e175..5b3a9b5dd4 100644 --- a/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp +++ b/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp @@ -3,7 +3,7 @@ #include "RTC/RTCP/XrDelaySinceLastRr.hpp" #include "Logger.hpp" -#include +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/RTCP/XrReceiverReferenceTime.cpp b/worker/src/RTC/RTCP/XrReceiverReferenceTime.cpp index 674595296f..3a93026bf2 100644 --- a/worker/src/RTC/RTCP/XrReceiverReferenceTime.cpp +++ b/worker/src/RTC/RTCP/XrReceiverReferenceTime.cpp @@ -3,7 +3,7 @@ #include "RTC/RTCP/XrReceiverReferenceTime.hpp" #include "Logger.hpp" -#include +#include // std::memcpy namespace RTC { diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index d5fe22e621..fab0173952 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -7,7 +7,6 @@ #endif #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/ActiveSpeakerObserver.hpp" #include "RTC/AudioLevelObserver.hpp" #include "RTC/DirectTransport.hpp" diff --git a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp index 1b735e9c8d..6f132a8dc5 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp @@ -2,7 +2,6 @@ // #define MS_LOG_DEV_LEVEL 3 #include "Logger.hpp" -#include "MediaSoupErrors.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp index 7766cf3881..d9283771d1 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp @@ -2,8 +2,6 @@ // #define MS_LOG_DEV_LEVEL 3 #include "Logger.hpp" -#include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp index 024e4229d0..b0fc5001cc 100644 --- a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp @@ -3,7 +3,6 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp index ec79f515bf..ccab2e2f37 100644 --- a/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp @@ -3,7 +3,6 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" #include #include diff --git a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp index 051e42f5ae..d8c90e5641 100644 --- a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp @@ -2,7 +2,6 @@ // #define MS_LOG_DEV_LEVEL 3 #include "Logger.hpp" -#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp index 41272388b1..3e760bb581 100644 --- a/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp @@ -2,8 +2,6 @@ // #define MS_LOG_DEV_LEVEL 3 #include "Logger.hpp" -#include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC diff --git a/worker/src/RTC/RtpProbationGenerator.cpp b/worker/src/RTC/RtpProbationGenerator.cpp index 959bf7470a..e6f9a6dd92 100644 --- a/worker/src/RTC/RtpProbationGenerator.cpp +++ b/worker/src/RTC/RtpProbationGenerator.cpp @@ -2,7 +2,6 @@ // #define MS_LOG_DEV_LEVEL 3 #include "RTC/RtpProbationGenerator.hpp" -#include "DepLibUV.hpp" #include "Logger.hpp" #include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 3fceb890d1..79875ce9c3 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -8,7 +8,6 @@ #include "Logger.hpp" #include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" -#include "RTC/SeqManager.hpp" namespace RTC { diff --git a/worker/src/RTC/SenderBandwidthEstimator.cpp b/worker/src/RTC/SenderBandwidthEstimator.cpp index 834c21ea35..6b02411428 100644 --- a/worker/src/RTC/SenderBandwidthEstimator.cpp +++ b/worker/src/RTC/SenderBandwidthEstimator.cpp @@ -4,7 +4,6 @@ #include "RTC/SenderBandwidthEstimator.hpp" #include "DepLibUV.hpp" #include "Logger.hpp" -#include namespace RTC { diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index 1140d0c517..24ddf2418c 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -5,7 +5,6 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" #include "RTC/Codecs/Tools.hpp" namespace RTC diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 1e1bbedab3..830b31ddb7 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -26,7 +26,6 @@ #include // webrtc::RtpPacketSendInfo #include // std::ostream_iterator #include // std::multimap -#include // std::ostringstream namespace RTC { diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index 98ddd17286..e6622b75e6 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -5,7 +5,6 @@ #include "RTC/TransportCongestionControlClient.hpp" #include "DepLibUV.hpp" #include "Logger.hpp" -#include "MediaSoupErrors.hpp" #include // webrtc::TargetRateConstraints #include diff --git a/worker/src/lib.cpp b/worker/src/lib.cpp index 8ea2572b6a..d4f7a253b0 100644 --- a/worker/src/lib.cpp +++ b/worker/src/lib.cpp @@ -20,7 +20,6 @@ #include "RTC/SrtpSession.hpp" #include #include -#include #include // sigaction() #include From 561a34154dcfc0fa766c8abd6ddddb95d8c18e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Jan 2024 18:16:29 +0100 Subject: [PATCH 327/525] CI codeql.yaml: use custom build instead of reyling on autodetected Autobuild ssytem (#1310) --- .github/workflows/codeql.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 3e65363d6e..16712fe8d3 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -41,6 +41,7 @@ jobs: env: MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' + MEDIASOUP_LOCAL_DEV: 'true' steps: - name: Checkout repository @@ -60,14 +61,10 @@ jobs: # https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality - # We need to install pip invoke library. - - name: pip3 install invoke - run: pip3 install invoke - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v3 + # - name: Autobuild + # uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -80,6 +77,11 @@ jobs: # echo "Run, Build Application using script" # ./location_of_script_within_repo/buildscript.sh + # Use npm ci to build mediasoup Node and worker instead of relying on + # Autobuild. + - name: npm ci + run: npm ci --foreground-scripts + - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: From 07ea35febe2e22a2d4f843e001d24f9ab4d2a0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Wed, 10 Jan 2024 18:16:44 +0100 Subject: [PATCH 328/525] C++: Add NOLINT rules for unwanted changes (#1311) --- worker/include/handles/UdpSocketHandle.hpp | 2 -- worker/src/handles/UdpSocketHandle.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/worker/include/handles/UdpSocketHandle.hpp b/worker/include/handles/UdpSocketHandle.hpp index 8a4085c33f..2b7a708105 100644 --- a/worker/include/handles/UdpSocketHandle.hpp +++ b/worker/include/handles/UdpSocketHandle.hpp @@ -84,10 +84,8 @@ class UdpSocketHandle /* Callbacks fired by UV events. */ public: - // NOLINTNEXTLINE(readability-convert-member-functions-to-static) void OnUvRecvAlloc(size_t suggestedSize, uv_buf_t* buf); void OnUvRecv(ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned int flags); - // NOLINTNEXTLINE(readability-convert-member-functions-to-static) void OnUvSend(int status, UdpSocketHandle::onSendCallback* cb); /* Pure virtual methods that must be implemented by the subclass. */ diff --git a/worker/src/handles/UdpSocketHandle.cpp b/worker/src/handles/UdpSocketHandle.cpp index 471d28366f..b544794e34 100644 --- a/worker/src/handles/UdpSocketHandle.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -363,6 +363,7 @@ bool UdpSocketHandle::SetLocalAddress() return true; } +// NOLINTNEXTLINE(readability-convert-member-functions-to-static) inline void UdpSocketHandle::OnUvRecvAlloc(size_t /*suggestedSize*/, uv_buf_t* buf) { MS_TRACE(); @@ -408,6 +409,7 @@ inline void UdpSocketHandle::OnUvRecv( } } +// NOLINTNEXTLINE(readability-convert-member-functions-to-static) inline void UdpSocketHandle::OnUvSend(int status, UdpSocketHandle::onSendCallback* cb) { MS_TRACE(); From c3e181d4947049c0f7238393fc30791a509dda81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 11 Jan 2024 11:01:04 +0100 Subject: [PATCH 329/525] Update NPM types/node dep --- .github/workflows/mediasoup-node.yaml | 3 +-- package-lock.json | 14 +++++++------- package.json | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 0618603bc7..3cda494ef0 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -48,8 +48,7 @@ jobs: restore-keys: | ${{ matrix.ci.os }}-node- - # NOTE: Add --force since otherwise `npm ci` fails in Node 16 because - # @octokit/auth-token dev dependency requires Node >= 16. + # NOTE: Add --force since some dev dependencies require Node >= 18. - name: npm ci run: npm ci --force --foreground-scripts diff --git a/package-lock.json b/package-lock.json index 71123e5af9..a96f727203 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.8", + "@types/node": "^20.11.0", "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", "eslint": "^8.56.0", @@ -1632,9 +1632,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.10.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", - "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", + "version": "20.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", + "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -8203,9 +8203,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.10.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", - "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", + "version": "20.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", + "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", "dev": true, "requires": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index 58f1bfc861..d675d03d33 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.10.8", + "@types/node": "^20.11.0", "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", "eslint": "^8.56.0", From c5af766ba51a1553f1fa26b667bd36f3582c0635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 11 Jan 2024 11:03:00 +0100 Subject: [PATCH 330/525] Update NPM open-cli to 8.0.0 It requires Node >= 18 but shouldn't be a problem since in CI we use `npm ci --force`. --- package-lock.json | 1410 ++++----------------------------------------- package.json | 2 +- 2 files changed, 118 insertions(+), 1294 deletions(-) diff --git a/package-lock.json b/package-lock.json index a96f727203..f5795b33fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,7 @@ "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^11.1.1", - "open-cli": "^7.2.0", + "open-cli": "^8.0.0", "pick-port": "^2.0.0", "prettier": "^3.1.1", "sctp": "^1.0.0", @@ -1620,12 +1620,6 @@ "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -1640,12 +1634,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, "node_modules/@types/semver": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", @@ -2332,15 +2320,6 @@ "node": ">=8" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -2444,27 +2423,6 @@ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "dev": true }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2543,15 +2501,15 @@ "dev": true }, "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, "dependencies": { - "run-applescript": "^5.0.0" + "run-applescript": "^7.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2575,48 +2533,6 @@ "node": ">=6" } }, - "node_modules/camelcase-keys": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-8.0.2.tgz", - "integrity": "sha512-qMKdlOfsjlezMqxkUGGMaWWs17i2HoL15tM+wtx8ld4nLrUwU58TFdvyGOz/piNP842KeO8yXvggVQSdQ828NA==", - "dev": true, - "dependencies": { - "camelcase": "^7.0.0", - "map-obj": "^4.3.0", - "quick-lru": "^6.1.1", - "type-fest": "^2.13.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001431", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz", @@ -2797,45 +2713,6 @@ "node": ">= 8" } }, - "node_modules/cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", - "deprecated": "cross-spawn no longer requires a build toolchain, use it instead", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.0", - "which": "^1.2.8" - } - }, - "node_modules/cross-spawn-async/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/cross-spawn-async/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/cross-spawn-async/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, "node_modules/crypto-random-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", @@ -2887,52 +2764,6 @@ } } }, - "node_modules/decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/dedent": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", @@ -2963,34 +2794,28 @@ } }, "node_modules/default-browser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", - "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^5.0.0", - "xdg-default-browser": "^2.1.0" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", "dev": true, - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3525,9 +3350,9 @@ } }, "node_modules/file-type": { - "version": "18.2.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", - "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", + "version": "18.7.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.7.0.tgz", + "integrity": "sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==", "dev": true, "dependencies": { "readable-web-to-node-stream": "^3.0.2", @@ -3798,15 +3623,6 @@ "url": "https://opencollective.com/mediasoup" } }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -3828,27 +3644,6 @@ "node": ">=4" } }, - "node_modules/hosted-git-info": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", - "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", - "dev": true, - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -3937,18 +3732,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -4079,15 +3862,6 @@ "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -4110,27 +3884,15 @@ } }, "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-wsl/node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4862,15 +4624,6 @@ "node": ">=6" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -4977,18 +4730,6 @@ "tmpl": "1.0.5" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/marked": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", @@ -5002,38 +4743,12 @@ } }, "node_modules/meow": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", - "integrity": "sha512-Cl0yeeIrko6d94KpUo1M+0X1sB14ikoaqlIGuTH1fW4I+E3+YljL54/hb/BWmVfrV9tTV9zU04+xjw08Fh2WkA==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^8.0.2", - "decamelize": "^6.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^4.0.1", - "read-pkg-up": "^9.1.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^3.1.0", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.1.tgz", - "integrity": "sha512-htXWckxlT6U4+ilVgweNliPqlsVSSucbxVexRYllyMVJDtf5rTjv6kF/s+qAd4QSL1BZcnJPEJavYBPQiWuZDA==", + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", "dev": true, "engines": { - "node": ">=14.16" + "node": ">=16.10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5076,15 +4791,6 @@ "node": ">=6" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5097,20 +4803,6 @@ "node": "*" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -5211,21 +4903,6 @@ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, - "node_modules/normalize-package-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", - "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", - "dev": true, - "dependencies": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -5247,15 +4924,6 @@ "node": ">=8" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5281,40 +4949,40 @@ } }, "node_modules/open": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", - "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/open/-/open-10.0.3.tgz", + "integrity": "sha512-dtbI5oW7987hwC9qjJTyABldTaa19SuyJse1QboWv3b0qCcrrLNVDqBx1XgELAjh9QTVQaP/C5b1nhQebd1H2A==", "dev": true, "dependencies": { - "default-browser": "^3.1.0", + "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" + "is-wsl": "^3.1.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/open-cli": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.2.0.tgz", - "integrity": "sha512-1ANJc8oJ92FiaNZ0o2Hw4WBvDJoXs1P74aFMtpAvlbkIPV4uPcQvDz7V6kMOrsZkmB4tglrHVMlLQaafuUuxXg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-8.0.0.tgz", + "integrity": "sha512-3muD3BbfLyzl+aMVSEfn2FfOqGdPYR0O4KNnxXsLEPE2q9OSjBfJAaB6XKbrUzLgymoSMejvb5jpXJfru/Ko2A==", "dev": true, "dependencies": { - "file-type": "^18.2.1", + "file-type": "^18.7.0", "get-stdin": "^9.0.0", - "meow": "^11.0.0", - "open": "^9.0.0", - "tempy": "^3.0.0" + "meow": "^12.1.1", + "open": "^10.0.0", + "tempy": "^3.1.0" }, "bin": { "open-cli": "cli.js" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5645,12 +5313,6 @@ "node": ">= 6" } }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5696,236 +5358,40 @@ } ] }, - "node_modules/quick-lru": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.1.tgz", - "integrity": "sha512-S27GBT+F0NTRiehtbrgaSE1idUAJ5bX8dPAQTdylEyNlrdcH5X4Lz7Edz3DYzecbsCluD5zO8ZNEe04z3D3u6Q==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "node_modules/read-pkg": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", - "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { - "@types/normalize-package-data": "^2.4.1", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^2.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/read-pkg-up": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", - "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", "dev": true, "dependencies": { - "find-up": "^6.3.0", - "read-pkg": "^7.1.0", - "type-fest": "^2.5.0" + "readable-stream": "^3.6.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "dev": true, - "dependencies": { - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/redent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "dependencies": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, "node_modules/require-directory": { @@ -6019,15 +5485,12 @@ } }, "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6166,38 +5629,6 @@ "source-map": "^0.6.0" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6282,15 +5713,6 @@ "node": ">=8" } }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -6300,21 +5722,6 @@ "node": ">=6" } }, - "node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -6406,22 +5813,22 @@ } }, "node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=14.16" } }, "node_modules/tempy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz", - "integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", "dev": true, "dependencies": { "is-stream": "^3.0.0", - "temp-dir": "^2.0.0", + "temp-dir": "^3.0.0", "type-fest": "^2.12.2", "unique-string": "^3.0.0" }, @@ -6476,15 +5883,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/titleize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", - "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -6529,18 +5927,6 @@ "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/trim-newlines": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", - "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ts-api-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", @@ -6690,15 +6076,6 @@ "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", "dev": true }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", @@ -6760,16 +6137,6 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -6838,56 +6205,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/xdg-default-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", - "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", - "dev": true, - "dependencies": { - "execa": "^0.2.2", - "titleize": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/xdg-default-browser/node_modules/execa": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", - "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", - "dev": true, - "dependencies": { - "cross-spawn-async": "^2.1.1", - "npm-run-path": "^1.0.0", - "object-assign": "^4.0.1", - "path-key": "^1.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/xdg-default-browser/node_modules/npm-run-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", - "dev": true, - "dependencies": { - "path-key": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/xdg-default-browser/node_modules/path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -8191,12 +7508,6 @@ "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, "@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -8211,12 +7522,6 @@ "undici-types": "~5.26.4" } }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, "@types/semver": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", @@ -8646,12 +7951,6 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true - }, "babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -8734,21 +8033,6 @@ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "dev": true }, - "big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true - }, - "bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "requires": { - "big-integer": "^1.6.44" - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -8805,12 +8089,12 @@ "dev": true }, "bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, "requires": { - "run-applescript": "^5.0.0" + "run-applescript": "^7.0.0" } }, "callsites": { @@ -8825,32 +8109,6 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, - "camelcase-keys": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-8.0.2.tgz", - "integrity": "sha512-qMKdlOfsjlezMqxkUGGMaWWs17i2HoL15tM+wtx8ld4nLrUwU58TFdvyGOz/piNP842KeO8yXvggVQSdQ828NA==", - "dev": true, - "requires": { - "camelcase": "^7.0.0", - "map-obj": "^4.3.0", - "quick-lru": "^6.1.1", - "type-fest": "^2.13.0" - }, - "dependencies": { - "camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "dev": true - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - } - } - }, "caniuse-lite": { "version": "1.0.30001431", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz", @@ -8983,43 +8241,6 @@ "which": "^2.0.1" } }, - "cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", - "dev": true, - "requires": { - "lru-cache": "^4.0.0", - "which": "^1.2.8" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - } - } - }, "crypto-random-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", @@ -9050,36 +8271,6 @@ "ms": "2.1.2" } }, - "decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true - } - } - }, "dedent": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", @@ -9100,26 +8291,20 @@ "dev": true }, "default-browser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", - "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, "requires": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^5.0.0", - "xdg-default-browser": "^2.1.0" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" } }, "default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, - "requires": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true }, "define-lazy-prop": { "version": "3.0.0", @@ -9492,9 +8677,9 @@ } }, "file-type": { - "version": "18.2.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", - "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", + "version": "18.7.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.7.0.tgz", + "integrity": "sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==", "dev": true, "requires": { "readable-web-to-node-stream": "^3.0.2", @@ -9684,12 +8869,6 @@ "debug": "^4.3.4" } }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -9705,23 +8884,6 @@ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, - "hosted-git-info": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", - "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - } - } - }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -9772,12 +8934,6 @@ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, - "indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -9869,12 +9025,6 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true - }, "is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -9888,20 +9038,12 @@ "dev": true }, "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "requires": { - "is-docker": "^2.0.0" - }, - "dependencies": { - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - } + "is-inside-container": "^1.0.0" } }, "isexe": { @@ -10463,12 +9605,6 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -10551,12 +9687,6 @@ "tmpl": "1.0.5" } }, - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true - }, "marked": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", @@ -10564,32 +9694,10 @@ "dev": true }, "meow": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", - "integrity": "sha512-Cl0yeeIrko6d94KpUo1M+0X1sB14ikoaqlIGuTH1fW4I+E3+YljL54/hb/BWmVfrV9tTV9zU04+xjw08Fh2WkA==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^8.0.2", - "decamelize": "^6.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^4.0.1", - "read-pkg-up": "^9.1.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^3.1.0", - "yargs-parser": "^21.1.1" - }, - "dependencies": { - "type-fest": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.1.tgz", - "integrity": "sha512-htXWckxlT6U4+ilVgweNliPqlsVSSucbxVexRYllyMVJDtf5rTjv6kF/s+qAd4QSL1BZcnJPEJavYBPQiWuZDA==", - "dev": true - } - } + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true }, "merge-stream": { "version": "2.0.0", @@ -10619,12 +9727,6 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -10634,17 +9736,6 @@ "brace-expansion": "^1.1.7" } }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - } - }, "minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -10712,18 +9803,6 @@ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, - "normalize-package-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", - "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -10739,12 +9818,6 @@ "path-key": "^3.0.0" } }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -10764,28 +9837,28 @@ } }, "open": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", - "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/open/-/open-10.0.3.tgz", + "integrity": "sha512-dtbI5oW7987hwC9qjJTyABldTaa19SuyJse1QboWv3b0qCcrrLNVDqBx1XgELAjh9QTVQaP/C5b1nhQebd1H2A==", "dev": true, "requires": { - "default-browser": "^3.1.0", + "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" + "is-wsl": "^3.1.0" } }, "open-cli": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-7.2.0.tgz", - "integrity": "sha512-1ANJc8oJ92FiaNZ0o2Hw4WBvDJoXs1P74aFMtpAvlbkIPV4uPcQvDz7V6kMOrsZkmB4tglrHVMlLQaafuUuxXg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-8.0.0.tgz", + "integrity": "sha512-3muD3BbfLyzl+aMVSEfn2FfOqGdPYR0O4KNnxXsLEPE2q9OSjBfJAaB6XKbrUzLgymoSMejvb5jpXJfru/Ko2A==", "dev": true, "requires": { - "file-type": "^18.2.1", + "file-type": "^18.7.0", "get-stdin": "^9.0.0", - "meow": "^11.0.0", - "open": "^9.0.0", - "tempy": "^3.0.0" + "meow": "^12.1.1", + "open": "^10.0.0", + "tempy": "^3.1.0" } }, "optionator": { @@ -11014,12 +10087,6 @@ "sisteransi": "^1.0.5" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -11038,127 +10105,12 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, - "quick-lru": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.1.tgz", - "integrity": "sha512-S27GBT+F0NTRiehtbrgaSE1idUAJ5bX8dPAQTdylEyNlrdcH5X4Lz7Edz3DYzecbsCluD5zO8ZNEe04z3D3u6Q==", - "dev": true - }, "react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "read-pkg": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", - "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.1", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^2.0.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", - "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", - "dev": true, - "requires": { - "find-up": "^6.3.0", - "read-pkg": "^7.1.0", - "type-fest": "^2.5.0" - }, - "dependencies": { - "find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "requires": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - } - }, - "locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "requires": { - "p-locate": "^6.0.0" - } - }, - "p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "requires": { - "yocto-queue": "^1.0.0" - } - }, - "p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "requires": { - "p-limit": "^4.0.0" - } - }, - "path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - }, - "yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true - } - } - }, "readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -11179,16 +10131,6 @@ "readable-stream": "^3.6.0" } }, - "redent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "requires": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -11251,13 +10193,10 @@ } }, "run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - } + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true }, "run-parallel": { "version": "1.2.0", @@ -11343,38 +10282,6 @@ "source-map": "^0.6.0" } }, - "spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -11443,27 +10350,12 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true - }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, - "strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "requires": { - "min-indent": "^1.0.1" - } - }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -11523,19 +10415,19 @@ } }, "temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", "dev": true }, "tempy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz", - "integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", "dev": true, "requires": { "is-stream": "^3.0.0", - "temp-dir": "^2.0.0", + "temp-dir": "^3.0.0", "type-fest": "^2.12.2", "unique-string": "^3.0.0" }, @@ -11571,12 +10463,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "titleize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", - "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", - "dev": true - }, "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -11608,12 +10494,6 @@ "ieee754": "^1.2.1" } }, - "trim-newlines": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", - "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", - "dev": true - }, "ts-api-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", @@ -11700,12 +10580,6 @@ "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", "dev": true }, - "untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true - }, "update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", @@ -11750,16 +10624,6 @@ } } }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -11810,46 +10674,6 @@ "signal-exit": "^3.0.7" } }, - "xdg-default-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", - "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", - "dev": true, - "requires": { - "execa": "^0.2.2", - "titleize": "^1.0.0" - }, - "dependencies": { - "execa": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", - "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", - "dev": true, - "requires": { - "cross-spawn-async": "^2.1.1", - "npm-run-path": "^1.0.0", - "object-assign": "^4.0.1", - "path-key": "^1.0.0", - "strip-eof": "^1.0.0" - } - }, - "npm-run-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", - "dev": true, - "requires": { - "path-key": "^1.0.0" - } - }, - "path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", - "dev": true - } - } - }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index d675d03d33..eb02a93aa4 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^11.1.1", - "open-cli": "^7.2.0", + "open-cli": "^8.0.0", "pick-port": "^2.0.0", "prettier": "^3.1.1", "sctp": "^1.0.0", From d17a9374055e5ea8fb44d1bbf661a01661f6270e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 11 Jan 2024 23:11:44 +0100 Subject: [PATCH 331/525] Fix repository url in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index eb02a93aa4..7308e7ef3e 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "homepage": "https://mediasoup.org", "repository": { "type": "git", - "url": "https://github.com/versatica/mediasoup.git" + "url": "git+https://github.com/versatica/mediasoup.git" }, "funding": { "type": "opencollective", From e226f2f9dfcb3124d6a472b051353f75b3959290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Tue, 16 Jan 2024 17:00:37 +0100 Subject: [PATCH 332/525] C++: Update libsrtp (#1314) --- CHANGELOG.md | 4 ++++ worker/include/RTC/SrtpSession.hpp | 10 +++++----- worker/src/RTC/PipeTransport.cpp | 32 ++++++++++-------------------- worker/src/RTC/PlainTransport.cpp | 32 ++++++++++-------------------- worker/src/RTC/SrtpSession.cpp | 25 +++++++++++------------ worker/src/RTC/WebRtcTransport.cpp | 32 ++++++++++-------------------- worker/subprojects/libsrtp2.wrap | 8 ++++---- 7 files changed, 58 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afa31f1bc8..dbbf6c418c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- C++: Update libsrtp to v3.0-alpha. + ### 3.13.16 - Node: Add new `worker.on('subprocessclose')` event ([PR #1307](https://github.com/versatica/mediasoup/pull/1307)). diff --git a/worker/include/RTC/SrtpSession.hpp b/worker/include/RTC/SrtpSession.hpp index fa14a14760..b50f6d9b87 100644 --- a/worker/include/RTC/SrtpSession.hpp +++ b/worker/include/RTC/SrtpSession.hpp @@ -38,13 +38,13 @@ namespace RTC ~SrtpSession(); public: - bool EncryptRtp(const uint8_t** data, int* len); - bool DecryptSrtp(uint8_t* data, int* len); - bool EncryptRtcp(const uint8_t** data, int* len); - bool DecryptSrtcp(uint8_t* data, int* len); + bool EncryptRtp(const uint8_t** data, size_t* len); + bool DecryptSrtp(uint8_t* data, size_t* len); + bool EncryptRtcp(const uint8_t** data, size_t* len); + bool DecryptSrtcp(uint8_t* data, size_t* len); void RemoveStream(uint32_t ssrc) { - srtp_remove_stream(this->session, uint32_t{ htonl(ssrc) }); + srtp_stream_remove(this->session, uint32_t{ htonl(ssrc) }); } private: diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index 8706f5a60b..ff39616228 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -484,9 +484,9 @@ namespace RTC } const uint8_t* data = packet->GetData(); - auto intLen = static_cast(packet->GetSize()); + auto len = packet->GetSize(); - if (HasSrtp() && !this->srtpSendSession->EncryptRtp(&data, &intLen)) + if (HasSrtp() && !this->srtpSendSession->EncryptRtp(&data, &len)) { if (cb) { @@ -497,8 +497,6 @@ namespace RTC return; } - auto len = static_cast(intLen); - this->tuple->Send(data, len, cb); // Increase send transmission. @@ -515,15 +513,13 @@ namespace RTC } const uint8_t* data = packet->GetData(); - auto intLen = static_cast(packet->GetSize()); + auto len = packet->GetSize(); - if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &intLen)) + if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &len)) { return; } - auto len = static_cast(intLen); - this->tuple->Send(data, len); // Increase send transmission. @@ -542,15 +538,13 @@ namespace RTC packet->Serialize(RTC::RTCP::Buffer); const uint8_t* data = packet->GetData(); - auto intLen = static_cast(packet->GetSize()); + auto len = packet->GetSize(); - if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &intLen)) + if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &len)) { return; } - auto len = static_cast(intLen); - this->tuple->Send(data, len); // Increase send transmission. @@ -638,11 +632,9 @@ namespace RTC } // Decrypt the SRTP packet. - auto intLen = static_cast(len); - - if (HasSrtp() && !this->srtpRecvSession->DecryptSrtp(const_cast(data), &intLen)) + if (HasSrtp() && !this->srtpRecvSession->DecryptSrtp(const_cast(data), &len)) { - RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, static_cast(intLen)); + RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, len); if (!packet) { @@ -663,7 +655,7 @@ namespace RTC return; } - RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, static_cast(intLen)); + RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, len); if (!packet) { @@ -700,9 +692,7 @@ namespace RTC } // Decrypt the SRTCP packet. - auto intLen = static_cast(len); - - if (HasSrtp() && !this->srtpRecvSession->DecryptSrtcp(const_cast(data), &intLen)) + if (HasSrtp() && !this->srtpRecvSession->DecryptSrtcp(const_cast(data), &len)) { return; } @@ -715,7 +705,7 @@ namespace RTC return; } - RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, static_cast(intLen)); + RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, len); if (!packet) { diff --git a/worker/src/RTC/PlainTransport.cpp b/worker/src/RTC/PlainTransport.cpp index f985dc8fa8..f6da989dd3 100644 --- a/worker/src/RTC/PlainTransport.cpp +++ b/worker/src/RTC/PlainTransport.cpp @@ -764,9 +764,9 @@ namespace RTC } const uint8_t* data = packet->GetData(); - auto intLen = static_cast(packet->GetSize()); + auto len = packet->GetSize(); - if (HasSrtp() && !this->srtpSendSession->EncryptRtp(&data, &intLen)) + if (HasSrtp() && !this->srtpSendSession->EncryptRtp(&data, &len)) { if (cb) { @@ -777,8 +777,6 @@ namespace RTC return; } - auto len = static_cast(intLen); - this->tuple->Send(data, len, cb); // Increase send transmission. @@ -795,15 +793,13 @@ namespace RTC } const uint8_t* data = packet->GetData(); - auto intLen = static_cast(packet->GetSize()); + auto len = packet->GetSize(); - if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &intLen)) + if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &len)) { return; } - auto len = static_cast(intLen); - if (this->rtcpMux) { this->tuple->Send(data, len); @@ -829,15 +825,13 @@ namespace RTC packet->Serialize(RTC::RTCP::Buffer); const uint8_t* data = packet->GetData(); - auto intLen = static_cast(packet->GetSize()); + auto len = packet->GetSize(); - if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &intLen)) + if (HasSrtp() && !this->srtpSendSession->EncryptRtcp(&data, &len)) { return; } - auto len = static_cast(intLen); - if (this->rtcpMux) { this->tuple->Send(data, len); @@ -933,11 +927,9 @@ namespace RTC } // Decrypt the SRTP packet. - auto intLen = static_cast(len); - - if (HasSrtp() && !this->srtpRecvSession->DecryptSrtp(const_cast(data), &intLen)) + if (HasSrtp() && !this->srtpRecvSession->DecryptSrtp(const_cast(data), &len)) { - RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, static_cast(intLen)); + RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, len); if (!packet) { @@ -958,7 +950,7 @@ namespace RTC return; } - RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, static_cast(intLen)); + RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, len); if (!packet) { @@ -1031,9 +1023,7 @@ namespace RTC } // Decrypt the SRTCP packet. - auto intLen = static_cast(len); - - if (HasSrtp() && !this->srtpRecvSession->DecryptSrtcp(const_cast(data), &intLen)) + if (HasSrtp() && !this->srtpRecvSession->DecryptSrtcp(const_cast(data), &len)) { return; } @@ -1107,7 +1097,7 @@ namespace RTC return; } - RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, static_cast(intLen)); + RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, len); if (!packet) { diff --git a/worker/src/RTC/SrtpSession.cpp b/worker/src/RTC/SrtpSession.cpp index 5c2c810e0f..20755dc656 100644 --- a/worker/src/RTC/SrtpSession.cpp +++ b/worker/src/RTC/SrtpSession.cpp @@ -189,14 +189,14 @@ namespace RTC } } - bool SrtpSession::EncryptRtp(const uint8_t** data, int* len) + bool SrtpSession::EncryptRtp(const uint8_t** data, size_t* len) { MS_TRACE(); // Ensure that the resulting SRTP packet fits into the encrypt buffer. - if (static_cast(*len) + SRTP_MAX_TRAILER_LEN > EncryptBufferSize) + if (*len + SRTP_MAX_TRAILER_LEN > EncryptBufferSize) { - MS_WARN_TAG(srtp, "cannot encrypt RTP packet, size too big (%i bytes)", *len); + MS_WARN_TAG(srtp, "cannot encrypt RTP packet, size too big (%zu bytes)", *len); return false; } @@ -224,7 +224,7 @@ namespace RTC std::memcpy(encryptBuffer, *data, *len); - const srtp_err_status_t err = srtp_protect(this->session, static_cast(encryptBuffer), len); + const srtp_err_status_t err = srtp_protect(this->session, encryptBuffer, len); if (DepLibSRTP::IsError(err)) { @@ -239,11 +239,11 @@ namespace RTC return true; } - bool SrtpSession::DecryptSrtp(uint8_t* data, int* len) + bool SrtpSession::DecryptSrtp(uint8_t* data, size_t* len) { MS_TRACE(); - const srtp_err_status_t err = srtp_unprotect(this->session, static_cast(data), len); + const srtp_err_status_t err = srtp_unprotect(this->session, data, len); if (DepLibSRTP::IsError(err)) { @@ -255,22 +255,21 @@ namespace RTC return true; } - bool SrtpSession::EncryptRtcp(const uint8_t** data, int* len) + bool SrtpSession::EncryptRtcp(const uint8_t** data, size_t* len) { MS_TRACE(); // Ensure that the resulting SRTCP packet fits into the encrypt buffer. - if (static_cast(*len) + SRTP_MAX_TRAILER_LEN > EncryptBufferSize) + if (*len + SRTP_MAX_TRAILER_LEN > EncryptBufferSize) { - MS_WARN_TAG(srtp, "cannot encrypt RTCP packet, size too big (%i bytes)", *len); + MS_WARN_TAG(srtp, "cannot encrypt RTCP packet, size too big (%zu bytes)", *len); return false; } std::memcpy(EncryptBuffer, *data, *len); - const srtp_err_status_t err = - srtp_protect_rtcp(this->session, static_cast(EncryptBuffer), len); + const srtp_err_status_t err = srtp_protect_rtcp(this->session, EncryptBuffer, len); if (DepLibSRTP::IsError(err)) { @@ -285,11 +284,11 @@ namespace RTC return true; } - bool SrtpSession::DecryptSrtcp(uint8_t* data, int* len) + bool SrtpSession::DecryptSrtcp(uint8_t* data, size_t* len) { MS_TRACE(); - const srtp_err_status_t err = srtp_unprotect_rtcp(this->session, static_cast(data), len); + const srtp_err_status_t err = srtp_unprotect_rtcp(this->session, data, len); if (DepLibSRTP::IsError(err)) { diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index a795fef798..e699a26ed5 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -708,9 +708,9 @@ namespace RTC } const uint8_t* data = packet->GetData(); - auto intLen = static_cast(packet->GetSize()); + auto len = packet->GetSize(); - if (!this->srtpSendSession->EncryptRtp(&data, &intLen)) + if (!this->srtpSendSession->EncryptRtp(&data, &len)) { if (cb) { @@ -721,8 +721,6 @@ namespace RTC return; } - auto len = static_cast(intLen); - this->iceServer->GetSelectedTuple()->Send(data, len, cb); // Increase send transmission. @@ -739,7 +737,7 @@ namespace RTC } const uint8_t* data = packet->GetData(); - auto intLen = static_cast(packet->GetSize()); + auto len = packet->GetSize(); // Ensure there is sending SRTP session. if (!this->srtpSendSession) @@ -749,13 +747,11 @@ namespace RTC return; } - if (!this->srtpSendSession->EncryptRtcp(&data, &intLen)) + if (!this->srtpSendSession->EncryptRtcp(&data, &len)) { return; } - auto len = static_cast(intLen); - this->iceServer->GetSelectedTuple()->Send(data, len); // Increase send transmission. @@ -774,7 +770,7 @@ namespace RTC packet->Serialize(RTC::RTCP::Buffer); const uint8_t* data = packet->GetData(); - auto intLen = static_cast(packet->GetSize()); + auto len = packet->GetSize(); // Ensure there is sending SRTP session. if (!this->srtpSendSession) @@ -784,13 +780,11 @@ namespace RTC return; } - if (!this->srtpSendSession->EncryptRtcp(&data, &intLen)) + if (!this->srtpSendSession->EncryptRtcp(&data, &len)) { return; } - auto len = static_cast(intLen); - this->iceServer->GetSelectedTuple()->Send(data, len); // Increase send transmission. @@ -957,11 +951,9 @@ namespace RTC } // Decrypt the SRTP packet. - auto intLen = static_cast(len); - - if (!this->srtpRecvSession->DecryptSrtp(const_cast(data), &intLen)) + if (!this->srtpRecvSession->DecryptSrtp(const_cast(data), &len)) { - RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, static_cast(intLen)); + RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, len); if (!packet) { @@ -982,7 +974,7 @@ namespace RTC return; } - RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, static_cast(intLen)); + RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, len); if (!packet) { @@ -1028,14 +1020,12 @@ namespace RTC } // Decrypt the SRTCP packet. - auto intLen = static_cast(len); - - if (!this->srtpRecvSession->DecryptSrtcp(const_cast(data), &intLen)) + if (!this->srtpRecvSession->DecryptSrtcp(const_cast(data), &len)) { return; } - RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, static_cast(intLen)); + RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, len); if (!packet) { diff --git a/worker/subprojects/libsrtp2.wrap b/worker/subprojects/libsrtp2.wrap index aa1b767f2d..d0181794b0 100644 --- a/worker/subprojects/libsrtp2.wrap +++ b/worker/subprojects/libsrtp2.wrap @@ -1,8 +1,8 @@ [wrap-file] -directory = libsrtp-4c9f0956f2933ac0650208d69c8d897625ba6301 -source_url = https://github.com/versatica/libsrtp/archive/4c9f0956f2933ac0650208d69c8d897625ba6301.zip -source_filename = libsrtp-4c9f0956f2933ac0650208d69c8d897625ba6301.zip -source_hash = 4f3af61e26df398569605fc4bcf377587ca2d8bd34b2b4bf9cdb9590cadbd662 +directory = libsrtp-3.0-alpha +source_url = https://github.com/versatica/libsrtp/archive/v3.0-alpha.zip +source_filename = libsrtp-3.0-alpha.zip +source_hash = 946a472b888ca8d51df172def7681f3f9b14768109ffd22af08fddb1be77d2c6 [provide] libsrtp2 = libsrtp2_dep From 6fdc0c4d5c554d7dc6e4f55f194ec34738f326f7 Mon Sep 17 00:00:00 2001 From: Bryn Date: Fri, 26 Jan 2024 14:41:14 +0000 Subject: [PATCH 333/525] Fix prebuilt worker download (#1319) --- npm-scripts.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 91dbed9114..1090f6e17c 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -488,7 +488,9 @@ async function prebuildWorker() { async function downloadPrebuiltWorker() { const releaseBase = process.env.MEDIASOUP_WORKER_PREBUILT_DOWNLOAD_BASE_URL || - `${PKG.repository.url.replace(/\.git$/, '')}/releases/download`; + `${PKG.repository.url + .replace(/^git\+/, '') + .replace(/\.git$/, '')}/releases/download`; const tarUrl = `${releaseBase}/${PKG.version}/${WORKER_PREBUILD_TAR}`; From 8f44f406821e4171e420dde9662897f838f867f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 Jan 2024 17:37:58 +0100 Subject: [PATCH 334/525] Update deps Also change Prettier `trailingComma` to 'es5' since otherwise it also adds trailing commas in `tsconfig.json` which is INVALID in JSON. --- .prettierrc.json | 2 +- CHANGELOG.md | 2 +- node/src/ActiveSpeakerObserver.ts | 4 +- node/src/AudioLevelObserver.ts | 6 +- node/src/Channel.ts | 52 +-- node/src/Consumer.ts | 58 +-- node/src/DataConsumer.ts | 48 +-- node/src/DataProducer.ts | 30 +- node/src/DirectTransport.ts | 24 +- node/src/EnhancedEventEmitter.ts | 16 +- node/src/PipeTransport.ts | 20 +- node/src/PlainTransport.ts | 16 +- node/src/Producer.ts | 38 +- node/src/Router.ts | 160 ++++---- node/src/RtpObserver.ts | 18 +- node/src/RtpParameters.ts | 60 +-- node/src/RtpStream.ts | 8 +- node/src/SctpParameters.ts | 8 +- node/src/SrtpParameters.ts | 10 +- node/src/Transport.ts | 104 ++--- node/src/WebRtcServer.ts | 12 +- node/src/WebRtcTransport.ts | 40 +- node/src/Worker.ts | 52 +-- node/src/ortc.ts | 105 +++-- node/src/scalabilityModes.ts | 2 +- node/src/test/test-ActiveSpeakerObserver.ts | 12 +- node/src/test/test-AudioLevelObserver.ts | 14 +- node/src/test/test-Consumer.ts | 64 +-- node/src/test/test-DataConsumer.ts | 24 +- node/src/test/test-DataProducer.ts | 42 +- node/src/test/test-DirectTransport.ts | 44 +-- node/src/test/test-PipeTransport.ts | 54 +-- node/src/test/test-PlainTransport.ts | 52 +-- node/src/test/test-Producer.ts | 70 ++-- node/src/test/test-Router.ts | 10 +- node/src/test/test-WebRtcServer.ts | 26 +- node/src/test/test-WebRtcTransport.ts | 94 ++--- node/src/test/test-Worker.ts | 34 +- node/src/test/test-mediasoup.ts | 2 +- node/src/test/test-multiopus.ts | 18 +- node/src/test/test-node-sctp.ts | 18 +- node/src/test/test-ortc.ts | 18 +- node/src/utils.ts | 14 +- node/tsconfig.json | 6 +- npm-scripts.mjs | 38 +- package-lock.json | 418 ++++++++++---------- package.json | 16 +- worker/scripts/clang-format.mjs | 6 +- 48 files changed, 991 insertions(+), 998 deletions(-) diff --git a/.prettierrc.json b/.prettierrc.json index 7cae653bfe..a824e54211 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -5,6 +5,6 @@ "bracketSpacing": true, "semi": true, "singleQuote": true, - "trailingComma": "all", + "trailingComma": "es5", "endOfLine": "auto" } diff --git a/CHANGELOG.md b/CHANGELOG.md index dbbf6c418c..bf08470556 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### NEXT -- C++: Update libsrtp to v3.0-alpha. +- libsrtp: Update to v3.0-alpha version in our fork. ### 3.13.16 diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index 6ac2825451..4cdd1d675e 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -52,7 +52,7 @@ export class ActiveSpeakerObserver< * @private */ constructor( - options: RtpObserverObserverConstructorOptions, + options: RtpObserverObserverConstructorOptions ) { super(options); @@ -97,7 +97,7 @@ export class ActiveSpeakerObserver< logger.error('ignoring unknown event "%s"', event); } } - }, + } ); } } diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index 39a22472da..b6a725ae39 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -72,7 +72,7 @@ export class AudioLevelObserver< * @private */ constructor( - options: AudioLevelObserverConstructorOptions, + options: AudioLevelObserverConstructorOptions ) { super(options); @@ -111,7 +111,7 @@ export class AudioLevelObserver< }) => ({ producer: this.getProducerById(producerId)!, volume, - }), + }) ) .filter(({ producer }: { producer: Producer }) => producer); @@ -138,7 +138,7 @@ export class AudioLevelObserver< logger.error('ignoring unknown event "%s"', event); } } - }, + } ); } } diff --git a/node/src/Channel.ts b/node/src/Channel.ts index 1f50bf9489..fca87950f9 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -78,7 +78,7 @@ export class Channel extends EnhancedEventEmitter { } else { this.#recvBuffer = Buffer.concat( [this.#recvBuffer, buffer], - this.#recvBuffer.length + buffer.length, + this.#recvBuffer.length + buffer.length ); } @@ -104,7 +104,7 @@ export class Channel extends EnhancedEventEmitter { const dataView = new DataView( this.#recvBuffer.buffer, - this.#recvBuffer.byteOffset + msgStart, + this.#recvBuffer.byteOffset + msgStart ); const msgLen = dataView.getUint32(0, IS_LITTLE_ENDIAN); @@ -115,7 +115,7 @@ export class Channel extends EnhancedEventEmitter { const payload = this.#recvBuffer.subarray( msgStart + 4, - msgStart + 4 + msgLen, + msgStart + 4 + msgLen ); msgStart += 4 + msgLen; @@ -160,14 +160,14 @@ export class Channel extends EnhancedEventEmitter { console.warn( `worker[pid:${pid}] unexpected data: ${payload.toString( 'utf8', - 1, - )}`, + 1 + )}` ); } } } catch (error) { logger.error( - `received invalid message from the worker process: ${error}`, + `received invalid message from the worker process: ${error}` ); } } @@ -178,19 +178,19 @@ export class Channel extends EnhancedEventEmitter { }); this.#consumerSocket.on('end', () => - logger.debug('Consumer Channel ended by the worker process'), + logger.debug('Consumer Channel ended by the worker process') ); this.#consumerSocket.on('error', error => - logger.error(`Consumer Channel error: ${error}`), + logger.error(`Consumer Channel error: ${error}`) ); this.#producerSocket.on('end', () => - logger.debug('Producer Channel ended by the worker process'), + logger.debug('Producer Channel ended by the worker process') ); this.#producerSocket.on('error', error => - logger.error(`Producer Channel error: ${error}`), + logger.error(`Producer Channel error: ${error}`) ); } @@ -244,13 +244,13 @@ export class Channel extends EnhancedEventEmitter { event: Event, bodyType?: NotificationBody, bodyOffset?: number, - handlerId?: string, + handlerId?: string ): void { logger.debug(`notify() [event:${Event[event]}]`); if (this.#closed) { throw new InvalidStateError( - `Channel closed, cannot send notification [event:${Event[event]}]`, + `Channel closed, cannot send notification [event:${Event[event]}]` ); } @@ -264,7 +264,7 @@ export class Channel extends EnhancedEventEmitter { handlerIdOffset, event, bodyType, - bodyOffset, + bodyOffset ); } else { notificationOffset = Notification.createNotification( @@ -272,14 +272,14 @@ export class Channel extends EnhancedEventEmitter { handlerIdOffset, event, NotificationBody.NONE, - 0, + 0 ); } const messageOffset = Message.createMessage( this.#bufferBuilder, MessageBody.Notification, - notificationOffset, + notificationOffset ); // Finalizes the buffer and adds a 4 byte prefix with the size of the buffer. @@ -310,13 +310,13 @@ export class Channel extends EnhancedEventEmitter { method: Method, bodyType?: RequestBody, bodyOffset?: number, - handlerId?: string, + handlerId?: string ): Promise { logger.debug(`request() [method:${Method[method]}]`); if (this.#closed) { throw new InvalidStateError( - `Channel closed, cannot send request [method:${Method[method]}]`, + `Channel closed, cannot send request [method:${Method[method]}]` ); } @@ -335,7 +335,7 @@ export class Channel extends EnhancedEventEmitter { method, handlerIdOffset, bodyType, - bodyOffset, + bodyOffset ); } else { requestOffset = Request.createRequest( @@ -344,14 +344,14 @@ export class Channel extends EnhancedEventEmitter { method, handlerIdOffset, RequestBody.NONE, - 0, + 0 ); } const messageOffset = Message.createMessage( this.#bufferBuilder, MessageBody.Request, - requestOffset, + requestOffset ); // Finalizes the buffer and adds a 4 byte prefix with the size of the buffer. @@ -392,8 +392,8 @@ export class Channel extends EnhancedEventEmitter { close: () => { pReject( new InvalidStateError( - `Channel closed, pending request aborted [method:${Method[method]}, id:${id}]`, - ), + `Channel closed, pending request aborted [method:${Method[method]}, id:${id}]` + ) ); }, }; @@ -408,7 +408,7 @@ export class Channel extends EnhancedEventEmitter { if (!sent) { logger.error( - `received response does not match any sent request [id:${response.id}]`, + `received response does not match any sent request [id:${response.id}]` ); return; @@ -422,7 +422,7 @@ export class Channel extends EnhancedEventEmitter { logger.warn( `request failed [method:${sent.method}, id:${ sent.id - }]: ${response.reason()}`, + }]: ${response.reason()}` ); switch (response.error()!) { @@ -438,7 +438,7 @@ export class Channel extends EnhancedEventEmitter { } } else { logger.error( - `received response is not accepted nor rejected [method:${sent.method}, id:${sent.id}]`, + `received response is not accepted nor rejected [method:${sent.method}, id:${sent.id}]` ); } } @@ -451,7 +451,7 @@ export class Channel extends EnhancedEventEmitter { // here. // See https://github.com/versatica/mediasoup/issues/510 setImmediate(() => - this.emit(notification.handlerId()!, notification.event(), notification), + this.emit(notification.handlerId()!, notification.event(), notification) ); } diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 3ef48aee06..6b70025d18 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -488,7 +488,7 @@ export class Consumer< /* Build Request. */ const requestOffset = new FbsTransport.CloseConsumerRequestT( - this.#internal.consumerId, + this.#internal.consumerId ).pack(this.#channel.bufferBuilder); this.#channel @@ -496,7 +496,7 @@ export class Consumer< FbsRequest.Method.TRANSPORT_CLOSE_CONSUMER, FbsRequest.Body.Transport_CloseConsumerRequest, requestOffset, - this.#internal.transportId, + this.#internal.transportId ) .catch(() => {}); @@ -539,7 +539,7 @@ export class Consumer< FbsRequest.Method.CONSUMER_DUMP, undefined, undefined, - this.#internal.consumerId, + this.#internal.consumerId ); /* Decode Response. */ @@ -560,7 +560,7 @@ export class Consumer< FbsRequest.Method.CONSUMER_GET_STATS, undefined, undefined, - this.#internal.consumerId, + this.#internal.consumerId ); /* Decode Response. */ @@ -581,7 +581,7 @@ export class Consumer< FbsRequest.Method.CONSUMER_PAUSE, undefined, undefined, - this.#internal.consumerId, + this.#internal.consumerId ); const wasPaused = this.#paused; @@ -604,7 +604,7 @@ export class Consumer< FbsRequest.Method.CONSUMER_RESUME, undefined, undefined, - this.#internal.consumerId, + this.#internal.consumerId ); const wasPaused = this.#paused; @@ -639,19 +639,19 @@ export class Consumer< FbsConsumer.ConsumerLayers.createConsumerLayers( builder, spatialLayer, - temporalLayer !== undefined ? temporalLayer : null, + temporalLayer !== undefined ? temporalLayer : null ); const requestOffset = FbsConsumer.SetPreferredLayersRequest.createSetPreferredLayersRequest( builder, - preferredLayersOffset, + preferredLayersOffset ); const response = await this.#channel.request( FbsRequest.Method.CONSUMER_SET_PREFERRED_LAYERS, FbsRequest.Body.Consumer_SetPreferredLayersRequest, requestOffset, - this.#internal.consumerId, + this.#internal.consumerId ); /* Decode Response. */ @@ -690,14 +690,14 @@ export class Consumer< const requestOffset = FbsConsumer.SetPriorityRequest.createSetPriorityRequest( this.#channel.bufferBuilder, - priority, + priority ); const response = await this.#channel.request( FbsRequest.Method.CONSUMER_SET_PRIORITY, FbsRequest.Body.Consumer_SetPriorityRequest, requestOffset, - this.#internal.consumerId, + this.#internal.consumerId ); const data = new FbsConsumer.SetPriorityResponse(); @@ -728,7 +728,7 @@ export class Consumer< FbsRequest.Method.CONSUMER_REQUEST_KEY_FRAME, undefined, undefined, - this.#internal.consumerId, + this.#internal.consumerId ); } @@ -758,14 +758,14 @@ export class Consumer< /* Build Request. */ const requestOffset = new FbsConsumer.EnableTraceEventRequestT( - fbsEventTypes, + fbsEventTypes ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.CONSUMER_ENABLE_TRACE_EVENT, FbsRequest.Body.Consumer_EnableTraceEventRequest, requestOffset, - this.#internal.consumerId, + this.#internal.consumerId ); } @@ -902,13 +902,13 @@ export class Consumer< logger.error('ignoring unknown event "%s"', event); } } - }, + } ); } } export function parseTraceEventData( - trace: FbsConsumer.TraceNotification, + trace: FbsConsumer.TraceNotification ): ConsumerTraceEventData { let info: any; @@ -930,7 +930,7 @@ export function parseTraceEventData( } function consumerTraceEventTypeToFbs( - eventType: ConsumerTraceEventType, + eventType: ConsumerTraceEventType ): FbsConsumer.TraceEventType { switch (eventType) { case 'keyframe': { @@ -960,7 +960,7 @@ function consumerTraceEventTypeToFbs( } function consumerTraceEventTypeFromFbs( - traceType: FbsConsumer.TraceEventType, + traceType: FbsConsumer.TraceEventType ): ConsumerTraceEventType { switch (traceType) { case FbsConsumer.TraceEventType.KEYFRAME: { @@ -1001,7 +1001,7 @@ function parseConsumerLayers(data: FbsConsumer.ConsumerLayers): ConsumerLayers { } function parseRtpStreamParameters( - data: FbsRtpStream.Params, + data: FbsRtpStream.Params ): RtpStreamParameters { return { encodingIdx: data.encodingIdx(), @@ -1025,7 +1025,7 @@ function parseRtpStreamParameters( } function parseRtxStreamParameters( - data: FbsRtxStream.Params, + data: FbsRtxStream.Params ): RtxStreamParameters { return { ssrc: data.ssrc(), @@ -1062,7 +1062,7 @@ function parseRtpStream(data: FbsRtpStream.Dump): RtpStreamDump { } function parseBaseConsumerDump( - data: FbsConsumer.BaseConsumerDump, + data: FbsConsumer.BaseConsumerDump ): BaseConsumerDump { return { id: data.id()!, @@ -1074,17 +1074,17 @@ function parseBaseConsumerDump( ? utils.parseVector( data, 'consumableRtpEncodings', - parseRtpEncodingParameters, + parseRtpEncodingParameters ) : undefined, traceEventTypes: utils.parseVector( data, 'traceEventTypes', - consumerTraceEventTypeFromFbs, + consumerTraceEventTypeFromFbs ), supportedCodecPayloadTypes: utils.parseVector( data, - 'supportedCodecPayloadTypes', + 'supportedCodecPayloadTypes' ), paused: data.paused(), producerPaused: data.producerPaused(), @@ -1093,7 +1093,7 @@ function parseBaseConsumerDump( } function parseSimpleConsumerDump( - data: FbsConsumer.ConsumerDump, + data: FbsConsumer.ConsumerDump ): SimpleConsumerDump { const base = parseBaseConsumerDump(data.base()!); const rtpStream = parseRtpStream(data.rtpStreams(0)!); @@ -1106,7 +1106,7 @@ function parseSimpleConsumerDump( } function parseSimulcastConsumerDump( - data: FbsConsumer.ConsumerDump, + data: FbsConsumer.ConsumerDump ): SimulcastConsumerDump { const base = parseBaseConsumerDump(data.base()!); const rtpStream = parseRtpStream(data.rtpStreams(0)!); @@ -1133,7 +1133,7 @@ function parseSvcConsumerDump(data: FbsConsumer.ConsumerDump): SvcConsumerDump { } function parsePipeConsumerDump( - data: FbsConsumer.ConsumerDump, + data: FbsConsumer.ConsumerDump ): PipeConsumerDump { const base = parseBaseConsumerDump(data.base()!); const rtpStreams = utils.parseVector(data, 'rtpStreams', parseRtpStream); @@ -1146,7 +1146,7 @@ function parsePipeConsumerDump( } function parseConsumerDumpResponse( - data: FbsConsumer.DumpResponse, + data: FbsConsumer.DumpResponse ): ConsumerDump { const type = data.data()!.base()!.type(); @@ -1190,7 +1190,7 @@ function parseConsumerDumpResponse( } function parseConsumerStats( - binary: FbsConsumer.GetStatsResponse, + binary: FbsConsumer.GetStatsResponse ): Array { return utils.parseVector(binary, 'stats', parseRtpStreamStats); } diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 11ff7b14e5..202b5d32f4 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -293,7 +293,7 @@ export class DataConsumer< /* Build Request. */ const requestOffset = new FbsTransport.CloseDataConsumerRequestT( - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ).pack(this.#channel.bufferBuilder); this.#channel @@ -301,7 +301,7 @@ export class DataConsumer< FbsRequest.Method.TRANSPORT_CLOSE_DATACONSUMER, FbsRequest.Body.Transport_CloseDataConsumerRequest, requestOffset, - this.#internal.transportId, + this.#internal.transportId ) .catch(() => {}); @@ -344,7 +344,7 @@ export class DataConsumer< FbsRequest.Method.DATACONSUMER_DUMP, undefined, undefined, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); /* Decode Response. */ @@ -365,7 +365,7 @@ export class DataConsumer< FbsRequest.Method.DATACONSUMER_GET_STATS, undefined, undefined, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); /* Decode Response. */ @@ -386,7 +386,7 @@ export class DataConsumer< FbsRequest.Method.DATACONSUMER_PAUSE, undefined, undefined, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); const wasPaused = this.#paused; @@ -409,7 +409,7 @@ export class DataConsumer< FbsRequest.Method.DATACONSUMER_RESUME, undefined, undefined, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); const wasPaused = this.#paused; @@ -432,14 +432,14 @@ export class DataConsumer< const requestOffset = FbsDataConsumer.SetBufferedAmountLowThresholdRequest.createSetBufferedAmountLowThresholdRequest( this.#channel.bufferBuilder, - threshold, + threshold ); await this.#channel.request( FbsRequest.Method.DATACONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, FbsRequest.Body.DataConsumer_SetBufferedAmountLowThresholdRequest, requestOffset, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); } @@ -498,14 +498,14 @@ export class DataConsumer< const requestOffset = FbsDataConsumer.SendRequest.createSendRequest( builder, ppid, - dataOffset, + dataOffset ); await this.#channel.request( FbsRequest.Method.DATACONSUMER_SEND, FbsRequest.Body.DataConsumer_SendRequest, requestOffset, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); } @@ -519,7 +519,7 @@ export class DataConsumer< FbsRequest.Method.DATACONSUMER_GET_BUFFERED_AMOUNT, undefined, undefined, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); const data = new FbsDataConsumer.GetBufferedAmountResponse(); @@ -537,14 +537,14 @@ export class DataConsumer< /* Build Request. */ const requestOffset = new FbsDataConsumer.SetSubchannelsRequestT( - subchannels, + subchannels ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( FbsRequest.Method.DATACONSUMER_SET_SUBCHANNELS, FbsRequest.Body.DataConsumer_SetSubchannelsRequest, requestOffset, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); /* Decode Response. */ @@ -566,14 +566,14 @@ export class DataConsumer< const requestOffset = FbsDataConsumer.AddSubchannelRequest.createAddSubchannelRequest( this.#channel.bufferBuilder, - subchannel, + subchannel ); const response = await this.#channel.request( FbsRequest.Method.DATACONSUMER_ADD_SUBCHANNEL, FbsRequest.Body.DataConsumer_AddSubchannelRequest, requestOffset, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); /* Decode Response. */ @@ -595,14 +595,14 @@ export class DataConsumer< const requestOffset = FbsDataConsumer.RemoveSubchannelRequest.createRemoveSubchannelRequest( this.#channel.bufferBuilder, - subchannel, + subchannel ); const response = await this.#channel.request( FbsRequest.Method.DATACONSUMER_REMOVE_SUBCHANNEL, FbsRequest.Body.DataConsumer_RemoveSubchannelRequest, requestOffset, - this.#internal.dataConsumerId, + this.#internal.dataConsumerId ); /* Decode Response. */ @@ -703,7 +703,7 @@ export class DataConsumer< this.safeEmit( 'message', Buffer.from(notification.dataArray()!), - notification.ppid(), + notification.ppid() ); break; @@ -712,17 +712,17 @@ export class DataConsumer< default: { logger.error( 'ignoring unknown event "%s" in channel listener', - event, + event ); } } - }, + } ); } } export function dataConsumerTypeToFbs( - type: DataConsumerType, + type: DataConsumerType ): FbsDataProducer.Type { switch (type) { case 'sctp': { @@ -740,7 +740,7 @@ export function dataConsumerTypeToFbs( } export function dataConsumerTypeFromFbs( - type: FbsDataProducer.Type, + type: FbsDataProducer.Type ): DataConsumerType { switch (type) { case FbsDataProducer.Type.SCTP: { @@ -754,7 +754,7 @@ export function dataConsumerTypeFromFbs( } export function parseDataConsumerDumpResponse( - data: FbsDataConsumer.DumpResponse, + data: FbsDataConsumer.DumpResponse ): DataConsumerDump { return { id: data.id()!, @@ -774,7 +774,7 @@ export function parseDataConsumerDumpResponse( } function parseDataConsumerStats( - binary: FbsDataConsumer.GetStatsResponse, + binary: FbsDataConsumer.GetStatsResponse ): DataConsumerStat { return { type: 'data-consumer', diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index c78818f0f7..2763e4fbfa 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -231,7 +231,7 @@ export class DataProducer< /* Build Request. */ const requestOffset = new FbsTransport.CloseDataProducerRequestT( - this.#internal.dataProducerId, + this.#internal.dataProducerId ).pack(this.#channel.bufferBuilder); this.#channel @@ -239,7 +239,7 @@ export class DataProducer< FbsRequest.Method.TRANSPORT_CLOSE_DATAPRODUCER, FbsRequest.Body.Transport_CloseDataProducerRequest, requestOffset, - this.#internal.transportId, + this.#internal.transportId ) .catch(() => {}); @@ -282,7 +282,7 @@ export class DataProducer< FbsRequest.Method.DATAPRODUCER_DUMP, undefined, undefined, - this.#internal.dataProducerId, + this.#internal.dataProducerId ); /* Decode Response. */ @@ -303,7 +303,7 @@ export class DataProducer< FbsRequest.Method.DATAPRODUCER_GET_STATS, undefined, undefined, - this.#internal.dataProducerId, + this.#internal.dataProducerId ); /* Decode Response. */ @@ -324,7 +324,7 @@ export class DataProducer< FbsRequest.Method.DATAPRODUCER_PAUSE, undefined, undefined, - this.#internal.dataProducerId, + this.#internal.dataProducerId ); const wasPaused = this.#paused; @@ -347,7 +347,7 @@ export class DataProducer< FbsRequest.Method.DATAPRODUCER_RESUME, undefined, undefined, - this.#internal.dataProducerId, + this.#internal.dataProducerId ); const wasPaused = this.#paused; @@ -367,7 +367,7 @@ export class DataProducer< message: string | Buffer, ppid?: number, subchannels?: number[], - requiredSubchannel?: number, + requiredSubchannel?: number ): void { if (typeof message !== 'string' && !Buffer.isBuffer(message)) { throw new TypeError('message must be a string or a Buffer'); @@ -414,7 +414,7 @@ export class DataProducer< const subchannelsOffset = FbsDataProducer.SendNotification.createSubchannelsVector( builder, - subchannels ?? [], + subchannels ?? [] ); if (typeof message === 'string') { @@ -423,7 +423,7 @@ export class DataProducer< dataOffset = FbsDataProducer.SendNotification.createDataVector( builder, - message, + message ); const notificationOffset = @@ -432,14 +432,14 @@ export class DataProducer< ppid, dataOffset, subchannelsOffset, - requiredSubchannel ?? null, + requiredSubchannel ?? null ); this.#channel.notify( FbsNotification.Event.DATAPRODUCER_SEND, FbsNotification.Body.DataProducer_SendNotification, notificationOffset, - this.#internal.dataProducerId, + this.#internal.dataProducerId ); } @@ -449,7 +449,7 @@ export class DataProducer< } export function dataProducerTypeToFbs( - type: DataProducerType, + type: DataProducerType ): FbsDataProducer.Type { switch (type) { case 'sctp': { @@ -467,7 +467,7 @@ export function dataProducerTypeToFbs( } export function dataProducerTypeFromFbs( - type: FbsDataProducer.Type, + type: FbsDataProducer.Type ): DataProducerType { switch (type) { case FbsDataProducer.Type.SCTP: { @@ -481,7 +481,7 @@ export function dataProducerTypeFromFbs( } export function parseDataProducerDumpResponse( - data: FbsDataProducer.DumpResponse, + data: FbsDataProducer.DumpResponse ): DataProducerDump { return { id: data.id()!, @@ -497,7 +497,7 @@ export function parseDataProducerDumpResponse( } function parseDataProducerStats( - binary: FbsDataProducer.GetStatsResponse, + binary: FbsDataProducer.GetStatsResponse ): DataProducerStat { return { type: 'data-producer', diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 1cea2c9bb3..f37edd379b 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -73,7 +73,7 @@ export class DirectTransport< * @private */ constructor( - options: DirectTransportConstructorOptions, + options: DirectTransportConstructorOptions ) { super(options); @@ -123,7 +123,7 @@ export class DirectTransport< FbsRequest.Method.TRANSPORT_DUMP, undefined, undefined, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -146,7 +146,7 @@ export class DirectTransport< FbsRequest.Method.TRANSPORT_GET_STATS, undefined, undefined, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -172,7 +172,7 @@ export class DirectTransport< // eslint-disable-next-line @typescript-eslint/no-unused-vars async setMaxIncomingBitrate(bitrate: number): Promise { throw new UnsupportedError( - 'setMaxIncomingBitrate() not implemented in DirectTransport', + 'setMaxIncomingBitrate() not implemented in DirectTransport' ); } @@ -182,7 +182,7 @@ export class DirectTransport< // eslint-disable-next-line @typescript-eslint/no-unused-vars async setMaxOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( - 'setMaxOutgoingBitrate() not implemented in DirectTransport', + 'setMaxOutgoingBitrate() not implemented in DirectTransport' ); } @@ -192,7 +192,7 @@ export class DirectTransport< // eslint-disable-next-line @typescript-eslint/no-unused-vars async setMinOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( - 'setMinOutgoingBitrate() not implemented in DirectTransport', + 'setMinOutgoingBitrate() not implemented in DirectTransport' ); } @@ -207,19 +207,19 @@ export class DirectTransport< const builder = this.channel.bufferBuilder; const dataOffset = FbsTransport.SendRtcpNotification.createDataVector( builder, - rtcpPacket, + rtcpPacket ); const notificationOffset = FbsTransport.SendRtcpNotification.createSendRtcpNotification( builder, - dataOffset, + dataOffset ); this.channel.notify( FbsNotification.Event.TRANSPORT_SEND_RTCP, FbsNotification.Body.Transport_SendRtcpNotification, notificationOffset, - this.internal.transportId, + this.internal.transportId ); } @@ -261,19 +261,19 @@ export class DirectTransport< logger.error('ignoring unknown event "%s"', event); } } - }, + } ); } } export function parseDirectTransportDumpResponse( - binary: FbsDirectTransport.DumpResponse, + binary: FbsDirectTransport.DumpResponse ): BaseTransportDump { return parseBaseTransportDump(binary.base()!); } function parseGetStatsResponse( - binary: FbsDirectTransport.GetStatsResponse, + binary: FbsDirectTransport.GetStatsResponse ): DirectTransportStat { const base = parseBaseTransportStats(binary.base()!); diff --git a/node/src/EnhancedEventEmitter.ts b/node/src/EnhancedEventEmitter.ts index a0dce20193..f5d1f688a3 100644 --- a/node/src/EnhancedEventEmitter.ts +++ b/node/src/EnhancedEventEmitter.ts @@ -27,7 +27,7 @@ export class EnhancedEventEmitter< logger.error( 'safeEmit() | event listener threw an error [eventName:%s]:%o', eventName, - error, + error ); try { @@ -42,7 +42,7 @@ export class EnhancedEventEmitter< on( eventName: K, - listener: (...args: E[K]) => void, + listener: (...args: E[K]) => void ): this { super.on(eventName, listener as (...args: any[]) => void); @@ -51,7 +51,7 @@ export class EnhancedEventEmitter< off( eventName: K, - listener: (...args: E[K]) => void, + listener: (...args: E[K]) => void ): this { super.off(eventName, listener as (...args: any[]) => void); @@ -60,7 +60,7 @@ export class EnhancedEventEmitter< addListener( eventName: K, - listener: (...args: E[K]) => void, + listener: (...args: E[K]) => void ): this { super.on(eventName, listener as (...args: any[]) => void); @@ -69,7 +69,7 @@ export class EnhancedEventEmitter< prependListener( eventName: K, - listener: (...args: E[K]) => void, + listener: (...args: E[K]) => void ): this { super.prependListener(eventName, listener as (...args: any[]) => void); @@ -78,7 +78,7 @@ export class EnhancedEventEmitter< once( eventName: K, - listener: (...args: E[K]) => void, + listener: (...args: E[K]) => void ): this { super.once(eventName, listener as (...args: any[]) => void); @@ -87,7 +87,7 @@ export class EnhancedEventEmitter< prependOnceListener( eventName: K, - listener: (...args: E[K]) => void, + listener: (...args: E[K]) => void ): this { super.prependOnceListener(eventName, listener as (...args: any[]) => void); @@ -96,7 +96,7 @@ export class EnhancedEventEmitter< removeListener( eventName: K, - listener: (...args: E[K]) => void, + listener: (...args: E[K]) => void ): this { super.off(eventName, listener as (...args: any[]) => void); diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index b801a83ed6..3bd9eb0dd1 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -262,7 +262,7 @@ export class PipeTransport< FbsRequest.Method.TRANSPORT_GET_STATS, undefined, undefined, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -301,7 +301,7 @@ export class PipeTransport< FbsRequest.Method.PIPETRANSPORT_CONNECT, FbsRequest.Body.PipeTransport_ConnectRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -357,7 +357,7 @@ export class PipeTransport< FbsRequest.Method.TRANSPORT_CONSUME, FbsRequest.Body.Transport_ConsumeRequest, consumeRequestOffset, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -437,7 +437,7 @@ export class PipeTransport< logger.error('ignoring unknown event "%s"', event); } } - }, + } ); } } @@ -447,7 +447,7 @@ export class PipeTransport< */ export function parsePipeTransportDumpResponse( - binary: FbsPipeTransport.DumpResponse, + binary: FbsPipeTransport.DumpResponse ): PipeTransportDump { // Retrieve BaseTransportDump. const baseTransportDump = parseBaseTransportDump(binary.base()!); @@ -470,7 +470,7 @@ export function parsePipeTransportDumpResponse( } function parseGetStatsResponse( - binary: FbsPipeTransport.GetStatsResponse, + binary: FbsPipeTransport.GetStatsResponse ): PipeTransportStat { const base = parseBaseTransportStats(binary.base()!); @@ -501,7 +501,7 @@ function createConsumeRequest({ if (producer.consumableRtpParameters.encodings) { consumableRtpEncodingsOffset = serializeRtpEncodingParameters( builder, - producer.consumableRtpParameters.encodings, + producer.consumableRtpParameters.encodings ); } @@ -513,7 +513,7 @@ function createConsumeRequest({ ConsumeRequest.addProducerId(builder, producerIdOffset); ConsumeRequest.addKind( builder, - producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO, + producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO ); ConsumeRequest.addRtpParameters(builder, rtpParametersOffset); ConsumeRequest.addType(builder, FbsRtpParameters.Type.PIPE); @@ -521,7 +521,7 @@ function createConsumeRequest({ if (consumableRtpEncodingsOffset) { ConsumeRequest.addConsumableRtpEncodings( builder, - consumableRtpEncodingsOffset, + consumableRtpEncodingsOffset ); } @@ -561,7 +561,7 @@ function createConnectRequest({ if (srtpParameters) { FbsPipeTransport.ConnectRequest.addSrtpParameters( builder, - srtpParametersOffset, + srtpParametersOffset ); } diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index 3f6f4382b4..7d118207c0 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -175,7 +175,7 @@ export class PlainTransport< * @private */ constructor( - options: PlainTransportConstructorOptions, + options: PlainTransportConstructorOptions ) { super(options); @@ -276,7 +276,7 @@ export class PlainTransport< FbsRequest.Method.TRANSPORT_DUMP, undefined, undefined, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -299,7 +299,7 @@ export class PlainTransport< FbsRequest.Method.TRANSPORT_GET_STATS, undefined, undefined, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -341,7 +341,7 @@ export class PlainTransport< FbsRequest.Method.PLAINTRANSPORT_CONNECT, FbsRequest.Body.PlainTransport_ConnectRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -438,13 +438,13 @@ export class PlainTransport< logger.error('ignoring unknown event "%s"', event); } } - }, + } ); } } export function parsePlainTransportDumpResponse( - binary: FbsPlainTransport.DumpResponse, + binary: FbsPlainTransport.DumpResponse ): PlainTransportDump { // Retrieve BaseTransportDump. const baseTransportDump = parseBaseTransportDump(binary.base()!); @@ -476,7 +476,7 @@ export function parsePlainTransportDumpResponse( } function parseGetStatsResponse( - binary: FbsPlainTransport.GetStatsResponse, + binary: FbsPlainTransport.GetStatsResponse ): PlainTransportStat { const base = parseBaseTransportStats(binary.base()!); @@ -528,7 +528,7 @@ function createConnectRequest({ if (srtpParameters) { FbsPlainTransport.ConnectRequest.addSrtpParameters( builder, - srtpParametersOffset, + srtpParametersOffset ); } diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 7c08d427d2..a36f7c5a75 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -333,7 +333,7 @@ export class Producer< /* Build Request. */ const requestOffset = new FbsTransport.CloseProducerRequestT( - this.#internal.producerId, + this.#internal.producerId ).pack(this.#channel.bufferBuilder); this.#channel @@ -341,7 +341,7 @@ export class Producer< FbsRequest.Method.TRANSPORT_CLOSE_PRODUCER, FbsRequest.Body.Transport_CloseProducerRequest, requestOffset, - this.#internal.transportId, + this.#internal.transportId ) .catch(() => {}); @@ -384,7 +384,7 @@ export class Producer< FbsRequest.Method.PRODUCER_DUMP, undefined, undefined, - this.#internal.producerId, + this.#internal.producerId ); /* Decode Response. */ @@ -405,7 +405,7 @@ export class Producer< FbsRequest.Method.PRODUCER_GET_STATS, undefined, undefined, - this.#internal.producerId, + this.#internal.producerId ); /* Decode Response. */ @@ -426,7 +426,7 @@ export class Producer< FbsRequest.Method.PRODUCER_PAUSE, undefined, undefined, - this.#internal.producerId, + this.#internal.producerId ); const wasPaused = this.#paused; @@ -449,7 +449,7 @@ export class Producer< FbsRequest.Method.PRODUCER_RESUME, undefined, undefined, - this.#internal.producerId, + this.#internal.producerId ); const wasPaused = this.#paused; @@ -488,14 +488,14 @@ export class Producer< /* Build Request. */ const requestOffset = new FbsProducer.EnableTraceEventRequestT( - fbsEventTypes, + fbsEventTypes ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.PRODUCER_ENABLE_TRACE_EVENT, FbsRequest.Body.Producer_EnableTraceEventRequest, requestOffset, - this.#internal.producerId, + this.#internal.producerId ); } @@ -510,7 +510,7 @@ export class Producer< const builder = this.#channel.bufferBuilder; const dataOffset = FbsProducer.SendNotification.createDataVector( builder, - rtpPacket, + rtpPacket ); const notificationOffset = FbsProducer.SendNotification.createSendNotification(builder, dataOffset); @@ -519,7 +519,7 @@ export class Producer< FbsNotification.Event.PRODUCER_SEND, FbsNotification.Body.Producer_SendNotification, notificationOffset, - this.#internal.producerId, + this.#internal.producerId ); } @@ -536,7 +536,7 @@ export class Producer< const score: ProducerScore[] = utils.parseVector( notification, 'scores', - parseProducerScore, + parseProducerScore ); this.#score = score; @@ -586,7 +586,7 @@ export class Producer< logger.error('ignoring unknown event "%s"', event); } } - }, + } ); } } @@ -628,7 +628,7 @@ export function producerTypeToFbs(type: ProducerType): FbsRtpParameters.Type { } function producerTraceEventTypeToFbs( - eventType: ProducerTraceEventType, + eventType: ProducerTraceEventType ): FbsProducer.TraceEventType { switch (eventType) { case 'keyframe': { @@ -662,7 +662,7 @@ function producerTraceEventTypeToFbs( } function producerTraceEventTypeFromFbs( - eventType: FbsProducer.TraceEventType, + eventType: FbsProducer.TraceEventType ): ProducerTraceEventType { switch (eventType) { case FbsProducer.TraceEventType.KEYFRAME: { @@ -692,7 +692,7 @@ function producerTraceEventTypeFromFbs( } export function parseProducerDump( - data: FbsProducer.DumpResponse, + data: FbsProducer.DumpResponse ): ProducerDump { return { id: data.id()!, @@ -707,20 +707,20 @@ export function parseProducerDump( rtpStreams: data.rtpStreamsLength() > 0 ? utils.parseVector(data, 'rtpStreams', (rtpStream: any) => - rtpStream.unpack(), + rtpStream.unpack() ) : undefined, traceEventTypes: utils.parseVector( data, 'traceEventTypes', - producerTraceEventTypeFromFbs, + producerTraceEventTypeFromFbs ), paused: data.paused(), }; } function parseProducerStats( - binary: FbsProducer.GetStatsResponse, + binary: FbsProducer.GetStatsResponse ): ProducerStat[] { return utils.parseVector(binary, 'stats', parseRtpStreamRecvStats); } @@ -735,7 +735,7 @@ function parseProducerScore(binary: FbsProducer.Score): ProducerScore { } function parseTraceEventData( - trace: FbsProducer.TraceNotification, + trace: FbsProducer.TraceNotification ): ProducerTraceEventData { let info: any; diff --git a/node/src/Router.ts b/node/src/Router.ts index 6afa5a3e41..6ed415e540 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -340,14 +340,14 @@ export class Router< this.#closed = true; const requestOffset = new FbsWorker.CloseRouterRequestT( - this.#internal.routerId, + this.#internal.routerId ).pack(this.#channel.bufferBuilder); this.#channel .request( FbsRequest.Method.WORKER_CLOSE_ROUTER, FbsRequest.Body.Worker_CloseRouterRequest, - requestOffset, + requestOffset ) .catch(() => {}); @@ -424,7 +424,7 @@ export class Router< FbsRequest.Method.ROUTER_DUMP, undefined, undefined, - this.#internal.routerId, + this.#internal.routerId ); /* Decode Response. */ @@ -466,11 +466,11 @@ export class Router< !Array.isArray(listenIps) ) { throw new TypeError( - 'missing webRtcServer, listenInfos and listenIps (one of them is mandatory)', + 'missing webRtcServer, listenInfos and listenIps (one of them is mandatory)' ); } else if (webRtcServer && listenInfos && listenIps) { throw new TypeError( - 'only one of webRtcServer, listenInfos and listenIps must be given', + 'only one of webRtcServer, listenInfos and listenIps must be given' ); } else if ( numSctpStreams && @@ -545,7 +545,7 @@ export class Router< if (webRtcServer) { webRtcTransportListenServer = new FbsWebRtcTransport.ListenServerT( - webRtcServer.id, + webRtcServer.id ); } else { const fbsListenInfos: FbsTransport.ListenInfoT[] = []; @@ -561,8 +561,8 @@ export class Router< listenInfo.port, socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, - listenInfo.recvBufferSize, - ), + listenInfo.recvBufferSize + ) ); } @@ -577,11 +577,11 @@ export class Router< enableSctp, new FbsSctpParameters.NumSctpStreamsT( numSctpStreams.OS, - numSctpStreams.MIS, + numSctpStreams.MIS ), maxSctpMessageSize, sctpSendBufferSize, - true /* isDataChannel */, + true /* isDataChannel */ ); const webRtcTransportOptions = @@ -596,12 +596,12 @@ export class Router< enableUdp, enableTcp, preferUdp, - preferTcp, + preferTcp ); const requestOffset = new FbsRouter.CreateWebRtcTransportRequestT( transportId, - webRtcTransportOptions, + webRtcTransportOptions ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( @@ -610,7 +610,7 @@ export class Router< : FbsRequest.Method.ROUTER_CREATE_WEBRTCTRANSPORT, FbsRequest.Body.Router_CreateWebRtcTransportRequest, requestOffset, - this.#internal.routerId, + this.#internal.routerId ); /* Decode Response. */ @@ -639,19 +639,19 @@ export class Router< this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); transport.on('@listenserverclose', () => - this.#transports.delete(transport.id), + this.#transports.delete(transport.id) ); transport.on('@newproducer', (producer: Producer) => - this.#producers.set(producer.id, producer), + this.#producers.set(producer.id, producer) ); transport.on('@producerclose', (producer: Producer) => - this.#producers.delete(producer.id), + this.#producers.delete(producer.id) ); transport.on('@newdataproducer', (dataProducer: DataProducer) => - this.#dataProducers.set(dataProducer.id, dataProducer), + this.#dataProducers.set(dataProducer.id, dataProducer) ); transport.on('@dataproducerclose', (dataProducer: DataProducer) => - this.#dataProducers.delete(dataProducer.id), + this.#dataProducers.delete(dataProducer.id) ); // Emit observer event. @@ -688,7 +688,7 @@ export class Router< if (!listenInfo && !listenIp) { throw new TypeError( - 'missing listenInfo and listenIp (one of them is mandatory)', + 'missing listenInfo and listenIp (one of them is mandatory)' ); } else if (listenInfo && listenIp) { throw new TypeError('only one of listenInfo and listenIp must be given'); @@ -699,7 +699,7 @@ export class Router< // If rtcpMux is enabled, ignore rtcpListenInfo. if (rtcpMux && rtcpListenInfo) { logger.warn( - 'createPlainTransport() | ignoring rtcpMux since rtcpListenInfo is given', + 'createPlainTransport() | ignoring rtcpMux since rtcpListenInfo is given' ); rtcpMux = false; @@ -730,11 +730,11 @@ export class Router< enableSctp, new FbsSctpParameters.NumSctpStreamsT( numSctpStreams.OS, - numSctpStreams.MIS, + numSctpStreams.MIS ), maxSctpMessageSize, sctpSendBufferSize, - false /* isDataChannel */, + false /* isDataChannel */ ); const plainTransportOptions = new FbsPlainTransport.PlainTransportOptionsT( @@ -748,7 +748,7 @@ export class Router< listenInfo!.port, socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, - listenInfo!.recvBufferSize, + listenInfo!.recvBufferSize ), rtcpListenInfo ? new FbsTransport.ListenInfoT( @@ -760,25 +760,25 @@ export class Router< rtcpListenInfo.port, socketFlagsToFbs(rtcpListenInfo.flags), rtcpListenInfo.sendBufferSize, - rtcpListenInfo.recvBufferSize, + rtcpListenInfo.recvBufferSize ) : undefined, rtcpMux, comedia, enableSrtp, - cryptoSuiteToFbs(srtpCryptoSuite), + cryptoSuiteToFbs(srtpCryptoSuite) ); const requestOffset = new FbsRouter.CreatePlainTransportRequestT( transportId, - plainTransportOptions, + plainTransportOptions ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_PLAINTRANSPORT, FbsRequest.Body.Router_CreatePlainTransportRequest, requestOffset, - this.#internal.routerId, + this.#internal.routerId ); /* Decode Response. */ @@ -807,19 +807,19 @@ export class Router< this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); transport.on('@listenserverclose', () => - this.#transports.delete(transport.id), + this.#transports.delete(transport.id) ); transport.on('@newproducer', (producer: Producer) => - this.#producers.set(producer.id, producer), + this.#producers.set(producer.id, producer) ); transport.on('@producerclose', (producer: Producer) => - this.#producers.delete(producer.id), + this.#producers.delete(producer.id) ); transport.on('@newdataproducer', (dataProducer: DataProducer) => - this.#dataProducers.set(dataProducer.id, dataProducer), + this.#dataProducers.set(dataProducer.id, dataProducer) ); transport.on('@dataproducerclose', (dataProducer: DataProducer) => - this.#dataProducers.delete(dataProducer.id), + this.#dataProducers.delete(dataProducer.id) ); // Emit observer event. @@ -849,7 +849,7 @@ export class Router< if (!listenInfo && !listenIp) { throw new TypeError( - 'missing listenInfo and listenIp (one of them is mandatory)', + 'missing listenInfo and listenIp (one of them is mandatory)' ); } else if (listenInfo && listenIp) { throw new TypeError('only one of listenInfo and listenIp must be given'); @@ -882,11 +882,11 @@ export class Router< enableSctp, new FbsSctpParameters.NumSctpStreamsT( numSctpStreams.OS, - numSctpStreams.MIS, + numSctpStreams.MIS ), maxSctpMessageSize, sctpSendBufferSize, - false /* isDataChannel */, + false /* isDataChannel */ ); const pipeTransportOptions = new FbsPipeTransport.PipeTransportOptionsT( @@ -900,22 +900,22 @@ export class Router< listenInfo!.port, socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, - listenInfo!.recvBufferSize, + listenInfo!.recvBufferSize ), enableRtx, - enableSrtp, + enableSrtp ); const requestOffset = new FbsRouter.CreatePipeTransportRequestT( transportId, - pipeTransportOptions, + pipeTransportOptions ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_PIPETRANSPORT, FbsRequest.Body.Router_CreatePipeTransportRequest, requestOffset, - this.#internal.routerId, + this.#internal.routerId ); /* Decode Response. */ @@ -944,19 +944,19 @@ export class Router< this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); transport.on('@listenserverclose', () => - this.#transports.delete(transport.id), + this.#transports.delete(transport.id) ); transport.on('@newproducer', (producer: Producer) => - this.#producers.set(producer.id, producer), + this.#producers.set(producer.id, producer) ); transport.on('@producerclose', (producer: Producer) => - this.#producers.delete(producer.id), + this.#producers.delete(producer.id) ); transport.on('@newdataproducer', (dataProducer: DataProducer) => - this.#dataProducers.set(dataProducer.id, dataProducer), + this.#dataProducers.set(dataProducer.id, dataProducer) ); transport.on('@dataproducerclose', (dataProducer: DataProducer) => - this.#dataProducers.delete(dataProducer.id), + this.#dataProducers.delete(dataProducer.id) ); // Emit observer event. @@ -974,7 +974,7 @@ export class Router< appData, }: DirectTransportOptions = { maxMessageSize: 262144, - }, + } ): Promise> { logger.debug('createDirectTransport()'); @@ -995,7 +995,7 @@ export class Router< undefined /* numSctpStreams */, undefined /* maxSctpMessageSize */, undefined /* sctpSendBufferSize */, - undefined /* isDataChannel */, + undefined /* isDataChannel */ ); const directTransportOptions = @@ -1003,14 +1003,14 @@ export class Router< const requestOffset = new FbsRouter.CreateDirectTransportRequestT( transportId, - directTransportOptions, + directTransportOptions ).pack(this.#channel.bufferBuilder); const response = await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_DIRECTTRANSPORT, FbsRequest.Body.Router_CreateDirectTransportRequest, requestOffset, - this.#internal.routerId, + this.#internal.routerId ); /* Decode Response. */ @@ -1039,19 +1039,19 @@ export class Router< this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); transport.on('@listenserverclose', () => - this.#transports.delete(transport.id), + this.#transports.delete(transport.id) ); transport.on('@newproducer', (producer: Producer) => - this.#producers.set(producer.id, producer), + this.#producers.set(producer.id, producer) ); transport.on('@producerclose', (producer: Producer) => - this.#producers.delete(producer.id), + this.#producers.delete(producer.id) ); transport.on('@newdataproducer', (dataProducer: DataProducer) => - this.#dataProducers.set(dataProducer.id, dataProducer), + this.#dataProducers.set(dataProducer.id, dataProducer) ); transport.on('@dataproducerclose', (dataProducer: DataProducer) => - this.#dataProducers.delete(dataProducer.id), + this.#dataProducers.delete(dataProducer.id) ); // Emit observer event. @@ -1177,14 +1177,14 @@ export class Router< localPipeTransport.observer.on('close', () => { remotePipeTransport.close(); this.#mapRouterPairPipeTransportPairPromise.delete( - pipeTransportPairKey, + pipeTransportPairKey ); }); remotePipeTransport.observer.on('close', () => { localPipeTransport.close(); this.#mapRouterPairPipeTransportPairPromise.delete( - pipeTransportPairKey, + pipeTransportPairKey ); }); @@ -1196,7 +1196,7 @@ export class Router< .catch(error => { logger.error( 'pipeToRouter() | error creating PipeTransport pair:%o', - error, + error ); if (localPipeTransport) { @@ -1213,7 +1213,7 @@ export class Router< this.#mapRouterPairPipeTransportPairPromise.set( pipeTransportPairKey, - pipeTransportPairPromise, + pipeTransportPairPromise ); router.addPipeTransportPair(this.id, pipeTransportPairPromise); @@ -1265,7 +1265,7 @@ export class Router< } catch (error) { logger.error( 'pipeToRouter() | error creating pipe Consumer/Producer pair:%o', - error, + error ); if (pipeConsumer) { @@ -1310,7 +1310,7 @@ export class Router< } catch (error) { logger.error( 'pipeToRouter() | error creating pipe DataConsumer/DataProducer pair:%o', - error, + error ); if (pipeDataConsumer) { @@ -1333,17 +1333,17 @@ export class Router< */ addPipeTransportPair( pipeTransportPairKey: string, - pipeTransportPairPromise: Promise, + pipeTransportPairPromise: Promise ): void { if (this.#mapRouterPairPipeTransportPairPromise.has(pipeTransportPairKey)) { throw new Error( - 'given pipeTransportPairKey already exists in this Router', + 'given pipeTransportPairKey already exists in this Router' ); } this.#mapRouterPairPipeTransportPairPromise.set( pipeTransportPairKey, - pipeTransportPairPromise, + pipeTransportPairPromise ); pipeTransportPairPromise @@ -1354,13 +1354,13 @@ export class Router< // Router calling this method on us. localPipeTransport.observer.on('close', () => { this.#mapRouterPairPipeTransportPairPromise.delete( - pipeTransportPairKey, + pipeTransportPairKey ); }); }) .catch(() => { this.#mapRouterPairPipeTransportPairPromise.delete( - pipeTransportPairKey, + pipeTransportPairKey ); }); } @@ -1392,14 +1392,14 @@ export class Router< const requestOffset = new FbsRouter.CreateActiveSpeakerObserverRequestT( rtpObserverId, - activeRtpObserverOptions, + activeRtpObserverOptions ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_ACTIVESPEAKEROBSERVER, FbsRequest.Body.Router_CreateActiveSpeakerObserverRequest, requestOffset, - this.#internal.routerId, + this.#internal.routerId ); const activeSpeakerObserver = @@ -1448,7 +1448,7 @@ export class Router< threshold > 0 ) { throw new TypeError( - 'if given, threshole must be a negative number greater than -127', + 'if given, threshole must be a negative number greater than -127' ); } else if (typeof interval !== 'number') { throw new TypeError('if given, interval must be an number'); @@ -1463,19 +1463,19 @@ export class Router< new FbsAudioLevelObserver.AudioLevelObserverOptionsT( maxEntries, threshold, - interval, + interval ); const requestOffset = new FbsRouter.CreateAudioLevelObserverRequestT( rtpObserverId, - audioLevelObserverOptions, + audioLevelObserverOptions ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.ROUTER_CREATE_AUDIOLEVELOBSERVER, FbsRequest.Body.Router_CreateAudioLevelObserverRequest, requestOffset, - this.#internal.routerId, + this.#internal.routerId ); const audioLevelObserver = @@ -1516,7 +1516,7 @@ export class Router< if (!producer) { logger.error( 'canConsume() | Producer with id "%s" not found', - producerId, + producerId ); return false; @@ -1528,7 +1528,7 @@ export class Router< try { return ortc.canConsume( producer.consumableRtpParameters, - clonedRtpCapabilities, + clonedRtpCapabilities ); } catch (error) { logger.error('canConsume() | unexpected error: %s', String(error)); @@ -1539,7 +1539,7 @@ export class Router< } export function parseRouterDumpResponse( - binary: FbsRouter.DumpResponse, + binary: FbsRouter.DumpResponse ): RouterDump { return { id: binary.id()!, @@ -1547,32 +1547,32 @@ export function parseRouterDumpResponse( rtpObserverIds: parseVector(binary, 'rtpObserverIds'), mapProducerIdConsumerIds: parseStringStringArrayVector( binary, - 'mapProducerIdConsumerIds', + 'mapProducerIdConsumerIds' ), mapConsumerIdProducerId: parseStringStringVector( binary, - 'mapConsumerIdProducerId', + 'mapConsumerIdProducerId' ), mapProducerIdObserverIds: parseStringStringArrayVector( binary, - 'mapProducerIdObserverIds', + 'mapProducerIdObserverIds' ), mapDataProducerIdDataConsumerIds: parseStringStringArrayVector( binary, - 'mapDataProducerIdDataConsumerIds', + 'mapDataProducerIdDataConsumerIds' ), mapDataConsumerIdDataProducerId: parseStringStringVector( binary, - 'mapDataConsumerIdDataProducerId', + 'mapDataConsumerIdDataProducerId' ), }; } export function socketFlagsToFbs( - flags: TransportSocketFlags = {}, + flags: TransportSocketFlags = {} ): FbsTransport.SocketFlagsT { return new FbsTransport.SocketFlagsT( Boolean(flags.ipv6Only), - Boolean(flags.udpReusePort), + Boolean(flags.udpReusePort) ); } diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 3243ef3727..705488f0d4 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -64,7 +64,7 @@ export class RtpObserver< // Method to retrieve a Producer. protected readonly getProducerById: ( - producerId: string, + producerId: string ) => Producer | undefined; // Observer instance. @@ -149,7 +149,7 @@ export class RtpObserver< /* Build Request. */ const requestOffset = new FbsRouter.CloseRtpObserverRequestT( - this.internal.rtpObserverId, + this.internal.rtpObserverId ).pack(this.channel.bufferBuilder); this.channel @@ -157,7 +157,7 @@ export class RtpObserver< FbsRequest.Method.ROUTER_CLOSE_RTPOBSERVER, FbsRequest.Body.Router_CloseRtpObserverRequest, requestOffset, - this.internal.routerId, + this.internal.routerId ) .catch(() => {}); @@ -202,7 +202,7 @@ export class RtpObserver< FbsRequest.Method.RTPOBSERVER_PAUSE, undefined, undefined, - this.internal.rtpObserverId, + this.internal.rtpObserverId ); this.#paused = true; @@ -225,7 +225,7 @@ export class RtpObserver< FbsRequest.Method.RTPOBSERVER_RESUME, undefined, undefined, - this.internal.rtpObserverId, + this.internal.rtpObserverId ); this.#paused = false; @@ -251,14 +251,14 @@ export class RtpObserver< } const requestOffset = new FbsRtpObserver.AddProducerRequestT( - producerId, + producerId ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.RTPOBSERVER_ADD_PRODUCER, FbsRequest.Body.RtpObserver_AddProducerRequest, requestOffset, - this.internal.rtpObserverId, + this.internal.rtpObserverId ); // Emit observer event. @@ -280,14 +280,14 @@ export class RtpObserver< } const requestOffset = new FbsRtpObserver.RemoveProducerRequestT( - producerId, + producerId ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.RTPOBSERVER_REMOVE_PRODUCER, FbsRequest.Body.RtpObserver_RemoveProducerRequest, requestOffset, - this.internal.rtpObserverId, + this.internal.rtpObserverId ); // Emit observer event. diff --git a/node/src/RtpParameters.ts b/node/src/RtpParameters.ts index 8978aea24d..0c0ea65532 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/RtpParameters.ts @@ -377,7 +377,7 @@ export type RtcpParameters = { export function serializeRtpParameters( builder: flatbuffers.Builder, - rtpParameters: RtpParameters, + rtpParameters: RtpParameters ): number { const codecs: number[] = []; const headerExtensions: number[] = []; @@ -387,7 +387,7 @@ export function serializeRtpParameters( const parameters = serializeParameters(builder, codec.parameters); const parametersOffset = FbsRtpCodecParameters.createParametersVector( builder, - parameters, + parameters ); const rtcpFeedback: number[] = []; @@ -400,13 +400,13 @@ export function serializeRtpParameters( FbsRtcpFeedback.createRtcpFeedback( builder, typeOffset, - rtcpParametersOffset, - ), + rtcpParametersOffset + ) ); } const rtcpFeedbackOffset = FbsRtpCodecParameters.createRtcpFeedbackVector( builder, - rtcpFeedback, + rtcpFeedback ); codecs.push( @@ -417,8 +417,8 @@ export function serializeRtpParameters( codec.clockRate, Number(codec.channels), parametersOffset, - rtcpFeedbackOffset, - ), + rtcpFeedbackOffset + ) ); } const codecsOffset = FbsRtpParameters.createCodecsVector(builder, codecs); @@ -429,7 +429,7 @@ export function serializeRtpParameters( const parameters = serializeParameters(builder, headerExtension.parameters); const parametersOffset = FbsRtpCodecParameters.createParametersVector( builder, - parameters, + parameters ); headerExtensions.push( @@ -438,19 +438,19 @@ export function serializeRtpParameters( uri, headerExtension.id, Boolean(headerExtension.encrypt), - parametersOffset, - ), + parametersOffset + ) ); } const headerExtensionsOffset = FbsRtpParameters.createHeaderExtensionsVector( builder, - headerExtensions, + headerExtensions ); // RtpEncodingParameters. const encodingsOffset = serializeRtpEncodingParameters( builder, - rtpParameters.encodings ?? [], + rtpParameters.encodings ?? [] ); // RtcpParameters. @@ -460,7 +460,7 @@ export function serializeRtpParameters( const rtcpOffset = FbsRtcpParameters.createRtcpParameters( builder, cnameOffset, - Boolean(reducedSize), + Boolean(reducedSize) ); const midOffset = builder.createString(rtpParameters.mid); @@ -478,7 +478,7 @@ export function serializeRtpParameters( export function serializeRtpEncodingParameters( builder: flatbuffers.Builder, - rtpEncodingParameters: RtpEncodingParameters[] = [], + rtpEncodingParameters: RtpEncodingParameters[] = [] ): number { const encodings: number[] = []; @@ -515,7 +515,7 @@ export function serializeRtpEncodingParameters( if (encoding.codecPayloadType) { FbsRtpEncodingParameters.addCodecPayloadType( builder, - encoding.codecPayloadType, + encoding.codecPayloadType ); } @@ -533,7 +533,7 @@ export function serializeRtpEncodingParameters( if (scalabilityModeOffset) { FbsRtpEncodingParameters.addScalabilityMode( builder, - scalabilityModeOffset, + scalabilityModeOffset ); } @@ -551,7 +551,7 @@ export function serializeRtpEncodingParameters( export function serializeParameters( builder: flatbuffers.Builder, - parameters: any, + parameters: any ): number[] { const fbsParameters: number[] = []; @@ -565,7 +565,7 @@ export function serializeParameters( builder, keyOffset, FbsValue.Boolean, - value === true ? 1 : 0, + value === true ? 1 : 0 ); } else if (typeof value === 'number') { // Integer. @@ -576,7 +576,7 @@ export function serializeParameters( builder, keyOffset, FbsValue.Integer32, - valueOffset, + valueOffset ); } // Float. @@ -587,20 +587,20 @@ export function serializeParameters( builder, keyOffset, FbsValue.Double, - valueOffset, + valueOffset ); } } else if (typeof value === 'string') { const valueOffset = FbsString.createString( builder, - builder.createString(value), + builder.createString(value) ); parameterOffset = FbsParameter.createParameter( builder, keyOffset, FbsValue.String, - valueOffset, + valueOffset ); } else if (Array.isArray(value)) { const valueOffset = FbsInteger32Array.createValueVector(builder, value); @@ -609,7 +609,7 @@ export function serializeParameters( builder, keyOffset, FbsValue.Integer32Array, - valueOffset, + valueOffset ); } else { throw new Error(`invalid parameter type [key:'${key}', value:${value}]`); @@ -691,7 +691,7 @@ export function parseParameters(data: any): any { } export function parseRtpCodecParameters( - data: FbsRtpCodecParameters, + data: FbsRtpCodecParameters ): RtpCodecParameters { const parameters = parseParameters(data); @@ -712,7 +712,7 @@ export function parseRtpCodecParameters( } export function rtpHeaderExtensionUriFromFbs( - uri: FbsRtpHeaderExtensionUri, + uri: FbsRtpHeaderExtensionUri ): RtpHeaderExtensionUri { switch (uri) { case FbsRtpHeaderExtensionUri.Mid: { @@ -762,7 +762,7 @@ export function rtpHeaderExtensionUriFromFbs( } export function rtpHeaderExtensionUriToFbs( - uri: RtpHeaderExtensionUri, + uri: RtpHeaderExtensionUri ): FbsRtpHeaderExtensionUri { switch (uri) { case 'urn:ietf:params:rtp-hdrext:sdes:mid': { @@ -816,7 +816,7 @@ export function rtpHeaderExtensionUriToFbs( } export function parseRtpHeaderExtensionParameters( - data: FbsRtpHeaderExtensionParameters, + data: FbsRtpHeaderExtensionParameters ): RtpHeaderExtensionParameters { return { uri: rtpHeaderExtensionUriFromFbs(data.uri()), @@ -827,7 +827,7 @@ export function parseRtpHeaderExtensionParameters( } export function parseRtpEncodingParameters( - data: FbsRtpEncodingParameters, + data: FbsRtpEncodingParameters ): RtpEncodingParameters { return { ssrc: data.ssrc() ?? undefined, @@ -850,7 +850,7 @@ export function parseRtpParameters(data: FbsRtpParameters): RtpParameters { headerExtensions = utils.parseVector( data, 'headerExtensions', - parseRtpHeaderExtensionParameters, + parseRtpHeaderExtensionParameters ); } @@ -860,7 +860,7 @@ export function parseRtpParameters(data: FbsRtpParameters): RtpParameters { encodings = utils.parseVector( data, 'encodings', - parseRtpEncodingParameters, + parseRtpEncodingParameters ); } diff --git a/node/src/RtpStream.ts b/node/src/RtpStream.ts index f42cb23c36..af0296bb61 100644 --- a/node/src/RtpStream.ts +++ b/node/src/RtpStream.ts @@ -39,7 +39,7 @@ type BaseRtpStreamStats = { }; export function parseRtpStreamStats( - binary: FbsRtpStream.Stats, + binary: FbsRtpStream.Stats ): RtpStreamRecvStats | RtpStreamSendStats { if (binary.dataType() === FbsRtpStream.StatsData.RecvStats) { return parseRtpStreamRecvStats(binary); @@ -49,7 +49,7 @@ export function parseRtpStreamStats( } export function parseRtpStreamRecvStats( - binary: FbsRtpStream.Stats, + binary: FbsRtpStream.Stats ): RtpStreamRecvStats { const recvStats = new FbsRtpStream.RecvStats(); const baseStats = new FbsRtpStream.BaseStats(); @@ -71,7 +71,7 @@ export function parseRtpStreamRecvStats( } export function parseSendStreamStats( - binary: FbsRtpStream.Stats, + binary: FbsRtpStream.Stats ): RtpStreamSendStats { const sendStats = new FbsRtpStream.SendStats(); const baseStats = new FbsRtpStream.BaseStats(); @@ -91,7 +91,7 @@ export function parseSendStreamStats( } function parseBaseStreamStats( - binary: FbsRtpStream.BaseStats, + binary: FbsRtpStream.BaseStats ): BaseRtpStreamStats { return { timestamp: Number(binary.timestamp()), diff --git a/node/src/SctpParameters.ts b/node/src/SctpParameters.ts index ab6daec1d4..849ff20143 100644 --- a/node/src/SctpParameters.ts +++ b/node/src/SctpParameters.ts @@ -104,7 +104,7 @@ export type SctpParametersDump = { }; export function parseSctpParametersDump( - binary: FbsSctpParameters.SctpParameters, + binary: FbsSctpParameters.SctpParameters ): SctpParametersDump { return { port: binary.port(), @@ -119,7 +119,7 @@ export function parseSctpParametersDump( export function serializeSctpStreamParameters( builder: flatbuffers.Builder, - parameters: SctpStreamParameters, + parameters: SctpStreamParameters ): number { return FbsSctpParameters.SctpStreamParameters.createSctpStreamParameters( builder, @@ -130,12 +130,12 @@ export function serializeSctpStreamParameters( : null, typeof parameters.maxRetransmits === 'number' ? parameters.maxRetransmits - : null, + : null ); } export function parseSctpStreamParameters( - parameters: FbsSctpParameters.SctpStreamParameters, + parameters: FbsSctpParameters.SctpStreamParameters ): SctpStreamParameters { return { streamId: parameters.streamId(), diff --git a/node/src/SrtpParameters.ts b/node/src/SrtpParameters.ts index d76baccb1a..1077ed5207 100644 --- a/node/src/SrtpParameters.ts +++ b/node/src/SrtpParameters.ts @@ -26,7 +26,7 @@ export type SrtpCryptoSuite = | 'AES_CM_128_HMAC_SHA1_32'; export function cryptoSuiteFromFbs( - binary: FbsSrtpParameters.SrtpCryptoSuite, + binary: FbsSrtpParameters.SrtpCryptoSuite ): SrtpCryptoSuite { switch (binary) { case FbsSrtpParameters.SrtpCryptoSuite.AEAD_AES_256_GCM: { @@ -48,7 +48,7 @@ export function cryptoSuiteFromFbs( } export function cryptoSuiteToFbs( - cryptoSuite: SrtpCryptoSuite, + cryptoSuite: SrtpCryptoSuite ): FbsSrtpParameters.SrtpCryptoSuite { switch (cryptoSuite) { case 'AEAD_AES_256_GCM': { @@ -74,7 +74,7 @@ export function cryptoSuiteToFbs( } export function parseSrtpParameters( - binary: FbsSrtpParameters.SrtpParameters, + binary: FbsSrtpParameters.SrtpParameters ): SrtpParameters { return { cryptoSuite: cryptoSuiteFromFbs(binary.cryptoSuite()), @@ -84,13 +84,13 @@ export function parseSrtpParameters( export function serializeSrtpParameters( builder: flatbuffers.Builder, - srtpParameters: SrtpParameters, + srtpParameters: SrtpParameters ): number { const keyBase64Offset = builder.createString(srtpParameters.keyBase64); return FbsSrtpParameters.SrtpParameters.createSrtpParameters( builder, cryptoSuiteToFbs(srtpParameters.cryptoSuite), - keyBase64Offset, + keyBase64Offset ); } diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 3da3b248bf..0ba15020c6 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -309,12 +309,12 @@ export class Transport< // Method to retrieve a Producer. protected readonly getProducerById: ( - producerId: string, + producerId: string ) => Producer | undefined; // Method to retrieve a DataProducer. protected readonly getDataProducerById: ( - dataProducerId: string, + dataProducerId: string ) => DataProducer | undefined; // Producers map. @@ -430,7 +430,7 @@ export class Transport< /* Build Request. */ const requestOffset = new FbsRouter.CloseTransportRequestT( - this.internal.transportId, + this.internal.transportId ).pack(this.channel.bufferBuilder); this.channel @@ -438,7 +438,7 @@ export class Transport< FbsRequest.Method.ROUTER_CLOSE_TRANSPORT, FbsRequest.Body.Router_CloseTransportRequest, requestOffset, - this.internal.routerId, + this.internal.routerId ) .catch(() => {}); @@ -632,14 +632,14 @@ export class Transport< const requestOffset = FbsTransport.SetMaxIncomingBitrateRequest.createSetMaxIncomingBitrateRequest( this.channel.bufferBuilder, - bitrate, + bitrate ); await this.channel.request( FbsRequest.Method.TRANSPORT_SET_MAX_INCOMING_BITRATE, FbsRequest.Body.Transport_SetMaxIncomingBitrateRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); } @@ -651,14 +651,14 @@ export class Transport< /* Build Request. */ const requestOffset = new FbsTransport.SetMaxOutgoingBitrateRequestT( - bitrate, + bitrate ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.TRANSPORT_SET_MAX_OUTGOING_BITRATE, FbsRequest.Body.Transport_SetMaxOutgoingBitrateRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); } @@ -670,14 +670,14 @@ export class Transport< /* Build Request. */ const requestOffset = new FbsTransport.SetMinOutgoingBitrateRequestT( - bitrate, + bitrate ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.TRANSPORT_SET_MIN_OUTGOING_BITRATE, FbsRequest.Body.Transport_SetMinOutgoingBitrateRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); } @@ -745,7 +745,7 @@ export class Transport< // This may throw. const rtpMapping = ortc.getProducerRtpParametersMapping( clonedRtpParameters, - routerRtpCapabilities, + routerRtpCapabilities ); // This may throw. @@ -753,7 +753,7 @@ export class Transport< kind, clonedRtpParameters, routerRtpCapabilities, - rtpMapping, + rtpMapping ); const producerId = id || utils.generateUUIDv4(); @@ -771,7 +771,7 @@ export class Transport< FbsRequest.Method.TRANSPORT_PRODUCE, FbsRequest.Body.Transport_ProduceRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -874,7 +874,7 @@ export class Transport< // We use up to 8 bytes for MID (string). if (this.#nextMidForConsumers === 100000000) { logger.error( - `consume() | reaching max MID value "${this.#nextMidForConsumers}"`, + `consume() | reaching max MID value "${this.#nextMidForConsumers}"` ); this.#nextMidForConsumers = 0; @@ -898,7 +898,7 @@ export class Transport< FbsRequest.Method.TRANSPORT_CONSUME, FbsRequest.Body.Transport_ConsumeRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -988,7 +988,7 @@ export class Transport< if (sctpStreamParameters) { logger.warn( - 'produceData() | sctpStreamParameters are ignored when producing data on a DirectTransport', + 'produceData() | sctpStreamParameters are ignored when producing data on a DirectTransport' ); clonedSctpStreamParameters = undefined; @@ -1010,7 +1010,7 @@ export class Transport< FbsRequest.Method.TRANSPORT_PRODUCE_DATA, FbsRequest.Body.Transport_ProduceDataRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -1089,7 +1089,7 @@ export class Transport< sctpStreamParameters = utils.clone( - dataProducer.sctpStreamParameters, + dataProducer.sctpStreamParameters ) ?? ({} as SctpStreamParameters); // Override if given. @@ -1121,7 +1121,7 @@ export class Transport< maxRetransmits !== undefined ) { logger.warn( - 'consumeData() | ordered, maxPacketLifeTime and maxRetransmits are ignored when consuming data on a DirectTransport', + 'consumeData() | ordered, maxPacketLifeTime and maxRetransmits are ignored when consuming data on a DirectTransport' ); } } @@ -1145,7 +1145,7 @@ export class Transport< FbsRequest.Method.TRANSPORT_CONSUME_DATA, FbsRequest.Body.Transport_ConsumeDataRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -1222,14 +1222,14 @@ export class Transport< /* Build Request. */ const requestOffset = new FbsTransport.EnableTraceEventRequestT( - fbsEventTypes, + fbsEventTypes ).pack(this.channel.bufferBuilder); await this.channel.request( FbsRequest.Method.TRANSPORT_ENABLE_TRACE_EVENT, FbsRequest.Body.Transport_EnableTraceEventRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); } @@ -1265,7 +1265,7 @@ export class Transport< } function transportTraceEventTypeToFbs( - eventType: TransportTraceEventType, + eventType: TransportTraceEventType ): FbsTransport.TraceEventType { switch (eventType) { case 'probation': { @@ -1283,7 +1283,7 @@ function transportTraceEventTypeToFbs( } function transportTraceEventTypeFromFbs( - eventType: FbsTransport.TraceEventType, + eventType: FbsTransport.TraceEventType ): TransportTraceEventType { switch (eventType) { case FbsTransport.TraceEventType.PROBATION: { @@ -1325,7 +1325,7 @@ export function parseSctpState(fbsSctpState: FbsSctpState): SctpState { } export function parseProtocol( - protocol: FbsTransport.Protocol, + protocol: FbsTransport.Protocol ): TransportProtocol { switch (protocol) { case FbsTransport.Protocol.UDP: { @@ -1339,7 +1339,7 @@ export function parseProtocol( } export function serializeProtocol( - protocol: TransportProtocol, + protocol: TransportProtocol ): FbsTransport.Protocol { switch (protocol) { case 'udp': { @@ -1363,7 +1363,7 @@ export function parseTuple(binary: FbsTransport.Tuple): TransportTuple { } export function parseBaseTransportDump( - binary: FbsTransport.Dump, + binary: FbsTransport.Dump ): BaseTransportDump { // Retrieve producerIds. const producerIds = utils.parseVector(binary, 'producerIds'); @@ -1372,12 +1372,12 @@ export function parseBaseTransportDump( // Retrieve map SSRC consumerId. const mapSsrcConsumerId = utils.parseUint32StringVector( binary, - 'mapSsrcConsumerId', + 'mapSsrcConsumerId' ); // Retrieve map RTX SSRC consumerId. const mapRtxSsrcConsumerId = utils.parseUint32StringVector( binary, - 'mapRtxSsrcConsumerId', + 'mapRtxSsrcConsumerId' ); // Retrieve dataProducerIds. const dataProducerIds = utils.parseVector(binary, 'dataProducerIds'); @@ -1385,7 +1385,7 @@ export function parseBaseTransportDump( const dataConsumerIds = utils.parseVector(binary, 'dataConsumerIds'); // Retrieve recvRtpHeaderExtesions. const recvRtpHeaderExtensions = parseRecvRtpHeaderExtensions( - binary.recvRtpHeaderExtensions()!, + binary.recvRtpHeaderExtensions()! ); // Retrieve RtpListener. const rtpListener = parseRtpListenerDump(binary.rtpListener()!); @@ -1413,7 +1413,7 @@ export function parseBaseTransportDump( const traceEventTypes = utils.parseVector( binary, 'traceEventTypes', - transportTraceEventTypeFromFbs, + transportTraceEventTypeFromFbs ); return { @@ -1436,7 +1436,7 @@ export function parseBaseTransportDump( } export function parseBaseTransportStats( - binary: FbsTransport.Stats, + binary: FbsTransport.Stats ): BaseTransportStats { const sctpState = binary.sctpState() === null @@ -1470,7 +1470,7 @@ export function parseBaseTransportStats( } export function parseTransportTraceEventData( - trace: FbsTransport.TraceNotification, + trace: FbsTransport.TraceNotification ): TransportTraceEventData { switch (trace.type()) { case FbsTransport.TraceEventType.BWE: { @@ -1500,7 +1500,7 @@ export function parseTransportTraceEventData( } function parseRecvRtpHeaderExtensions( - binary: FbsTransport.RecvRtpHeaderExtensions, + binary: FbsTransport.RecvRtpHeaderExtensions ): RecvRtpHeaderExtensions { return { mid: binary.mid() !== null ? binary.mid()! : undefined, @@ -1568,7 +1568,7 @@ function createConsumeRequest({ if (producer.consumableRtpParameters.encodings) { consumableRtpEncodingsOffset = serializeRtpEncodingParameters( builder, - producer.consumableRtpParameters.encodings, + producer.consumableRtpParameters.encodings ); } @@ -1576,13 +1576,13 @@ function createConsumeRequest({ FbsConsumer.ConsumerLayers.startConsumerLayers(builder); FbsConsumer.ConsumerLayers.addSpatialLayer( builder, - preferredLayers.spatialLayer, + preferredLayers.spatialLayer ); if (preferredLayers.temporalLayer !== undefined) { FbsConsumer.ConsumerLayers.addTemporalLayer( builder, - preferredLayers.temporalLayer, + preferredLayers.temporalLayer ); } @@ -1598,18 +1598,18 @@ function createConsumeRequest({ ConsumeRequest.addProducerId(builder, producerIdOffset); ConsumeRequest.addKind( builder, - producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO, + producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO ); ConsumeRequest.addRtpParameters(builder, rtpParametersOffset); ConsumeRequest.addType( builder, - pipe ? FbsRtpParameters.Type.PIPE : producerTypeToFbs(producer.type), + pipe ? FbsRtpParameters.Type.PIPE : producerTypeToFbs(producer.type) ); if (consumableRtpEncodingsOffset) { ConsumeRequest.addConsumableRtpEncodings( builder, - consumableRtpEncodingsOffset, + consumableRtpEncodingsOffset ); } @@ -1649,13 +1649,13 @@ function createProduceRequest({ FbsTransport.ProduceRequest.addProducerId(builder, producerIdOffset); FbsTransport.ProduceRequest.addKind( builder, - kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO, + kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO ); FbsTransport.ProduceRequest.addRtpParameters(builder, rtpParametersOffset); FbsTransport.ProduceRequest.addRtpMapping(builder, rtpMappingOffset); FbsTransport.ProduceRequest.addKeyFrameRequestDelay( builder, - keyFrameRequestDelay ?? 0, + keyFrameRequestDelay ?? 0 ); FbsTransport.ProduceRequest.addPaused(builder, paused); @@ -1688,21 +1688,21 @@ function createProduceDataRequest({ if (sctpStreamParameters) { sctpStreamParametersOffset = serializeSctpStreamParameters( builder, - sctpStreamParameters, + sctpStreamParameters ); } FbsTransport.ProduceDataRequest.startProduceDataRequest(builder); FbsTransport.ProduceDataRequest.addDataProducerId( builder, - dataProducerIdOffset, + dataProducerIdOffset ); FbsTransport.ProduceDataRequest.addType(builder, dataProducerTypeToFbs(type)); if (sctpStreamParametersOffset) { FbsTransport.ProduceDataRequest.addSctpStreamParameters( builder, - sctpStreamParametersOffset, + sctpStreamParametersOffset ); } @@ -1744,31 +1744,31 @@ function createConsumeDataRequest({ if (sctpStreamParameters) { sctpStreamParametersOffset = serializeSctpStreamParameters( builder, - sctpStreamParameters, + sctpStreamParameters ); } const subchannelsOffset = FbsTransport.ConsumeDataRequest.createSubchannelsVector( builder, - subchannels, + subchannels ); FbsTransport.ConsumeDataRequest.startConsumeDataRequest(builder); FbsTransport.ConsumeDataRequest.addDataConsumerId( builder, - dataConsumerIdOffset, + dataConsumerIdOffset ); FbsTransport.ConsumeDataRequest.addDataProducerId( builder, - dataProducerIdOffset, + dataProducerIdOffset ); FbsTransport.ConsumeDataRequest.addType(builder, dataConsumerTypeToFbs(type)); if (sctpStreamParametersOffset) { FbsTransport.ConsumeDataRequest.addSctpStreamParameters( builder, - sctpStreamParametersOffset, + sctpStreamParametersOffset ); } @@ -1781,7 +1781,7 @@ function createConsumeDataRequest({ } function parseRtpListenerDump( - binary: FbsTransport.RtpListener, + binary: FbsTransport.RtpListener ): RtpListenerDump { // Retrieve ssrcTable. const ssrcTable = utils.parseUint32StringVector(binary, 'ssrcTable'); @@ -1798,7 +1798,7 @@ function parseRtpListenerDump( } function parseSctpListenerDump( - binary: FbsTransport.SctpListener, + binary: FbsTransport.SctpListener ): SctpListenerDump { // Retrieve streamIdTable. const streamIdTable = utils.parseUint32StringVector(binary, 'streamIdTable'); diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index c0984a47f0..bfe2714007 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -170,14 +170,14 @@ export class WebRtcServer< // Build the request. const requestOffset = new FbsWorker.CloseWebRtcServerRequestT( - this.#internal.webRtcServerId, + this.#internal.webRtcServerId ).pack(this.#channel.bufferBuilder); this.#channel .request( Method.WORKER_WEBRTCSERVER_CLOSE, RequestBody.Worker_CloseWebRtcServerRequest, - requestOffset, + requestOffset ) .catch(() => {}); @@ -230,7 +230,7 @@ export class WebRtcServer< Method.WEBRTCSERVER_DUMP, undefined, undefined, - this.#internal.webRtcServerId, + this.#internal.webRtcServerId ); /* Decode Response. */ @@ -267,7 +267,7 @@ function parseIpPort(binary: FbsWebRtcServer.IpPort): IpPort { } function parseIceUserNameFragment( - binary: FbsWebRtcServer.IceUserNameFragment, + binary: FbsWebRtcServer.IceUserNameFragment ): IceUserNameFragment { return { localIceUsernameFragment: binary.localIceUsernameFragment()!, @@ -283,7 +283,7 @@ function parseTupleHash(binary: FbsWebRtcServer.TupleHash): TupleHash { } function parseWebRtcServerDump( - data: FbsWebRtcServer.DumpResponse, + data: FbsWebRtcServer.DumpResponse ): WebRtcServerDump { return { id: data.id()!, @@ -293,7 +293,7 @@ function parseWebRtcServerDump( localIceUsernameFragments: utils.parseVector( data, 'localIceUsernameFragments', - parseIceUserNameFragment, + parseIceUserNameFragment ), tupleHashes: utils.parseVector(data, 'tupleHashes', parseTupleHash), }; diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 2625e5e4b7..4e37a50763 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -260,7 +260,7 @@ export class WebRtcTransport< * @private */ constructor( - options: WebRtcTransportConstructorOptions, + options: WebRtcTransportConstructorOptions ) { super(options); @@ -428,7 +428,7 @@ export class WebRtcTransport< FbsRequest.Method.TRANSPORT_DUMP, undefined, undefined, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -451,7 +451,7 @@ export class WebRtcTransport< FbsRequest.Method.TRANSPORT_GET_STATS, undefined, undefined, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -484,7 +484,7 @@ export class WebRtcTransport< FbsRequest.Method.WEBRTCTRANSPORT_CONNECT, FbsRequest.Body.WebRtcTransport_ConnectRequest, requestOffset, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -506,7 +506,7 @@ export class WebRtcTransport< FbsRequest.Method.TRANSPORT_RESTART_ICE, undefined, undefined, - this.internal.transportId, + this.internal.transportId ); /* Decode Response. */ @@ -624,7 +624,7 @@ export class WebRtcTransport< logger.error('ignoring unknown event "%s"', event); } } - }, + } ); } } @@ -670,7 +670,7 @@ function iceCandidateTypeFromFbs(type: FbsIceCandidateType): IceCandidateType { } function iceCandidateTcpTypeFromFbs( - type: FbsIceCandidateTcpType, + type: FbsIceCandidateTcpType ): IceCandidateTcpType { switch (type) { case FbsIceCandidateTcpType.PASSIVE: { @@ -720,7 +720,7 @@ function dtlsRoleFromFbs(role: FbsDtlsRole): DtlsRole { } function fingerprintAlgorithmsFromFbs( - algorithm: FbsFingerprintAlgorithm, + algorithm: FbsFingerprintAlgorithm ): FingerprintAlgorithm { switch (algorithm) { case FbsFingerprintAlgorithm.SHA1: { @@ -746,7 +746,7 @@ function fingerprintAlgorithmsFromFbs( } function fingerprintAlgorithmToFbs( - algorithm: FingerprintAlgorithm, + algorithm: FingerprintAlgorithm ): FbsFingerprintAlgorithm { switch (algorithm) { case 'sha-1': { @@ -796,7 +796,7 @@ function dtlsRoleToFbs(role: DtlsRole): FbsDtlsRole { } export function parseWebRtcTransportDumpResponse( - binary: FbsWebRtcTransport.DumpResponse, + binary: FbsWebRtcTransport.DumpResponse ): WebRtcTransportDump { // Retrieve BaseTransportDump. const baseTransportDump = parseBaseTransportDump(binary.base()!); @@ -804,7 +804,7 @@ export function parseWebRtcTransportDumpResponse( const iceCandidates = parseVector( binary, 'iceCandidates', - parseIceCandidate, + parseIceCandidate ); // Retrieve ICE parameters. const iceParameters = parseIceParameters(binary.iceParameters()!); @@ -837,12 +837,12 @@ function createConnectRequest({ // Create request. return FbsWebRtcTransport.ConnectRequest.createConnectRequest( builder, - dtlsParametersOffset, + dtlsParametersOffset ); } function parseGetStatsResponse( - binary: FbsWebRtcTransport.GetStatsResponse, + binary: FbsWebRtcTransport.GetStatsResponse ): WebRtcTransportStat { const base = parseBaseTransportStats(binary.base()!); @@ -859,7 +859,7 @@ function parseGetStatsResponse( } function parseIceCandidate( - binary: FbsWebRtcTransport.IceCandidate, + binary: FbsWebRtcTransport.IceCandidate ): IceCandidate { return { foundation: binary.foundation()!, @@ -876,7 +876,7 @@ function parseIceCandidate( } function parseIceParameters( - binary: FbsWebRtcTransport.IceParameters, + binary: FbsWebRtcTransport.IceParameters ): IceParameters { return { usernameFragment: binary.usernameFragment()!, @@ -886,7 +886,7 @@ function parseIceParameters( } function parseDtlsParameters( - binary: FbsWebRtcTransport.DtlsParameters, + binary: FbsWebRtcTransport.DtlsParameters ): DtlsParameters { const fingerprints: DtlsFingerprint[] = []; @@ -908,7 +908,7 @@ function parseDtlsParameters( function serializeDtlsParameters( builder: flatbuffers.Builder, - dtlsParameters: DtlsParameters, + dtlsParameters: DtlsParameters ): number { const fingerprints: number[] = []; @@ -918,7 +918,7 @@ function serializeDtlsParameters( const fingerprintOffset = FbsWebRtcTransport.Fingerprint.createFingerprint( builder, algorithm, - valueOffset, + valueOffset ); fingerprints.push(fingerprintOffset); @@ -927,7 +927,7 @@ function serializeDtlsParameters( const fingerprintsOffset = FbsWebRtcTransport.DtlsParameters.createFingerprintsVector( builder, - fingerprints, + fingerprints ); const role = @@ -938,6 +938,6 @@ function serializeDtlsParameters( return FbsWebRtcTransport.DtlsParameters.createDtlsParameters( builder, fingerprintsOffset, - role, + role ); } diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 6e1f5e46c9..0b7112b492 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -226,7 +226,7 @@ export const workerBin = process.env.MEDIASOUP_WORKER_BIN 'worker', 'out', 'Debug', - 'mediasoup-worker', + 'mediasoup-worker' ) : path.join( __dirname, @@ -235,7 +235,7 @@ export const workerBin = process.env.MEDIASOUP_WORKER_BIN 'worker', 'out', 'Release', - 'mediasoup-worker', + 'mediasoup-worker' ); const logger = new Logger('Worker'); @@ -299,7 +299,7 @@ export class Worker< if (process.env.MEDIASOUP_VALGRIND_OPTIONS) { spawnArgs = spawnArgs.concat( - process.env.MEDIASOUP_VALGRIND_OPTIONS.split(/\s+/), + process.env.MEDIASOUP_VALGRIND_OPTIONS.split(/\s+/) ); } @@ -339,7 +339,7 @@ export class Worker< logger.debug( 'spawning worker process: %s %s', spawnBin, - spawnArgs.join(' '), + spawnArgs.join(' ') ); this.#child = spawn( @@ -366,7 +366,7 @@ export class Worker< // fd 4 (channel) : Consumer Channel fd. stdio: ['ignore', 'pipe', 'pipe', 'pipe', 'pipe'], windowsHide: true, - }, + } ); this.#pid = this.#child.pid!; @@ -404,7 +404,7 @@ export class Worker< if (code === 42) { logger.error( 'worker process failed due to wrong settings [pid:%s]', - this.#pid, + this.#pid ); this.close(); @@ -414,13 +414,13 @@ export class Worker< 'worker process failed unexpectedly [pid:%s, code:%s, signal:%s]', this.#pid, code, - signal, + signal ); this.close(); this.emit( '@failure', - new Error(`[pid:${this.#pid}, code:${code}, signal:${signal}]`), + new Error(`[pid:${this.#pid}, code:${code}, signal:${signal}]`) ); } } else { @@ -428,11 +428,11 @@ export class Worker< 'worker process died unexpectedly [pid:%s, code:%s, signal:%s]', this.#pid, code, - signal, + signal ); this.workerDied( - new Error(`[pid:${this.#pid}, code:${code}, signal:${signal}]`), + new Error(`[pid:${this.#pid}, code:${code}, signal:${signal}]`) ); } }); @@ -449,7 +449,7 @@ export class Worker< logger.error( 'worker process failed [pid:%s]: %s', this.#pid, - error.message, + error.message ); this.close(); @@ -458,7 +458,7 @@ export class Worker< logger.error( 'worker process error [pid:%s]: %s', this.#pid, - error.message, + error.message ); this.workerDied(error); @@ -470,7 +470,7 @@ export class Worker< 'worker subprocess closed [pid:%s, code:%s, signal:%s]', this.#pid, code, - signal, + signal ); this.#subprocessClosed = true; @@ -620,7 +620,7 @@ export class Worker< logger.debug('getResourceUsage()'); const response = await this.#channel.request( - FbsRequest.Method.WORKER_GET_RESOURCE_USAGE, + FbsRequest.Method.WORKER_GET_RESOURCE_USAGE ); /* Decode Response. */ @@ -664,13 +664,13 @@ export class Worker< // Build the request. const requestOffset = new FbsWorker.UpdateSettingsRequestT( logLevel, - logTags, + logTags ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.WORKER_UPDATE_SETTINGS, FbsRequest.Body.Worker_UpdateSettingsRequest, - requestOffset, + requestOffset ); } @@ -703,8 +703,8 @@ export class Worker< listenInfo.port, socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, - listenInfo.recvBufferSize, - ), + listenInfo.recvBufferSize + ) ); } @@ -713,13 +713,13 @@ export class Worker< const createWebRtcServerRequestOffset = new FbsWorker.CreateWebRtcServerRequestT( webRtcServerId, - fbsListenInfos, + fbsListenInfos ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.WORKER_CREATE_WEBRTCSERVER, FbsRequest.Body.Worker_CreateWebRtcServerRequest, - createWebRtcServerRequestOffset, + createWebRtcServerRequestOffset ); const webRtcServer = new WebRtcServer({ @@ -752,7 +752,7 @@ export class Worker< // Clone given media codecs to not modify input data. const clonedMediaCodecs = utils.clone( - mediaCodecs, + mediaCodecs ); // This may throw. @@ -763,13 +763,13 @@ export class Worker< // Get flatbuffer builder. const createRouterRequestOffset = new FbsWorker.CreateRouterRequestT( - routerId, + routerId ).pack(this.#channel.bufferBuilder); await this.#channel.request( FbsRequest.Method.WORKER_CREATE_ROUTER, FbsRequest.Body.Worker_CreateRouterRequest, - createRouterRequestOffset, + createRouterRequestOffset ); const data = { rtpCapabilities }; @@ -824,7 +824,7 @@ export class Worker< } export function parseWorkerDumpResponse( - binary: FbsWorker.DumpResponse, + binary: FbsWorker.DumpResponse ): WorkerDump { const dump: WorkerDump = { pid: binary.pid()!, @@ -833,11 +833,11 @@ export function parseWorkerDumpResponse( channelMessageHandlers: { channelRequestHandlers: utils.parseVector( binary.channelMessageHandlers()!, - 'channelRequestHandlers', + 'channelRequestHandlers' ), channelNotificationHandlers: utils.parseVector( binary.channelMessageHandlers()!, - 'channelNotificationHandlers', + 'channelNotificationHandlers' ), }, }; diff --git a/node/src/ortc.ts b/node/src/ortc.ts index 0ca8640db3..3b36297493 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -134,7 +134,7 @@ export function validateRtpParameters(params: RtpParameters): void { * It throws if invalid. */ export function validateSctpStreamParameters( - params: SctpStreamParameters, + params: SctpStreamParameters ): void { if (typeof params !== 'object') { throw new TypeError('params is not an object'); @@ -169,7 +169,7 @@ export function validateSctpStreamParameters( if (params.maxPacketLifeTime && params.maxRetransmits) { throw new TypeError( - 'cannot provide both maxPacketLifeTime and maxRetransmits', + 'cannot provide both maxPacketLifeTime and maxRetransmits' ); } @@ -179,7 +179,7 @@ export function validateSctpStreamParameters( (params.maxPacketLifeTime || params.maxRetransmits) ) { throw new TypeError( - 'cannot be ordered with maxPacketLifeTime or maxRetransmits', + 'cannot be ordered with maxPacketLifeTime or maxRetransmits' ); } else if ( !orderedGiven && @@ -194,7 +194,7 @@ export function validateSctpStreamParameters( * mediasoup supported RTP capabilities. */ export function generateRouterRtpCapabilities( - mediaCodecs: RtpCodecCapability[] = [], + mediaCodecs: RtpCodecCapability[] = [] ): RtpCapabilities { // Normalize supported RTP capabilities. validateRtpCapabilities(supportedRtpCapabilities); @@ -204,7 +204,7 @@ export function generateRouterRtpCapabilities( } const clonedSupportedRtpCapabilities = utils.clone( - supportedRtpCapabilities, + supportedRtpCapabilities ); const dynamicPayloadTypes = utils.clone(DynamicPayloadTypes); const caps: RtpCapabilities = { @@ -218,12 +218,12 @@ export function generateRouterRtpCapabilities( const matchedSupportedCodec = clonedSupportedRtpCapabilities.codecs!.find( supportedCodec => - matchCodecs(mediaCodec, supportedCodec, { strict: false }), + matchCodecs(mediaCodec, supportedCodec, { strict: false }) ); if (!matchedSupportedCodec) { throw new UnsupportedError( - `media codec not supported [mimeType:${mediaCodec.mimeType}]`, + `media codec not supported [mimeType:${mediaCodec.mimeType}]` ); } @@ -260,7 +260,7 @@ export function generateRouterRtpCapabilities( // Ensure there is not duplicated preferredPayloadType values. if ( caps.codecs!.some( - c => c.preferredPayloadType === codec.preferredPayloadType, + c => c.preferredPayloadType === codec.preferredPayloadType ) ) { throw new TypeError('duplicated codec.preferredPayloadType'); @@ -308,7 +308,7 @@ export function generateRouterRtpCapabilities( */ export function getProducerRtpParametersMapping( params: RtpParameters, - caps: RtpCapabilities, + caps: RtpCapabilities ): RtpMapping { const rtpMapping: RtpMapping = { codecs: [], @@ -326,12 +326,12 @@ export function getProducerRtpParametersMapping( // Search for the same media codec in capabilities. const matchedCapCodec = caps.codecs!.find(capCodec => - matchCodecs(codec, capCodec, { strict: true, modify: true }), + matchCodecs(codec, capCodec, { strict: true, modify: true }) ); if (!matchedCapCodec) { throw new UnsupportedError( - `unsupported codec [mimeType:${codec.mimeType}, payloadType:${codec.payloadType}]`, + `unsupported codec [mimeType:${codec.mimeType}, payloadType:${codec.payloadType}]` ); } @@ -346,12 +346,12 @@ export function getProducerRtpParametersMapping( // Search for the associated media codec. const associatedMediaCodec = params.codecs.find( - mediaCodec => mediaCodec.payloadType === codec.parameters.apt, + mediaCodec => mediaCodec.payloadType === codec.parameters.apt ); if (!associatedMediaCodec) { throw new TypeError( - `missing media codec found for RTX PT ${codec.payloadType}`, + `missing media codec found for RTX PT ${codec.payloadType}` ); } @@ -361,14 +361,14 @@ export function getProducerRtpParametersMapping( const associatedCapRtxCodec = caps.codecs!.find( capCodec => isRtxCodec(capCodec) && - capCodec.parameters.apt === capMediaCodec!.preferredPayloadType, + capCodec.parameters.apt === capMediaCodec!.preferredPayloadType ); if (!associatedCapRtxCodec) { throw new UnsupportedError( `no RTX codec for capability codec PT ${ capMediaCodec!.preferredPayloadType - }`, + }` ); } @@ -415,7 +415,7 @@ export function getConsumableRtpParameters( kind: string, params: RtpParameters, caps: RtpCapabilities, - rtpMapping: RtpMapping, + rtpMapping: RtpMapping ): RtpParameters { const consumableParams: RtpParameters = { codecs: [], @@ -430,11 +430,11 @@ export function getConsumableRtpParameters( } const consumableCodecPt = rtpMapping.codecs.find( - entry => entry.payloadType === codec.payloadType, + entry => entry.payloadType === codec.payloadType )!.mappedPayloadType; const matchedCapCodec = caps.codecs!.find( - capCodec => capCodec.preferredPayloadType === consumableCodecPt, + capCodec => capCodec.preferredPayloadType === consumableCodecPt )!; const consumableCodec: RtpCodecParameters = { @@ -451,7 +451,7 @@ export function getConsumableRtpParameters( const consumableCapRtxCodec = caps.codecs!.find( capRtxCodec => isRtxCodec(capRtxCodec) && - capRtxCodec.parameters.apt === consumableCodec.payloadType, + capRtxCodec.parameters.apt === consumableCodec.payloadType ); if (consumableCapRtxCodec) { @@ -518,7 +518,7 @@ export function getConsumableRtpParameters( */ export function canConsume( consumableParams: RtpParameters, - caps: RtpCapabilities, + caps: RtpCapabilities ): boolean { // This may throw. validateRtpCapabilities(caps); @@ -527,7 +527,7 @@ export function canConsume( for (const codec of consumableParams.codecs) { const matchedCapCodec = caps.codecs!.find(capCodec => - matchCodecs(capCodec, codec, { strict: true }), + matchCodecs(capCodec, codec, { strict: true }) ); if (!matchedCapCodec) { @@ -576,7 +576,7 @@ export function getConsumerRtpParameters({ const consumableCodecs = utils.clone( - consumableRtpParameters.codecs, + consumableRtpParameters.codecs ) ?? []; let rtxSupported = false; @@ -587,7 +587,7 @@ export function getConsumerRtpParameters({ } const matchedCapCodec = remoteRtpCapabilities.codecs!.find(capCodec => - matchCodecs(capCodec, codec, { strict: true }), + matchCodecs(capCodec, codec, { strict: true }) ); if (!matchedCapCodec) { @@ -595,7 +595,7 @@ export function getConsumerRtpParameters({ } codec.rtcpFeedback = matchedCapCodec.rtcpFeedback!.filter( - fb => enableRtx || fb.type !== 'nack' || fb.parameter, + fb => enableRtx || fb.type !== 'nack' || fb.parameter ); consumerParams.codecs.push(codec); @@ -608,7 +608,7 @@ export function getConsumerRtpParameters({ if (isRtxCodec(codec)) { // Search for the associated media codec. const associatedMediaCodec = consumerParams.codecs.find( - mediaCodec => mediaCodec.payloadType === codec.parameters.apt, + mediaCodec => mediaCodec.payloadType === codec.parameters.apt ); if (associatedMediaCodec) { @@ -630,8 +630,8 @@ export function getConsumerRtpParameters({ consumerParams.headerExtensions = consumableRtpParameters.headerExtensions!.filter(ext => remoteRtpCapabilities.headerExtensions!.some( - capExt => capExt.preferredId === ext.id && capExt.uri === ext.uri, - ), + capExt => capExt.preferredId === ext.id && capExt.uri === ext.uri + ) ); // Reduce codecs' RTCP feedback. Use Transport-CC if available, REMB otherwise. @@ -639,30 +639,29 @@ export function getConsumerRtpParameters({ consumerParams.headerExtensions.some( ext => ext.uri === - 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' ) ) { for (const codec of consumerParams.codecs) { codec.rtcpFeedback = codec.rtcpFeedback!.filter( - fb => fb.type !== 'goog-remb', + fb => fb.type !== 'goog-remb' ); } } else if ( consumerParams.headerExtensions.some( ext => - ext.uri === - 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + ext.uri === 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' ) ) { for (const codec of consumerParams.codecs) { codec.rtcpFeedback = codec.rtcpFeedback!.filter( - fb => fb.type !== 'transport-cc', + fb => fb.type !== 'transport-cc' ); } } else { for (const codec of consumerParams.codecs) { codec.rtcpFeedback = codec.rtcpFeedback!.filter( - fb => fb.type !== 'transport-cc' && fb.type !== 'goog-remb', + fb => fb.type !== 'transport-cc' && fb.type !== 'goog-remb' ); } } @@ -679,7 +678,7 @@ export function getConsumerRtpParameters({ // If any of the consumableRtpParameters.encodings has scalabilityMode, // process it (assume all encodings have the same value). const encodingWithScalabilityMode = consumableRtpParameters.encodings!.find( - encoding => encoding.scalabilityMode, + encoding => encoding.scalabilityMode ); let scalabilityMode = encodingWithScalabilityMode @@ -706,7 +705,7 @@ export function getConsumerRtpParameters({ encoding.maxBitrate && encoding.maxBitrate > maxBitrate ? encoding.maxBitrate : maxBitrate, - 0, + 0 ); if (maxEncodingMaxBitrate) { @@ -718,7 +717,7 @@ export function getConsumerRtpParameters({ } else { const consumableEncodings = utils.clone( - consumableRtpParameters.encodings, + consumableRtpParameters.encodings ) ?? []; const baseSsrc = utils.generateRandomNumber(); const baseRtxSsrc = utils.generateRandomNumber(); @@ -763,7 +762,7 @@ export function getPipeConsumerRtpParameters({ const consumableCodecs = utils.clone( - consumableRtpParameters.codecs, + consumableRtpParameters.codecs ) ?? []; for (const codec of consumableCodecs) { @@ -775,7 +774,7 @@ export function getPipeConsumerRtpParameters({ fb => (fb.type === 'nack' && fb.parameter === 'pli') || (fb.type === 'ccm' && fb.parameter === 'fir') || - (enableRtx && fb.type === 'nack' && !fb.parameter), + (enableRtx && fb.type === 'nack' && !fb.parameter) ); consumerParams.codecs.push(codec); @@ -789,12 +788,12 @@ export function getPipeConsumerRtpParameters({ ext.uri !== 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' && ext.uri !== - 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' ); const consumableEncodings = utils.clone( - consumableRtpParameters.encodings, + consumableRtpParameters.encodings ) ?? []; const baseSsrc = utils.generateRandomNumber(); const baseRtxSsrc = utils.generateRandomNumber(); @@ -823,7 +822,7 @@ function isRtxCodec(codec: RtpCodecCapability | RtpCodecParameters): boolean { function matchCodecs( aCodec: RtpCodecCapability | RtpCodecParameters, bCodec: RtpCodecCapability | RtpCodecParameters, - { strict = false, modify = false } = {}, + { strict = false, modify = false } = {} ): boolean { const aMimeType = aCodec.mimeType.toLowerCase(); const bMimeType = bCodec.mimeType.toLowerCase(); @@ -879,7 +878,7 @@ function matchCodecs( try { selectedProfileLevelId = h264.generateProfileLevelIdStringForAnswer( aCodec.parameters, - bCodec.parameters, + bCodec.parameters ); } catch (error) { return false; @@ -916,7 +915,7 @@ function matchCodecs( export function serializeRtpMapping( builder: flatbuffers.Builder, - rtpMapping: RtpMapping, + rtpMapping: RtpMapping ): number { const codecs: number[] = []; @@ -925,13 +924,13 @@ export function serializeRtpMapping( FbsRtpParameters.CodecMapping.createCodecMapping( builder, codec.payloadType, - codec.mappedPayloadType, - ), + codec.mappedPayloadType + ) ); } const codecsOffset = FbsRtpParameters.RtpMapping.createCodecsVector( builder, - codecs, + codecs ); const encodings: number[] = []; @@ -943,20 +942,20 @@ export function serializeRtpMapping( builder.createString(encoding.rid), encoding.ssrc ?? null, builder.createString(encoding.scalabilityMode), - encoding.mappedSsrc, - ), + encoding.mappedSsrc + ) ); } const encodingsOffset = FbsRtpParameters.RtpMapping.createEncodingsVector( builder, - encodings, + encodings ); return FbsRtpParameters.RtpMapping.createRtpMapping( builder, codecsOffset, - encodingsOffset, + encodingsOffset ); } @@ -1023,7 +1022,7 @@ function validateRtpCodecCapability(codec: RtpCodecCapability): void { if (typeof value !== 'string' && typeof value !== 'number') { throw new TypeError( - `invalid codec parameter [key:${key}s, value:${value}]`, + `invalid codec parameter [key:${key}s, value:${value}]` ); } @@ -1164,7 +1163,7 @@ function validateRtpCodecParameters(codec: RtpCodecParameters): void { if (typeof value !== 'string' && typeof value !== 'number') { throw new TypeError( - `invalid codec parameter [key:${key}s, value:${value}]`, + `invalid codec parameter [key:${key}s, value:${value}]` ); } @@ -1191,7 +1190,7 @@ function validateRtpCodecParameters(codec: RtpCodecParameters): void { * missing fields with default values. It throws if invalid. */ function validateRtpHeaderExtensionParameters( - ext: RtpHeaderExtensionParameters, + ext: RtpHeaderExtensionParameters ): void { if (typeof ext !== 'object') { throw new TypeError('ext is not an object'); diff --git a/node/src/scalabilityModes.ts b/node/src/scalabilityModes.ts index 4f9f93845d..2804e29b2e 100644 --- a/node/src/scalabilityModes.ts +++ b/node/src/scalabilityModes.ts @@ -1,5 +1,5 @@ const ScalabilityModeRegex = new RegExp( - '^[LS]([1-9]\\d{0,1})T([1-9]\\d{0,1})(_KEY)?', + '^[LS]([1-9]\\d{0,1})T([1-9]\\d{0,1})(_KEY)?' ); export type ScalabilityMode = { diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index 13eb1014cf..2f31ff5379 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -31,8 +31,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -60,15 +60,15 @@ test('router.createActiveSpeakerObserver() with wrong arguments rejects with Typ await expect( ctx.router!.createActiveSpeakerObserver( // @ts-ignore - { interval: false }, - ), + { interval: false } + ) ).rejects.toThrow(TypeError); await expect( ctx.router!.createActiveSpeakerObserver( // @ts-ignore - { appData: 'NOT-AN-OBJECT' }, - ), + { appData: 'NOT-AN-OBJECT' } + ) ).rejects.toThrow(TypeError); }, 2000); diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index 21e943099d..f981d59df9 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -31,8 +31,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -58,26 +58,26 @@ test('router.createAudioLevelObserver() succeeds', async () => { test('router.createAudioLevelObserver() with wrong arguments rejects with TypeError', async () => { await expect( - ctx.router!.createAudioLevelObserver({ maxEntries: 0 }), + ctx.router!.createAudioLevelObserver({ maxEntries: 0 }) ).rejects.toThrow(TypeError); await expect( - ctx.router!.createAudioLevelObserver({ maxEntries: -10 }), + ctx.router!.createAudioLevelObserver({ maxEntries: -10 }) ).rejects.toThrow(TypeError); await expect( // @ts-ignore - ctx.router!.createAudioLevelObserver({ threshold: 'foo' }), + ctx.router!.createAudioLevelObserver({ threshold: 'foo' }) ).rejects.toThrow(TypeError); await expect( // @ts-ignore - ctx.router!.createAudioLevelObserver({ interval: false }), + ctx.router!.createAudioLevelObserver({ interval: false }) ).rejects.toThrow(TypeError); await expect( // @ts-ignore - ctx.router!.createAudioLevelObserver({ appData: 'NOT-AN-OBJECT' }), + ctx.router!.createAudioLevelObserver({ appData: 'NOT-AN-OBJECT' }) ).rejects.toThrow(TypeError); }, 2000); diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index ce4a938197..6d4c5f84ba 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -234,10 +234,10 @@ beforeEach(async () => { listenIps: ['127.0.0.1'], }); ctx.audioProducer = await ctx.webRtcTransport1.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); ctx.videoProducer = await ctx.webRtcTransport1.produce( - ctx.videoProducerOptions, + ctx.videoProducerOptions ); }); @@ -245,8 +245,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -260,7 +260,7 @@ test('transport.consume() succeeds', async () => { ctx.router!.canConsume({ producerId: ctx.audioProducer!.id, rtpCapabilities: ctx.consumerDeviceCapabilities, - }), + }) ).toBe(true); const audioConsumer = await ctx.webRtcTransport2!.consume({ @@ -309,13 +309,13 @@ test('transport.consume() succeeds', async () => { expect(dump1.mapProducerIdConsumerIds).toEqual( expect.arrayContaining([ { key: ctx.audioProducer!.id, values: [audioConsumer.id] }, - ]), + ]) ); expect(dump1.mapConsumerIdProducerId).toEqual( expect.arrayContaining([ { key: audioConsumer.id, value: ctx.audioProducer!.id }, - ]), + ]) ); await expect(ctx.webRtcTransport2!.dump()).resolves.toMatchObject({ @@ -332,7 +332,7 @@ test('transport.consume() succeeds', async () => { ctx.router!.canConsume({ producerId: ctx.videoProducer!.id, rtpCapabilities: ctx.consumerDeviceCapabilities, - }), + }) ).toBe(true); // Pause videoProducer. @@ -401,7 +401,7 @@ test('transport.consume() succeeds', async () => { ctx.router!.canConsume({ producerId: ctx.videoProducer!.id, rtpCapabilities: ctx.consumerDeviceCapabilities, - }), + }) ).toBe(true); const videoPipeConsumer = await ctx.webRtcTransport2!.consume({ @@ -471,14 +471,14 @@ test('transport.consume() succeeds', async () => { videoPipeConsumer.id, ]), }, - ]), + ]) ); expect(dump2.mapConsumerIdProducerId).toEqual( expect.arrayContaining([ { key: audioConsumer.id, value: ctx.audioProducer!.id }, { key: videoConsumer.id, value: ctx.videoProducer!.id }, { key: videoPipeConsumer.id, value: ctx.videoProducer!.id }, - ]), + ]) ); await expect(ctx.webRtcTransport2!.dump()).resolves.toMatchObject({ @@ -523,7 +523,7 @@ test('transport.consume() can be created with user provided mid', async () => { }); expect(audioConsumer1.rtpParameters.mid).toEqual( - expect.stringMatching(/^[0-9]+/), + expect.stringMatching(/^[0-9]+/) ); const audioConsumer2 = await ctx.webRtcTransport2!.consume({ @@ -540,10 +540,10 @@ test('transport.consume() can be created with user provided mid', async () => { }); expect(audioConsumer3.rtpParameters.mid).toEqual( - expect.stringMatching(/^[0-9]+/), + expect.stringMatching(/^[0-9]+/) ); expect(Number(audioConsumer1.rtpParameters.mid) + 1).toBe( - Number(audioConsumer3.rtpParameters.mid), + Number(audioConsumer3.rtpParameters.mid) ); }, 2000); @@ -567,14 +567,14 @@ test('transport.consume() with incompatible rtpCapabilities rejects with Unsuppo ctx.router!.canConsume({ producerId: ctx.audioProducer!.id, rtpCapabilities: invalidDeviceCapabilities, - }), + }) ).toBe(false); await expect( ctx.webRtcTransport2!.consume({ producerId: ctx.audioProducer!.id, rtpCapabilities: invalidDeviceCapabilities, - }), + }) ).rejects.toThrow(UnsupportedError); invalidDeviceCapabilities = { @@ -586,14 +586,14 @@ test('transport.consume() with incompatible rtpCapabilities rejects with Unsuppo ctx.router!.canConsume({ producerId: ctx.audioProducer!.id, rtpCapabilities: invalidDeviceCapabilities, - }), + }) ).toBe(false); await expect( ctx.webRtcTransport2!.consume({ producerId: ctx.audioProducer!.id, rtpCapabilities: invalidDeviceCapabilities, - }), + }) ).rejects.toThrow(UnsupportedError); }, 2000); @@ -736,22 +736,22 @@ test('consumer.dump() succeeds', async () => { expect(dump2.consumableRtpEncodings![0]).toEqual( expect.objectContaining({ ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[0].ssrc, - }), + }) ); expect(dump2.consumableRtpEncodings![1]).toEqual( expect.objectContaining({ ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[1].ssrc, - }), + }) ); expect(dump2.consumableRtpEncodings![2]).toEqual( expect.objectContaining({ ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[2].ssrc, - }), + }) ); expect(dump2.consumableRtpEncodings![3]).toEqual( expect.objectContaining({ ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[3].ssrc, - }), + }) ); expect(dump2.supportedCodecPayloadTypes).toEqual([103]); expect(dump2.paused).toBe(true); @@ -884,18 +884,18 @@ test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError' await expect( // @ts-ignore - videoConsumer.setPreferredLayers({ foo: '123' }), + videoConsumer.setPreferredLayers({ foo: '123' }) ).rejects.toThrow(TypeError); // @ts-ignore await expect(videoConsumer.setPreferredLayers('foo')).rejects.toThrow( - TypeError, + TypeError ); // Missing spatialLayer. await expect( // @ts-ignore - videoConsumer.setPreferredLayers({ temporalLayer: 2 }), + videoConsumer.setPreferredLayers({ temporalLayer: 2 }) ).rejects.toThrow(TypeError); }, 2000); @@ -957,7 +957,7 @@ test('consumer.enableTraceEvent() succeed', async () => { const dump3 = await audioConsumer.dump(); expect(dump3.traceEventTypes).toEqual( - expect.arrayContaining(['nack', 'fir']), + expect.arrayContaining(['nack', 'fir']) ); await audioConsumer.enableTraceEvent(); @@ -978,12 +978,12 @@ test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', // @ts-ignore await expect(audioConsumer.enableTraceEvent('rtp')).rejects.toThrow( - TypeError, + TypeError ); await expect( // @ts-ignore - audioConsumer.enableTraceEvent(['fir', 123.123]), + audioConsumer.enableTraceEvent(['fir', 123.123]) ).rejects.toThrow(TypeError); }, 2000); @@ -1034,20 +1034,20 @@ test('Consumer emits "score"', async () => { const builder = new flatbuffers.Builder(); const consumerScore = new FbsConsumer.ConsumerScoreT(9, 10, [8]); const consumerScoreNotification = new FbsConsumer.ScoreNotificationT( - consumerScore, + consumerScore ); const notificationOffset = Notification.createNotification( builder, builder.createString(audioConsumer.id), Event.CONSUMER_SCORE, NotificationBody.Consumer_ScoreNotification, - consumerScoreNotification.pack(builder), + consumerScoreNotification.pack(builder) ); builder.finish(notificationOffset); const notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array()), + new flatbuffers.ByteBuffer(builder.asUint8Array()) ); channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); @@ -1085,7 +1085,7 @@ test('consumer.close() succeeds', async () => { expect.arrayContaining([ { key: ctx.audioProducer!.id, values: [] }, { key: ctx.videoProducer!.id, values: [videoConsumer.id] }, - ]), + ]) ); expect(routerDump.mapConsumerIdProducerId).toEqual([ { key: videoConsumer!.id, value: ctx.videoProducer!.id }, diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index 9bd160563d..d37ab10c30 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -36,7 +36,7 @@ beforeEach(async () => { }); ctx.directTransport = await ctx.router.createDirectTransport(); ctx.dataProducer = await ctx.webRtcTransport1.produceData( - ctx.dataProducerOptions, + ctx.dataProducerOptions ); }); @@ -44,8 +44,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -55,7 +55,7 @@ test('transport.consumeData() succeeds', async () => { ctx.webRtcTransport2!.observer.once( 'newdataconsumer', - onObserverNewDataConsumer, + onObserverNewDataConsumer ); const dataConsumer1 = await ctx.webRtcTransport2!.consumeData({ @@ -82,7 +82,7 @@ test('transport.consumeData() succeeds', async () => { expect(dataConsumer1.protocol).toBe('bar'); expect(dataConsumer1.paused).toBe(false); expect(dataConsumer1.subchannels).toEqual( - expect.arrayContaining([0, 1, 2, 100, 65535]), + expect.arrayContaining([0, 1, 2, 100, 65535]) ); expect(dataConsumer1.appData).toEqual({ baz: 'LOL' }); @@ -91,13 +91,13 @@ test('transport.consumeData() succeeds', async () => { expect(dump.mapDataProducerIdDataConsumerIds).toEqual( expect.arrayContaining([ { key: ctx.dataProducer!.id, values: [dataConsumer1.id] }, - ]), + ]) ); expect(dump.mapDataConsumerIdDataProducerId).toEqual( expect.arrayContaining([ { key: dataConsumer1.id, value: ctx.dataProducer!.id }, - ]), + ]) ); await expect(ctx.webRtcTransport2!.dump()).resolves.toMatchObject({ @@ -124,7 +124,7 @@ test('dataConsumer.dump() succeeds', async () => { expect(dump.type).toBe('sctp'); expect(typeof dump.sctpStreamParameters).toBe('object'); expect(dump.sctpStreamParameters!.streamId).toBe( - dataConsumer.sctpStreamParameters?.streamId, + dataConsumer.sctpStreamParameters?.streamId ); expect(dump.sctpStreamParameters!.ordered).toBe(false); expect(dump.sctpStreamParameters!.maxPacketLifeTime).toBe(4000); @@ -134,7 +134,7 @@ test('dataConsumer.dump() succeeds', async () => { expect(dump.paused).toBe(false); expect(dump.dataProducerPaused).toBe(false); expect(dump.subchannels).toEqual( - expect.arrayContaining([0, 1, 2, 100, 65535]), + expect.arrayContaining([0, 1, 2, 100, 65535]) ); }, 2000); @@ -162,7 +162,7 @@ test('dataConsumer.setSubchannels() succeeds', async () => { await dataConsumer.setSubchannels([999, 999, 998, 65536]); expect(dataConsumer.subchannels).toEqual( - expect.arrayContaining([0, 998, 999]), + expect.arrayContaining([0, 998, 999]) ); }, 2000); @@ -198,7 +198,7 @@ test('transport.consumeData() on a DirectTransport succeeds', async () => { ctx.directTransport!.observer.once( 'newdataconsumer', - onObserverNewDataConsumer, + onObserverNewDataConsumer ); const dataConsumer = await ctx.directTransport!.consumeData({ @@ -342,7 +342,7 @@ test('dataConsumer.close() succeeds', async () => { const dump = await ctx.router!.dump(); expect(dump.mapDataProducerIdDataConsumerIds).toEqual( - expect.arrayContaining([{ key: ctx.dataProducer!.id, values: [] }]), + expect.arrayContaining([{ key: ctx.dataProducer!.id, values: [] }]) ); expect(dump.mapDataConsumerIdDataProducerId).toEqual([]); diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index de0b4fc7d3..54362f4381 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -48,8 +48,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -59,11 +59,11 @@ test('webRtcTransport1.produceData() succeeds', async () => { ctx.webRtcTransport1!.observer.once( 'newdataproducer', - onObserverNewDataProducer, + onObserverNewDataProducer ); const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1, + ctx.dataProducerOptions1 ); expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); @@ -84,7 +84,7 @@ test('webRtcTransport1.produceData() succeeds', async () => { const dump = await ctx.router!.dump(); expect(dump.mapDataProducerIdDataConsumerIds).toEqual( - expect.arrayContaining([{ key: dataProducer1.id, values: [] }]), + expect.arrayContaining([{ key: dataProducer1.id, values: [] }]) ); expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); @@ -101,11 +101,11 @@ test('webRtcTransport2.produceData() succeeds', async () => { ctx.webRtcTransport2!.observer.once( 'newdataproducer', - onObserverNewDataProducer, + onObserverNewDataProducer ); const dataProducer2 = await ctx.webRtcTransport2!.produceData( - ctx.dataProducerOptions2, + ctx.dataProducerOptions2 ); expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); @@ -126,7 +126,7 @@ test('webRtcTransport2.produceData() succeeds', async () => { const dump = await ctx.router!.dump(); expect(dump.mapDataProducerIdDataConsumerIds).toEqual( - expect.arrayContaining([{ key: dataProducer2.id, values: [] }]), + expect.arrayContaining([{ key: dataProducer2.id, values: [] }]) ); expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); @@ -140,7 +140,7 @@ test('webRtcTransport2.produceData() succeeds', async () => { test('webRtcTransport1.produceData() with wrong arguments rejects with TypeError', async () => { await expect(ctx.webRtcTransport1!.produceData({})).rejects.toThrow( - TypeError, + TypeError ); // Missing or empty sctpStreamParameters.streamId. @@ -148,7 +148,7 @@ test('webRtcTransport1.produceData() with wrong arguments rejects with TypeError ctx.webRtcTransport1!.produceData({ // @ts-ignore sctpStreamParameters: { foo: 'foo' }, - }), + }) ).rejects.toThrow(TypeError); }, 2000); @@ -160,7 +160,7 @@ test('transport.produceData() with already used streamId rejects with Error', as sctpStreamParameters: { streamId: 666, }, - }), + }) ).rejects.toThrow(Error); }, 2000); @@ -172,13 +172,13 @@ test('transport.produceData() with ordered and maxPacketLifeTime rejects with Ty ordered: true, maxPacketLifeTime: 4000, }, - }), + }) ).rejects.toThrow(TypeError); }, 2000); test('dataProducer.dump() succeeds', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1, + ctx.dataProducerOptions1 ); const dump1 = await dataProducer1.dump(); @@ -195,7 +195,7 @@ test('dataProducer.dump() succeeds', async () => { expect(dump1.paused).toBe(false); const dataProducer2 = await ctx.webRtcTransport2!.produceData( - ctx.dataProducerOptions2, + ctx.dataProducerOptions2 ); const dump2 = await dataProducer2.dump(); @@ -214,7 +214,7 @@ test('dataProducer.dump() succeeds', async () => { test('dataProducer.getStats() succeeds', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1, + ctx.dataProducerOptions1 ); await expect(dataProducer1.getStats()).resolves.toMatchObject([ @@ -228,7 +228,7 @@ test('dataProducer.getStats() succeeds', async () => { ]); const dataProducer2 = await ctx.webRtcTransport2!.produceData( - ctx.dataProducerOptions2, + ctx.dataProducerOptions2 ); await expect(dataProducer2.getStats()).resolves.toMatchObject([ @@ -244,7 +244,7 @@ test('dataProducer.getStats() succeeds', async () => { test('dataProducer.pause() and resume() succeed', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1, + ctx.dataProducerOptions1 ); const onObserverPause = jest.fn(); @@ -284,7 +284,7 @@ test('dataProducer.pause() and resume() succeed', async () => { test('producer.pause() and resume() emit events', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1, + ctx.dataProducerOptions1 ); const promises = []; @@ -309,7 +309,7 @@ test('producer.pause() and resume() emit events', async () => { test('dataProducer.close() succeeds', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1, + ctx.dataProducerOptions1 ); const onObserverClose = jest.fn(); @@ -334,7 +334,7 @@ test('dataProducer.close() succeeds', async () => { test('DataProducer methods reject if closed', async () => { const dataProducer1 = await ctx.webRtcTransport1!.produceData( - ctx.dataProducerOptions1, + ctx.dataProducerOptions1 ); dataProducer1.close(); @@ -346,7 +346,7 @@ test('DataProducer methods reject if closed', async () => { test('DataProducer emits "transportclose" if Transport is closed', async () => { const dataProducer2 = await ctx.webRtcTransport2!.produceData( - ctx.dataProducerOptions2, + ctx.dataProducerOptions2 ); const onObserverClose = jest.fn(); diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index 42c50c9464..f9c233a7d8 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -16,8 +16,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -60,11 +60,11 @@ test('router.createDirectTransport() succeeds', async () => { test('router.createDirectTransport() with wrong arguments rejects with TypeError', async () => { await expect( // @ts-ignore - ctx.router!.createDirectTransport({ maxMessageSize: 'foo' }), + ctx.router!.createDirectTransport({ maxMessageSize: 'foo' }) ).rejects.toThrow(TypeError); await expect( - ctx.router!.createDirectTransport({ maxMessageSize: -2000 }), + ctx.router!.createDirectTransport({ maxMessageSize: -2000 }) ).rejects.toThrow(TypeError); }, 2000); @@ -131,16 +131,16 @@ test('dataProducer.send() succeeds', async () => { dataProducer.on('listenererror', (eventName, error) => { reject( new Error( - `dataProducer 'listenererror' [eventName:${eventName}]: ${error}`, - ), + `dataProducer 'listenererror' [eventName:${eventName}]: ${error}` + ) ); }); dataConsumer.on('listenererror', (eventName, error) => { reject( new Error( - `dataConsumer 'listenererror' [eventName:${eventName}]: ${error}`, - ), + `dataConsumer 'listenererror' [eventName:${eventName}]: ${error}` + ) ); }); @@ -199,16 +199,16 @@ test('dataProducer.send() succeeds', async () => { else if (id < numMessages / 2 && ppid !== 51) { reject( new Error( - `ppid in message with id ${id} should be 51 but it is ${ppid}`, - ), + `ppid in message with id ${id} should be 51 but it is ${ppid}` + ) ); } // PPID of WebRTC DataChannel binary. else if (id > numMessages / 2 && ppid !== 53) { reject( new Error( - `ppid in message with id ${id} should be 53 but it is ${ppid}`, - ), + `ppid in message with id ${id} should be 53 but it is ${ppid}` + ) ); } }); @@ -262,7 +262,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'both', /* ppid */ undefined, /* subchannels */ undefined, - /* requiredSubchannel */ undefined, + /* requiredSubchannel */ undefined ); // Must be received by dataConsumer1 and dataConsumer2. @@ -270,7 +270,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'both', /* ppid */ undefined, /* subchannels */ [1, 2], - /* requiredSubchannel */ undefined, + /* requiredSubchannel */ undefined ); // Must be received by dataConsumer1 and dataConsumer2. @@ -278,7 +278,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'both', /* ppid */ undefined, /* subchannels */ [11, 22, 33], - /* requiredSubchannel */ 666, + /* requiredSubchannel */ 666 ); // Must not be received by neither dataConsumer1 nor dataConsumer2. @@ -286,7 +286,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'none', /* ppid */ undefined, /* subchannels */ [3], - /* requiredSubchannel */ 666, + /* requiredSubchannel */ 666 ); // Must not be received by neither dataConsumer1 nor dataConsumer2. @@ -294,7 +294,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'none', /* ppid */ undefined, /* subchannels */ [666], - /* requiredSubchannel */ 3, + /* requiredSubchannel */ 3 ); // Must be received by dataConsumer1. @@ -302,7 +302,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'dc1', /* ppid */ undefined, /* subchannels */ [1], - /* requiredSubchannel */ undefined, + /* requiredSubchannel */ undefined ); // Must be received by dataConsumer1. @@ -310,7 +310,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'dc1', /* ppid */ undefined, /* subchannels */ [11], - /* requiredSubchannel */ 1, + /* requiredSubchannel */ 1 ); // Must be received by dataConsumer1. @@ -318,7 +318,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'dc1', /* ppid */ undefined, /* subchannels */ [666], - /* requiredSubchannel */ 11, + /* requiredSubchannel */ 11 ); // Must be received by dataConsumer2. @@ -326,7 +326,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'dc2', /* ppid */ undefined, /* subchannels */ [666], - /* requiredSubchannel */ 2, + /* requiredSubchannel */ 2 ); // Make dataConsumer2 also subscribe to subchannel 1. @@ -338,7 +338,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { 'both', /* ppid */ undefined, /* subchannels */ [1], - /* requiredSubchannel */ 666, + /* requiredSubchannel */ 666 ); dataConsumer1.on('message', message => { diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index fc07859c9f..7be3294d07 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -184,13 +184,13 @@ beforeEach(async () => { enableSctp: true, }); ctx.audioProducer = await ctx.webRtcTransport1.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); ctx.videoProducer = await ctx.webRtcTransport1.produce( - ctx.videoProducerOptions, + ctx.videoProducerOptions ); ctx.dataProducer = await ctx.webRtcTransport1.produceData( - ctx.dataProducerOptions, + ctx.dataProducerOptions ); }); @@ -199,14 +199,14 @@ afterEach(async () => { ctx.worker2?.close(); if (ctx.worker1?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker1?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker1?.on('subprocessclose', resolve) ); } if (ctx.worker2?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker2?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker2?.on('subprocessclose', resolve) ); } }); @@ -452,18 +452,18 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', await expect(ctx.router1!.createPipeTransport({})).rejects.toThrow(TypeError); await expect( - ctx.router1!.createPipeTransport({ listenIp: '123' }), + ctx.router1!.createPipeTransport({ listenIp: '123' }) ).rejects.toThrow(TypeError); await expect( // @ts-ignore - ctx.router1!.createPipeTransport({ listenIp: ['127.0.0.1'] }), + ctx.router1!.createPipeTransport({ listenIp: ['127.0.0.1'] }) ).rejects.toThrow(TypeError); await expect( ctx.router1!.createPipeTransport({ listenInfo: { protocol: 'tcp', ip: '127.0.0.1' }, - }), + }) ).rejects.toThrow(TypeError); await expect( @@ -471,7 +471,7 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, // @ts-ignore appData: 'NOT-AN-OBJECT', - }), + }) ).rejects.toThrow(TypeError); }, 2000); @@ -575,7 +575,7 @@ test('pipeTransport.connect() with valid SRTP parameters succeeds', async () => keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', }, - }), + }) ).resolves.toBeUndefined(); }, 2000); @@ -597,7 +597,7 @@ test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', }, - }), + }) ).rejects.toThrow(TypeError); // No SRTP enabled so passing srtpParameters (even if invalid) must fail. @@ -607,7 +607,7 @@ test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', port: 9999, // @ts-ignore srtpParameters: 'invalid', - }), + }) ).rejects.toThrow(TypeError); }); @@ -627,7 +627,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { pipeTransport.connect({ ip: '127.0.0.2', port: 9999, - }), + }) ).rejects.toThrow(TypeError); // Invalid srtpParameters. @@ -637,7 +637,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { port: 9999, // @ts-ignore srtpParameters: 1, - }), + }) ).rejects.toThrow(TypeError); // Missing srtpParameters.cryptoSuite. @@ -650,7 +650,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', }, - }), + }) ).rejects.toThrow(TypeError); // Missing srtpParameters.keyBase64. @@ -662,7 +662,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { srtpParameters: { cryptoSuite: 'AEAD_AES_256_GCM', }, - }), + }) ).rejects.toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. @@ -676,7 +676,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', }, - }), + }) ).rejects.toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. @@ -690,7 +690,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', }, - }), + }) ).rejects.toThrow(TypeError); // Invalid srtpParameters.keyBase64. @@ -703,7 +703,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { // @ts-ignore keyBase64: [], }, - }), + }) ).rejects.toThrow(TypeError); }, 2000); @@ -776,7 +776,7 @@ test('transport.consume() for a pipe Producer succeeds', async () => { expect(typeof videoConsumer.rtpParameters.encodings?.[0].ssrc).toBe('number'); expect(typeof videoConsumer.rtpParameters.encodings?.[0].rtx).toBe('object'); expect(typeof videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc).toBe( - 'number', + 'number' ); expect(videoConsumer.type).toBe('simulcast'); expect(videoConsumer.paused).toBe(false); @@ -808,7 +808,7 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', // NOTE: Let's use a Promise since otherwise there may be race conditions // between events and await lines below. const promise1 = new Promise(resolve => - videoConsumer.once('producerresume', resolve), + videoConsumer.once('producerresume', resolve) ); await ctx.videoProducer!.resume(); @@ -818,7 +818,7 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', expect(videoConsumer.paused).toBe(false); const promise2 = new Promise(resolve => - videoConsumer.once('producerpause', resolve), + videoConsumer.once('producerpause', resolve) ); await ctx.videoProducer!.pause(); @@ -845,7 +845,7 @@ test('producer.close() is transmitted to pipe Consumer', async () => { if (!videoConsumer.closed) { await new Promise(resolve => - videoConsumer.once('producerclose', resolve), + videoConsumer.once('producerclose', resolve) ); } @@ -861,7 +861,7 @@ test('router.pipeToRouter() fails if both Routers belong to the same Worker', as ctx.router1!.pipeToRouter({ producerId: ctx.videoProducer!.id, router: router1bis, - }), + }) ).rejects.toThrow(Error); }, 2000); @@ -950,7 +950,7 @@ test('dataProducer.close() is transmitted to pipe DataConsumer', async () => { if (!dataConsumer.closed) { await new Promise(resolve => - dataConsumer.once('dataproducerclose', resolve), + dataConsumer.once('dataproducerclose', resolve) ); } diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index 8e6413fb47..6ea15e625f 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -52,8 +52,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -162,18 +162,18 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' await expect(ctx.router!.createPlainTransport({})).rejects.toThrow(TypeError); await expect( - ctx.router!.createPlainTransport({ listenIp: '123' }), + ctx.router!.createPlainTransport({ listenIp: '123' }) ).rejects.toThrow(TypeError); await expect( // @ts-ignore - ctx.router!.createPlainTransport({ listenIp: ['127.0.0.1'] }), + ctx.router!.createPlainTransport({ listenIp: ['127.0.0.1'] }) ).rejects.toThrow(TypeError); await expect( ctx.router!.createPipeTransport({ listenInfo: { protocol: 'tcp', ip: '127.0.0.1' }, - }), + }) ).rejects.toThrow(TypeError); await expect( @@ -181,7 +181,7 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, // @ts-ignore appData: 'NOT-AN-OBJECT', - }), + }) ).rejects.toThrow(TypeError); }, 2000); @@ -195,7 +195,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { expect(typeof plainTransport.id).toBe('string'); expect(typeof plainTransport.srtpParameters).toBe('object'); expect(plainTransport.srtpParameters?.cryptoSuite).toBe( - 'AES_CM_128_HMAC_SHA1_80', + 'AES_CM_128_HMAC_SHA1_80' ); expect(plainTransport.srtpParameters?.keyBase64.length).toBe(40); @@ -204,7 +204,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { plainTransport.connect({ ip: '127.0.0.2', port: 9999, - }), + }) ).rejects.toThrow(TypeError); // Invalid srtpParameters. @@ -214,7 +214,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { port: 9999, // @ts-ignore srtpParameters: 1, - }), + }) ).rejects.toThrow(TypeError); // Missing srtpParameters.cryptoSuite. @@ -226,7 +226,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { srtpParameters: { keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, - }), + }) ).rejects.toThrow(TypeError); // Missing srtpParameters.keyBase64. @@ -238,7 +238,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { srtpParameters: { cryptoSuite: 'AES_CM_128_HMAC_SHA1_80', }, - }), + }) ).rejects.toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. @@ -251,7 +251,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { cryptoSuite: 'FOO', keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, - }), + }) ).rejects.toThrow(TypeError); // Invalid srtpParameters.cryptoSuite. @@ -264,7 +264,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { cryptoSuite: 123, keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, - }), + }) ).rejects.toThrow(TypeError); // Invalid srtpParameters.keyBase64. @@ -277,7 +277,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { // @ts-ignore keyBase64: [], }, - }), + }) ).rejects.toThrow(TypeError); // Valid srtpParameters. And let's update the crypto suite. @@ -290,7 +290,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', }, - }), + }) ).resolves.toBeUndefined(); expect(plainTransport.srtpParameters?.cryptoSuite).toBe('AEAD_AES_256_GCM'); @@ -299,7 +299,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { test('router.createPlainTransport() with non bindable IP rejects with Error', async () => { await expect( - ctx.router!.createPlainTransport({ listenIp: '8.8.8.8' }), + ctx.router!.createPlainTransport({ listenIp: '8.8.8.8' }) ).rejects.toThrow(Error); }, 2000); @@ -321,7 +321,7 @@ if (!IS_WINDOWS) { // NOTE: ipv6Only flag will be ignored since ip is IPv4. flags: { udpReusePort: true, ipv6Only: true }, }, - }), + }) ).resolves.toBeDefined(); await expect( @@ -332,7 +332,7 @@ if (!IS_WINDOWS) { port: port, flags: { udpReusePort: true }, }, - }), + }) ).resolves.toBeDefined(); }, 2000); @@ -352,7 +352,7 @@ if (!IS_WINDOWS) { port: port, flags: { udpReusePort: false }, }, - }), + }) ).resolves.toBeDefined(); await expect( @@ -363,7 +363,7 @@ if (!IS_WINDOWS) { port: port, flags: { udpReusePort: false }, }, - }), + }) ).rejects.toThrow(); }, 2000); } @@ -408,12 +408,12 @@ test('plainTransport.connect() succeeds', async () => { }); await expect( - plainTransport.connect({ ip: '1.2.3.4', port: 1234, rtcpPort: 1235 }), + plainTransport.connect({ ip: '1.2.3.4', port: 1234, rtcpPort: 1235 }) ).resolves.toBeUndefined(); // Must fail if connected. await expect( - plainTransport.connect({ ip: '1.2.3.4', port: 1234, rtcpPort: 1235 }), + plainTransport.connect({ ip: '1.2.3.4', port: 1234, rtcpPort: 1235 }) ).rejects.toThrow(Error); expect(plainTransport.tuple.remoteIp).toBe('1.2.3.4'); @@ -440,13 +440,13 @@ test('plainTransport.connect() with wrong arguments rejects with TypeError', asy cryptoSuite: 'AES_CM_128_HMAC_SHA1_80', keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, - }), + }) ).rejects.toThrow(TypeError); await expect(plainTransport.connect({})).rejects.toThrow(TypeError); await expect(plainTransport.connect({ ip: '::::1234' })).rejects.toThrow( - TypeError, + TypeError ); // Must fail because transport has rtcpMux: false so rtcpPort must be given @@ -457,7 +457,7 @@ test('plainTransport.connect() with wrong arguments rejects with TypeError', asy port: 1234, // @ts-ignore __rtcpPort: 1235, - }), + }) ).rejects.toThrow(TypeError); await expect( @@ -466,7 +466,7 @@ test('plainTransport.connect() with wrong arguments rejects with TypeError', asy // @ts-ignore __port: 'chicken', rtcpPort: 1235, - }), + }) ).rejects.toThrow(TypeError); }, 2000); diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index 5ee64b9e8e..18cc7eaa90 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -148,8 +148,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -160,7 +160,7 @@ test('webRtcTransport1.produce() succeeds', async () => { ctx.webRtcTransport1!.observer.once('newproducer', onObserverNewProducer); const audioProducer = await ctx.webRtcTransport1!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); @@ -194,7 +194,7 @@ test('webRtcTransport2.produce() succeeds', async () => { ctx.webRtcTransport2!.observer.once('newproducer', onObserverNewProducer); const videoProducer = await ctx.webRtcTransport2!.produce( - ctx.videoProducerOptions, + ctx.videoProducerOptions ); expect(onObserverNewProducer).toHaveBeenCalledTimes(1); @@ -213,7 +213,7 @@ test('webRtcTransport2.produce() succeeds', async () => { const dump = await ctx.router!.dump(); expect(dump.mapProducerIdConsumerIds).toEqual( - expect.arrayContaining([{ key: videoProducer.id, values: [] }]), + expect.arrayContaining([{ key: videoProducer.id, values: [] }]) ); expect(dump.mapConsumerIdProducerId.length).toBe(0); @@ -275,7 +275,7 @@ test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', a kind: 'chicken', // @ts-ignore rtpParameters: {}, - }), + }) ).rejects.toThrow(TypeError); await expect( @@ -283,7 +283,7 @@ test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', a kind: 'audio', // @ts-ignore rtpParameters: {}, - }), + }) ).rejects.toThrow(TypeError); // Invalid ssrc. @@ -297,7 +297,7 @@ test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', a encodings: [{ ssrc: '1111' }], rtcp: { cname: 'qwerty' }, }, - }), + }) ).rejects.toThrow(TypeError); // Missing or empty rtpParameters.encodings. @@ -326,7 +326,7 @@ test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', a encodings: [], rtcp: { cname: 'qwerty' }, }, - }), + }) ).rejects.toThrow(TypeError); // Wrong apt in RTX codec. @@ -357,7 +357,7 @@ test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', a cname: 'video-1', }, }, - }), + }) ).rejects.toThrow(TypeError); }, 2000); @@ -377,7 +377,7 @@ test('webRtcTransport1.produce() with unsupported codecs rejects with Unsupporte encodings: [{ ssrc: 1111 }], rtcp: { cname: 'audio' }, }, - }), + }) ).rejects.toThrow(UnsupportedError); // Invalid H264 profile-level-id. @@ -405,7 +405,7 @@ test('webRtcTransport1.produce() with unsupported codecs rejects with Unsupporte headerExtensions: [], encodings: [{ ssrc: 6666, rtx: { ssrc: 6667 } }], }, - }), + }) ).rejects.toThrow(UnsupportedError); }, 2000); @@ -457,13 +457,13 @@ test('transport.produce() with already used MID or SSRC rejects with Error', asy await ctx.webRtcTransport1!.produce(audioProducerOptions); await expect( - ctx.webRtcTransport1!.produce(audioProducerOptions), + ctx.webRtcTransport1!.produce(audioProducerOptions) ).rejects.toThrow(Error); await ctx.webRtcTransport2!.produce(videoProducerOptions); await expect( - ctx.webRtcTransport2!.produce(videoProducerOptions), + ctx.webRtcTransport2!.produce(videoProducerOptions) ).rejects.toThrow(Error); }, 2000); @@ -482,13 +482,13 @@ test('transport.produce() with no MID and with single encoding without RID or SS ], encodings: [{}], }, - }), + }) ).rejects.toThrow(Error); }, 2000); test('producer.dump() succeeds', async () => { const audioProducer = await ctx.webRtcTransport1!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); const dump1 = await audioProducer.dump(); @@ -530,12 +530,12 @@ test('producer.dump() succeeds', async () => { expect(dump1.rtpParameters.encodings![0]).toEqual( expect.objectContaining({ codecPayloadType: 0, - }), + }) ); expect(dump1.type).toBe('simple'); const videoProducer = await ctx.webRtcTransport2!.produce( - ctx.videoProducerOptions, + ctx.videoProducerOptions ); const dump2 = await videoProducer.dump(); @@ -598,11 +598,11 @@ test('producer.dump() succeeds', async () => { test('producer.getStats() succeeds', async () => { const audioProducer = await ctx.webRtcTransport1!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); const videoProducer = await ctx.webRtcTransport2!.produce( - ctx.videoProducerOptions, + ctx.videoProducerOptions ); await expect(audioProducer.getStats()).resolves.toEqual([]); @@ -612,7 +612,7 @@ test('producer.getStats() succeeds', async () => { test('producer.pause() and resume() succeed', async () => { const audioProducer = await ctx.webRtcTransport1!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); const onObserverPause = jest.fn(); @@ -646,7 +646,7 @@ test('producer.pause() and resume() succeed', async () => { test('producer.pause() and resume() emit events', async () => { const audioProducer = await ctx.webRtcTransport1!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); const promises = []; @@ -671,7 +671,7 @@ test('producer.pause() and resume() emit events', async () => { test('producer.enableTraceEvent() succeed', async () => { const audioProducer = await ctx.webRtcTransport1!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); await audioProducer.enableTraceEvent(['rtp', 'pli']); @@ -692,7 +692,7 @@ test('producer.enableTraceEvent() succeed', async () => { const dump3 = await audioProducer.dump(); expect(dump3.traceEventTypes).toEqual( - expect.arrayContaining(['nack', 'fir']), + expect.arrayContaining(['nack', 'fir']) ); await audioProducer.enableTraceEvent(); @@ -704,7 +704,7 @@ test('producer.enableTraceEvent() succeed', async () => { test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { const audioProducer = await ctx.webRtcTransport1!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); // @ts-ignore @@ -712,18 +712,18 @@ test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', // @ts-ignore await expect(audioProducer.enableTraceEvent('rtp')).rejects.toThrow( - TypeError, + TypeError ); await expect( // @ts-ignore - audioProducer.enableTraceEvent(['fir', 123.123]), + audioProducer.enableTraceEvent(['fir', 123.123]) ).rejects.toThrow(TypeError); }, 2000); test('Producer emits "score"', async () => { const videoProducer = await ctx.webRtcTransport2!.produce( - ctx.videoProducerOptions, + ctx.videoProducerOptions ); // Private API. @@ -739,13 +739,13 @@ test('Producer emits "score"', async () => { /* encodingIdx */ 0, /* ssrc */ 11, /* rid */ undefined, - /* score */ 10, + /* score */ 10 ), new FbsProducer.ScoreT( /* encodingIdx */ 1, /* ssrc */ 22, /* rid */ undefined, - /* score */ 9, + /* score */ 9 ), ]); const notificationOffset = Notification.createNotification( @@ -753,13 +753,13 @@ test('Producer emits "score"', async () => { builder.createString(videoProducer.id), Event.PRODUCER_SCORE, NotificationBody.Producer_ScoreNotification, - producerScoreNotification.pack(builder), + producerScoreNotification.pack(builder) ); builder.finish(notificationOffset); const notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array()), + new flatbuffers.ByteBuffer(builder.asUint8Array()) ); channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); @@ -775,7 +775,7 @@ test('Producer emits "score"', async () => { test('producer.close() succeeds', async () => { const audioProducer = await ctx.webRtcTransport1!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); const onObserverClose = jest.fn(); @@ -800,7 +800,7 @@ test('producer.close() succeeds', async () => { test('Producer methods reject if closed', async () => { const audioProducer = await ctx.webRtcTransport1!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); audioProducer.close(); @@ -816,7 +816,7 @@ test('Producer methods reject if closed', async () => { test('Producer emits "transportclose" if Transport is closed', async () => { const videoProducer = await ctx.webRtcTransport2!.produce( - ctx.videoProducerOptions, + ctx.videoProducerOptions ); const onObserverClose = jest.fn(); diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index 80e1f263e2..b5f989bfe4 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -46,8 +46,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -108,12 +108,12 @@ test('worker.createRouter() succeeds', async () => { test('worker.createRouter() with wrong arguments rejects with TypeError', async () => { // @ts-ignore await expect(ctx.worker!.createRouter({ mediaCodecs: {} })).rejects.toThrow( - TypeError, + TypeError ); await expect( // @ts-ignore - ctx.worker!.createRouter({ appData: 'NOT-AN-OBJECT' }), + ctx.worker!.createRouter({ appData: 'NOT-AN-OBJECT' }) ).rejects.toThrow(TypeError); }, 2000); @@ -121,7 +121,7 @@ test('worker.createRouter() rejects with InvalidStateError if Worker is closed', ctx.worker!.close(); await expect( - ctx.worker!.createRouter({ mediaCodecs: ctx.mediaCodecs }), + ctx.worker!.createRouter({ mediaCodecs: ctx.mediaCodecs }) ).rejects.toThrow(InvalidStateError); }, 2000); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index 85a83df6a2..a48d0d129c 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -16,8 +16,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -153,17 +153,17 @@ test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', await expect( // @ts-ignore - ctx.worker!.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' }), + ctx.worker!.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' }) ).rejects.toThrow(TypeError); await expect( // @ts-ignore - ctx.worker!.createWebRtcServer({ listenInfos: ['NOT-AN-OBJECT'] }), + ctx.worker!.createWebRtcServer({ listenInfos: ['NOT-AN-OBJECT'] }) ).rejects.toThrow(Error); // Empty listenInfos so should fail. await expect( - ctx.worker!.createWebRtcServer({ listenInfos: [] }), + ctx.worker!.createWebRtcServer({ listenInfos: [] }) ).rejects.toThrow(TypeError); }, 2000); @@ -195,7 +195,7 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro port: port2, }, ], - }), + }) ).rejects.toThrow(Error); // Using the same UDP port in two listenInfos. @@ -214,7 +214,7 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro port: port1, }, ], - }), + }) ).rejects.toThrow(Error); await ctx.worker!.createWebRtcServer({ @@ -237,7 +237,7 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro port: port1, }, ], - }), + }) ).rejects.toThrow(Error); worker2.close(); @@ -255,7 +255,7 @@ test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is cl await expect( ctx.worker!.createWebRtcServer({ listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', port }], - }), + }) ).rejects.toThrow(InvalidStateError); }, 2000); @@ -322,11 +322,11 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is webRtcServer.observer.once( 'webrtctransporthandled', - onObserverWebRtcTransportHandled, + onObserverWebRtcTransportHandled ); webRtcServer.observer.once( 'webrtctransportunhandled', - onObserverWebRtcTransportUnhandled, + onObserverWebRtcTransportUnhandled ); const router = await ctx.worker!.createRouter(); @@ -421,11 +421,11 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer webRtcServer.observer.once( 'webrtctransporthandled', - onObserverWebRtcTransportHandled, + onObserverWebRtcTransportHandled ); webRtcServer.observer.once( 'webrtctransportunhandled', - onObserverWebRtcTransportUnhandled, + onObserverWebRtcTransportUnhandled ); const router = await ctx.worker!.createRouter(); diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 7e10d17dda..79fdd25041 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -57,8 +57,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); @@ -176,22 +176,22 @@ test('router.createWebRtcTransport() succeeds', async () => { test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore await expect(ctx.router!.createWebRtcTransport({})).rejects.toThrow( - TypeError, + TypeError ); await expect( // @ts-ignore - ctx.router!.createWebRtcTransport({ listenIps: [123] }), + ctx.router!.createWebRtcTransport({ listenIps: [123] }) ).rejects.toThrow(TypeError); await expect( // @ts-ignore - ctx.router!.createWebRtcTransport({ listenInfos: '127.0.0.1' }), + ctx.router!.createWebRtcTransport({ listenInfos: '127.0.0.1' }) ).rejects.toThrow(TypeError); await expect( // @ts-ignore - ctx.router!.createWebRtcTransport({ listenIps: '127.0.0.1' }), + ctx.router!.createWebRtcTransport({ listenIps: '127.0.0.1' }) ).rejects.toThrow(TypeError); await expect( @@ -199,7 +199,7 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError listenIps: ['127.0.0.1'], // @ts-ignore appData: 'NOT-AN-OBJECT', - }), + }) ).rejects.toThrow(TypeError); await expect( @@ -208,7 +208,7 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError enableSctp: true, // @ts-ignore numSctpStreams: 'foo', - }), + }) ).rejects.toThrow(TypeError); }, 2000); @@ -216,7 +216,7 @@ test('router.createWebRtcTransport() with non bindable IP rejects with Error', a await expect( ctx.router!.createWebRtcTransport({ listenInfos: [{ protocol: 'udp', ip: '8.8.8.8' }], - }), + }) ).rejects.toThrow(Error); }, 2000); @@ -271,12 +271,12 @@ test('webRtcTransport.connect() succeeds', async () => { }; await expect( - webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }) ).resolves.toBeUndefined(); // Must fail if connected. await expect( - webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }) ).rejects.toThrow(Error); expect(webRtcTransport.dtlsParameters.role).toBe('server'); @@ -305,7 +305,7 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as }; await expect( - webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }) ).rejects.toThrow(TypeError); dtlsRemoteParameters = { @@ -321,7 +321,7 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as }; await expect( - webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }) ).rejects.toThrow(TypeError); dtlsRemoteParameters = { @@ -330,11 +330,11 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as }; await expect( - webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }) ).rejects.toThrow(TypeError); await expect( - webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }), + webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }) ).rejects.toThrow(TypeError); expect(webRtcTransport.dtlsParameters.role).toBe('auto'); @@ -346,12 +346,12 @@ test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => { }); await expect( - webRtcTransport.setMaxIncomingBitrate(1000000), + webRtcTransport.setMaxIncomingBitrate(1000000) ).resolves.toBeUndefined(); // Remove limit. await expect( - webRtcTransport.setMaxIncomingBitrate(0), + webRtcTransport.setMaxIncomingBitrate(0) ).resolves.toBeUndefined(); }, 2000); @@ -361,12 +361,12 @@ test('webRtcTransport.setMaxOutgoingBitrate() succeeds', async () => { }); await expect( - webRtcTransport.setMaxOutgoingBitrate(2000000), + webRtcTransport.setMaxOutgoingBitrate(2000000) ).resolves.toBeUndefined(); // Remove limit. await expect( - webRtcTransport.setMaxOutgoingBitrate(0), + webRtcTransport.setMaxOutgoingBitrate(0) ).resolves.toBeUndefined(); }, 2000); @@ -376,12 +376,12 @@ test('webRtcTransport.setMinOutgoingBitrate() succeeds', async () => { }); await expect( - webRtcTransport.setMinOutgoingBitrate(100000), + webRtcTransport.setMinOutgoingBitrate(100000) ).resolves.toBeUndefined(); // Remove limit. await expect( - webRtcTransport.setMinOutgoingBitrate(0), + webRtcTransport.setMinOutgoingBitrate(0) ).resolves.toBeUndefined(); }, 2000); @@ -391,16 +391,16 @@ test('webRtcTransport.setMaxOutgoingBitrate() fails if value is lower than curre }); await expect( - webRtcTransport.setMinOutgoingBitrate(3000000), + webRtcTransport.setMinOutgoingBitrate(3000000) ).resolves.toBeUndefined(); await expect(webRtcTransport.setMaxOutgoingBitrate(2000000)).rejects.toThrow( - Error, + Error ); // Remove limit. await expect( - webRtcTransport.setMinOutgoingBitrate(0), + webRtcTransport.setMinOutgoingBitrate(0) ).resolves.toBeUndefined(); }, 2000); @@ -410,16 +410,16 @@ test('webRtcTransport.setMinOutgoingBitrate() fails if value is higher than curr }); await expect( - webRtcTransport.setMaxOutgoingBitrate(2000000), + webRtcTransport.setMaxOutgoingBitrate(2000000) ).resolves.toBeUndefined(); await expect(webRtcTransport.setMinOutgoingBitrate(3000000)).rejects.toThrow( - Error, + Error ); // Remove limit. await expect( - webRtcTransport.setMaxOutgoingBitrate(0), + webRtcTransport.setMaxOutgoingBitrate(0) ).resolves.toBeUndefined(); }, 2000); @@ -441,7 +441,7 @@ test('webRtcTransport.restartIce() succeeds', async () => { expect(typeof webRtcTransport.iceParameters.usernameFragment).toBe('string'); expect(typeof webRtcTransport.iceParameters.password).toBe('string'); expect(webRtcTransport.iceParameters.usernameFragment).not.toBe( - previousIceUsernameFragment, + previousIceUsernameFragment ); expect(webRtcTransport.iceParameters.password).not.toBe(previousIcePassword); }, 2000); @@ -481,17 +481,17 @@ test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', // @ts-ignore await expect(webRtcTransport.enableTraceEvent(123)).rejects.toThrow( - TypeError, + TypeError ); // @ts-ignore await expect(webRtcTransport.enableTraceEvent('probation')).rejects.toThrow( - TypeError, + TypeError ); await expect( // @ts-ignore - webRtcTransport.enableTraceEvent(['probation', 123.123]), + webRtcTransport.enableTraceEvent(['probation', 123.123]) ).rejects.toThrow(TypeError); }, 2000); @@ -511,7 +511,7 @@ test('WebRtcTransport events succeed', async () => { const builder = new flatbuffers.Builder(); const iceStateChangeNotification = new FbsWebRtcTransport.IceStateChangeNotificationT( - FbsWebRtcTransport.IceState.COMPLETED, + FbsWebRtcTransport.IceState.COMPLETED ); let notificationOffset = Notification.createNotification( @@ -519,19 +519,19 @@ test('WebRtcTransport events succeed', async () => { builder.createString(webRtcTransport.id), Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, NotificationBody.WebRtcTransport_IceStateChangeNotification, - iceStateChangeNotification.pack(builder), + iceStateChangeNotification.pack(builder) ); builder.finish(notificationOffset); let notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array()), + new flatbuffers.ByteBuffer(builder.asUint8Array()) ); channel.emit( webRtcTransport.id, Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, - notification, + notification ); expect(onIceStateChange).toHaveBeenCalledTimes(1); @@ -559,8 +559,8 @@ test('WebRtcTransport events succeed', async () => { iceSelectedTuple.localPort, iceSelectedTuple.remoteIp, iceSelectedTuple.remotePort, - serializeProtocol(iceSelectedTuple.protocol), - ), + serializeProtocol(iceSelectedTuple.protocol) + ) ); notificationOffset = Notification.createNotification( @@ -568,19 +568,19 @@ test('WebRtcTransport events succeed', async () => { builder.createString(webRtcTransport.id), Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, NotificationBody.WebRtcTransport_IceSelectedTupleChangeNotification, - iceSelectedTupleChangeNotification.pack(builder), + iceSelectedTupleChangeNotification.pack(builder) ); builder.finish(notificationOffset); notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array()), + new flatbuffers.ByteBuffer(builder.asUint8Array()) ); channel.emit( webRtcTransport.id, Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, - notification, + notification ); expect(onIceSelectedTuple).toHaveBeenCalledTimes(1); @@ -596,7 +596,7 @@ test('WebRtcTransport events succeed', async () => { // Simulate a 'dtlsstatechange' notification coming through the channel. const dtlsStateChangeNotification = new FbsWebRtcTransport.DtlsStateChangeNotificationT( - FbsWebRtcTransport.DtlsState.CONNECTING, + FbsWebRtcTransport.DtlsState.CONNECTING ); notificationOffset = Notification.createNotification( @@ -604,19 +604,19 @@ test('WebRtcTransport events succeed', async () => { builder.createString(webRtcTransport.id), Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, NotificationBody.WebRtcTransport_DtlsStateChangeNotification, - dtlsStateChangeNotification.pack(builder), + dtlsStateChangeNotification.pack(builder) ); builder.finish(notificationOffset); notification = Notification.getRootAsNotification( - new flatbuffers.ByteBuffer(builder.asUint8Array()), + new flatbuffers.ByteBuffer(builder.asUint8Array()) ); channel.emit( webRtcTransport.id, Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, - notification, + notification ); expect(onDtlsStateChange).toHaveBeenCalledTimes(1); @@ -649,15 +649,15 @@ test('WebRtcTransport methods reject if closed', async () => { await expect(webRtcTransport.connect({})).rejects.toThrow(Error); await expect(webRtcTransport.setMaxIncomingBitrate(200000)).rejects.toThrow( - Error, + Error ); await expect(webRtcTransport.setMaxOutgoingBitrate(200000)).rejects.toThrow( - Error, + Error ); await expect(webRtcTransport.setMinOutgoingBitrate(100000)).rejects.toThrow( - Error, + Error ); await expect(webRtcTransport.restartIce()).rejects.toThrow(Error); diff --git a/node/src/test/test-Worker.ts b/node/src/test/test-Worker.ts index 3c5314e2ed..a29fa5e457 100644 --- a/node/src/test/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -16,7 +16,7 @@ test('Worker.workerBin matches mediasoup-worker absolute path', () => { 'worker', 'out', 'Debug', - 'mediasoup-worker', + 'mediasoup-worker' ) : path.join( __dirname, @@ -26,7 +26,7 @@ test('Worker.workerBin matches mediasoup-worker absolute path', () => { 'worker', 'out', 'Release', - 'mediasoup-worker', + 'mediasoup-worker' ); expect(mediasoup.workerBin).toBe(workerBin); @@ -81,29 +81,29 @@ test('createWorker() succeeds', async () => { test('createWorker() with wrong settings rejects with TypeError', async () => { // @ts-ignore await expect(mediasoup.createWorker({ logLevel: 'chicken' })).rejects.toThrow( - TypeError, + TypeError ); await expect( - mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 999 }), + mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 999 }) ).rejects.toThrow(TypeError); // Port is from 0 to 65535. await expect( - mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 65536 }), + mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 65536 }) ).rejects.toThrow(TypeError); await expect( - mediasoup.createWorker({ dtlsCertificateFile: '/notfound/cert.pem' }), + mediasoup.createWorker({ dtlsCertificateFile: '/notfound/cert.pem' }) ).rejects.toThrow(TypeError); await expect( - mediasoup.createWorker({ dtlsPrivateKeyFile: '/notfound/priv.pem' }), + mediasoup.createWorker({ dtlsPrivateKeyFile: '/notfound/priv.pem' }) ).rejects.toThrow(TypeError); await expect( // @ts-ignore - mediasoup.createWorker({ appData: 'NOT-AN-OBJECT' }), + mediasoup.createWorker({ appData: 'NOT-AN-OBJECT' }) ).rejects.toThrow(TypeError); }, 2000); @@ -111,7 +111,7 @@ test('worker.updateSettings() succeeds', async () => { const worker = await mediasoup.createWorker(); await expect( - worker.updateSettings({ logLevel: 'debug', logTags: ['ice'] }), + worker.updateSettings({ logLevel: 'debug', logTags: ['ice'] }) ).resolves.toBeUndefined(); worker.close(); @@ -124,7 +124,7 @@ test('worker.updateSettings() with wrong settings rejects with TypeError', async // @ts-ignore await expect(worker.updateSettings({ logLevel: 'chicken' })).rejects.toThrow( - TypeError, + TypeError ); worker.close(); @@ -140,7 +140,7 @@ test('worker.updateSettings() rejects with InvalidStateError if closed', async ( await new Promise(resolve => worker.on('subprocessclose', resolve)); await expect(worker.updateSettings({ logLevel: 'error' })).rejects.toThrow( - InvalidStateError, + InvalidStateError ); }, 2000); @@ -211,9 +211,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { if (onObserverClose.mock.calls.length > 0) { reject( - new Error( - 'observer "close" event emitted before worker "died" event', - ), + new Error('observer "close" event emitted before worker "died" event') ); } else if (worker1.closed) { resolve(); @@ -247,9 +245,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { if (onObserverClose.mock.calls.length > 0) { reject( - new Error( - 'observer "close" event emitted before worker "died" event', - ), + new Error('observer "close" event emitted before worker "died" event') ); } else if (worker2.closed) { resolve(); @@ -283,9 +279,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { if (onObserverClose.mock.calls.length > 0) { reject( - new Error( - 'observer "close" event emitted before worker "died" event', - ), + new Error('observer "close" event emitted before worker "died" event') ); } else if (worker3.closed) { resolve(); diff --git a/node/src/test/test-mediasoup.ts b/node/src/test/test-mediasoup.ts index d3643639a8..455d6472eb 100644 --- a/node/src/test/test-mediasoup.ts +++ b/node/src/test/test-mediasoup.ts @@ -5,7 +5,7 @@ import * as mediasoup from '../'; const PKG = JSON.parse( fs.readFileSync(path.join(__dirname, '..', '..', '..', 'package.json'), { encoding: 'utf-8', - }), + }) ); const { version, getSupportedRtpCapabilities, parseScalabilityMode } = diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index 95f65dcb33..cf7ea964f1 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -107,15 +107,15 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } }); test('produce() and consume() succeed', async () => { const audioProducer = await ctx.webRtcTransport!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); expect(audioProducer.rtpParameters.codecs).toEqual([ @@ -138,7 +138,7 @@ test('produce() and consume() succeed', async () => { ctx.router!.canConsume({ producerId: audioProducer.id, rtpCapabilities: ctx.consumerDeviceCapabilities, - }), + }) ).toBe(true); const audioConsumer = await ctx.webRtcTransport!.consume({ @@ -183,7 +183,7 @@ test('fails to produce wrong parameters', async () => { }, ], }, - }), + }) ).rejects.toThrow(UnsupportedError); await expect( @@ -205,13 +205,13 @@ test('fails to produce wrong parameters', async () => { }, ], }, - }), + }) ).rejects.toThrow(UnsupportedError); }, 2000); test('fails to consume wrong channels', async () => { const audioProducer = await ctx.webRtcTransport!.produce( - ctx.audioProducerOptions, + ctx.audioProducerOptions ); const localConsumerDeviceCapabilities: mediasoup.types.RtpCapabilities = { @@ -235,13 +235,13 @@ test('fails to consume wrong channels', async () => { !ctx.router!.canConsume({ producerId: audioProducer.id, rtpCapabilities: localConsumerDeviceCapabilities, - }), + }) ).toBe(true); await expect( ctx.webRtcTransport!.consume({ producerId: audioProducer.id, rtpCapabilities: localConsumerDeviceCapabilities, - }), + }) ).rejects.toThrow(Error); }, 2000); diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index fda8c9169c..513b27becd 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -68,7 +68,7 @@ beforeEach(async () => { await Promise.race([ new Promise(resolve => ctx.sctpSocket.on('connect', resolve)), new Promise((resolve, reject) => - setTimeout(() => reject(new Error('SCTP connection timeout')), 3000), + setTimeout(() => reject(new Error('SCTP connection timeout')), 3000) ), ]); @@ -100,8 +100,8 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise( - resolve => ctx.worker?.on('subprocessclose', resolve), + await new Promise(resolve => + ctx.worker?.on('subprocessclose', resolve) ); } @@ -174,22 +174,22 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn if (id !== numReceivedMessages) { reject( new Error( - `id ${id} in message should match numReceivedMessages ${numReceivedMessages}`, - ), + `id ${id} in message should match numReceivedMessages ${numReceivedMessages}` + ) ); } else if (id === numMessages) { resolve(); } else if (id < numMessages / 2 && ppid !== sctp.PPID.WEBRTC_STRING) { reject( new Error( - `ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_STRING} but it is ${ppid}`, - ), + `ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_STRING} but it is ${ppid}` + ) ); } else if (id > numMessages / 2 && ppid !== sctp.PPID.WEBRTC_BINARY) { reject( new Error( - `ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_BINARY} but it is ${ppid}`, - ), + `ppid in message with id ${id} should be ${sctp.PPID.WEBRTC_BINARY} but it is ${ppid}` + ) ); return; diff --git a/node/src/test/test-ortc.ts b/node/src/test/test-ortc.ts index 11b8cbbec9..e07ad9d091 100644 --- a/node/src/test/test-ortc.ts +++ b/node/src/test/test-ortc.ts @@ -131,7 +131,7 @@ test('generateRouterRtpCapabilities() with unsupported codecs throws Unsupported ]; expect(() => ortc.generateRouterRtpCapabilities(mediaCodecs)).toThrow( - UnsupportedError, + UnsupportedError ); mediaCodecs = [ @@ -144,7 +144,7 @@ test('generateRouterRtpCapabilities() with unsupported codecs throws Unsupported ]; expect(() => ortc.generateRouterRtpCapabilities(mediaCodecs)).toThrow( - UnsupportedError, + UnsupportedError ); }); @@ -161,7 +161,7 @@ test('generateRouterRtpCapabilities() with too many codecs throws', () => { } expect(() => ortc.generateRouterRtpCapabilities(mediaCodecs)).toThrow( - 'cannot allocate', + 'cannot allocate' ); }); @@ -251,7 +251,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum const rtpMapping = ortc.getProducerRtpParametersMapping( rtpParameters, - routerRtpCapabilities, + routerRtpCapabilities ); expect(rtpMapping.codecs).toEqual([ @@ -273,7 +273,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum 'video', rtpParameters, routerRtpCapabilities, - rtpMapping, + rtpMapping ); expect(consumableRtpParameters.codecs[0].mimeType).toBe('video/H264'); @@ -486,19 +486,19 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(typeof pipeConsumerRtpParameters.encodings?.[0].ssrc).toBe('number'); expect(pipeConsumerRtpParameters.encodings?.[0].rtx).toBeUndefined(); expect(typeof pipeConsumerRtpParameters.encodings?.[0].maxBitrate).toBe( - 'number', + 'number' ); expect(pipeConsumerRtpParameters.encodings?.[0].scalabilityMode).toBe('L1T3'); expect(typeof pipeConsumerRtpParameters.encodings?.[1].ssrc).toBe('number'); expect(pipeConsumerRtpParameters.encodings?.[1].rtx).toBeUndefined(); expect(typeof pipeConsumerRtpParameters.encodings?.[1].maxBitrate).toBe( - 'number', + 'number' ); expect(pipeConsumerRtpParameters.encodings?.[1].scalabilityMode).toBe('L1T3'); expect(typeof pipeConsumerRtpParameters.encodings?.[2].ssrc).toBe('number'); expect(pipeConsumerRtpParameters.encodings?.[2].rtx).toBeUndefined(); expect(typeof pipeConsumerRtpParameters.encodings?.[2].maxBitrate).toBe( - 'number', + 'number' ); expect(pipeConsumerRtpParameters.encodings?.[2].scalabilityMode).toBe('L1T3'); @@ -549,6 +549,6 @@ test('getProducerRtpParametersMapping() with incompatible params throws Unsuppor }; expect(() => - ortc.getProducerRtpParametersMapping(rtpParameters, routerRtpCapabilities), + ortc.getProducerRtpParametersMapping(rtpParameters, routerRtpCapabilities) ).toThrow(UnsupportedError); }); diff --git a/node/src/utils.ts b/node/src/utils.ts index f7af5c17f3..eef0a53663 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -37,7 +37,7 @@ export function generateRandomNumber(): number { */ export function getRtpParametersType( producerType: ProducerType, - pipe: boolean, + pipe: boolean ): FbsRtpParametersType { if (pipe) { return FbsRtpParametersType.PIPE; @@ -64,7 +64,7 @@ export function getRtpParametersType( export function parseVector( binary: any, methodName: string, - parseFn?: (binary2: any) => Type, + parseFn?: (binary2: any) => Type ): Type[] { const array: Type[] = []; @@ -84,7 +84,7 @@ export function parseVector( */ export function parseStringStringVector( binary: any, - methodName: string, + methodName: string ): { key: string; value: string }[] { const array: { key: string; value: string }[] = []; @@ -102,7 +102,7 @@ export function parseStringStringVector( */ export function parseStringUint8Vector( binary: any, - methodName: string, + methodName: string ): { key: string; value: number }[] { const array: { key: string; value: number }[] = []; @@ -120,7 +120,7 @@ export function parseStringUint8Vector( */ export function parseUint16StringVector( binary: any, - methodName: string, + methodName: string ): { key: number; value: string }[] { const array: { key: number; value: string }[] = []; @@ -138,7 +138,7 @@ export function parseUint16StringVector( */ export function parseUint32StringVector( binary: any, - methodName: string, + methodName: string ): { key: number; value: string }[] { const array: { key: number; value: string }[] = []; @@ -156,7 +156,7 @@ export function parseUint32StringVector( */ export function parseStringStringArrayVector( binary: any, - methodName: string, + methodName: string ): { key: string; values: string[] }[] { const array: { key: string; values: string[] }[] = []; diff --git a/node/tsconfig.json b/node/tsconfig.json index 87394576c7..93b6d29477 100644 --- a/node/tsconfig.json +++ b/node/tsconfig.json @@ -8,13 +8,13 @@ "strict": true, "outDir": "lib", "declaration": true, - "declarationMap": true + "declarationMap": true, }, "include": ["src"], "watchOptions": { "watchFile": "useFsEvents", "watchDirectory": "useFsEvents", "fallbackPolling": "dynamicPriority", - "synchronousWatchDirectory": true - } + "synchronousWatchDirectory": true, + }, } diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 1090f6e17c..5b1ab8f57a 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -81,7 +81,7 @@ async function run() { !process.env.MEDIASOUP_FORCE_WORKER_PREBUILT_DOWNLOAD ) { logInfo( - 'skipping mediasoup-worker prebuilt download, building it locally', + 'skipping mediasoup-worker prebuilt download, building it locally' ); buildWorker(); @@ -93,7 +93,7 @@ async function run() { // Attempt to download a prebuilt binary. Fallback to building locally. else if (!(await downloadPrebuiltWorker())) { logInfo( - `couldn't fetch any mediasoup-worker prebuilt binary, building it locally`, + `couldn't fetch any mediasoup-worker prebuilt binary, building it locally` ); buildWorker(); @@ -297,7 +297,7 @@ function installInvoke() { // installation. executeCmd( `"${PYTHON}" -m pip install --upgrade --no-user --target "${PIP_INVOKE_DIR}" invoke`, - /* exitOnError */ true, + /* exitOnError */ true ); } @@ -353,7 +353,7 @@ function lintNode() { executeCmd('eslint-config-prettier .eslintrc.js'); executeCmd( - 'eslint -c .eslintrc.js --ignore-path .eslintignore --max-warnings 0 .', + 'eslint -c .eslintrc.js --ignore-path .eslintignore --max-warnings 0 .' ); } @@ -389,8 +389,8 @@ function flatcNode() { 'build', 'subprojects', `flatbuffers-${FLATBUFFERS_VERSION}`, - `flatc${extension}`, - ), + `flatc${extension}` + ) ); const out = path.resolve(path.join('node', 'src')); @@ -404,7 +404,7 @@ function flatcNode() { const filePath = path.resolve(path.join('worker', 'fbs', dirent.name)); executeCmd( - `"${flatc}" --ts --ts-no-import-ext --gen-object-api -o "${out}" "${filePath}"`, + `"${flatc}" --ts --ts-no-import-ext --gen-object-api -o "${out}" "${filePath}"` ); } } @@ -475,7 +475,7 @@ async function prebuildWorker() { cwd: WORKER_RELEASE_DIR, gzip: true, }, - [WORKER_RELEASE_BIN], + [WORKER_RELEASE_BIN] ) .pipe(fs.createWriteStream(WORKER_PREBUILD_TAR_PATH)) .on('finish', resolve) @@ -505,20 +505,20 @@ async function downloadPrebuiltWorker() { if (res.status === 404) { logInfo( - 'downloadPrebuiltWorker() | no available mediasoup-worker prebuilt binary for current architecture', + 'downloadPrebuiltWorker() | no available mediasoup-worker prebuilt binary for current architecture' ); return false; } else if (!res.ok) { logError( - `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${res.status} ${res.statusText}`, + `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${res.status} ${res.statusText}` ); return false; } } catch (error) { logError( - `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${error}`, + `downloadPrebuiltWorker() | failed to download mediasoup-worker prebuilt binary: ${error}` ); return false; @@ -533,11 +533,11 @@ async function downloadPrebuiltWorker() { tar.extract({ newer: false, cwd: WORKER_RELEASE_DIR, - }), + }) ) .on('finish', () => { logInfo( - 'downloadPrebuiltWorker() | got mediasoup-worker prebuilt binary', + 'downloadPrebuiltWorker() | got mediasoup-worker prebuilt binary' ); try { @@ -545,7 +545,7 @@ async function downloadPrebuiltWorker() { fs.chmodSync(WORKER_RELEASE_BIN_PATH, 0o775); } catch (error) { logWarn( - `downloadPrebuiltWorker() | failed to give execution permissions to the mediasoup-worker prebuilt binary: ${error}`, + `downloadPrebuiltWorker() | failed to give execution permissions to the mediasoup-worker prebuilt binary: ${error}` ); } @@ -556,7 +556,7 @@ async function downloadPrebuiltWorker() { // expect exit code 41 (see main.cpp). logInfo( - 'downloadPrebuiltWorker() | checking fetched mediasoup-worker prebuilt binary in current host', + 'downloadPrebuiltWorker() | checking fetched mediasoup-worker prebuilt binary in current host' ); try { @@ -572,13 +572,13 @@ async function downloadPrebuiltWorker() { } catch (error) { if (error.status === 41) { logInfo( - 'downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary is valid for current host', + 'downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary is valid for current host' ); resolve(true); } else { logError( - `downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary fails to run in this host [status:${error.status}]`, + `downloadPrebuiltWorker() | fetched mediasoup-worker prebuilt binary fails to run in this host [status:${error.status}]` ); try { @@ -591,7 +591,7 @@ async function downloadPrebuiltWorker() { }) .on('error', error => { logError( - `downloadPrebuiltWorker() | failed to uncompress downloaded mediasoup-worker prebuilt binary: ${error}`, + `downloadPrebuiltWorker() | failed to uncompress downloaded mediasoup-worker prebuilt binary: ${error}` ); resolve(false); @@ -664,7 +664,7 @@ async function getVersionChanges() { // This should not happen (unless author forgot to update CHANGELOG). throw new Error( - `no entry found in CHANGELOG.md for version '${PKG.version}'`, + `no entry found in CHANGELOG.md for version '${PKG.version}'` ); } diff --git a/package-lock.json b/package-lock.json index f5795b33fb..c9a7fd26ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,20 +21,20 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.11.0", - "@typescript-eslint/eslint-plugin": "^6.18.1", - "@typescript-eslint/parser": "^6.18.1", + "@types/node": "^20.11.10", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.6.2", + "eslint-plugin-jest": "^27.6.3", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^11.1.1", + "marked": "^11.2.0", "open-cli": "^8.0.0", - "pick-port": "^2.0.0", - "prettier": "^3.1.1", + "pick-port": "^2.0.1", + "prettier": "^3.2.4", "sctp": "^1.0.0", - "ts-jest": "^29.1.1", + "ts-jest": "^29.1.2", "typescript": "^5.3.3" }, "engines": { @@ -1626,9 +1626,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", - "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", + "version": "20.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", + "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1662,16 +1662,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz", - "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", + "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/type-utils": "6.18.1", - "@typescript-eslint/utils": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/type-utils": "6.19.1", + "@typescript-eslint/utils": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1697,13 +1697,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", - "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", + "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1" + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1714,9 +1714,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", - "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", + "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1727,13 +1727,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", - "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", + "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1755,17 +1755,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", - "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", + "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", "semver": "^7.5.4" }, "engines": { @@ -1780,12 +1780,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", - "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", + "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/types": "6.19.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1821,15 +1821,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz", - "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", + "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4" }, "engines": { @@ -1849,13 +1849,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", - "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", + "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1" + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1866,9 +1866,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", - "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", + "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1879,13 +1879,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", - "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", + "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1907,12 +1907,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", - "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", + "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/types": "6.19.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1965,13 +1965,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz", - "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", + "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.18.1", - "@typescript-eslint/utils": "6.18.1", + "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/utils": "6.19.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1992,13 +1992,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", - "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", + "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1" + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2009,9 +2009,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", - "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", + "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2022,13 +2022,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", - "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", + "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2050,17 +2050,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", - "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", + "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", "semver": "^7.5.4" }, "engines": { @@ -2075,12 +2075,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", - "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", + "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/types": "6.19.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3003,9 +3003,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.2.tgz", - "integrity": "sha512-CI1AlKrsNhYFoP48VU8BVWOi7+qHTq4bRxyUlGjeU8SfFt8abjXhjOuDzUoMp68DoXIx17KpNpIkMrl4s4ZW0g==", + "version": "27.6.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz", + "integrity": "sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -4731,9 +4731,9 @@ } }, "node_modules/marked": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", - "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz", + "integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -5130,9 +5130,9 @@ } }, "node_modules/pick-port": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.0.0.tgz", - "integrity": "sha512-J0la9VzIUofUKs4EhWuwbtsEJjkvs7rAOp/JbXE0RlR0ZMI0AhwiCm1roIUhK/gnOGvTE7OJznFW48mmOQyz/A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.0.1.tgz", + "integrity": "sha512-8GSFuOCelctwcW0CkNGFahrGJyKxx2hMOmzDxVaHTknsikh4Zi+edCFUMgfAcBLRkV0GYQT64QivSi4SxDeKdA==", "dev": true, "dependencies": { "debug": "^4.3.4" @@ -5248,9 +5248,9 @@ } }, "node_modules/prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", - "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -5940,9 +5940,9 @@ } }, "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -5958,7 +5958,7 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", @@ -7514,9 +7514,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", - "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", + "version": "20.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", + "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7550,16 +7550,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz", - "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", + "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/type-utils": "6.18.1", - "@typescript-eslint/utils": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/type-utils": "6.19.1", + "@typescript-eslint/utils": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7569,29 +7569,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", - "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", + "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1" + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1" } }, "@typescript-eslint/types": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", - "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", + "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", - "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", + "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7601,27 +7601,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", - "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", + "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", - "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", + "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/types": "6.19.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -7646,42 +7646,42 @@ } }, "@typescript-eslint/parser": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz", - "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", + "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", - "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", + "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1" + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1" } }, "@typescript-eslint/types": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", - "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", + "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", - "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", + "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7691,12 +7691,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", - "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", + "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/types": "6.19.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -7731,41 +7731,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz", - "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", + "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.18.1", - "@typescript-eslint/utils": "6.18.1", + "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/utils": "6.19.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", - "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", + "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1" + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1" } }, "@typescript-eslint/types": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", - "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", + "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", - "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", + "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7775,27 +7775,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", - "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", + "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", - "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", + "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/types": "6.19.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -8459,9 +8459,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "27.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.2.tgz", - "integrity": "sha512-CI1AlKrsNhYFoP48VU8BVWOi7+qHTq4bRxyUlGjeU8SfFt8abjXhjOuDzUoMp68DoXIx17KpNpIkMrl4s4ZW0g==", + "version": "27.6.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz", + "integrity": "sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" @@ -9688,9 +9688,9 @@ } }, "marked": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz", - "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz", + "integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==", "dev": true }, "meow": { @@ -9957,9 +9957,9 @@ "dev": true }, "pick-port": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.0.0.tgz", - "integrity": "sha512-J0la9VzIUofUKs4EhWuwbtsEJjkvs7rAOp/JbXE0RlR0ZMI0AhwiCm1roIUhK/gnOGvTE7OJznFW48mmOQyz/A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.0.1.tgz", + "integrity": "sha512-8GSFuOCelctwcW0CkNGFahrGJyKxx2hMOmzDxVaHTknsikh4Zi+edCFUMgfAcBLRkV0GYQT64QivSi4SxDeKdA==", "dev": true, "requires": { "debug": "^4.3.4" @@ -10044,9 +10044,9 @@ "dev": true }, "prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", - "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true }, "prettier-linter-helpers": { @@ -10502,9 +10502,9 @@ "requires": {} }, "ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", "dev": true, "requires": { "bs-logger": "0.x", diff --git a/package.json b/package.json index 7308e7ef3e..62e505220c 100644 --- a/package.json +++ b/package.json @@ -111,20 +111,20 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.11.0", - "@typescript-eslint/eslint-plugin": "^6.18.1", - "@typescript-eslint/parser": "^6.18.1", + "@types/node": "^20.11.10", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.6.2", + "eslint-plugin-jest": "^27.6.3", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^11.1.1", + "marked": "^11.2.0", "open-cli": "^8.0.0", - "pick-port": "^2.0.0", - "prettier": "^3.1.1", + "pick-port": "^2.0.1", + "prettier": "^3.2.4", "sctp": "^1.0.0", - "ts-jest": "^29.1.1", + "ts-jest": "^29.1.2", "typescript": "^5.3.3" } } diff --git a/worker/scripts/clang-format.mjs b/worker/scripts/clang-format.mjs index ce48f07d2f..c17152998a 100644 --- a/worker/scripts/clang-format.mjs +++ b/worker/scripts/clang-format.mjs @@ -21,8 +21,8 @@ async function run() { case 'lint': { executeCmd( `"${clangFormatNativeBinary}" --Werror --dry-run ${workerFiles.join( - ' ', - )}`, + ' ' + )}` ); break; @@ -30,7 +30,7 @@ async function run() { case 'format': { executeCmd( - `"${clangFormatNativeBinary}" --Werror -i ${workerFiles.join(' ')}`, + `"${clangFormatNativeBinary}" --Werror -i ${workerFiles.join(' ')}` ); break; From 7378ae732a8d819f7deb528d5e946efd585fbd93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 Jan 2024 17:50:44 +0100 Subject: [PATCH 335/525] 3.13.16 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf08470556..7cf8fffe86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog -### NEXT +### 3.13.17 +- Fix prebuilt worker download ([PR #1319](https://github.com/versatica/mediasoup/pull/1319) by @brynrichards). - libsrtp: Update to v3.0-alpha version in our fork. ### 3.13.16 From 83a456ed15b7f2db3e5ac4ae89472e8e719716dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 Jan 2024 17:53:04 +0100 Subject: [PATCH 336/525] 3.13.17 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c9a7fd26ba..33f06e72ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.16", + "version": "3.13.17", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.16", + "version": "3.13.17", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 62e505220c..e038c6a552 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.16", + "version": "3.13.17", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 01075b1b79998e044a52cf2f2f63ef5b007d7452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 29 Jan 2024 17:58:30 +0100 Subject: [PATCH 337/525] Include doc/ folder in Prettier --- .eslintignore | 1 - .prettierignore | 1 - doc/Building.md | 3 +- doc/Charts.md | 6 +-- doc/Consumer.md | 91 ++++++++++++++++++++++--------------- doc/Fuzzer.md | 34 +++++++------- doc/README.md | 11 ++--- doc/RTCP.md | 25 +++++----- doc/closures.md | 118 ++++++++++++++++++++++++------------------------ 9 files changed, 150 insertions(+), 140 deletions(-) diff --git a/.eslintignore b/.eslintignore index 6e2bd913cd..cab871b0c9 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,7 +3,6 @@ /.cache /art /coverage -/doc /node/lib /node/src/fbs /rust diff --git a/.prettierignore b/.prettierignore index f154487ec4..1a5b7522c6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,7 +3,6 @@ /.cache /art /coverage -/doc /node/lib /node/src/fbs /rust diff --git a/doc/Building.md b/doc/Building.md index 66b8cd17e8..fa5364bfd4 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -134,11 +134,12 @@ Cleans built objects and binaries, `meson` and `ninja` installed in local prefix ### `invoke update-wrap-file [subproject]` -Updates the wrap file of a subproject (those in `worker/subprojects` folder) with Meson. Usage example: +Updates the wrap file of a subproject (those in `worker/subprojects` folder) with Meson. After updating it, `invoke setup` must be called by passing `MESON_ARGS="--reconfigure"` environment variable. Usage example: ```bash cd worker invoke update-wrap-file openssl +MESON_ARGS="--reconfigure" invoke setup ``` ### `invoke mediasoup-worker` diff --git a/doc/Charts.md b/doc/Charts.md index 6be4f00efc..266700b464 100644 --- a/doc/Charts.md +++ b/doc/Charts.md @@ -1,6 +1,5 @@ # Charts - ## Broadcasting mediasoup **v2** (a room uses a single media worker subprocess by design, so a single CPU). @@ -9,9 +8,8 @@ Charts provided by [CoSMo](https://www.cosmosoftware.io) team. Scenario: -* 1 peer producing audio and video tracks. -* N spy peers receiving them. - +- 1 peer producing audio and video tracks. +- N spy peers receiving them. #### Bandwidth out (Mbps) / number of viewers diff --git a/doc/Consumer.md b/doc/Consumer.md index 6c246e8d2d..824ac03a53 100644 --- a/doc/Consumer.md +++ b/doc/Consumer.md @@ -1,92 +1,109 @@ # Consumer - ## RTP sequence number handling ------------------------------------------------- +--- INIT: -* rtpLastSeq: 1000 -* rtpPreviousBaseSeq: 0 -* rtpBaseSeq: 0 +- rtpLastSeq: 1000 +- rtpPreviousBaseSeq: 0 +- rtpBaseSeq: 0 ------------------------------------------------- +--- packet (SYNC): -* seq: 3000 -* rtpPreviousBaseSeq: 1000 -* rtpBaseSeq: 3000 + +- seq: 3000 +- rtpPreviousBaseSeq: 1000 +- rtpBaseSeq: 3000 out: -* rtpLastSeq: 3000 - 3000 + 1000 + 1 = 1001 ------------------------------------------------- +- rtpLastSeq: 3000 - 3000 + 1000 + 1 = 1001 + +--- packet: -* seq: 3001 + +- seq: 3001 out: -* rtpLastSeq: 3001 - 3000 + 1000 + 1 = 1002 ------------------------------------------------- +- rtpLastSeq: 3001 - 3000 + 1000 + 1 = 1002 + +--- packet: -* seq: 3003 + +- seq: 3003 out: -* rtpLastSeq: 3003 - 3000 + 1000 + 1 = 1004 ------------------------------------------------- +- rtpLastSeq: 3003 - 3000 + 1000 + 1 = 1004 + +--- packet (SYNC): -* seq: 4050 -- rtpPreviousBaseSeq: 1004 -- rtpBaseSeq: 4050 + +- seq: 4050 + +* rtpPreviousBaseSeq: 1004 +* rtpBaseSeq: 4050 out: -* rtpLastSeq: 4050 - 4050 + 1004 + 1 = 1005 ------------------------------------------------- +- rtpLastSeq: 4050 - 4050 + 1004 + 1 = 1005 + +--- packet: -* seq: 4051 + +- seq: 4051 out: -* rtpLastSeq: 4051 - 4050 + 1004 + 1 = 1006 ------------------------------------------------- +- rtpLastSeq: 4051 - 4050 + 1004 + 1 = 1006 + +--- packet (DROP): -* seq: 4052 + +- seq: 4052 if (seq > rtpLastSeq) -* rtpBaseSeq++: 4051 ------------------------------------------------- +- rtpBaseSeq++: 4051 + +--- packet: -* seq: 4053 + +- seq: 4053 out: -* rtpLastSeq: 4053 - 4051 + 1004 + 1 = 1007 ------------------------------------------------- +- rtpLastSeq: 4053 - 4051 + 1004 + 1 = 1007 + +--- probation packet: -* rtpLastSeq++ = 1008 + +- rtpLastSeq++ = 1008 out: -* rtpLastSeq: 1008 -* rtpBaseSeq--: 4050 + +- rtpLastSeq: 1008 +- rtpBaseSeq--: 4050 NOTE: probation packets should just be sent (assuming same RTP timestamp) **after** a video packet with `marker` bit set to 1. ------------------------------------------------- +--- packet: -* seq: 4054 + +- seq: 4054 out: -* rtpLastSeq: 4054 - 4050 + 1004 + 1 = 1009 +- rtpLastSeq: 4054 - 4050 + 1004 + 1 = 1009 diff --git a/doc/Fuzzer.md b/doc/Fuzzer.md index fb478d5fbd..d993e43684 100644 --- a/doc/Fuzzer.md +++ b/doc/Fuzzer.md @@ -6,10 +6,10 @@ Once we have built the `mediasoup-worker-fuzzer` target in a Linux environment w ## Related documentation -* [libFuzzer documentation](http://llvm.org/docs/LibFuzzer.html) -* [libFuzzer Tutorial](https://github.com/google/fuzzer-test-suite/blob/master/tutorial/libFuzzerTutorial.md) -* [webrtcH4cKS ~ Lets get better at fuzzing in 2019](https://webrtchacks.com/lets-get-better-at-fuzzing-in-2019-heres-how/) -* [OSS-Fuzz](https://github.com/google/oss-fuzz) - Continuous fuzzing of open source software ("fuzz for me") +- [libFuzzer documentation](http://llvm.org/docs/LibFuzzer.html) +- [libFuzzer Tutorial](https://github.com/google/fuzzer-test-suite/blob/master/tutorial/libFuzzerTutorial.md) +- [webrtcH4cKS ~ Lets get better at fuzzing in 2019](https://webrtchacks.com/lets-get-better-at-fuzzing-in-2019-heres-how/) +- [OSS-Fuzz](https://github.com/google/oss-fuzz) - Continuous fuzzing of open source software ("fuzz for me") ## Corpus files @@ -31,55 +31,55 @@ The `fuzzer/reports` directory should be used to store those new crash reports. It's recommended to (also) pass the following options to the fuzzer: -* `-max_len=1400`: We don't need much more input size. +- `-max_len=1400`: We don't need much more input size. For memory leak detection enable the following environment variable: -* `LSAN_OPTIONS=verbosity=1:log_threads=1` +- `LSAN_OPTIONS=verbosity=1:log_threads=1` The mediasoup-worker fuzzer reads some custom environment variables to decide which kind of fuzzing perform: -* `MS_FUZZ_STUN=1`: Do STUN fuzzing. -* `MS_FUZZ_RTP=1`: Do RTP fuzzing. -* `MS_FUZZ_RTCP=1`: Do RTCP fuzzing. -* `MS_FUZZ_UTILS=1`: Do C++ utils fuzzing. -* If none of them is given, then **all** fuzzers are enabled. +- `MS_FUZZ_STUN=1`: Do STUN fuzzing. +- `MS_FUZZ_RTP=1`: Do RTP fuzzing. +- `MS_FUZZ_RTCP=1`: Do RTCP fuzzing. +- `MS_FUZZ_UTILS=1`: Do C++ utils fuzzing. +- If none of them is given, then **all** fuzzers are enabled. The log level can also be set by setting the `MS_FUZZ_LOG_LEVEL` environment variable to "debug", "warn" or "error" (it is "none" if unset). ## Usage examples -* Detect memory leaks and just fuzz STUN: +- Detect memory leaks and just fuzz STUN: ```bash MS_FUZZ_STUN=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus ``` -* Detect memory leaks and just fuzz RTP: +- Detect memory leaks and just fuzz RTP: ```bash MS_FUZZ_RTP=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus ``` -* Detect memory leaks and just fuzz RTCP: +- Detect memory leaks and just fuzz RTCP: ```bash MS_FUZZ_RTCP=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus ``` -* Detect memory leaks and just fuzz mediasoup-worker C++ utils: +- Detect memory leaks and just fuzz mediasoup-worker C++ utils: ```bash MS_FUZZ_UTILS=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=2000 fuzzer/new-corpus ``` -* Detect memory leaks and fuzz everything with log level "warn": +- Detect memory leaks and fuzz everything with log level "warn": ```bash MS_FUZZ_LOG_LEVEL=warn LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus ``` -* Verify that a specific crash is fixed: +- Verify that a specific crash is fixed: ```bash LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer fuzzer/reports/crash-f39771f7a03c0e7e539d4e52f48f7adad8976404 diff --git a/doc/README.md b/doc/README.md index f17d5a4944..3efef33aa6 100644 --- a/doc/README.md +++ b/doc/README.md @@ -2,9 +2,8 @@ **NOTE:** Internal documentation for developing purposes. Get the mediasoup public documentation at [mediasoup.org](https://mediasoup.org). -* [Building](Building.md) -* [Fuzzer](Fuzzer.md) -* [RTCP](RTCP.md) -* [Consumer](Consumer.md) -* [Charts](Charts.md) - +- [Building](Building.md) +- [Fuzzer](Fuzzer.md) +- [RTCP](RTCP.md) +- [Consumer](Consumer.md) +- [Charts](Charts.md) diff --git a/doc/RTCP.md b/doc/RTCP.md index dac8e9287a..13fde78342 100644 --- a/doc/RTCP.md +++ b/doc/RTCP.md @@ -8,7 +8,6 @@ This document also describes which RTCP packets are locally generated by mediaso mediasoup does not forward feedback information from a remote RTP receiver, which could incur in the remote sender modifying the transmition rate in a way that it would affect the reception quality for the overall participants in a router (i.e. limiting the remote RTP sender transmition rate). - ### Sender Reports mediasoup locally generates the Sender Reports of the streams it sends and processes the Sender Reports is receives from producer endpoints. @@ -150,31 +149,29 @@ This information is locally consumed to perform sender side bandwidth estimation REMB RTCP is generated locally based on the remote bitrate estimation. - ## Mediasoup internal behaviour for each type of RTCP ### Generic RTCP -| | SR | RR | SDES | BYE | APP | -| --------- | -- | -- | ---- | --- | --- | -| Consumer | G | C | | | | -| Producer | C | G | C | I | I | +| | SR | RR | SDES | BYE | APP | +| -------- | --- | --- | ---- | --- | --- | +| Consumer | G | C | | | | +| Producer | C | G | C | I | I | ### RTP Feedback RTCP -| | NACK | TMMBR | TMMBN | TLLEI | ECN-FB | PAUSE-RESUME | TCC | -| --------- | ---- | ----- | ----- | ----- | ------ | ------------ | --- | -| Consumer | C | I | I | I | I | I | | -| Producer | G | | I | I | | | | +| | NACK | TMMBR | TMMBN | TLLEI | ECN-FB | PAUSE-RESUME | TCC | +| -------- | ---- | ----- | ----- | ----- | ------ | ------------ | --- | +| Consumer | C | I | I | I | I | I | | +| Producer | G | | I | I | | | | ## PS Feedback RTCP | | PLI | SLI | RPSI | FIR | TSTR | TSTN | VBCM | PSLI | AFB | REMB | | --------- | --- | --- | ---- | --- | ---- | ---- | ---- | ---- | --- | ---- | -| Consumer | C | I | I | C | I | | I | | I | C | -| Producer | G | | | | | I | | I | | | -| Transport | | | | | | | | | | G | - +| Consumer | C | I | I | C | I | | I | | I | C | +| Producer | G | | | | | I | | I | | | +| Transport | | | | | | | | | | G | ( ): Does not apply. diff --git a/doc/closures.md b/doc/closures.md index 11086ae6c9..bb3dca3150 100644 --- a/doc/closures.md +++ b/doc/closures.md @@ -2,147 +2,147 @@ Some considerations: -* Any JS `xxxxx.yyyyyClosed()` method is equivalent to the corresponding C++ `~Xxxxx()` destructor. They both silently destroy things without generating any internal notifications/events. - - *NOTE:* Yes, the JS `xxxxx.yyyyyClosed()` produces **public** JS event `xxxxx.on('yyyyyclose')`, but that's not internal stuff. - +- Any JS `xxxxx.yyyyyClosed()` method is equivalent to the corresponding C++ `~Xxxxx()` destructor. They both silently destroy things without generating any internal notifications/events. + - _NOTE:_ Yes, the JS `xxxxx.yyyyyClosed()` produces **public** JS event `xxxxx.on('yyyyyclose')`, but that's not internal stuff. ## JS worker.close() -* Public API. -* Kills the mediasoup-worker process (if not already died) via signal. -* Iterates all JS Routers and calls `router.workerClosed()`. +- Public API. +- Kills the mediasoup-worker process (if not already died) via signal. +- Iterates all JS Routers and calls `router.workerClosed()`. ## mediasoup-worker process dies unexpectely -* The JS Worker emits public JS `worker.on('died')`. -* Iterates all JS Routers and calls `router.workerClosed()`. +- The JS Worker emits public JS `worker.on('died')`. +- Iterates all JS Routers and calls `router.workerClosed()`. ## C++ Worker::Close() -* Called when the mediasoup-worker process is killed. -* Iterates all C++ Routers and calls `delete router`. +- Called when the mediasoup-worker process is killed. +- Iterates all C++ Routers and calls `delete router`. ## JS router.workerClosed() -* Private API. -* Emits public JS `router.on('workerclose')`. +- Private API. +- Emits public JS `router.on('workerclose')`. ## JS router.close() -* Public API. -* Sends channel request `WORKER_CLOSE_ROUTER`: +- Public API. +- Sends channel request `WORKER_CLOSE_ROUTER`: - Processed by the C++ Worker. - It removes the C++ Router from its map. - It calls C++ `delete router`. -* Iterates all JS Transports and calls `transport.routerClosed()`. -* Emits private JS `router.on('@close')` (so the JS Worker cleans its map). +- Iterates all JS Transports and calls `transport.routerClosed()`. +- Emits private JS `router.on('@close')` (so the JS Worker cleans its map). ## C++ ~Router() destructor -* Iterates all C++ Transports and calls `delete transport`. +- Iterates all C++ Transports and calls `delete transport`. ## JS transport.routerClosed() -* Private API. -* Iterates all JS Producers and calls `producer.transportClosed()`. -* Iterates all JS Consumers and calls `consumer.transportClosed()`. -* Emits public JS `transport.on('routerclose')`. +- Private API. +- Iterates all JS Producers and calls `producer.transportClosed()`. +- Iterates all JS Consumers and calls `consumer.transportClosed()`. +- Emits public JS `transport.on('routerclose')`. ## JS transport.close() -* Public API. -* Sends channel request `ROUTER_CLOSE_TRANSPORT`. +- Public API. +- Sends channel request `ROUTER_CLOSE_TRANSPORT`. - Processed by the C++ Router. - It calls C++ `transport->Close()` (so the C++ Transport will notify the C++ Router about closed Producers and Consumers in that Transport). - It removes the C++ Transport from its map. - It calls C++ `delete transport`. -* Iterates all JS Producers and calls `producer.transportClosed()`. -* For each JS Producer, the JS Transport emits private JS `transport.on('@producerclose')` (so the JS Router cleans its maps). -* Iterates all JS Consumers and calls `consumer.transportClosed()`. -* Emits private JS `transport.on('@close')` (so the JS Router cleans its map). +- Iterates all JS Producers and calls `producer.transportClosed()`. +- For each JS Producer, the JS Transport emits private JS `transport.on('@producerclose')` (so the JS Router cleans its maps). +- Iterates all JS Consumers and calls `consumer.transportClosed()`. +- Emits private JS `transport.on('@close')` (so the JS Router cleans its map). ## C++ ~Transport() destructor -* Iterates all C++ Producers and calls `delete producer`. -* Iterates all C++ Consumer and calls `delete consumer`. +- Iterates all C++ Producers and calls `delete producer`. +- Iterates all C++ Consumer and calls `delete consumer`. ## C++ Transport::Close() -* Iterates all C++ Producers. For each Producer: +- Iterates all C++ Producers. For each Producer: - Removes it from its map of Producers. - Calls its `listener->OnTransportProducerClosed(this, producer)` (so the C++ Router cleans its maps and calls `consumer->ProducerClosed()` on its associated Consumers). - Calls `delete producer`. -* It clears its map of C++ Producers. -* Iterates all C++ Consumer. For each Consumer: +- It clears its map of C++ Producers. +- Iterates all C++ Consumer. For each Consumer: - Removes it from its map of Consumers. - Call its `listener->OnTransportConsumerClosed(this, consumer)` (so the C++ Router cleans its maps). - Calls `delete consumer`. -* It clears its map of C++ Consumers. +- It clears its map of C++ Consumers. + +_NOTE:_ If a Transport holds a Producer and a Consumer associated to that Producer, ugly things may happen when calling `Transport::Close()`: -*NOTE:* If a Transport holds a Producer and a Consumer associated to that Producer, ugly things may happen when calling `Transport::Close()`: - - While iterating the C++ Producers as above, the C++ Consumer would be deleted (via `Consumer::ProducerClosed()`). - + As far as it's properly removed from the `Transport::mapConsumers` everything would be ok when later iterating the map of Consumers. - - Must ensure that, in this scenario, the JS event `consumer.on('producerclose')` is not called since `consumer.on('transportclose')` is supposed to happen before. - + This won't happen since the JS `Consumer` has removed its channel notifications within its `transportClosed()` method. +- While iterating the C++ Producers as above, the C++ Consumer would be deleted (via `Consumer::ProducerClosed()`). + - As far as it's properly removed from the `Transport::mapConsumers` everything would be ok when later iterating the map of Consumers. +- Must ensure that, in this scenario, the JS event `consumer.on('producerclose')` is not called since `consumer.on('transportclose')` is supposed to happen before. + - This won't happen since the JS `Consumer` has removed its channel notifications within its `transportClosed()` method. ## C++ Router::OnTransportProducerClosed(transport, producer) -* Gets the set of C++ Consumers associated to the closed Producer in its `mapProducerConsumers`. For each Consumer: +- Gets the set of C++ Consumers associated to the closed Producer in its `mapProducerConsumers`. For each Consumer: - Calls `consumer->ProducerClosed()`. -* Deletes the entry in `mapProducerConsumers` with key `producer`. -* Deletes the entry in `mapProducers` with key `producer->id`. +- Deletes the entry in `mapProducerConsumers` with key `producer`. +- Deletes the entry in `mapProducers` with key `producer->id`. ## C++ Router::OnTransportConsumerClosed(transport, consumer) -* Get the associated C++ Producer from `mapConsumerProducer`. -* Remove the closed C++ Consumer from the set of Consumers in the corresponding `mapProducerConsumers` entry for the given Producer. -* Deletes the entry in `mapConsumerProducer` with key `consumer`. +- Get the associated C++ Producer from `mapConsumerProducer`. +- Remove the closed C++ Consumer from the set of Consumers in the corresponding `mapProducerConsumers` entry for the given Producer. +- Deletes the entry in `mapConsumerProducer` with key `consumer`. ## JS producer.transportClosed() -* Private API. -* Emits public JS `producer.on('transportclose')`. +- Private API. +- Emits public JS `producer.on('transportclose')`. ## JS producer.close() -* Public API. -* Sends channel request `TRANSPORT_CLOSE_PRODUCER`. +- Public API. +- Sends channel request `TRANSPORT_CLOSE_PRODUCER`. - Processed by the C++ Transport. - Removes it from its map of Producers. - Calls its `listener->OnTransportProducerClosed(this, producer)` (so the C++ Router cleans its maps and calls `consumer->ProducerClose()` on its associated Consumers). - Calls `delete producer`. -* Emits private JS `producer.on('@close')` (so the JS Transport cleans its map and will also emit private JS `transport.on('@producerclose')` so the JS Router cleans its map). +- Emits private JS `producer.on('@close')` (so the JS Transport cleans its map and will also emit private JS `transport.on('@producerclose')` so the JS Router cleans its map). ## C++ ~Producer() destructor -* Destroys its stuff. +- Destroys its stuff. ## JS consumer.transportClosed() -* Private API. -* Emits public JS `consumer.on('transportclose')`. +- Private API. +- Emits public JS `consumer.on('transportclose')`. ## JS consumer.close() -* Public API. -* Sends channel request `TRANSPORT_CLOSE_CONSUMER`. +- Public API. +- Sends channel request `TRANSPORT_CLOSE_CONSUMER`. - Processed by the C++ Transport. - Removes it from its map of Consumers. - Calls its `listener->OnTransportConsumerClosed(this, consumer)` (so the C++ Router cleans its maps). - Calls `delete consumer`. -* Emits private JS `consumer.on('@close')` (so the JS Transport cleans its map). +- Emits private JS `consumer.on('@close')` (so the JS Transport cleans its map). ## C++ ~Consumer() destructor -* Destroys its stuff. +- Destroys its stuff. ## C++ Consumer::ProducerClosed() -* Called from the C++ Router within the `Router::OnTransportProducerClosed()` listener. -* Send a channel notification `producerclose` to the JS Consumer. +- Called from the C++ Router within the `Router::OnTransportProducerClosed()` listener. +- Send a channel notification `producerclose` to the JS Consumer. - The JS Consumer emits private JS `consumer.on('@produceclose')` (so the JS Transport cleans its map). - The JS Consumer emits public JS `consumer.on('produceclose')`. -* Notifies its C++ Transport via `listener->onConsumerProducerClosed()` which: +- Notifies its C++ Transport via `listener->onConsumerProducerClosed()` which: - cleans its map of Consumers, - notifies the Router via `listener->OnTransportConsumerClosed()`), and - deletes the Consumer. From 9378b596624806d82c5d896ae342cf1b04fe7922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 1 Feb 2024 15:54:58 +0100 Subject: [PATCH 338/525] Update Node dev deps --- package-lock.json | 346 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 176 insertions(+), 176 deletions(-) diff --git a/package-lock.json b/package-lock.json index 33f06e72ee..b22ffce243 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,9 +21,9 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.11.10", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", + "@types/node": "^20.11.15", + "@typescript-eslint/eslint-plugin": "^6.20.0", + "@typescript-eslint/parser": "^6.20.0", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.6.3", @@ -1626,9 +1626,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", - "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "version": "20.11.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.15.tgz", + "integrity": "sha512-gscmuADZfvNULx1eyirVbr3kVOVZtpQtzKMCZpeSZcN6MfbkRXAR4s9/gsQ4CzxLHw6EStDtKLNtSDL3vbq05A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1662,16 +1662,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", - "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz", + "integrity": "sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/type-utils": "6.19.1", - "@typescript-eslint/utils": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/type-utils": "6.20.0", + "@typescript-eslint/utils": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1697,13 +1697,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", + "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1714,9 +1714,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", + "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1727,13 +1727,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", + "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1755,17 +1755,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", - "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", + "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", "semver": "^7.5.4" }, "engines": { @@ -1780,12 +1780,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", + "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "6.20.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1821,15 +1821,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", - "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.20.0.tgz", + "integrity": "sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4" }, "engines": { @@ -1849,13 +1849,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", + "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1866,9 +1866,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", + "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1879,13 +1879,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", + "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1907,12 +1907,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", + "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "6.20.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1965,13 +1965,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", - "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz", + "integrity": "sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/utils": "6.19.1", + "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/utils": "6.20.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1992,13 +1992,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", + "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2009,9 +2009,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", + "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2022,13 +2022,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", + "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2050,17 +2050,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", - "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", + "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", "semver": "^7.5.4" }, "engines": { @@ -2075,12 +2075,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", + "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "6.20.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -7514,9 +7514,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", - "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "version": "20.11.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.15.tgz", + "integrity": "sha512-gscmuADZfvNULx1eyirVbr3kVOVZtpQtzKMCZpeSZcN6MfbkRXAR4s9/gsQ4CzxLHw6EStDtKLNtSDL3vbq05A==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7550,16 +7550,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", - "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz", + "integrity": "sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/type-utils": "6.19.1", - "@typescript-eslint/utils": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/type-utils": "6.20.0", + "@typescript-eslint/utils": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7569,29 +7569,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", + "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0" } }, "@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", + "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", + "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", "dev": true, "requires": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7601,27 +7601,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", - "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", + "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", + "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "6.20.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7646,42 +7646,42 @@ } }, "@typescript-eslint/parser": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", - "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.20.0.tgz", + "integrity": "sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", + "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0" } }, "@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", + "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", + "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", "dev": true, "requires": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7691,12 +7691,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", + "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "6.20.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7731,41 +7731,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", - "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz", + "integrity": "sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/utils": "6.19.1", + "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/utils": "6.20.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", + "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0" } }, "@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", + "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", + "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", "dev": true, "requires": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7775,27 +7775,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", - "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", + "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", + "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "6.20.0", "eslint-visitor-keys": "^3.4.1" } }, diff --git a/package.json b/package.json index e038c6a552..233ff82afa 100644 --- a/package.json +++ b/package.json @@ -111,9 +111,9 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.11", - "@types/node": "^20.11.10", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", + "@types/node": "^20.11.15", + "@typescript-eslint/eslint-plugin": "^6.20.0", + "@typescript-eslint/parser": "^6.20.0", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.6.3", From b6cce5befbe50bd680192ebec32c1ce10716711d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 1 Feb 2024 15:58:08 +0100 Subject: [PATCH 339/525] Remove useless `--ignore` option in eslint --- npm-scripts.mjs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 5b1ab8f57a..aab6a7a44c 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -352,9 +352,7 @@ function lintNode() { // rules. executeCmd('eslint-config-prettier .eslintrc.js'); - executeCmd( - 'eslint -c .eslintrc.js --ignore-path .eslintignore --max-warnings 0 .' - ); + executeCmd('eslint -c .eslintrc.js --max-warnings 0 .'); } function lintWorker() { From 42bc0f7abbcb4639f5a9f01cafe15b2f9b8675bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 1 Feb 2024 17:45:06 +0100 Subject: [PATCH 340/525] announced_ip can be a hostname as per spec (#1322) --- CHANGELOG.md | 4 +++ node/src/Transport.ts | 8 ++--- node/src/test/test-WebRtcServer.ts | 2 +- node/src/test/test-WebRtcTransport.ts | 9 +++-- rust/src/data_structures.rs | 17 +++++----- rust/src/messages.rs | 11 ++++--- rust/src/router.rs | 14 ++++---- rust/src/router/plain_transport/tests.rs | 2 +- rust/src/router/webrtc_transport/tests.rs | 4 +-- rust/tests/integration/plain_transport.rs | 18 +++++----- rust/tests/integration/webrtc_server.rs | 6 ++-- rust/tests/integration/webrtc_transport.rs | 38 +++++++++++----------- 12 files changed, 69 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cf8fffe86..44ff9e6990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- `TransportListenInfo`: announced ip can also be a hostname ([PR #1322](https://github.com/versatica/mediasoup/pull/1322)). + ### 3.13.17 - Fix prebuilt worker download ([PR #1319](https://github.com/versatica/mediasoup/pull/1319) by @brynrichards). diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 0ba15020c6..c2428ec802 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -72,8 +72,8 @@ export type TransportListenInfo = { ip: string; /** - * Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with - * private IP). + * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT + * with private IP). */ announcedIp?: string; @@ -109,8 +109,8 @@ export type TransportListenIp = { ip: string; /** - * Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with - * private IP). + * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT + * with private IP). */ announcedIp?: string; }; diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index a48d0d129c..3ffdeb2afe 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -48,7 +48,7 @@ test('worker.createWebRtcServer() succeeds', async () => { { protocol: 'tcp', ip: '127.0.0.1', - announcedIp: '1.2.3.4', + announcedIp: 'foo.bar.org', port: port2, }, ], diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 79fdd25041..a6f7d871e4 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -68,13 +68,12 @@ test('router.createWebRtcTransport() succeeds', async () => { ctx.router!.observer.once('newtransport', onObserverNewTransport); - // Create a separate transport here. const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, { protocol: 'tcp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, - { protocol: 'udp', ip: '0.0.0.0', announcedIp: '9.9.9.2' }, - { protocol: 'tcp', ip: '0.0.0.0', announcedIp: '9.9.9.2' }, + { protocol: 'udp', ip: '0.0.0.0', announcedIp: 'foo1.bar.org' }, + { protocol: 'tcp', ip: '0.0.0.0', announcedIp: 'foo2.bar.org' }, { protocol: 'udp', ip: '127.0.0.1', announcedIp: undefined }, { protocol: 'tcp', ip: '127.0.0.1', announcedIp: undefined }, ], @@ -119,11 +118,11 @@ test('router.createWebRtcTransport() succeeds', async () => { expect(iceCandidates[1].protocol).toBe('tcp'); expect(iceCandidates[1].type).toBe('host'); expect(iceCandidates[1].tcpType).toBe('passive'); - expect(iceCandidates[2].ip).toBe('9.9.9.2'); + expect(iceCandidates[2].ip).toBe('foo1.bar.org'); expect(iceCandidates[2].protocol).toBe('udp'); expect(iceCandidates[2].type).toBe('host'); expect(iceCandidates[2].tcpType).toBeUndefined(); - expect(iceCandidates[3].ip).toBe('9.9.9.2'); + expect(iceCandidates[3].ip).toBe('foo2.bar.org'); expect(iceCandidates[3].protocol).toBe('tcp'); expect(iceCandidates[3].type).toBe('host'); expect(iceCandidates[3].tcpType).toBe('passive'); diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index f0e7aa4d5c..4fd5cf1d35 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -51,16 +51,17 @@ impl AppData { /// /// # Notes on usage /// If you use "0.0.0.0" or "::" as ip value, then you need to also provide `announced_ip`. -#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] +#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ListenInfo { /// Network protocol. pub protocol: Protocol, /// Listening IPv4 or IPv6. pub ip: IpAddr, - /// Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with private IP). + /// Announced IPv4, IPv6 or hostname (useful when running mediasoup behind + /// NAT with private IP). #[serde(skip_serializing_if = "Option::is_none")] - pub announced_ip: Option, + pub announced_ip: Option, /// Listening port. #[serde(skip_serializing_if = "Option::is_none")] pub port: Option, @@ -76,14 +77,14 @@ pub struct ListenInfo { } impl ListenInfo { - pub(crate) fn to_fbs(self) -> transport::ListenInfo { + pub(crate) fn to_fbs(&self) -> transport::ListenInfo { transport::ListenInfo { protocol: match self.protocol { Protocol::Tcp => transport::Protocol::Tcp, Protocol::Udp => transport::Protocol::Udp, }, ip: self.ip.to_string(), - announced_ip: self.announced_ip.map(|ip| ip.to_string()), + announced_ip: self.announced_ip.clone().map(|ip| ip.to_string()), port: self.port.unwrap_or(0), flags: Box::new(self.flags.unwrap_or_default().to_fbs()), send_buffer_size: self.send_buffer_size.unwrap_or(0), @@ -229,8 +230,8 @@ pub struct IceCandidate { pub foundation: String, /// The assigned priority of the candidate. pub priority: u32, - /// The IP address of the candidate. - pub ip: IpAddr, + /// The IP address or hostname of the candidate. + pub ip: String, /// The protocol of the candidate. pub protocol: Protocol, /// The port for the candidate. @@ -247,7 +248,7 @@ impl IceCandidate { Self { foundation: candidate.foundation.clone(), priority: candidate.priority, - ip: candidate.ip.parse().expect("Error parsing IP address"), + ip: candidate.ip.clone(), protocol: Protocol::from_fbs(candidate.protocol), port: candidate.port, r#type: IceCandidateType::from_fbs(candidate.type_), diff --git a/rust/src/messages.rs b/rust/src/messages.rs index 1eb50f46cc..0dc8f57f06 100644 --- a/rust/src/messages.rs +++ b/rust/src/messages.rs @@ -921,8 +921,8 @@ impl RouterCreatePlainTransportData { ) -> Self { Self { transport_id, - listen_info: plain_transport_options.listen_info, - rtcp_listen_info: plain_transport_options.rtcp_listen_info, + listen_info: plain_transport_options.listen_info.clone(), + rtcp_listen_info: plain_transport_options.rtcp_listen_info.clone(), rtcp_mux: plain_transport_options.rtcp_mux, comedia: plain_transport_options.comedia, enable_sctp: plain_transport_options.enable_sctp, @@ -947,9 +947,10 @@ impl RouterCreatePlainTransportData { sctp_send_buffer_size: self.sctp_send_buffer_size, is_data_channel: self.is_data_channel, }), - listen_info: Box::new(self.listen_info.to_fbs()), + listen_info: Box::new(self.listen_info.clone().to_fbs()), rtcp_listen_info: self .rtcp_listen_info + .clone() .map(|listen_info| Box::new(listen_info.to_fbs())), rtcp_mux: self.rtcp_mux, comedia: self.comedia, @@ -1055,7 +1056,7 @@ impl RouterCreatePipeTransportData { ) -> Self { Self { transport_id, - listen_info: pipe_transport_options.listen_info, + listen_info: pipe_transport_options.listen_info.clone(), enable_sctp: pipe_transport_options.enable_sctp, num_sctp_streams: pipe_transport_options.num_sctp_streams, max_sctp_message_size: pipe_transport_options.max_sctp_message_size, @@ -1078,7 +1079,7 @@ impl RouterCreatePipeTransportData { sctp_send_buffer_size: self.sctp_send_buffer_size, is_data_channel: self.is_data_channel, }), - listen_info: Box::new(self.listen_info.to_fbs()), + listen_info: Box::new(self.listen_info.clone().to_fbs()), enable_rtx: self.enable_rtx, enable_srtp: self.enable_srtp, } diff --git a/rust/src/router.rs b/rust/src/router.rs index 931593932c..0824bec0f8 100644 --- a/rust/src/router.rs +++ b/rust/src/router.rs @@ -608,7 +608,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// announced_ip: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -696,7 +696,7 @@ impl Router { /// .create_pipe_transport(PipeTransportOptions::new(ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// announced_ip: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -762,7 +762,7 @@ impl Router { /// .create_plain_transport(PlainTransportOptions::new(ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// announced_ip: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -973,7 +973,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// announced_ip: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -1016,7 +1016,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// announced_ip: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -1202,7 +1202,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// announced_ip: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -1234,7 +1234,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".parse().unwrap()), + /// announced_ip: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, diff --git a/rust/src/router/plain_transport/tests.rs b/rust/src/router/plain_transport/tests.rs index a0f0af8d16..5a7d806104 100644 --- a/rust/src/router/plain_transport/tests.rs +++ b/rust/src/router/plain_transport/tests.rs @@ -40,7 +40,7 @@ fn router_close_event() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".parse().unwrap()), + announced_ip: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, diff --git a/rust/src/router/webrtc_transport/tests.rs b/rust/src/router/webrtc_transport/tests.rs index fe8a81de43..9e0d48e0db 100644 --- a/rust/src/router/webrtc_transport/tests.rs +++ b/rust/src/router/webrtc_transport/tests.rs @@ -132,7 +132,7 @@ fn create_with_webrtc_server_succeeds() { { let ice_candidates = transport.ice_candidates(); assert_eq!(ice_candidates.len(), 1); - assert_eq!(ice_candidates[0].ip, IpAddr::V4(Ipv4Addr::LOCALHOST)); + assert_eq!(ice_candidates[0].ip, "127.0.0.1"); assert_eq!(ice_candidates[0].protocol, Protocol::Tcp); assert_eq!(ice_candidates[0].port, port2); assert_eq!(ice_candidates[0].r#type, IceCandidateType::Host); @@ -233,7 +233,7 @@ fn router_close_event() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/plain_transport.rs b/rust/tests/integration/plain_transport.rs index e40e79fb2c..13553cab3d 100644 --- a/rust/tests/integration/plain_transport.rs +++ b/rust/tests/integration/plain_transport.rs @@ -94,7 +94,7 @@ fn create_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".parse().unwrap()), + announced_ip: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -133,7 +133,7 @@ fn create_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -286,7 +286,7 @@ fn create_with_fixed_port_succeeds() { PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".parse().unwrap()), + announced_ip: Some("4.4.4.4".to_string()), port: Some(port), flags: None, send_buffer_size: None, @@ -310,7 +310,7 @@ fn weak() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".parse().unwrap()), + announced_ip: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -344,7 +344,7 @@ fn create_enable_srtp_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -532,7 +532,7 @@ fn get_stats_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".parse().unwrap()), + announced_ip: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -590,7 +590,7 @@ fn connect_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".parse().unwrap()), + announced_ip: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -666,7 +666,7 @@ fn connect_wrong_arguments() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".parse().unwrap()), + announced_ip: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -707,7 +707,7 @@ fn close_event() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".parse().unwrap()), + announced_ip: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/webrtc_server.rs b/rust/tests/integration/webrtc_server.rs index 76b25a8dc7..6986ddccc8 100644 --- a/rust/tests/integration/webrtc_server.rs +++ b/rust/tests/integration/webrtc_server.rs @@ -71,7 +71,7 @@ fn create_webrtc_server_succeeds() { let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), + announced_ip: Some("foo.bar.org".to_string()), port: Some(port2), flags: None, send_buffer_size: None, @@ -167,7 +167,7 @@ fn create_webrtc_server_without_specifying_port_succeeds() { let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), + announced_ip: Some("1.2.3.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -283,7 +283,7 @@ fn unavailable_infos_fails() { let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), - announced_ip: Some(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))), + announced_ip: Some("1.2.3.4".to_string()), port: Some(port1), flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/webrtc_transport.rs b/rust/tests/integration/webrtc_transport.rs index 9eec456aa4..35a02db1c0 100644 --- a/rust/tests/integration/webrtc_transport.rs +++ b/rust/tests/integration/webrtc_transport.rs @@ -98,7 +98,7 @@ fn create_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -136,7 +136,7 @@ fn create_succeeds() { ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -145,7 +145,7 @@ fn create_succeeds() { ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::UNSPECIFIED), - announced_ip: Some("9.9.9.2".parse().unwrap()), + announced_ip: Some("foo1.bar.org".to_string()), port: None, flags: None, send_buffer_size: None, @@ -200,19 +200,19 @@ fn create_succeeds() { { let ice_candidates = transport1.ice_candidates(); assert_eq!(ice_candidates.len(), 3); - assert_eq!(ice_candidates[0].ip, "9.9.9.1".parse::().unwrap()); + assert_eq!(ice_candidates[0].ip, "9.9.9.1"); assert_eq!(ice_candidates[0].protocol, Protocol::Udp); assert_eq!(ice_candidates[0].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[0].tcp_type, None); - assert_eq!(ice_candidates[1].ip, "9.9.9.2".parse::().unwrap()); + assert_eq!(ice_candidates[1].ip, "foo1.bar.org"); assert_eq!(ice_candidates[1].protocol, Protocol::Udp); assert_eq!(ice_candidates[1].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[1].tcp_type, None); - assert_eq!(ice_candidates[2].ip, "127.0.0.1".parse::().unwrap()); + assert_eq!(ice_candidates[2].ip, "127.0.0.1"); assert_eq!(ice_candidates[2].protocol, Protocol::Udp); assert_eq!(ice_candidates[2].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[2].tcp_type, None); - assert_eq!(ice_candidates[2].ip, "127.0.0.1".parse::().unwrap()); + assert_eq!(ice_candidates[2].ip, "127.0.0.1"); assert_eq!(ice_candidates[2].protocol, Protocol::Udp); assert_eq!(ice_candidates[2].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[2].tcp_type, None); @@ -265,7 +265,7 @@ fn create_with_fixed_port_succeeds() { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: Some(port), flags: None, send_buffer_size: None, @@ -289,7 +289,7 @@ fn weak() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -343,7 +343,7 @@ fn get_stats_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -395,7 +395,7 @@ fn connect_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -445,7 +445,7 @@ fn set_max_incoming_bitrate_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -478,7 +478,7 @@ fn set_max_outgoing_bitrate_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -511,7 +511,7 @@ fn set_min_outgoing_bitrate_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -544,7 +544,7 @@ fn set_max_outgoing_bitrate_fails_if_value_is_lower_than_current_min_limit() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -582,7 +582,7 @@ fn set_min_outgoing_bitrate_fails_if_value_is_higher_than_current_max_limit() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -620,7 +620,7 @@ fn restart_ice_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -656,7 +656,7 @@ fn enable_trace_event_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -732,7 +732,7 @@ fn close_event() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".parse().unwrap()), + announced_ip: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, From 57f74a838b4a216e01ecf000dd257e5571ddd766 Mon Sep 17 00:00:00 2001 From: Junlong Zou Date: Fri, 2 Feb 2024 01:16:46 +0800 Subject: [PATCH 341/525] Fix tcc feedback (#1088) --- CHANGELOG.md | 1 + .../include/RTC/RTCP/FeedbackRtpTransport.hpp | 3 + .../RTC/TransportCongestionControlServer.hpp | 9 +- worker/meson.build | 1 + worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 23 +- .../RTC/TransportCongestionControlServer.cpp | 175 ++++++++---- .../src/RTC/RTCP/TestFeedbackRtpTransport.cpp | 54 +++- .../TestTransportCongestionControlServer.cpp | 254 ++++++++++++++++++ 8 files changed, 443 insertions(+), 77 deletions(-) create mode 100644 worker/test/src/RTC/TestTransportCongestionControlServer.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 44ff9e6990..213dc349ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### NEXT +- Make transport-cc feedback work similarly to libwebrtc ([PR #1088](https://github.com/versatica/mediasoup/pull/1088) by @penguinol). - `TransportListenInfo`: announced ip can also be a hostname ([PR #1322](https://github.com/versatica/mediasoup/pull/1322)). ### 3.13.17 diff --git a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp index cfbbf0c276..901df0c46c 100644 --- a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp +++ b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp @@ -212,6 +212,7 @@ namespace RTC ~FeedbackRtpTransportPacket() override; public: + void SetBase(uint16_t sequenceNumber, uint64_t timestamp); AddPacketResult AddPacket(uint16_t sequenceNumber, uint64_t timestamp, size_t maxRtcpPacketLen); // Just for locally generated packets. void Finish(); @@ -317,6 +318,8 @@ namespace RTC void AddPendingChunks(); private: + // Whether baseSequenceNumber has been set. + bool baseSet{ false }; uint16_t baseSequenceNumber{ 0u }; // 24 bits signed integer. int32_t referenceTime{ 0 }; diff --git a/worker/include/RTC/TransportCongestionControlServer.hpp b/worker/include/RTC/TransportCongestionControlServer.hpp index d25483c90e..5cfd676796 100644 --- a/worker/include/RTC/TransportCongestionControlServer.hpp +++ b/worker/include/RTC/TransportCongestionControlServer.hpp @@ -6,6 +6,7 @@ #include "RTC/RTCP/FeedbackRtpTransport.hpp" #include "RTC/RTCP/Packet.hpp" #include "RTC/RtpPacket.hpp" +#include "RTC/SeqManager.hpp" #include "handles/TimerHandle.hpp" #include #include @@ -54,10 +55,12 @@ namespace RTC double GetPacketLoss() const; void IncomingPacket(uint64_t nowMs, const RTC::RtpPacket* packet); void SetMaxIncomingBitrate(uint32_t bitrate); + void FillAndSendTransportCcFeedback(); private: void SendTransportCcFeedback(); - void MaySendLimitationRembFeedback(); + void MayDropOldPacketArrivalTimes(uint16_t seqNum, uint64_t nowMs); + void MaySendLimitationRembFeedback(uint64_t nowMs); void UpdatePacketLoss(double packetLoss); /* Pure virtual methods inherited from webrtc::RemoteBitrateEstimator::Listener. */ @@ -89,6 +92,10 @@ namespace RTC uint8_t unlimitedRembCounter{ 0u }; std::deque packetLossHistory; double packetLoss{ 0 }; + // Whether any packet with transport wide sequence number was received. + bool transportWideSeqNumberReceived{ false }; + uint16_t transportCcFeedbackWideSeqNumStart{ 0u }; + std::map::SeqLowerThan> mapPacketArrivalTimes; }; } // namespace RTC diff --git a/worker/meson.build b/worker/meson.build index e2c294ce9f..77125be6e0 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -335,6 +335,7 @@ test_sources = [ 'test/src/RTC/TestSeqManager.cpp', 'test/src/RTC/TestTrendCalculator.cpp', 'test/src/RTC/TestRtpEncodingParameters.cpp', + 'test/src/RTC/TestTransportCongestionControlServer.cpp', 'test/src/RTC/Codecs/TestVP8.cpp', 'test/src/RTC/Codecs/TestVP9.cpp', 'test/src/RTC/Codecs/TestH264.cpp', diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index 0ec398cf12..21f09c9e8f 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -278,24 +278,25 @@ namespace RTC return offset; } + void FeedbackRtpTransportPacket::SetBase(uint16_t sequenceNumber, uint64_t timestamp) + { + MS_TRACE(); + + this->baseSet = true; + this->baseSequenceNumber = sequenceNumber; + this->referenceTime = static_cast((timestamp & 0x1FFFFFC0) / 64); + this->latestSequenceNumber = sequenceNumber - 1; + this->latestTimestamp = (timestamp >> 6) * 64; // IMPORTANT: Loose precision. + } + FeedbackRtpTransportPacket::AddPacketResult FeedbackRtpTransportPacket::AddPacket( uint16_t sequenceNumber, uint64_t timestamp, size_t maxRtcpPacketLen) { MS_TRACE(); + MS_ASSERT(baseSet, "base not set"); MS_ASSERT(!IsFull(), "packet is full"); - // Let's see if we must set our base. - if (this->latestTimestamp == 0u) - { - this->baseSequenceNumber = sequenceNumber + 1; - this->referenceTime = static_cast((timestamp & 0x1FFFFFC0) / 64); - this->latestSequenceNumber = sequenceNumber; - this->latestTimestamp = (timestamp >> 6) * 64; // IMPORTANT: Loose precision. - - return AddPacketResult::SUCCESS; - } - // If the wide sequence number of the new packet is lower than the latest seen, // ignore it. // NOTE: Not very spec compliant but libwebrtc does it. diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index 98ed26a575..6fe639e175 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -14,6 +14,7 @@ namespace RTC static constexpr uint64_t TransportCcFeedbackSendInterval{ 100u }; // In ms. static constexpr uint64_t LimitationRembInterval{ 1500u }; // In ms. + static constexpr uint64_t PacketArrivalTimestampWindow{ 500u }; // In ms. static constexpr uint8_t UnlimitedRembNumPackets{ 4u }; static constexpr size_t PacketLossHistogramLength{ 24 }; @@ -124,61 +125,32 @@ namespace RTC break; } - // Update the RTCP media SSRC of the ongoing Transport-CC Feedback packet. - this->transportCcFeedbackSenderSsrc = 0u; - this->transportCcFeedbackMediaSsrc = packet->GetSsrc(); - - this->transportCcFeedbackPacket->SetSenderSsrc(0u); - this->transportCcFeedbackPacket->SetMediaSsrc(this->transportCcFeedbackMediaSsrc); - - // Provide the feedback packet with the RTP packet info. If it fails, - // send current feedback and add the packet info to a new one. - auto result = - this->transportCcFeedbackPacket->AddPacket(wideSeqNumber, nowMs, this->maxRtcpPacketLen); - - switch (result) + // Only insert the packet when receiving it for the first time. + if (!this->mapPacketArrivalTimes.try_emplace(wideSeqNumber, nowMs).second) { - case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::SUCCESS: - { - // If the feedback packet is full, send it now. - if (this->transportCcFeedbackPacket->IsFull()) - { - MS_DEBUG_DEV("transport-cc feedback packet is full, sending feedback now"); - - SendTransportCcFeedback(); - } - - break; - } - - case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::MAX_SIZE_EXCEEDED: - { - // Send ongoing feedback packet and add the new packet info to the - // regenerated one. - SendTransportCcFeedback(); + break; + } - this->transportCcFeedbackPacket->AddPacket(wideSeqNumber, nowMs, this->maxRtcpPacketLen); + // We may receive packets with sequence number lower than the one in previous + // tcc feedback, these packets may have been reported as lost previously, + // therefore we need to reset the start sequence num for the next tcc feedback. + if ( + !this->transportWideSeqNumberReceived || + RTC::SeqManager::IsSeqLowerThan( + wideSeqNumber, this->transportCcFeedbackWideSeqNumStart)) + { + this->transportCcFeedbackWideSeqNumStart = wideSeqNumber; + } - break; - } + this->transportWideSeqNumberReceived = true; - case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::FATAL: - { - // Create a new feedback packet. - this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( - this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); + MayDropOldPacketArrivalTimes(wideSeqNumber, nowMs); - // Use current packet count. - // NOTE: Do not increment it since the previous ongoing feedback - // packet was not sent. - this->transportCcFeedbackPacket->SetFeedbackPacketCount( - this->transportCcFeedbackPacketCount); - - break; - } - } + // Update the RTCP media SSRC of the ongoing Transport-CC Feedback packet. + this->transportCcFeedbackSenderSsrc = 0u; + this->transportCcFeedbackMediaSsrc = packet->GetSsrc(); - MaySendLimitationRembFeedback(); + MaySendLimitationRembFeedback(nowMs); break; } @@ -204,6 +176,75 @@ namespace RTC } } + void TransportCongestionControlServer::FillAndSendTransportCcFeedback() + { + MS_TRACE(); + + if (!this->transportWideSeqNumberReceived) + { + return; + } + + auto it = this->mapPacketArrivalTimes.lower_bound(this->transportCcFeedbackWideSeqNumStart); + + if (it == this->mapPacketArrivalTimes.end()) + { + return; + } + + // Set base sequence num and reference time. + this->transportCcFeedbackPacket->SetBase(this->transportCcFeedbackWideSeqNumStart, it->second); + + for (; it != this->mapPacketArrivalTimes.end(); ++it) + { + auto result = + this->transportCcFeedbackPacket->AddPacket(it->first, it->second, this->maxRtcpPacketLen); + + switch (result) + { + case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::SUCCESS: + { + // If the feedback packet is full, send it now. + if (this->transportCcFeedbackPacket->IsFull()) + { + MS_DEBUG_DEV("transport-cc feedback packet is full, sending feedback now"); + + SendTransportCcFeedback(); + } + + break; + } + + case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::MAX_SIZE_EXCEEDED: + { + // This should not happen. + MS_WARN_DEV("transport-cc feedback packet is exceeded"); + + // Create a new feedback packet. + this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( + this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); + } + + case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::FATAL: + { + // Create a new feedback packet. + this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( + this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); + + // Use current packet count. + // NOTE: Do not increment it since the previous ongoing feedback + // packet was not sent. + this->transportCcFeedbackPacket->SetFeedbackPacketCount( + this->transportCcFeedbackPacketCount); + + break; + } + } + } + + SendTransportCcFeedback(); + } + void TransportCongestionControlServer::SetMaxIncomingBitrate(uint32_t bitrate) { MS_TRACE(); @@ -217,7 +258,9 @@ namespace RTC // This is to ensure that we send N REMB packets with bitrate 0 (unlimited). this->unlimitedRembCounter = UnlimitedRembNumPackets; - MaySendLimitationRembFeedback(); + auto nowMs = DepLibUV::GetTimeMs(); + + MaySendLimitationRembFeedback(nowMs); } } @@ -233,7 +276,6 @@ namespace RTC } auto latestWideSeqNumber = this->transportCcFeedbackPacket->GetLatestSequenceNumber(); - auto latestTimestamp = this->transportCcFeedbackPacket->GetLatestTimestamp(); // Notify the listener. this->listener->OnTransportCongestionControlServerSendRtcpPacket( @@ -262,21 +304,36 @@ namespace RTC // Increment packet count. this->transportCcFeedbackPacket->SetFeedbackPacketCount(++this->transportCcFeedbackPacketCount); + this->transportCcFeedbackWideSeqNumStart = latestWideSeqNumber + 1; + } + + inline void TransportCongestionControlServer::MayDropOldPacketArrivalTimes( + uint16_t seqNum, uint64_t nowMs) + { + MS_TRACE(); - // Pass the latest packet info (if any) as pre base for the new feedback packet. - if (latestTimestamp > 0u) + // Ignore nowMs value if it's smaller than PacketArrivalTimestampWindow in + // order to avoid negative values (should never happen) and return early if + // the condition is met. + if (nowMs >= PacketArrivalTimestampWindow) { - this->transportCcFeedbackPacket->AddPacket( - latestWideSeqNumber, latestTimestamp, this->maxRtcpPacketLen); + auto expiryTimestamp = nowMs - PacketArrivalTimestampWindow; + auto it = this->mapPacketArrivalTimes.begin(); + + while (it != this->mapPacketArrivalTimes.end() && + it->first != this->transportCcFeedbackWideSeqNumStart && + RTC::SeqManager::IsSeqLowerThan(it->first, seqNum) && + it->second <= expiryTimestamp) + { + it = this->mapPacketArrivalTimes.erase(it); + } } } - inline void TransportCongestionControlServer::MaySendLimitationRembFeedback() + inline void TransportCongestionControlServer::MaySendLimitationRembFeedback(uint64_t nowMs) { MS_TRACE(); - auto nowMs = DepLibUV::GetTimeMs(); - // May fix unlimitedRembCounter. if (this->unlimitedRembCounter > 0u && this->maxIncomingBitrate != 0u) { @@ -389,7 +446,7 @@ namespace RTC if (timer == this->transportCcFeedbackSendPeriodicTimer) { - SendTransportCcFeedback(); + FillAndSendTransportCcFeedback(); } } } // namespace RTC diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp index e34c99ae8e..0204f81480 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp @@ -98,7 +98,14 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" for (auto& input : inputs) { - packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + if (std::addressof(input) == std::addressof(inputs.front())) + { + packet->SetBase(input.sequenceNumber + 1, input.timestamp); + } + else + { + packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } } REQUIRE(packet->GetLatestSequenceNumber() == 1013); @@ -173,7 +180,14 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" for (auto& input : inputs) { - packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + if (std::addressof(input) == std::addressof(inputs.front())) + { + packet->SetBase(input.sequenceNumber + 1, input.timestamp); + } + else + { + packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } } packet->Finish(); @@ -238,7 +252,14 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" for (auto& input : inputs) { - packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + if (std::addressof(input) == std::addressof(inputs.front())) + { + packet->SetBase(input.sequenceNumber + 1, input.timestamp); + } + else + { + packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } } packet->Finish(); @@ -296,7 +317,14 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" for (auto& input : inputs) { - packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + if (std::addressof(input) == std::addressof(inputs.front())) + { + packet->SetBase(input.sequenceNumber + 1, input.timestamp); + } + else + { + packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } } packet->Finish(); @@ -363,7 +391,14 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" for (auto& input : inputs) { - packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + if (std::addressof(input) == std::addressof(inputs.front())) + { + packet->SetBase(input.sequenceNumber + 1, input.timestamp); + } + else + { + packet->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } } packet->Finish(); @@ -424,7 +459,14 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" for (auto& input : inputs2) { - packet2->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + if (std::addressof(input) == std::addressof(inputs2.front())) + { + packet2->SetBase(input.sequenceNumber + 1, input.timestamp); + } + else + { + packet2->AddPacket(input.sequenceNumber, input.timestamp, input.maxPacketSize); + } } packet2->Finish(); diff --git a/worker/test/src/RTC/TestTransportCongestionControlServer.cpp b/worker/test/src/RTC/TestTransportCongestionControlServer.cpp new file mode 100644 index 0000000000..27512b2b37 --- /dev/null +++ b/worker/test/src/RTC/TestTransportCongestionControlServer.cpp @@ -0,0 +1,254 @@ +#include "common.hpp" +#include "DepLibUV.hpp" +#include "RTC/TransportCongestionControlServer.hpp" +#include + +using namespace RTC; + +struct TestTransportCongestionControlServerInput +{ + uint16_t wideSeqNumber; + uint64_t nowMs; +}; + +struct TestTransportCongestionControlServerResult +{ + uint16_t wideSeqNumber; + bool received; + uint64_t timestamp; +}; + +using TestResults = std::deque>; + +class TestTransportCongestionControlServerListener : public TransportCongestionControlServer::Listener +{ +public: + virtual void OnTransportCongestionControlServerSendRtcpPacket( + RTC::TransportCongestionControlServer* tccServer, RTC::RTCP::Packet* packet) override + { + auto* tccPacket = dynamic_cast(packet); + + if (!tccPacket) + { + return; + } + + auto packetResults = tccPacket->GetPacketResults(); + + REQUIRE(!this->results.empty()); + + auto testResults = this->results.front(); + this->results.pop_front(); + + REQUIRE(testResults.size() == packetResults.size()); + + auto packetResultIt = packetResults.begin(); + auto testResultIt = testResults.begin(); + + for (; packetResultIt != packetResults.end() && testResultIt != testResults.end(); + ++packetResultIt, ++testResultIt) + { + REQUIRE(packetResultIt->sequenceNumber == testResultIt->wideSeqNumber); + REQUIRE(packetResultIt->received == testResultIt->received); + + if (packetResultIt->received) + { + REQUIRE(packetResultIt->receivedAtMs == testResultIt->timestamp); + } + } + } + +public: + void SetResults(TestResults& results) + { + this->results = results; + } + + void Check() + { + REQUIRE(this->results.empty()); + } + +private: + TestResults results; +}; + +// clang-format off +uint8_t buffer[] = +{ + 0x90, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x05, + 0xbe, 0xde, 0x00, 0x01, // Header Extensions + 0x51, 0x60, 0xee, 0x00 // TCC Feedback +}; +// clang-format on + +void validate(std::vector& inputs, TestResults& results) +{ + TestTransportCongestionControlServerListener listener; + auto tccServer = + TransportCongestionControlServer(&listener, RTC::BweType::TRANSPORT_CC, RTC::MtuSize); + + tccServer.SetMaxIncomingBitrate(150000); + tccServer.TransportConnected(); + + RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); + + packet->SetTransportWideCc01ExtensionId(5); + packet->SetSequenceNumber(1); + + // Save results. + listener.SetResults(results); + + uint64_t startTs = inputs[0].nowMs; + uint64_t TransportCcFeedbackSendInterval{ 100u }; // In ms. + + for (auto input : inputs) + { + // Periodic sending TCC packets. + uint64_t diffTs = input.nowMs - startTs; + + if (diffTs >= TransportCcFeedbackSendInterval) + { + tccServer.FillAndSendTransportCcFeedback(); + startTs = input.nowMs; + } + + packet->UpdateTransportWideCc01(input.wideSeqNumber); + tccServer.IncomingPacket(input.nowMs, packet); + } + + tccServer.FillAndSendTransportCcFeedback(); + listener.Check(); +}; + +SCENARIO("TransportCongestionControlServer", "[rtp]") +{ + SECTION("normal time and sequence") + { + // clang-format off + std::vector inputs + { + { 1u, 1000u }, + { 2u, 1050u }, + { 3u, 1100u }, + { 4u, 1150u }, + { 5u, 1200u }, + }; + + TestResults results + { + { + { 1u, true, 1000u }, + { 2u, true, 1050u }, + }, + { + { 3u, true, 1100u }, + { 4u, true, 1150u }, + }, + { + { 5u, true, 1200u }, + }, + }; + // clang-format on + + validate(inputs, results); + } + + SECTION("lost packets") + { + // clang-format off + std::vector inputs + { + { 1u, 1000u }, + { 3u, 1050u }, + { 5u, 1100u }, + { 6u, 1150u }, + }; + + TestResults results + { + { + { 1u, true, 1000u }, + { 2u, false, 0u }, + { 3u, true, 1050u }, + }, + { + { 4u, false, 0u }, + { 5u, true, 1100u }, + { 6u, true, 1150u }, + }, + }; + // clang-format on + + validate(inputs, results); + } + + SECTION("duplicate packets") + { + // clang-format off + std::vector inputs + { + { 1u, 1000u }, + { 1u, 1050u }, + { 2u, 1100u }, + { 3u, 1150u }, + { 3u, 1200u }, + { 4u, 1250u }, + }; + + TestResults results + { + { + { 1u, true, 1000u }, + }, + { + { 2u, true, 1100u }, + { 3u, true, 1150u }, + }, + { + { 4u, true, 1250u }, + }, + }; + // clang-format on + + validate(inputs, results); + } + + SECTION("packets arrive out of order") + { + // clang-format off + std::vector inputs + { + { 1u, 1000u }, + { 2u, 1050u }, + { 4u, 1100u }, + { 5u, 1150u }, + { 3u, 1200u }, // Out of order + { 6u, 1250u }, + }; + + TestResults results + { + { + { 1u, true, 1000u }, + { 2u, true, 1050u }, + }, + { + { 3u, false, 0u }, + { 4u, true, 1100u }, + { 5u, true, 1150u }, + }, + { + { 3u, true, 1200u }, + { 4u, true, 1100u }, + { 5u, true, 1150u }, + { 6u, true, 1250u }, + }, + }; + // clang-format on + + validate(inputs, results); + } +} From 20a606a3150a95f7aaf6497ce1b98301db848d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 5 Feb 2024 10:40:09 +0100 Subject: [PATCH 342/525] Rename "announced ip" to "announced address" (#1324) --- CHANGELOG.md | 3 +- Cargo.lock | 4 +- node/src/Router.ts | 20 ++++---- node/src/Transport.ts | 14 +++++- node/src/WebRtcTransport.ts | 5 +- node/src/Worker.ts | 2 +- node/src/test/test-PlainTransport.ts | 14 +++++- node/src/test/test-WebRtcServer.ts | 6 +-- node/src/test/test-WebRtcTransport.ts | 32 ++++++++---- node/src/test/test-node-sctp.ts | 2 +- rust/CHANGELOG.md | 7 +++ rust/Cargo.toml | 4 +- rust/benches/producer.rs | 2 +- rust/examples/echo.rs | 2 +- rust/examples/multiopus.rs | 12 ++--- rust/examples/svc-simulcast.rs | 2 +- rust/examples/videoroom.rs | 2 +- rust/src/data_structures.rs | 50 +++++++++++-------- rust/src/router.rs | 20 ++++---- rust/src/router/consumer/tests.rs | 2 +- rust/src/router/data_consumer/tests.rs | 6 +-- rust/src/router/data_producer/tests.rs | 2 +- rust/src/router/pipe_transport.rs | 4 +- rust/src/router/pipe_transport/tests.rs | 2 +- rust/src/router/plain_transport.rs | 12 ++--- rust/src/router/plain_transport/tests.rs | 2 +- rust/src/router/producer/tests.rs | 2 +- rust/src/router/webrtc_transport.rs | 10 ++-- rust/src/router/webrtc_transport/tests.rs | 12 ++--- rust/src/webrtc_server/tests.rs | 2 +- rust/tests/integration/consumer.rs | 2 +- rust/tests/integration/data_consumer.rs | 8 +-- rust/tests/integration/data_producer.rs | 4 +- rust/tests/integration/multiopus.rs | 2 +- rust/tests/integration/pipe_transport.rs | 14 +++--- rust/tests/integration/plain_transport.rs | 58 ++++++++++++---------- rust/tests/integration/producer.rs | 2 +- rust/tests/integration/smoke.rs | 4 +- rust/tests/integration/webrtc_server.rs | 22 ++++---- rust/tests/integration/webrtc_transport.rs | 42 ++++++++-------- worker/Cargo.toml | 2 +- worker/fbs/transport.fbs | 4 +- worker/fbs/webRtcTransport.fbs | 2 +- worker/include/RTC/IceCandidate.hpp | 18 +++---- worker/include/RTC/Transport.hpp | 2 +- worker/include/RTC/TransportTuple.hpp | 8 +-- worker/include/RTC/WebRtcServer.hpp | 7 +-- worker/include/RTC/WebRtcTransport.hpp | 2 +- worker/src/RTC/IceCandidate.cpp | 4 +- worker/src/RTC/PipeTransport.cpp | 22 ++++---- worker/src/RTC/PlainTransport.cpp | 46 +++++++++-------- worker/src/RTC/TransportTuple.cpp | 9 ++-- worker/src/RTC/WebRtcServer.cpp | 18 +++---- worker/src/RTC/WebRtcTransport.cpp | 18 +++---- 54 files changed, 325 insertions(+), 254 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 213dc349ff..ae8bd5082b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ### NEXT - Make transport-cc feedback work similarly to libwebrtc ([PR #1088](https://github.com/versatica/mediasoup/pull/1088) by @penguinol). -- `TransportListenInfo`: announced ip can also be a hostname ([PR #1322](https://github.com/versatica/mediasoup/pull/1322)). +- `TransportListenInfo`: "announced ip" can also be a hostname ([PR #1322](https://github.com/versatica/mediasoup/pull/1322)). +- `TransportListenInfo`: Rename "announced ip" to "announced address" ([PR #1324](https://github.com/versatica/mediasoup/pull/1324)). ### 3.13.17 diff --git a/Cargo.lock b/Cargo.lock index cf796abe99..815ea73405 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1354,7 +1354,7 @@ checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" [[package]] name = "mediasoup" -version = "0.15.0" +version = "0.16.0" dependencies = [ "actix", "actix-web", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "mediasoup-sys" -version = "0.7.2" +version = "0.8.0" dependencies = [ "planus", "planus-codegen", diff --git a/node/src/Router.ts b/node/src/Router.ts index 6ed415e540..42732654be 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -526,7 +526,7 @@ export class Router< listenInfos.push({ protocol: protocol, ip: listenIp.ip, - announcedIp: listenIp.announcedIp, + announcedAddress: listenIp.announcedIp, port: port, }); } @@ -557,7 +557,7 @@ export class Router< ? FbsTransportProtocol.UDP : FbsTransportProtocol.TCP, listenInfo.ip, - listenInfo.announcedIp, + listenInfo.announcedAddress ?? listenInfo.announcedIp, listenInfo.port, socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, @@ -715,7 +715,7 @@ export class Router< listenInfo = { protocol: 'udp', ip: listenIp.ip, - announcedIp: listenIp.announcedIp, + announcedAddress: listenIp.announcedIp, port: port, }; } @@ -744,7 +744,7 @@ export class Router< ? FbsTransportProtocol.UDP : FbsTransportProtocol.TCP, listenInfo!.ip, - listenInfo!.announcedIp, + listenInfo!.announcedAddress ?? listenInfo!.announcedIp, listenInfo!.port, socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, @@ -756,7 +756,7 @@ export class Router< ? FbsTransportProtocol.UDP : FbsTransportProtocol.TCP, rtcpListenInfo.ip, - rtcpListenInfo.announcedIp, + rtcpListenInfo.announcedAddress ?? rtcpListenInfo.announcedIp, rtcpListenInfo.port, socketFlagsToFbs(rtcpListenInfo.flags), rtcpListenInfo.sendBufferSize, @@ -867,7 +867,7 @@ export class Router< listenInfo = { protocol: 'udp', ip: listenIp.ip, - announcedIp: listenIp.announcedIp, + announcedAddress: listenIp.announcedIp, port: port, }; } @@ -896,7 +896,7 @@ export class Router< ? FbsTransportProtocol.UDP : FbsTransportProtocol.TCP, listenInfo!.ip, - listenInfo!.announcedIp, + listenInfo!.announcedAddress ?? listenInfo!.announcedIp, listenInfo!.port, socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, @@ -1105,7 +1105,7 @@ export class Router< listenInfo = { protocol: 'udp', ip: listenIp.ip, - announcedIp: listenIp.announcedIp, + announcedAddress: listenIp.announcedIp, }; } @@ -1162,12 +1162,12 @@ export class Router< .then(() => { return Promise.all([ localPipeTransport.connect({ - ip: remotePipeTransport.tuple.localIp, + ip: remotePipeTransport.tuple.localAddress, port: remotePipeTransport.tuple.localPort, srtpParameters: remotePipeTransport.srtpParameters, }), remotePipeTransport.connect({ - ip: localPipeTransport.tuple.localIp, + ip: localPipeTransport.tuple.localAddress, port: localPipeTransport.tuple.localPort, srtpParameters: localPipeTransport.srtpParameters, }), diff --git a/node/src/Transport.ts b/node/src/Transport.ts index c2428ec802..de25523662 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -72,11 +72,19 @@ export type TransportListenInfo = { ip: string; /** + * @deprecated Use |announcedAddress| instead. + * * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT * with private IP). */ announcedIp?: string; + /** + * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT + * with private IP). + */ + announcedAddress?: string; + /** * Listening port. */ @@ -136,7 +144,9 @@ export type TransportSocketFlags = { }; export type TransportTuple = { + // @deprecated Use localAddress instead. localIp: string; + localAddress: string; localPort: number; remoteIp?: string; remotePort?: number; @@ -1354,7 +1364,9 @@ export function serializeProtocol( export function parseTuple(binary: FbsTransport.Tuple): TransportTuple { return { - localIp: binary.localIp()!, + // @deprecated Use localAddress instead. + localIp: binary.localAddress()!, + localAddress: binary.localAddress()!, localPort: binary.localPort(), remoteIp: binary.remoteIp() ?? undefined, remotePort: binary.remotePort(), diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 4e37a50763..bdfb534e59 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -138,7 +138,9 @@ export type IceParameters = { export type IceCandidate = { foundation: string; priority: number; + // @deprecated Use |address| instead. ip: string; + address: string; protocol: TransportProtocol; port: number; type: IceCandidateType; @@ -864,7 +866,8 @@ function parseIceCandidate( return { foundation: binary.foundation()!, priority: binary.priority(), - ip: binary.ip()!, + ip: binary.address()!, + address: binary.address()!, protocol: parseProtocol(binary.protocol()), port: binary.port(), type: iceCandidateTypeFromFbs(binary.type()), diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 0b7112b492..ad9838ce4a 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -699,7 +699,7 @@ export class Worker< ? FbsTransportProtocol.UDP : FbsTransportProtocol.TCP, listenInfo.ip, - listenInfo.announcedIp, + listenInfo.announcedAddress ?? listenInfo.announcedIp, listenInfo.port, socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index 6ea15e625f..097cc2b91f 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -73,7 +73,11 @@ test('router.createPlainTransport() succeeds', async () => { // Create a separate transport here. const plainTransport2 = await ctx.router!.createPlainTransport({ - listenInfo: { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + }, enableSctp: true, appData: { foo: 'bar' }, }); @@ -84,7 +88,9 @@ test('router.createPlainTransport() succeeds', async () => { expect(plainTransport2.closed).toBe(false); expect(plainTransport2.appData).toEqual({ foo: 'bar' }); expect(typeof plainTransport2.tuple).toBe('object'); + // @deprecated Use tuple.localAddress instead. expect(plainTransport2.tuple.localIp).toBe('9.9.9.1'); + expect(plainTransport2.tuple.localAddress).toBe('9.9.9.1'); expect(typeof plainTransport2.tuple.localPort).toBe('number'); expect(plainTransport2.tuple.protocol).toBe('udp'); expect(plainTransport2.rtcpTuple).toBeUndefined(); @@ -138,11 +144,15 @@ test('router.createPlainTransport() succeeds', async () => { expect(transport2.closed).toBe(false); expect(transport2.appData).toEqual({}); expect(typeof transport2.tuple).toBe('object'); + // @deprecated Use tuple.localAddress instead. expect(transport2.tuple.localIp).toBe('127.0.0.1'); + expect(transport2.tuple.localAddress).toBe('127.0.0.1'); expect(transport2.tuple.localPort).toBe(rtpPort); expect(transport2.tuple.protocol).toBe('udp'); expect(typeof transport2.rtcpTuple).toBe('object'); + // @deprecated Use tuple.localAddress instead. expect(transport2.rtcpTuple?.localIp).toBe('127.0.0.1'); + expect(transport2.rtcpTuple?.localAddress).toBe('127.0.0.1'); expect(transport2.rtcpTuple?.localPort).toBe(rtcpPort); expect(transport2.rtcpTuple?.protocol).toBe('udp'); expect(transport2.sctpParameters).toBeUndefined(); @@ -395,7 +405,9 @@ test('plainTransport.getStats() succeeds', async () => { expect(stats[0].probationBytesSent).toBe(0); expect(stats[0].probationSendBitrate).toBe(0); expect(typeof stats[0].tuple).toBe('object'); + // @deprecated Use tuple.localAddress instead. expect(stats[0].tuple.localIp).toBe('127.0.0.1'); + expect(stats[0].tuple.localAddress).toBe('127.0.0.1'); expect(typeof stats[0].tuple.localPort).toBe('number'); expect(stats[0].tuple.protocol).toBe('udp'); expect(stats[0].rtcpTuple).toBeUndefined(); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index 3ffdeb2afe..e5e2e2b703 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -48,7 +48,7 @@ test('worker.createWebRtcServer() succeeds', async () => { { protocol: 'tcp', ip: '127.0.0.1', - announcedIp: 'foo.bar.org', + announcedAddress: 'foo.bar.org', port: port2, }, ], @@ -105,7 +105,7 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => { protocol: 'tcp', ip: '127.0.0.1', - announcedIp: '1.2.3.4', + announcedAddress: '1.2.3.4', }, ], appData: { foo: 123 }, @@ -210,7 +210,7 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro { protocol: 'udp', ip: '127.0.0.1', - announcedIp: '1.2.3.4', + announcedAddress: '1.2.3.4', port: port1, }, ], diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index a6f7d871e4..1e62a9dadb 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -70,12 +70,12 @@ test('router.createWebRtcTransport() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, - { protocol: 'tcp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }, - { protocol: 'udp', ip: '0.0.0.0', announcedIp: 'foo1.bar.org' }, - { protocol: 'tcp', ip: '0.0.0.0', announcedIp: 'foo2.bar.org' }, - { protocol: 'udp', ip: '127.0.0.1', announcedIp: undefined }, - { protocol: 'tcp', ip: '127.0.0.1', announcedIp: undefined }, + { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { protocol: 'tcp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { protocol: 'udp', ip: '0.0.0.0', announcedAddress: 'foo1.bar.org' }, + { protocol: 'tcp', ip: '0.0.0.0', announcedAddress: 'foo2.bar.org' }, + { protocol: 'udp', ip: '127.0.0.1', announcedAddress: undefined }, + { protocol: 'tcp', ip: '127.0.0.1', announcedAddress: undefined }, ], enableTcp: true, preferUdp: true, @@ -221,7 +221,9 @@ test('router.createWebRtcTransport() with non bindable IP rejects with Error', a test('webRtcTransport.getStats() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + ], }); const stats = await webRtcTransport.getStats(); @@ -255,7 +257,9 @@ test('webRtcTransport.getStats() succeeds', async () => { test('webRtcTransport.connect() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + ], }); const dtlsRemoteParameters: mediasoup.types.DtlsParameters = { @@ -283,7 +287,9 @@ test('webRtcTransport.connect() succeeds', async () => { test('webRtcTransport.connect() with wrong arguments rejects with TypeError', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + ], }); let dtlsRemoteParameters: mediasoup.types.DtlsParameters; @@ -341,7 +347,9 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', announcedIp: '9.9.9.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + ], }); await expect( @@ -541,7 +549,9 @@ test('WebRtcTransport events succeed', async () => { const onIceSelectedTuple = jest.fn(); const iceSelectedTuple: TransportTuple = { + // @deprecated Use localAddress. localIp: '1.1.1.1', + localAddress: '1.1.1.1', localPort: 1111, remoteIp: '2.2.2.2', remotePort: 2222, @@ -554,7 +564,7 @@ test('WebRtcTransport events succeed', async () => { const iceSelectedTupleChangeNotification = new FbsWebRtcTransport.IceSelectedTupleChangeNotificationT( new FbsTransport.TupleT( - iceSelectedTuple.localIp, + iceSelectedTuple.localAddress, iceSelectedTuple.localPort, iceSelectedTuple.remoteIp, iceSelectedTuple.remotePort, diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index 513b27becd..380549b161 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -39,7 +39,7 @@ beforeEach(async () => { ctx.udpSocket!.bind(0, '127.0.0.1', resolve); }); - const remoteUdpIp = ctx.plainTransport.tuple.localIp; + const remoteUdpIp = ctx.plainTransport.tuple.localAddress; const remoteUdpPort = ctx.plainTransport.tuple.localPort; const { OS, MIS } = ctx.plainTransport.sctpParameters!; diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index 3295e1d7d6..8152c3efb5 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +# 0.16.0 + +* Updates from mediasoup TypeScript `3.13.13..=3.13.17`. +* General mediasoup changes: + * `TransportListenInfo.announced_ip` can also be a hostname (PR #1322). + * `TransportListenInfo.announced_ip` is now `announced_address`, `IceCandidate.ip` is now `IceCandidate.address` and `TransportTuple.local_ip` is not `TransportTuple.local_address` (PR #1324). + # 0.15.0 * Expose DataChannel string message as binary (PR #1289). diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 270c2e4758..5003af1220 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup" -version = "0.15.0" +version = "0.16.0" description = "Cutting Edge WebRTC Video Conferencing in Rust" categories = ["api-bindings", "multimedia", "network-programming"] authors = ["Nazar Mokrynskyi "] @@ -46,7 +46,7 @@ version = "0.8.1" [dependencies.mediasoup-sys] path = "../worker" -version = "0.7.2" +version = "0.8.0" [dependencies.parking_lot] version = "0.12.1" diff --git a/rust/benches/producer.rs b/rust/benches/producer.rs index c9b98870dc..8d05625a26 100644 --- a/rust/benches/producer.rs +++ b/rust/benches/producer.rs @@ -65,7 +65,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/examples/echo.rs b/rust/examples/echo.rs index c64ed714d4..d8d751f55f 100644 --- a/rust/examples/echo.rs +++ b/rust/examples/echo.rs @@ -185,7 +185,7 @@ impl EchoConnection { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/examples/multiopus.rs b/rust/examples/multiopus.rs index a4f2f7be02..d78e8fd859 100644 --- a/rust/examples/multiopus.rs +++ b/rust/examples/multiopus.rs @@ -148,7 +148,7 @@ impl EchoConnection { let mut options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -198,9 +198,9 @@ impl EchoConnection { RTCP listening on {}:{}\n \ PT=100\n \ SSRC=1111", - plain_transport.tuple().local_ip(), + plain_transport.tuple().local_address(), plain_transport.tuple().local_port(), - plain_transport.rtcp_tuple().unwrap().local_ip(), + plain_transport.rtcp_tuple().unwrap().local_address(), plain_transport.rtcp_tuple().unwrap().local_port(), ); @@ -220,9 +220,9 @@ impl EchoConnection { rtpbin.send_rtp_sink_0 \\\n \ rtpbin.send_rtp_src_0 ! udpsink host={} port={} sync=false async=false \\\n \ rtpbin.send_rtcp_src_0 ! udpsink host={} port={} sync=false async=false", - plain_transport.tuple().local_ip(), + plain_transport.tuple().local_address(), plain_transport.tuple().local_port(), - plain_transport.rtcp_tuple().unwrap().local_ip(), + plain_transport.rtcp_tuple().unwrap().local_address(), plain_transport.rtcp_tuple().unwrap().local_port(), ); @@ -234,7 +234,7 @@ impl EchoConnection { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/examples/svc-simulcast.rs b/rust/examples/svc-simulcast.rs index 959d7ce056..4bf34bbf6c 100644 --- a/rust/examples/svc-simulcast.rs +++ b/rust/examples/svc-simulcast.rs @@ -205,7 +205,7 @@ impl SvcSimulcastConnection { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/examples/videoroom.rs b/rust/examples/videoroom.rs index ff7a6a0794..379958534e 100644 --- a/rust/examples/videoroom.rs +++ b/rust/examples/videoroom.rs @@ -499,7 +499,7 @@ mod participant { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index 4fd5cf1d35..807dee3990 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -50,7 +50,8 @@ impl AppData { /// Listening protocol, IP and port for [`WebRtcServer`](crate::webrtc_server::WebRtcServer) to listen on. /// /// # Notes on usage -/// If you use "0.0.0.0" or "::" as ip value, then you need to also provide `announced_ip`. +/// If you use "0.0.0.0" or "::" as ip value, then you need to also provide +/// `announced_address`. #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ListenInfo { @@ -61,7 +62,7 @@ pub struct ListenInfo { /// Announced IPv4, IPv6 or hostname (useful when running mediasoup behind /// NAT with private IP). #[serde(skip_serializing_if = "Option::is_none")] - pub announced_ip: Option, + pub announced_address: Option, /// Listening port. #[serde(skip_serializing_if = "Option::is_none")] pub port: Option, @@ -84,7 +85,10 @@ impl ListenInfo { Protocol::Udp => transport::Protocol::Udp, }, ip: self.ip.to_string(), - announced_ip: self.announced_ip.clone().map(|ip| ip.to_string()), + announced_address: self + .announced_address + .as_ref() + .map(|address| address.to_string()), port: self.port.unwrap_or(0), flags: Box::new(self.flags.unwrap_or_default().to_fbs()), send_buffer_size: self.send_buffer_size.unwrap_or(0), @@ -163,13 +167,13 @@ impl IceParameters { #[serde(rename_all = "lowercase")] pub enum IceCandidateType { /// The candidate is a host candidate, whose IP address as specified in the - /// [`IceCandidate::ip`] property is in fact the true address of the remote peer. + /// [`IceCandidate::address`] property is in fact the true address of the remote peer. Host, - /// The candidate is a server reflexive candidate; the [`IceCandidate::ip`] indicates an + /// The candidate is a server reflexive candidate; the [`IceCandidate::address`] indicates an /// intermediary address assigned by the STUN server to represent the candidate's peer /// anonymously. Srflx, - /// The candidate is a peer reflexive candidate; the [`IceCandidate::ip`] is an intermediary + /// The candidate is a peer reflexive candidate; the [`IceCandidate::address`] is an intermediary /// address assigned by the STUN server to represent the candidate's peer anonymously. Prflx, /// The candidate is a relay candidate, obtained from a TURN server. The relay candidate's IP @@ -231,7 +235,7 @@ pub struct IceCandidate { /// The assigned priority of the candidate. pub priority: u32, /// The IP address or hostname of the candidate. - pub ip: String, + pub address: String, /// The protocol of the candidate. pub protocol: Protocol, /// The port for the candidate. @@ -248,7 +252,7 @@ impl IceCandidate { Self { foundation: candidate.foundation.clone(), priority: candidate.priority, - ip: candidate.ip.clone(), + address: candidate.address.clone(), protocol: Protocol::from_fbs(candidate.protocol), port: candidate.port, r#type: IceCandidateType::from_fbs(candidate.type_), @@ -293,14 +297,14 @@ impl IceState { /// `PipeTransport`, or via dynamic detection as it happens in `WebRtcTransport` (in which the /// remote media address is detected by ICE means), or in `PlainTransport` (when using `comedia` /// mode). -#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] +#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(untagged)] pub enum TransportTuple { /// Transport tuple with remote endpoint info. #[serde(rename_all = "camelCase")] WithRemote { - /// Local IP address. - local_ip: IpAddr, + /// Local IP address or hostname. + local_address: String, /// Local port. local_port: u16, /// Remote IP address. @@ -313,8 +317,8 @@ pub enum TransportTuple { /// Transport tuple without remote endpoint info. #[serde(rename_all = "camelCase")] LocalOnly { - /// Local IP address. - local_ip: IpAddr, + /// Local IP address or hostname. + local_address: String, /// Local port. local_port: u16, /// Protocol @@ -323,10 +327,10 @@ pub enum TransportTuple { } impl TransportTuple { - /// Local IP address. - pub fn local_ip(&self) -> IpAddr { - let (Self::WithRemote { local_ip, .. } | Self::LocalOnly { local_ip, .. }) = self; - *local_ip + /// Local IP address or hostname. + pub fn local_address(&self) -> &String { + let (Self::WithRemote { local_address, .. } | Self::LocalOnly { local_address, .. }) = self; + local_address } /// Local port. @@ -362,19 +366,25 @@ impl TransportTuple { pub(crate) fn from_fbs(tuple: &transport::Tuple) -> TransportTuple { match &tuple.remote_ip { Some(_remote_ip) => TransportTuple::WithRemote { - local_ip: tuple.local_ip.parse().expect("Error parsing IP address"), + local_address: tuple + .local_address + .parse() + .expect("Error parsing local address"), local_port: tuple.local_port, remote_ip: tuple .remote_ip .as_ref() .unwrap() .parse() - .expect("Error parsing IP address"), + .expect("Error parsing remote IP address"), remote_port: tuple.remote_port, protocol: Protocol::from_fbs(tuple.protocol), }, None => TransportTuple::LocalOnly { - local_ip: tuple.local_ip.parse().expect("Error parsing IP address"), + local_address: tuple + .local_address + .parse() + .expect("Error parsing local address"), local_port: tuple.local_port, protocol: Protocol::from_fbs(tuple.protocol), }, diff --git a/rust/src/router.rs b/rust/src/router.rs index 0824bec0f8..c1259c3174 100644 --- a/rust/src/router.rs +++ b/rust/src/router.rs @@ -145,7 +145,7 @@ impl PipeToRouterOptions { listen_info: ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -608,7 +608,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".to_string()), + /// announced_address: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -696,7 +696,7 @@ impl Router { /// .create_pipe_transport(PipeTransportOptions::new(ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".to_string()), + /// announced_address: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -762,7 +762,7 @@ impl Router { /// .create_plain_transport(PlainTransportOptions::new(ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".to_string()), + /// announced_address: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -973,7 +973,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".to_string()), + /// announced_address: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -1016,7 +1016,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".to_string()), + /// announced_address: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -1202,7 +1202,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".to_string()), + /// announced_address: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -1234,7 +1234,7 @@ impl Router { /// ListenInfo { /// protocol: Protocol::Udp, /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - /// announced_ip: Some("9.9.9.1".to_string()), + /// announced_address: Some("9.9.9.1".to_string()), /// port: None, /// flags: None, /// send_buffer_size: None, @@ -1482,7 +1482,7 @@ impl Router { let tuple = remote_pipe_transport.tuple(); PipeTransportRemoteParameters { - ip: tuple.local_ip(), + ip: tuple.local_address().parse::().unwrap(), port: tuple.local_port(), srtp_parameters: remote_pipe_transport.srtp_parameters(), } @@ -1492,7 +1492,7 @@ impl Router { let tuple = local_pipe_transport.tuple(); PipeTransportRemoteParameters { - ip: tuple.local_ip(), + ip: tuple.local_address().parse::().unwrap(), port: tuple.local_port(), srtp_parameters: local_pipe_transport.srtp_parameters(), } diff --git a/rust/src/router/consumer/tests.rs b/rust/src/router/consumer/tests.rs index 94a5b2f9b6..0055fc3262 100644 --- a/rust/src/router/consumer/tests.rs +++ b/rust/src/router/consumer/tests.rs @@ -85,7 +85,7 @@ async fn init() -> (Router, WebRtcTransport, WebRtcTransport) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/src/router/data_consumer/tests.rs b/rust/src/router/data_consumer/tests.rs index 64a2dd884f..b04a0a81b8 100644 --- a/rust/src/router/data_consumer/tests.rs +++ b/rust/src/router/data_consumer/tests.rs @@ -39,7 +39,7 @@ async fn init() -> (Router, DataProducer) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -73,7 +73,7 @@ fn data_producer_close_event() { let mut transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -127,7 +127,7 @@ fn transport_close_event() { let mut transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/src/router/data_producer/tests.rs b/rust/src/router/data_producer/tests.rs index 52b585b162..349a0909d4 100644 --- a/rust/src/router/data_producer/tests.rs +++ b/rust/src/router/data_producer/tests.rs @@ -39,7 +39,7 @@ async fn init() -> (Router, WebRtcTransport) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/src/router/pipe_transport.rs b/rust/src/router/pipe_transport.rs index e69ee992da..633743bc19 100644 --- a/rust/src/router/pipe_transport.rs +++ b/rust/src/router/pipe_transport.rs @@ -719,12 +719,12 @@ impl PipeTransport { /// /// # Notes on usage /// * Once the pipe transport is created, `transport.tuple()` will contain information about - /// its `local_ip`, `local_port` and `protocol`. + /// its `local_address`, `local_port` and `protocol`. /// * Information about `remote_ip` and `remote_port` will be set after calling `connect()` /// method. #[must_use] pub fn tuple(&self) -> TransportTuple { - *self.inner.data.tuple.lock() + self.inner.data.tuple.lock().clone() } /// Local SCTP parameters. Or `None` if SCTP is not enabled. diff --git a/rust/src/router/pipe_transport/tests.rs b/rust/src/router/pipe_transport/tests.rs index 4e57984bcf..7a3864cfd5 100644 --- a/rust/src/router/pipe_transport/tests.rs +++ b/rust/src/router/pipe_transport/tests.rs @@ -101,7 +101,7 @@ async fn init() -> (Router, Router, WebRtcTransport, WebRtcTransport) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/src/router/plain_transport.rs b/rust/src/router/plain_transport.rs index 33debb2fbf..29e436f254 100644 --- a/rust/src/router/plain_transport.rs +++ b/rust/src/router/plain_transport.rs @@ -686,12 +686,12 @@ impl PlainTransport { match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::Tuple { tuple } => { - *data.tuple.lock() = tuple; + *data.tuple.lock() = tuple.clone(); handlers.tuple.call_simple(&tuple); } Notification::RtcpTuple { rtcp_tuple } => { - data.rtcp_tuple.lock().replace(rtcp_tuple); + data.rtcp_tuple.lock().replace(rtcp_tuple.clone()); handlers.rtcp_tuple.call_simple(&rtcp_tuple); } @@ -903,13 +903,13 @@ impl PlainTransport { /// /// # Notes on usage /// * Once the plain transport is created, `transport.tuple()` will contain information about - /// its `local_ip`, `local_port` and `protocol`. + /// its `local_address`, `local_port` and `protocol`. /// * Information about `remote_ip` and `remote_port` will be set: /// * after calling `connect()` method, or /// * via dynamic remote address detection when using `comedia` mode. #[must_use] pub fn tuple(&self) -> TransportTuple { - *self.inner.data.tuple.lock() + self.inner.data.tuple.lock().clone() } /// The transport tuple for RTCP. If RTCP-mux is enabled (`rtcp_mux` is set), its value is @@ -917,13 +917,13 @@ impl PlainTransport { /// /// # Notes on usage /// * Once the plain transport is created (with RTCP-mux disabled), `transport.rtcp_tuple()` - /// will contain information about its `local_ip`, `local_port` and `protocol`. + /// will contain information about its `local_address`, `local_port` and `protocol`. /// * Information about `remote_ip` and `remote_port` will be set: /// * after calling `connect()` method, or /// * via dynamic remote address detection when using `comedia` mode. #[must_use] pub fn rtcp_tuple(&self) -> Option { - *self.inner.data.rtcp_tuple.lock() + self.inner.data.rtcp_tuple.lock().clone() } /// Current SCTP state. Or `None` if SCTP is not enabled. diff --git a/rust/src/router/plain_transport/tests.rs b/rust/src/router/plain_transport/tests.rs index 5a7d806104..e10654f8cf 100644 --- a/rust/src/router/plain_transport/tests.rs +++ b/rust/src/router/plain_transport/tests.rs @@ -40,7 +40,7 @@ fn router_close_event() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".to_string()), + announced_address: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, diff --git a/rust/src/router/producer/tests.rs b/rust/src/router/producer/tests.rs index 21e18c21d7..68b73f4292 100644 --- a/rust/src/router/producer/tests.rs +++ b/rust/src/router/producer/tests.rs @@ -70,7 +70,7 @@ async fn init() -> (Router, WebRtcTransport) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/src/router/webrtc_transport.rs b/rust/src/router/webrtc_transport.rs index 809b91d7dc..7218c2a038 100644 --- a/rust/src/router/webrtc_transport.rs +++ b/rust/src/router/webrtc_transport.rs @@ -88,8 +88,8 @@ impl TryFrom> for WebRtcTransportListenInfos { /// # Notes on usage /// * Do not use "0.0.0.0" into `listen_infos`. Values in `listen_infos` must be specific bindable IPs /// on the host. -/// * If you use "0.0.0.0" or "::" into `listen_infos`, then you need to also provide `announced_ip` -/// in the corresponding entry in `listen_infos`. +/// * If you use "0.0.0.0" or "::" into `listen_infos`, then you need to also provide +/// `announced_address` in the corresponding entry in `listen_infos`. #[derive(Debug, Clone)] pub enum WebRtcTransportListen { /// Listen on individual protocol/IP/port combinations specific to this transport. @@ -809,7 +809,9 @@ impl WebRtcTransport { }); } Notification::IceSelectedTupleChange { ice_selected_tuple } => { - data.ice_selected_tuple.lock().replace(ice_selected_tuple); + data.ice_selected_tuple + .lock() + .replace(ice_selected_tuple.clone()); handlers .ice_selected_tuple_change .call_simple(&ice_selected_tuple); @@ -1021,7 +1023,7 @@ impl WebRtcTransport { /// ICE is not established (no working candidate pair was found). #[must_use] pub fn ice_selected_tuple(&self) -> Option { - *self.inner.data.ice_selected_tuple.lock() + self.inner.data.ice_selected_tuple.lock().clone() } /// Local DTLS parameters. diff --git a/rust/src/router/webrtc_transport/tests.rs b/rust/src/router/webrtc_transport/tests.rs index 9e0d48e0db..75ea2726b1 100644 --- a/rust/src/router/webrtc_transport/tests.rs +++ b/rust/src/router/webrtc_transport/tests.rs @@ -55,7 +55,7 @@ fn create_with_webrtc_server_succeeds() { let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port1), flags: None, send_buffer_size: None, @@ -64,7 +64,7 @@ fn create_with_webrtc_server_succeeds() { let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port2), flags: None, send_buffer_size: None, @@ -132,7 +132,7 @@ fn create_with_webrtc_server_succeeds() { { let ice_candidates = transport.ice_candidates(); assert_eq!(ice_candidates.len(), 1); - assert_eq!(ice_candidates[0].ip, "127.0.0.1"); + assert_eq!(ice_candidates[0].address, "127.0.0.1"); assert_eq!(ice_candidates[0].protocol, Protocol::Tcp); assert_eq!(ice_candidates[0].port, port2); assert_eq!(ice_candidates[0].r#type, IceCandidateType::Host); @@ -233,7 +233,7 @@ fn router_close_event() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -275,7 +275,7 @@ fn webrtc_server_close_event() { let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port1), flags: None, send_buffer_size: None, @@ -284,7 +284,7 @@ fn webrtc_server_close_event() { let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port2), flags: None, send_buffer_size: None, diff --git a/rust/src/webrtc_server/tests.rs b/rust/src/webrtc_server/tests.rs index 95f257bc77..468be2ba85 100644 --- a/rust/src/webrtc_server/tests.rs +++ b/rust/src/webrtc_server/tests.rs @@ -36,7 +36,7 @@ fn worker_close_event() { ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port), flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/consumer.rs b/rust/tests/integration/consumer.rs index 54338b00a2..35fdaa214e 100644 --- a/rust/tests/integration/consumer.rs +++ b/rust/tests/integration/consumer.rs @@ -350,7 +350,7 @@ async fn init() -> ( WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/data_consumer.rs b/rust/tests/integration/data_consumer.rs index 8ae3ed3cf1..609837fd9e 100644 --- a/rust/tests/integration/data_consumer.rs +++ b/rust/tests/integration/data_consumer.rs @@ -66,7 +66,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, DataProducer) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -98,7 +98,7 @@ fn consume_data_succeeds() { let mut transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -208,7 +208,7 @@ fn weak() { let mut transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -573,7 +573,7 @@ fn close_event() { let mut transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/data_producer.rs b/rust/tests/integration/data_producer.rs index 31516da931..3fe27a394b 100644 --- a/rust/tests/integration/data_producer.rs +++ b/rust/tests/integration/data_producer.rs @@ -52,7 +52,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -71,7 +71,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { let mut transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/multiopus.rs b/rust/tests/integration/multiopus.rs index f05170401e..0bcc1ea97d 100644 --- a/rust/tests/integration/multiopus.rs +++ b/rust/tests/integration/multiopus.rs @@ -133,7 +133,7 @@ async fn init() -> (Router, WebRtcTransport) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/pipe_transport.rs b/rust/tests/integration/pipe_transport.rs index 32a8170e96..aff1990092 100644 --- a/rust/tests/integration/pipe_transport.rs +++ b/rust/tests/integration/pipe_transport.rs @@ -259,7 +259,7 @@ async fn init() -> ( WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -604,7 +604,7 @@ fn weak() { let mut options = PipeTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -639,7 +639,7 @@ fn create_with_fixed_port_succeeds() { PipeTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port), flags: None, send_buffer_size: None, @@ -663,7 +663,7 @@ fn create_with_enable_rtx_succeeds() { let mut options = PipeTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -776,7 +776,7 @@ fn create_with_enable_srtp_succeeds() { let mut options = PipeTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -832,7 +832,7 @@ fn create_with_invalid_srtp_parameters_fails() { .create_pipe_transport(PipeTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -1159,7 +1159,7 @@ fn pipe_to_router_called_twice_generates_single_pair() { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/plain_transport.rs b/rust/tests/integration/plain_transport.rs index 13553cab3d..2edadb74ee 100644 --- a/rust/tests/integration/plain_transport.rs +++ b/rust/tests/integration/plain_transport.rs @@ -94,7 +94,7 @@ fn create_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".to_string()), + announced_address: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -133,7 +133,7 @@ fn create_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -164,10 +164,12 @@ fn create_succeeds() { TransportTuple::LocalOnly { .. }, )); if let TransportTuple::LocalOnly { - local_ip, protocol, .. + local_address, + protocol, + .. } = transport1.tuple() { - assert_eq!(local_ip, "9.9.9.1".parse::().unwrap()); + assert_eq!(local_address, "9.9.9.1"); assert_eq!(protocol, Protocol::Udp); } assert_eq!(transport1.rtcp_tuple(), None); @@ -207,7 +209,7 @@ fn create_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -218,7 +220,7 @@ fn create_succeeds() { plain_transport_options.rtcp_listen_info = Some(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(rtcp_port), flags: None, send_buffer_size: None, @@ -237,21 +239,23 @@ fn create_succeeds() { TransportTuple::LocalOnly { .. }, )); if let TransportTuple::LocalOnly { - local_ip, protocol, .. + local_address, + protocol, + .. } = transport2.tuple() { - assert_eq!(local_ip, "127.0.0.1".parse::().unwrap()); + assert_eq!(local_address, "127.0.0.1"); assert_eq!(protocol, Protocol::Udp); } assert!(transport2.rtcp_tuple().is_some()); if let TransportTuple::LocalOnly { - local_ip, + local_address, local_port, protocol, .. } = transport2.rtcp_tuple().unwrap() { - assert_eq!(local_ip, "127.0.0.1".parse::().unwrap()); + assert_eq!(local_address, "127.0.0.1"); assert_eq!(local_port, rtcp_port); assert_eq!(protocol, Protocol::Udp); } @@ -286,7 +290,7 @@ fn create_with_fixed_port_succeeds() { PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".to_string()), + announced_address: Some("4.4.4.4".to_string()), port: Some(port), flags: None, send_buffer_size: None, @@ -310,7 +314,7 @@ fn weak() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".to_string()), + announced_address: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -344,7 +348,7 @@ fn create_enable_srtp_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -410,7 +414,7 @@ fn create_non_bindable_ip() { .create_plain_transport(PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: "8.8.8.8".parse().unwrap(), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -436,7 +440,7 @@ fn create_two_transports_binding_to_same_ip_port_with_udp_reuse_port_flag_succee PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: multicast_ip, - announced_ip: None, + announced_address: None, port: Some(port), // NOTE: ipv6Only flag will be ignored since ip is IPv4. flags: Some(SocketFlags { @@ -455,7 +459,7 @@ fn create_two_transports_binding_to_same_ip_port_with_udp_reuse_port_flag_succee PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: multicast_ip, - announced_ip: None, + announced_address: None, port: Some(port), flags: Some(SocketFlags { ipv6_only: false, @@ -487,7 +491,7 @@ fn create_two_transports_binding_to_same_ip_port_without_udp_reuse_port_flag_fai PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: multicast_ip, - announced_ip: None, + announced_address: None, port: Some(port), flags: Some(SocketFlags { ipv6_only: false, @@ -505,7 +509,7 @@ fn create_two_transports_binding_to_same_ip_port_without_udp_reuse_port_flag_fai .create_plain_transport(PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: multicast_ip, - announced_ip: None, + announced_address: None, port: Some(port), flags: Some(SocketFlags { ipv6_only: false, @@ -532,7 +536,7 @@ fn get_stats_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".to_string()), + announced_address: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -570,11 +574,13 @@ fn get_stats_succeeds() { assert_eq!(stats[0].rtp_packet_loss_sent, None); assert!(matches!(stats[0].tuple, TransportTuple::LocalOnly { .. },)); if let TransportTuple::LocalOnly { - local_ip, protocol, .. - } = stats[0].tuple + local_address, + protocol, + .. + } = &stats[0].tuple { - assert_eq!(local_ip, "4.4.4.4".parse::().unwrap()); - assert_eq!(protocol, Protocol::Udp); + assert_eq!(local_address, "4.4.4.4"); + assert_eq!(*protocol, Protocol::Udp); } assert_eq!(stats[0].rtcp_tuple, None); }); @@ -590,7 +596,7 @@ fn connect_succeeds() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".to_string()), + announced_address: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -666,7 +672,7 @@ fn connect_wrong_arguments() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".to_string()), + announced_address: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -707,7 +713,7 @@ fn close_event() { let mut plain_transport_options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("4.4.4.4".to_string()), + announced_address: Some("4.4.4.4".to_string()), port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/producer.rs b/rust/tests/integration/producer.rs index 909d5cbac4..44197df4e6 100644 --- a/rust/tests/integration/producer.rs +++ b/rust/tests/integration/producer.rs @@ -205,7 +205,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/smoke.rs b/rust/tests/integration/smoke.rs index 7008ad5e83..1c0c48890f 100644 --- a/rust/tests/integration/smoke.rs +++ b/rust/tests/integration/smoke.rs @@ -86,7 +86,7 @@ fn smoke() { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -273,7 +273,7 @@ fn smoke() { let mut options = PlainTransportOptions::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/webrtc_server.rs b/rust/tests/integration/webrtc_server.rs index 6986ddccc8..c647d8a9bd 100644 --- a/rust/tests/integration/webrtc_server.rs +++ b/rust/tests/integration/webrtc_server.rs @@ -62,7 +62,7 @@ fn create_webrtc_server_succeeds() { let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port1), flags: None, send_buffer_size: None, @@ -71,7 +71,7 @@ fn create_webrtc_server_succeeds() { let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("foo.bar.org".to_string()), + announced_address: Some("foo.bar.org".to_string()), port: Some(port2), flags: None, send_buffer_size: None, @@ -158,7 +158,7 @@ fn create_webrtc_server_without_specifying_port_succeeds() { let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -167,7 +167,7 @@ fn create_webrtc_server_without_specifying_port_succeeds() { let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Tcp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("1.2.3.4".to_string()), + announced_address: Some("1.2.3.4".to_string()), port: None, flags: None, send_buffer_size: None, @@ -241,7 +241,7 @@ fn unavailable_infos_fails() { let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port1), flags: None, send_buffer_size: None, @@ -250,7 +250,7 @@ fn unavailable_infos_fails() { let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)), - announced_ip: None, + announced_address: None, port: Some(port2), flags: None, send_buffer_size: None, @@ -274,7 +274,7 @@ fn unavailable_infos_fails() { let listen_infos = WebRtcServerListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port1), flags: None, send_buffer_size: None, @@ -283,7 +283,7 @@ fn unavailable_infos_fails() { let listen_infos = listen_infos.insert(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), - announced_ip: Some("1.2.3.4".to_string()), + announced_address: Some("1.2.3.4".to_string()), port: Some(port1), flags: None, send_buffer_size: None, @@ -307,7 +307,7 @@ fn unavailable_infos_fails() { ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port1), flags: None, send_buffer_size: None, @@ -322,7 +322,7 @@ fn unavailable_infos_fails() { ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port1), flags: None, send_buffer_size: None, @@ -351,7 +351,7 @@ fn close_event() { ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: Some(port), flags: None, send_buffer_size: None, diff --git a/rust/tests/integration/webrtc_transport.rs b/rust/tests/integration/webrtc_transport.rs index 35a02db1c0..c1e9b4bffb 100644 --- a/rust/tests/integration/webrtc_transport.rs +++ b/rust/tests/integration/webrtc_transport.rs @@ -98,7 +98,7 @@ fn create_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -136,7 +136,7 @@ fn create_succeeds() { ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -145,7 +145,7 @@ fn create_succeeds() { ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::UNSPECIFIED), - announced_ip: Some("foo1.bar.org".to_string()), + announced_address: Some("foo1.bar.org".to_string()), port: None, flags: None, send_buffer_size: None, @@ -154,7 +154,7 @@ fn create_succeeds() { ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -200,19 +200,19 @@ fn create_succeeds() { { let ice_candidates = transport1.ice_candidates(); assert_eq!(ice_candidates.len(), 3); - assert_eq!(ice_candidates[0].ip, "9.9.9.1"); + assert_eq!(ice_candidates[0].address, "9.9.9.1"); assert_eq!(ice_candidates[0].protocol, Protocol::Udp); assert_eq!(ice_candidates[0].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[0].tcp_type, None); - assert_eq!(ice_candidates[1].ip, "foo1.bar.org"); + assert_eq!(ice_candidates[1].address, "foo1.bar.org"); assert_eq!(ice_candidates[1].protocol, Protocol::Udp); assert_eq!(ice_candidates[1].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[1].tcp_type, None); - assert_eq!(ice_candidates[2].ip, "127.0.0.1"); + assert_eq!(ice_candidates[2].address, "127.0.0.1"); assert_eq!(ice_candidates[2].protocol, Protocol::Udp); assert_eq!(ice_candidates[2].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[2].tcp_type, None); - assert_eq!(ice_candidates[2].ip, "127.0.0.1"); + assert_eq!(ice_candidates[2].address, "127.0.0.1"); assert_eq!(ice_candidates[2].protocol, Protocol::Udp); assert_eq!(ice_candidates[2].r#type, IceCandidateType::Host); assert_eq!(ice_candidates[2].tcp_type, None); @@ -265,7 +265,7 @@ fn create_with_fixed_port_succeeds() { WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: Some(port), flags: None, send_buffer_size: None, @@ -289,7 +289,7 @@ fn weak() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -320,7 +320,7 @@ fn create_non_bindable_ip() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: "8.8.8.8".parse().unwrap(), - announced_ip: None, + announced_address: None, port: None, flags: None, send_buffer_size: None, @@ -343,7 +343,7 @@ fn get_stats_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -395,7 +395,7 @@ fn connect_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -445,7 +445,7 @@ fn set_max_incoming_bitrate_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -478,7 +478,7 @@ fn set_max_outgoing_bitrate_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -511,7 +511,7 @@ fn set_min_outgoing_bitrate_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -544,7 +544,7 @@ fn set_max_outgoing_bitrate_fails_if_value_is_lower_than_current_min_limit() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -582,7 +582,7 @@ fn set_min_outgoing_bitrate_fails_if_value_is_higher_than_current_max_limit() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -620,7 +620,7 @@ fn restart_ice_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -656,7 +656,7 @@ fn enable_trace_event_succeeds() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, @@ -732,7 +732,7 @@ fn close_event() { WebRtcTransportListenInfos::new(ListenInfo { protocol: Protocol::Udp, ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - announced_ip: Some("9.9.9.1".to_string()), + announced_address: Some("9.9.9.1".to_string()), port: None, flags: None, send_buffer_size: None, diff --git a/worker/Cargo.toml b/worker/Cargo.toml index 1a55b6831c..bad31281f0 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup-sys" -version = "0.7.2" +version = "0.8.0" description = "FFI bindings to C++ libmediasoup-worker" authors = ["Nazar Mokrynskyi "] edition = "2021" diff --git a/worker/fbs/transport.fbs b/worker/fbs/transport.fbs index 001661b89f..fee932d964 100644 --- a/worker/fbs/transport.fbs +++ b/worker/fbs/transport.fbs @@ -21,7 +21,7 @@ table SocketFlags { table ListenInfo { protocol: Protocol = UDP; ip: string (required); - announced_ip: string; + announced_address: string; port: uint16 = 0; flags: SocketFlags (required); send_buffer_size: uint32 = 0; @@ -87,7 +87,7 @@ table ConsumeDataRequest { } table Tuple { - local_ip: string (required); + local_address: string (required); local_port: uint16; remote_ip: string; remote_port: uint16; diff --git a/worker/fbs/webRtcTransport.fbs b/worker/fbs/webRtcTransport.fbs index ad0a8e0fc8..4c12fb968c 100644 --- a/worker/fbs/webRtcTransport.fbs +++ b/worker/fbs/webRtcTransport.fbs @@ -86,7 +86,7 @@ enum IceState: uint8 { table IceCandidate { foundation: string (required); priority: uint32; - ip: string (required); + address: string (required); protocol: FBS.Transport.Protocol = UDP; port: uint16; type: IceCandidateType; diff --git a/worker/include/RTC/IceCandidate.hpp b/worker/include/RTC/IceCandidate.hpp index d2349706e0..cb634271b8 100644 --- a/worker/include/RTC/IceCandidate.hpp +++ b/worker/include/RTC/IceCandidate.hpp @@ -35,27 +35,27 @@ namespace RTC public: IceCandidate(RTC::UdpSocket* udpSocket, uint32_t priority) - : foundation("udpcandidate"), priority(priority), ip(udpSocket->GetLocalIp()), + : foundation("udpcandidate"), priority(priority), address(udpSocket->GetLocalIp()), protocol(Protocol::UDP), port(udpSocket->GetLocalPort()) { } - IceCandidate(RTC::UdpSocket* udpSocket, uint32_t priority, std::string& announcedIp) - : foundation("udpcandidate"), priority(priority), ip(announcedIp), protocol(Protocol::UDP), - port(udpSocket->GetLocalPort()) + IceCandidate(RTC::UdpSocket* udpSocket, uint32_t priority, std::string& announcedAddress) + : foundation("udpcandidate"), priority(priority), address(announcedAddress), + protocol(Protocol::UDP), port(udpSocket->GetLocalPort()) { } IceCandidate(RTC::TcpServer* tcpServer, uint32_t priority) - : foundation("tcpcandidate"), priority(priority), ip(tcpServer->GetLocalIp()), + : foundation("tcpcandidate"), priority(priority), address(tcpServer->GetLocalIp()), protocol(Protocol::TCP), port(tcpServer->GetLocalPort()) { } - IceCandidate(RTC::TcpServer* tcpServer, uint32_t priority, std::string& announcedIp) - : foundation("tcpcandidate"), priority(priority), ip(announcedIp), protocol(Protocol::TCP), - port(tcpServer->GetLocalPort()) + IceCandidate(RTC::TcpServer* tcpServer, uint32_t priority, std::string& announcedAddress) + : foundation("tcpcandidate"), priority(priority), address(announcedAddress), + protocol(Protocol::TCP), port(tcpServer->GetLocalPort()) { } @@ -67,7 +67,7 @@ namespace RTC // Others. std::string foundation; uint32_t priority{ 0u }; - std::string ip; + std::string address; Protocol protocol; uint16_t port{ 0u }; CandidateType type{ CandidateType::HOST }; diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index 8d0eed1615..1b0baaa9c3 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -128,7 +128,7 @@ namespace RTC struct ListenInfo { std::string ip; - std::string announcedIp; + std::string announcedAddress; uint16_t port{ 0u }; SocketFlags flags; uint32_t sendBufferSize{ 0u }; diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index d23545051a..9366ba5d54 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -41,7 +41,7 @@ namespace RTC explicit TransportTuple(const TransportTuple* tuple) : hash(tuple->hash), udpSocket(tuple->udpSocket), udpRemoteAddr(tuple->udpRemoteAddr), - tcpConnection(tuple->tcpConnection), localAnnouncedIp(tuple->localAnnouncedIp), + tcpConnection(tuple->tcpConnection), localAnnouncedAddress(tuple->localAnnouncedAddress), protocol(tuple->protocol) { if (protocol == TransportTuple::Protocol::UDP) @@ -92,9 +92,9 @@ namespace RTC return this->hash == tuple->hash; } - void SetLocalAnnouncedIp(std::string& localAnnouncedIp) + void SetLocalAnnouncedAddress(std::string& localAnnouncedAddress) { - this->localAnnouncedIp = localAnnouncedIp; + this->localAnnouncedAddress = localAnnouncedAddress; } void Send(const uint8_t* data, size_t len, RTC::TransportTuple::onSendCallback* cb = nullptr) @@ -243,7 +243,7 @@ namespace RTC RTC::UdpSocket* udpSocket{ nullptr }; struct sockaddr* udpRemoteAddr{ nullptr }; RTC::TcpConnection* tcpConnection{ nullptr }; - std::string localAnnouncedIp; + std::string localAnnouncedAddress; // Others. struct sockaddr_storage udpRemoteAddrStorage { diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index ea8fe12e71..96bde6e277 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -28,14 +28,15 @@ namespace RTC struct UdpSocketOrTcpServer { // Expose a constructor to use vector.emplace_back(). - UdpSocketOrTcpServer(RTC::UdpSocket* udpSocket, RTC::TcpServer* tcpServer, std::string& announcedIp) - : udpSocket(udpSocket), tcpServer(tcpServer), announcedIp(announcedIp) + UdpSocketOrTcpServer( + RTC::UdpSocket* udpSocket, RTC::TcpServer* tcpServer, std::string& announcedAddress) + : udpSocket(udpSocket), tcpServer(tcpServer), announcedAddress(announcedAddress) { } RTC::UdpSocket* udpSocket; RTC::TcpServer* tcpServer; - std::string announcedIp; + std::string announcedAddress; }; private: diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index e88047980c..31c7a1e484 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -153,7 +153,7 @@ namespace RTC WebRtcTransportListener* webRtcTransportListener{ nullptr }; // Allocated by this. RTC::IceServer* iceServer{ nullptr }; - // Map of UdpSocket/TcpServer and local announced IP (if any). + // Map of UdpSocket/TcpServer and local announced address (if any). absl::flat_hash_map udpSockets; absl::flat_hash_map tcpServers; RTC::DtlsTransport* dtlsTransport{ nullptr }; diff --git a/worker/src/RTC/IceCandidate.cpp b/worker/src/RTC/IceCandidate.cpp index d3e23ee978..07e603d79a 100644 --- a/worker/src/RTC/IceCandidate.cpp +++ b/worker/src/RTC/IceCandidate.cpp @@ -69,8 +69,8 @@ namespace RTC this->foundation.c_str(), // priority. this->priority, - // ip. - this->ip.c_str(), + // address. + this->address.c_str(), // protocol. protocol, // port. diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index ff39616228..07fc5b538b 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -40,14 +40,16 @@ namespace RTC // This may throw. Utils::IP::NormalizeIp(this->listenInfo.ip); - if (flatbuffers::IsFieldPresent(options->listenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) + if (flatbuffers::IsFieldPresent( + options->listenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDADDRESS)) { - this->listenInfo.announcedIp.assign(options->listenInfo()->announcedIp()->str()); + this->listenInfo.announcedAddress.assign(options->listenInfo()->announcedAddress()->str()); } - if (flatbuffers::IsFieldPresent(options->listenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) + if (flatbuffers::IsFieldPresent( + options->listenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDADDRESS)) { - this->listenInfo.announcedIp.assign(options->listenInfo()->announcedIp()->str()); + this->listenInfo.announcedAddress.assign(options->listenInfo()->announcedAddress()->str()); } this->listenInfo.port = options->listenInfo()->port(); @@ -151,13 +153,13 @@ namespace RTC { std::string localIp; - if (this->listenInfo.announcedIp.empty()) + if (this->listenInfo.announcedAddress.empty()) { localIp = this->udpSocket->GetLocalIp(); } else { - localIp = this->listenInfo.announcedIp; + localIp = this->listenInfo.announcedAddress; } tuple = FBS::Transport::CreateTupleDirect( @@ -202,13 +204,13 @@ namespace RTC { std::string localIp; - if (this->listenInfo.announcedIp.empty()) + if (this->listenInfo.announcedAddress.empty()) { localIp = this->udpSocket->GetLocalIp(); } else { - localIp = this->listenInfo.announcedIp; + localIp = this->listenInfo.announcedAddress; } tuple = FBS::Transport::CreateTupleDirect( @@ -408,9 +410,9 @@ namespace RTC this->tuple = new RTC::TransportTuple( this->udpSocket, reinterpret_cast(&this->remoteAddrStorage)); - if (!this->listenInfo.announcedIp.empty()) + if (!this->listenInfo.announcedAddress.empty()) { - this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + this->tuple->SetLocalAnnouncedAddress(this->listenInfo.announcedAddress); } } catch (const MediaSoupError& error) diff --git a/worker/src/RTC/PlainTransport.cpp b/worker/src/RTC/PlainTransport.cpp index f6da989dd3..2c8c14dfc4 100644 --- a/worker/src/RTC/PlainTransport.cpp +++ b/worker/src/RTC/PlainTransport.cpp @@ -47,9 +47,10 @@ namespace RTC // This may throw. Utils::IP::NormalizeIp(this->listenInfo.ip); - if (flatbuffers::IsFieldPresent(options->listenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) + if (flatbuffers::IsFieldPresent( + options->listenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDADDRESS)) { - this->listenInfo.announcedIp.assign(options->listenInfo()->announcedIp()->str()); + this->listenInfo.announcedAddress.assign(options->listenInfo()->announcedAddress()->str()); } this->listenInfo.port = options->listenInfo()->port(); @@ -77,9 +78,10 @@ namespace RTC Utils::IP::NormalizeIp(this->rtcpListenInfo.ip); if (flatbuffers::IsFieldPresent( - options->rtcpListenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) + options->rtcpListenInfo(), FBS::Transport::ListenInfo::VT_ANNOUNCEDADDRESS)) { - this->rtcpListenInfo.announcedIp.assign(options->rtcpListenInfo()->announcedIp()->str()); + this->rtcpListenInfo.announcedAddress.assign( + options->rtcpListenInfo()->announcedAddress()->str()); } this->rtcpListenInfo.port = options->rtcpListenInfo()->port(); @@ -254,13 +256,13 @@ namespace RTC { std::string localIp; - if (this->listenInfo.announcedIp.empty()) + if (this->listenInfo.announcedAddress.empty()) { localIp = this->udpSocket->GetLocalIp(); } else { - localIp = this->listenInfo.announcedIp; + localIp = this->listenInfo.announcedAddress; } tuple = FBS::Transport::CreateTupleDirect( @@ -285,13 +287,13 @@ namespace RTC { std::string localIp; - if (this->rtcpListenInfo.announcedIp.empty()) + if (this->rtcpListenInfo.announcedAddress.empty()) { localIp = this->rtcpUdpSocket->GetLocalIp(); } else { - localIp = this->rtcpListenInfo.announcedIp; + localIp = this->rtcpListenInfo.announcedAddress; } rtcpTuple = FBS::Transport::CreateTupleDirect( @@ -336,13 +338,13 @@ namespace RTC { std::string localIp; - if (this->listenInfo.announcedIp.empty()) + if (this->listenInfo.announcedAddress.empty()) { localIp = this->udpSocket->GetLocalIp(); } else { - localIp = this->listenInfo.announcedIp; + localIp = this->listenInfo.announcedAddress; } tuple = FBS::Transport::CreateTupleDirect( @@ -605,9 +607,9 @@ namespace RTC this->tuple = new RTC::TransportTuple( this->udpSocket, reinterpret_cast(&this->remoteAddrStorage)); - if (!this->listenInfo.announcedIp.empty()) + if (!this->listenInfo.announcedAddress.empty()) { - this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + this->tuple->SetLocalAnnouncedAddress(this->listenInfo.announcedAddress); } if (!this->rtcpMux) @@ -655,9 +657,9 @@ namespace RTC this->rtcpUdpSocket, reinterpret_cast(&this->rtcpRemoteAddrStorage)); - if (!this->rtcpListenInfo.announcedIp.empty()) + if (!this->rtcpListenInfo.announcedAddress.empty()) { - this->rtcpTuple->SetLocalAnnouncedIp(this->rtcpListenInfo.announcedIp); + this->rtcpTuple->SetLocalAnnouncedAddress(this->rtcpListenInfo.announcedAddress); } } } @@ -980,9 +982,9 @@ namespace RTC this->tuple = new RTC::TransportTuple(tuple); - if (!this->listenInfo.announcedIp.empty()) + if (!this->listenInfo.announcedAddress.empty()) { - this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + this->tuple->SetLocalAnnouncedAddress(this->listenInfo.announcedAddress); } // If not yet connected do it now. @@ -1045,9 +1047,9 @@ namespace RTC this->tuple = new RTC::TransportTuple(tuple); - if (!this->listenInfo.announcedIp.empty()) + if (!this->listenInfo.announcedAddress.empty()) { - this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + this->tuple->SetLocalAnnouncedAddress(this->listenInfo.announcedAddress); } // If not yet connected do it now. @@ -1074,9 +1076,9 @@ namespace RTC this->rtcpTuple = new RTC::TransportTuple(tuple); - if (!this->rtcpListenInfo.announcedIp.empty()) + if (!this->rtcpListenInfo.announcedAddress.empty()) { - this->rtcpTuple->SetLocalAnnouncedIp(this->rtcpListenInfo.announcedIp); + this->rtcpTuple->SetLocalAnnouncedAddress(this->rtcpListenInfo.announcedAddress); } // Notify the Node PlainTransport. @@ -1131,9 +1133,9 @@ namespace RTC this->tuple = new RTC::TransportTuple(tuple); - if (!this->listenInfo.announcedIp.empty()) + if (!this->listenInfo.announcedAddress.empty()) { - this->tuple->SetLocalAnnouncedIp(this->listenInfo.announcedIp); + this->tuple->SetLocalAnnouncedAddress(this->listenInfo.announcedAddress); } // If not yet connected do it now. diff --git a/worker/src/RTC/TransportTuple.cpp b/worker/src/RTC/TransportTuple.cpp index 12f045e49c..3055e8c2a9 100644 --- a/worker/src/RTC/TransportTuple.cpp +++ b/worker/src/RTC/TransportTuple.cpp @@ -46,8 +46,6 @@ namespace RTC Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort); - localIp = this->localAnnouncedIp.empty() ? localIp : this->localAnnouncedIp; - std::string remoteIp; uint16_t remotePort; @@ -56,7 +54,12 @@ namespace RTC auto protocol = TransportTuple::ProtocolToFbs(GetProtocol()); return FBS::Transport::CreateTupleDirect( - builder, localIp.c_str(), localPort, remoteIp.c_str(), remotePort, protocol); + builder, + (this->localAnnouncedAddress.empty() ? localIp : this->localAnnouncedAddress).c_str(), + localPort, + remoteIp.c_str(), + remotePort, + protocol); } void TransportTuple::Dump() const diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 0a4c027d40..bd1c095c13 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -77,11 +77,11 @@ namespace RTC // This may throw. Utils::IP::NormalizeIp(ip); - std::string announcedIp; + std::string announcedAddress; - if (flatbuffers::IsFieldPresent(listenInfo, FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) + if (flatbuffers::IsFieldPresent(listenInfo, FBS::Transport::ListenInfo::VT_ANNOUNCEDADDRESS)) { - announcedIp = listenInfo->announcedIp()->str(); + announcedAddress = listenInfo->announcedAddress()->str(); } RTC::Transport::SocketFlags flags; @@ -103,7 +103,7 @@ namespace RTC udpSocket = new RTC::UdpSocket(this, ip, flags); } - this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, announcedIp); + this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, announcedAddress); if (listenInfo->sendBufferSize() != 0) { @@ -135,7 +135,7 @@ namespace RTC tcpServer = new RTC::TcpServer(this, this, ip, flags); } - this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, announcedIp); + this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, announcedAddress); if (listenInfo->sendBufferSize() != 0) { @@ -310,14 +310,14 @@ namespace RTC const uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); - if (item.announcedIp.empty()) + if (item.announcedAddress.empty()) { iceCandidates.emplace_back(item.udpSocket, icePriority); } else { iceCandidates.emplace_back( - item.udpSocket, icePriority, const_cast(item.announcedIp)); + item.udpSocket, icePriority, const_cast(item.announcedAddress)); } } else if (item.tcpServer && enableTcp) @@ -331,14 +331,14 @@ namespace RTC const uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); - if (item.announcedIp.empty()) + if (item.announcedAddress.empty()) { iceCandidates.emplace_back(item.tcpServer, icePriority); } else { iceCandidates.emplace_back( - item.tcpServer, icePriority, const_cast(item.announcedIp)); + item.tcpServer, icePriority, const_cast(item.announcedAddress)); } } diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index e699a26ed5..c718c1179a 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -55,11 +55,11 @@ namespace RTC // This may throw. Utils::IP::NormalizeIp(ip); - std::string announcedIp; + std::string announcedAddress; - if (flatbuffers::IsFieldPresent(listenInfo, FBS::Transport::ListenInfo::VT_ANNOUNCEDIP)) + if (flatbuffers::IsFieldPresent(listenInfo, FBS::Transport::ListenInfo::VT_ANNOUNCEDADDRESS)) { - announcedIp = listenInfo->announcedIp()->str(); + announcedAddress = listenInfo->announcedAddress()->str(); } RTC::Transport::SocketFlags flags; @@ -84,15 +84,15 @@ namespace RTC udpSocket = new RTC::UdpSocket(this, ip, flags); } - this->udpSockets[udpSocket] = announcedIp; + this->udpSockets[udpSocket] = announcedAddress; - if (announcedIp.empty()) + if (announcedAddress.empty()) { this->iceCandidates.emplace_back(udpSocket, icePriority); } else { - this->iceCandidates.emplace_back(udpSocket, icePriority, announcedIp); + this->iceCandidates.emplace_back(udpSocket, icePriority, announcedAddress); } if (listenInfo->sendBufferSize() != 0) @@ -126,15 +126,15 @@ namespace RTC tcpServer = new RTC::TcpServer(this, this, ip, flags); } - this->tcpServers[tcpServer] = announcedIp; + this->tcpServers[tcpServer] = announcedAddress; - if (announcedIp.empty()) + if (announcedAddress.empty()) { this->iceCandidates.emplace_back(tcpServer, icePriority); } else { - this->iceCandidates.emplace_back(tcpServer, icePriority, announcedIp); + this->iceCandidates.emplace_back(tcpServer, icePriority, announcedAddress); } if (listenInfo->sendBufferSize() != 0) From 5775affed2193fe6664d52fd80468918a4d4cfe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 5 Feb 2024 10:44:39 +0100 Subject: [PATCH 343/525] Cleanup remaining payload channel references (#1326) Cleanup remaining payload channel references --- rust/src/worker/utils.rs | 2 -- worker/include/Channel/ChannelNotifier.hpp | 3 +-- worker/include/lib.hpp | 2 -- worker/src/Channel/ChannelSocket.cpp | 2 +- worker/src/lib.cpp | 2 -- worker/src/lib.rs | 2 -- worker/src/main.cpp | 14 +------------- 7 files changed, 3 insertions(+), 24 deletions(-) diff --git a/rust/src/worker/utils.rs b/rust/src/worker/utils.rs index fbbd2e1c38..b04d74acee 100644 --- a/rust/src/worker/utils.rs +++ b/rust/src/worker/utils.rs @@ -80,8 +80,6 @@ where version.as_ptr(), 0, 0, - 0, - 0, channel_read_fn, channel_read_ctx, channel_write_fn, diff --git a/worker/include/Channel/ChannelNotifier.hpp b/worker/include/Channel/ChannelNotifier.hpp index 098b4366df..c896ca3958 100644 --- a/worker/include/Channel/ChannelNotifier.hpp +++ b/worker/include/Channel/ChannelNotifier.hpp @@ -25,7 +25,7 @@ namespace Channel FBS::Notification::Body type, flatbuffers::Offset& body) { - auto& builder = ChannelNotifier::bufferBuilder; + auto& builder = this->bufferBuilder; auto notification = FBS::Notification::CreateNotificationDirect( builder, targetId.c_str(), event, type, body.Union()); @@ -50,7 +50,6 @@ namespace Channel this->channel->Send(builder.GetBufferPointer(), builder.GetSize()); builder.Reset(); } - void Emit(const FBS::Notification::Notification& notification); private: // Passed by argument. diff --git a/worker/include/lib.hpp b/worker/include/lib.hpp index 513e354b7d..8656a3c7df 100644 --- a/worker/include/lib.hpp +++ b/worker/include/lib.hpp @@ -6,8 +6,6 @@ extern "C" int mediasoup_worker_run( const char* version, int consumerChannelFd, int producerChannelFd, - int payloadConsumeChannelFd, - int payloadProduceChannelFd, ChannelReadFn channelReadFn, ChannelReadCtx channelReadCtx, ChannelWriteFn channelWriteFn, diff --git a/worker/src/Channel/ChannelSocket.cpp b/worker/src/Channel/ChannelSocket.cpp index 556072df7b..058d7b21b4 100644 --- a/worker/src/Channel/ChannelSocket.cpp +++ b/worker/src/Channel/ChannelSocket.cpp @@ -137,7 +137,7 @@ namespace Channel return; } - SendImpl(reinterpret_cast(data), dataLen); + SendImpl(data, dataLen); } void ChannelSocket::SendLog(const char* data, uint32_t dataLen) diff --git a/worker/src/lib.cpp b/worker/src/lib.cpp index d4f7a253b0..8387e5f35f 100644 --- a/worker/src/lib.cpp +++ b/worker/src/lib.cpp @@ -32,8 +32,6 @@ extern "C" int mediasoup_worker_run( const char* version, int consumerChannelFd, int producerChannelFd, - int /*payloadConsumeChannelFd*/, - int /*payloadProduceChannelFd*/, ChannelReadFn channelReadFn, ChannelReadCtx channelReadCtx, ChannelWriteFn channelWriteFn, diff --git a/worker/src/lib.rs b/worker/src/lib.rs index ad666d36a6..60bd8131ff 100644 --- a/worker/src/lib.rs +++ b/worker/src/lib.rs @@ -51,8 +51,6 @@ extern "C" { version: *const c_char, consumer_channel_fd: c_int, producer_channel_fd: c_int, - payload_consumer_channel_fd: c_int, - payload_producer_channel_fd: c_int, channel_read_fn: ChannelReadFn, channel_read_ctx: ChannelReadCtx, channel_write_fn: ChannelWriteFn, diff --git a/worker/src/main.cpp b/worker/src/main.cpp index 648565f80c..55f46c19c3 100644 --- a/worker/src/main.cpp +++ b/worker/src/main.cpp @@ -8,8 +8,6 @@ static constexpr int ConsumerChannelFd{ 3 }; static constexpr int ProducerChannelFd{ 4 }; -static constexpr int PayloadConsumerChannelFd{ 5 }; -static constexpr int PayloadProducerChannelFd{ 6 }; int main(int argc, char* argv[]) { @@ -25,17 +23,7 @@ int main(int argc, char* argv[]) const std::string version = std::getenv("MEDIASOUP_VERSION"); auto statusCode = mediasoup_worker_run( - argc, - argv, - version.c_str(), - ConsumerChannelFd, - ProducerChannelFd, - PayloadConsumerChannelFd, - PayloadProducerChannelFd, - nullptr, - nullptr, - nullptr, - nullptr); + argc, argv, version.c_str(), ConsumerChannelFd, ProducerChannelFd, nullptr, nullptr, nullptr, nullptr); std::_Exit(statusCode); } From c621b298b121a9ae8799d330cc5d02485a49b506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 5 Feb 2024 12:37:05 +0100 Subject: [PATCH 344/525] CI: Add macos-14 (#1328) --- .github/workflows/mediasoup-node.yaml | 2 + .github/workflows/mediasoup-rust.yaml | 1 + .../workflows/mediasoup-worker-prebuild.yaml | 3 + .github/workflows/mediasoup-worker.yaml | 2 +- CHANGELOG.md | 1 + node/tsconfig.json | 6 +- npm-scripts.mjs | 45 --------------- package-lock.json | 56 +++++++++---------- package.json | 11 ++-- 9 files changed, 44 insertions(+), 83 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 3cda494ef0..1c66a6e855 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -20,6 +20,8 @@ jobs: - os: ubuntu-22.04 node: 20 - os: macos-12 + node: 18 + - os: macos-14 node: 20 - os: windows-2022 node: 20 diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index f77892891d..5622ccc573 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -19,6 +19,7 @@ jobs: - ubuntu-20.04 - ubuntu-22.04 - macos-12 + - macos-14 - windows-2022 runs-on: ${{ matrix.os }} diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 6771289401..4b6f61c532 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -25,6 +25,9 @@ jobs: - os: macos-12 cc: clang cxx: clang++ + - os: macos-14 + cc: clang + cxx: clang++ - os: windows-2022 cc: cl cxx: cl diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 6192e75475..0ff40d5497 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -28,7 +28,7 @@ jobs: - os: macos-12 cc: gcc cxx: g++ - - os: macos-12 + - os: macos-14 cc: clang cxx: clang++ - os: windows-2022 diff --git a/CHANGELOG.md b/CHANGELOG.md index ae8bd5082b..9c4f3d7816 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Make transport-cc feedback work similarly to libwebrtc ([PR #1088](https://github.com/versatica/mediasoup/pull/1088) by @penguinol). - `TransportListenInfo`: "announced ip" can also be a hostname ([PR #1322](https://github.com/versatica/mediasoup/pull/1322)). - `TransportListenInfo`: Rename "announced ip" to "announced address" ([PR #1324](https://github.com/versatica/mediasoup/pull/1324)). +- CI: Add `macos-14`. ### 3.13.17 diff --git a/node/tsconfig.json b/node/tsconfig.json index 93b6d29477..87394576c7 100644 --- a/node/tsconfig.json +++ b/node/tsconfig.json @@ -8,13 +8,13 @@ "strict": true, "outDir": "lib", "declaration": true, - "declarationMap": true, + "declarationMap": true }, "include": ["src"], "watchOptions": { "watchFile": "useFsEvents", "watchDirectory": "useFsEvents", "fallbackPolling": "dynamicPriority", - "synchronousWatchDirectory": true, - }, + "synchronousWatchDirectory": true + } } diff --git a/npm-scripts.mjs b/npm-scripts.mjs index aab6a7a44c..56405fea8e 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -228,27 +228,11 @@ async function run() { draft: false, }); - // GitHub mediasoup-worker-prebuild CI action doesn't create mediasoup-worker - // prebuilt binary for macOS ARM. If this is a macOS ARM machine, do it here - // and upload it to the release. - if (os.platform() === 'darwin' && os.arch() === 'arm64') { - await prebuildWorker(); - await uploadMacArmPrebuiltWorker(); - } - executeCmd('npm publish'); break; } - case 'release:upload-mac-arm-prebuilt-worker': { - checkRelease(); - await prebuildWorker(); - await uploadMacArmPrebuiltWorker(); - - break; - } - default: { logError('unknown task'); @@ -597,35 +581,6 @@ async function downloadPrebuiltWorker() { }); } -async function uploadMacArmPrebuiltWorker() { - if (os.platform() !== 'darwin' || os.arch() !== 'arm64') { - logError('uploadMacArmPrebuiltWorker() | invalid platform or architecture'); - - exitWithError(); - } - - const octokit = await getOctokit(); - - logInfo('uploadMacArmPrebuiltWorker() | getting release info'); - - const release = await octokit.rest.repos.getReleaseByTag({ - owner: GH_OWNER, - repo: GH_REPO, - tag: PKG.version, - }); - - logInfo('uploadMacArmPrebuiltWorker() | uploading release asset'); - - await octokit.rest.repos.uploadReleaseAsset({ - owner: GH_OWNER, - repo: GH_REPO, - // eslint-disable-next-line camelcase - release_id: release.data.id, - name: WORKER_PREBUILD_TAR, - data: fs.readFileSync(WORKER_PREBUILD_TAR_PATH), - }); -} - async function getOctokit() { if (!process.env.GITHUB_TOKEN) { throw new Error('missing GITHUB_TOKEN environment variable'); diff --git a/package-lock.json b/package-lock.json index b22ffce243..9f6828b52d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,8 @@ "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.11", - "@types/node": "^20.11.15", + "@types/jest": "^29.5.12", + "@types/node": "^20.11.16", "@typescript-eslint/eslint-plugin": "^6.20.0", "@typescript-eslint/parser": "^6.20.0", "eslint": "^8.56.0", @@ -29,10 +29,10 @@ "eslint-plugin-jest": "^27.6.3", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^11.2.0", + "marked": "^12.0.0", "open-cli": "^8.0.0", "pick-port": "^2.0.1", - "prettier": "^3.2.4", + "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", "typescript": "^5.3.3" @@ -1605,9 +1605,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.11", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", - "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1626,9 +1626,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.15.tgz", - "integrity": "sha512-gscmuADZfvNULx1eyirVbr3kVOVZtpQtzKMCZpeSZcN6MfbkRXAR4s9/gsQ4CzxLHw6EStDtKLNtSDL3vbq05A==", + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -4731,9 +4731,9 @@ } }, "node_modules/marked": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz", - "integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.0.tgz", + "integrity": "sha512-Vkwtq9rLqXryZnWaQc86+FHLC6tr/fycMfYAhiOIXkrNmeGAyhSxjqu0Rs1i0bBqw5u0S7+lV9fdH2ZSVaoa0w==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -5248,9 +5248,9 @@ } }, "node_modules/prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -7493,9 +7493,9 @@ } }, "@types/jest": { - "version": "29.5.11", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", - "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", "dev": true, "requires": { "expect": "^29.0.0", @@ -7514,9 +7514,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.15.tgz", - "integrity": "sha512-gscmuADZfvNULx1eyirVbr3kVOVZtpQtzKMCZpeSZcN6MfbkRXAR4s9/gsQ4CzxLHw6EStDtKLNtSDL3vbq05A==", + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -9688,9 +9688,9 @@ } }, "marked": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz", - "integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.0.tgz", + "integrity": "sha512-Vkwtq9rLqXryZnWaQc86+FHLC6tr/fycMfYAhiOIXkrNmeGAyhSxjqu0Rs1i0bBqw5u0S7+lV9fdH2ZSVaoa0w==", "dev": true }, "meow": { @@ -10044,9 +10044,9 @@ "dev": true }, "prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true }, "prettier-linter-helpers": { diff --git a/package.json b/package.json index 233ff82afa..61f0a77b02 100644 --- a/package.json +++ b/package.json @@ -69,8 +69,7 @@ "test:worker": "node npm-scripts.mjs test:worker", "coverage:node": "node npm-scripts.mjs coverage:node", "release:check": "node npm-scripts.mjs release:check", - "release": "node npm-scripts.mjs release", - "release:upload-mac-arm-prebuilt-worker": "node npm-scripts.mjs release:upload-mac-arm-prebuilt-worker" + "release": "node npm-scripts.mjs release" }, "jest": { "verbose": true, @@ -110,8 +109,8 @@ "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.11", - "@types/node": "^20.11.15", + "@types/jest": "^29.5.12", + "@types/node": "^20.11.16", "@typescript-eslint/eslint-plugin": "^6.20.0", "@typescript-eslint/parser": "^6.20.0", "eslint": "^8.56.0", @@ -119,10 +118,10 @@ "eslint-plugin-jest": "^27.6.3", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^11.2.0", + "marked": "^12.0.0", "open-cli": "^8.0.0", "pick-port": "^2.0.1", - "prettier": "^3.2.4", + "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", "typescript": "^5.3.3" From 482afa4484ef6defc83ca05269ed8685d18390a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 5 Feb 2024 12:40:13 +0100 Subject: [PATCH 345/525] 3.13.18 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c4f3d7816..f6d65148bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### NEXT +### 3.13.18 - Make transport-cc feedback work similarly to libwebrtc ([PR #1088](https://github.com/versatica/mediasoup/pull/1088) by @penguinol). - `TransportListenInfo`: "announced ip" can also be a hostname ([PR #1322](https://github.com/versatica/mediasoup/pull/1322)). diff --git a/package-lock.json b/package-lock.json index 9f6828b52d..54bb599fd3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.17", + "version": "3.13.18", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.17", + "version": "3.13.18", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 61f0a77b02..964ae71b0f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.17", + "version": "3.13.18", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From bf7a3973f93282a3d296c8702ddad53c368076a8 Mon Sep 17 00:00:00 2001 From: Paul Olteanu Date: Mon, 5 Feb 2024 13:17:01 -0500 Subject: [PATCH 346/525] Add Send and Sync to dyn Errors (#1329) --- rust/src/messages.rs | 146 ++++++++++++++-------------- rust/src/ortc.rs | 6 +- rust/src/router/consumer.rs | 20 ++-- rust/src/router/data_consumer.rs | 4 +- rust/src/router/data_producer.rs | 4 +- rust/src/router/direct_transport.rs | 18 ++-- rust/src/router/pipe_transport.rs | 18 ++-- rust/src/router/plain_transport.rs | 18 ++-- rust/src/router/producer.rs | 8 +- rust/src/router/transport.rs | 16 +-- rust/src/router/webrtc_transport.rs | 18 ++-- rust/src/rtp_parameters.rs | 14 +-- rust/src/worker.rs | 2 +- 13 files changed, 158 insertions(+), 134 deletions(-) diff --git a/rust/src/messages.rs b/rust/src/messages.rs index 0dc8f57f06..c05eed1e08 100644 --- a/rust/src/messages.rs +++ b/rust/src/messages.rs @@ -64,7 +64,7 @@ where /// Convert generic response into specific type of this request. fn convert_response( response: Option>, - ) -> Result>; + ) -> Result>; } pub(crate) trait Notification: Debug { @@ -102,7 +102,7 @@ impl Request for WorkerCloseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -133,7 +133,7 @@ impl Request for WorkerDumpRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::WorkerDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -215,7 +215,7 @@ impl Request for WorkerUpdateSettingsRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -255,7 +255,7 @@ impl Request for WorkerCreateWebRtcServerRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -294,7 +294,7 @@ impl Request for WebRtcServerCloseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -325,7 +325,7 @@ impl Request for WebRtcServerDumpRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::WebRtcServerDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -407,7 +407,7 @@ impl Request for WorkerCreateRouterRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -442,7 +442,7 @@ impl Request for RouterCloseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -473,7 +473,7 @@ impl Request for RouterDumpRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::RouterDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -486,12 +486,12 @@ impl Request for RouterDumpRequest { .map_consumer_id_producer_id .into_iter() .map(|key_value| Ok((key_value.key.parse()?, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, map_data_consumer_id_data_producer_id: data .map_data_consumer_id_data_producer_id .into_iter() .map(|key_value| Ok((key_value.key.parse()?, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, map_data_producer_id_data_consumer_ids: data .map_data_producer_id_data_consumer_ids .into_iter() @@ -505,7 +505,7 @@ impl Request for RouterDumpRequest { .collect::>()?, )) }) - .collect::>>()?, + .collect::>>()?, map_producer_id_consumer_ids: data .map_producer_id_consumer_ids .into_iter() @@ -519,7 +519,7 @@ impl Request for RouterDumpRequest { .collect::>()?, )) }) - .collect::>>()?, + .collect::>>()?, map_producer_id_observer_ids: data .map_producer_id_observer_ids .into_iter() @@ -533,7 +533,7 @@ impl Request for RouterDumpRequest { .collect::>()?, )) }) - .collect::>>()?, + .collect::>>()?, rtp_observer_ids: data .rtp_observer_ids .into_iter() @@ -618,7 +618,7 @@ impl Request for RouterCreateDirectTransportRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -784,7 +784,7 @@ impl Request for RouterCreateWebRtcTransportRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::WebRtcTransportDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -861,7 +861,7 @@ impl Request for RouterCreateWebRtcTransportWithServerRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::WebRtcTransportDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -994,7 +994,7 @@ impl Request for RouterCreatePlainTransportRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::PlainTransportDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -1120,7 +1120,7 @@ impl Request for RouterCreatePipeTransportRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::PipeTransportDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -1221,7 +1221,7 @@ impl Request for RouterCreateAudioLevelObserverRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -1286,7 +1286,7 @@ impl Request for RouterCreateActiveSpeakerObserverRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -1317,7 +1317,7 @@ impl Request for TransportDumpRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { match response { Some(data) => Ok(data.try_into().unwrap()), _ => { @@ -1352,7 +1352,7 @@ impl Request for TransportGetStatsRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { match response { Some(data) => Ok(data.try_into().unwrap()), _ => { @@ -1393,7 +1393,7 @@ impl Request for TransportCloseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -1434,7 +1434,7 @@ impl Request for WebRtcTransportConnectRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::WebRtcTransportConnectResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -1488,7 +1488,7 @@ impl Request for PipeTransportConnectRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::PipeTransportConnectResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -1547,7 +1547,7 @@ impl Request for TransportConnectPlainRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::PlainTransportConnectResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -1597,7 +1597,7 @@ impl Request for TransportSetMaxIncomingBitrateRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -1633,7 +1633,7 @@ impl Request for TransportSetMaxOutgoingBitrateRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -1669,7 +1669,7 @@ impl Request for TransportSetMinOutgoingBitrateRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -1699,7 +1699,7 @@ impl Request for TransportRestartIceRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::TransportRestartIceResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -1761,7 +1761,7 @@ impl Request for TransportProduceRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::TransportProduceResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -1833,7 +1833,7 @@ impl Request for TransportConsumeRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::TransportConsumeResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -1915,7 +1915,7 @@ impl Request for TransportProduceDataRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::DataProducerDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -2006,7 +2006,7 @@ impl Request for TransportConsumeDataRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::DataConsumerDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -2067,7 +2067,7 @@ impl Request for TransportEnableTraceEventRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } @@ -2138,7 +2138,7 @@ impl Request for ProducerCloseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2169,7 +2169,7 @@ impl Request for ProducerDumpRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::ProducerDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -2204,7 +2204,7 @@ impl Request for ProducerGetStatsRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { match response { Some(data) => Ok(data.try_into().unwrap()), _ => { @@ -2240,7 +2240,7 @@ impl Request for ProducerPauseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2271,7 +2271,7 @@ impl Request for ProducerResumeRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2313,7 +2313,7 @@ impl Request for ProducerEnableTraceEventRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } @@ -2384,7 +2384,7 @@ impl Request for ConsumerCloseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2415,7 +2415,7 @@ impl Request for ConsumerDumpRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::ConsumerDumpResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -2450,7 +2450,7 @@ impl Request for ConsumerGetStatsRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { match response { Some(data) => Ok(data.try_into().unwrap()), _ => { @@ -2486,7 +2486,7 @@ impl Request for ConsumerPauseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2517,7 +2517,7 @@ impl Request for ConsumerResumeRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2557,7 +2557,7 @@ impl Request for ConsumerSetPreferredLayersRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::ConsumerSetPreferredLayersResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -2607,7 +2607,7 @@ impl Request for ConsumerSetPriorityRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::ConsumerSetPriorityResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -2645,7 +2645,7 @@ impl Request for ConsumerRequestKeyFrameRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2687,7 +2687,7 @@ impl Request for ConsumerEnableTraceEventRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } @@ -2730,7 +2730,7 @@ impl Request for DataProducerCloseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2761,7 +2761,7 @@ impl Request for DataProducerDumpRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { match response { Some(data) => Ok(data.try_into().unwrap()), _ => { @@ -2797,7 +2797,7 @@ impl Request for DataProducerGetStatsRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { match response { Some(data) => Ok(data.try_into().unwrap()), _ => { @@ -2833,7 +2833,7 @@ impl Request for DataProducerPauseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2864,7 +2864,7 @@ impl Request for DataProducerResumeRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2941,7 +2941,7 @@ impl Request for DataConsumerCloseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -2972,7 +2972,7 @@ impl Request for DataConsumerDumpRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { match response { Some(data) => Ok(data.try_into().unwrap()), _ => { @@ -3008,7 +3008,7 @@ impl Request for DataConsumerGetStatsRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { match response { Some(data) => Ok(data.try_into().unwrap()), _ => { @@ -3044,7 +3044,7 @@ impl Request for DataConsumerPauseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -3075,7 +3075,7 @@ impl Request for DataConsumerResumeRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -3111,7 +3111,7 @@ impl Request for DataConsumerGetBufferedAmountRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::DataConsumerGetBufferedAmountResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -3162,7 +3162,7 @@ impl Request for DataConsumerSetBufferedAmountLowThresholdRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -3200,7 +3200,7 @@ impl Request for DataConsumerSendRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -3248,7 +3248,7 @@ impl Request for DataConsumerSetSubchannelsRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::DataConsumerSetSubchannelsResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -3298,7 +3298,7 @@ impl Request for DataConsumerAddSubchannelRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::DataConsumerAddSubchannelResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -3348,7 +3348,7 @@ impl Request for DataConsumerRemoveSubchannelRequest { fn convert_response( response: Option>, - ) -> Result> { + ) -> Result> { let Some(response::BodyRef::DataConsumerRemoveSubchannelResponse(data)) = response else { panic!("Wrong message from worker: {response:?}"); }; @@ -3393,7 +3393,7 @@ impl Request for RtpObserverCloseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -3423,7 +3423,7 @@ impl Request for RtpObserverPauseRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -3453,7 +3453,7 @@ impl Request for RtpObserverResumeRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -3492,7 +3492,7 @@ impl Request for RtpObserverAddProducerRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } @@ -3531,7 +3531,7 @@ impl Request for RtpObserverRemoveProducerRequest { fn convert_response( _response: Option>, - ) -> Result> { + ) -> Result> { Ok(()) } } diff --git a/rust/src/ortc.rs b/rust/src/ortc.rs index 88acf21650..c5dd9ca3b4 100644 --- a/rust/src/ortc.rs +++ b/rust/src/ortc.rs @@ -80,7 +80,7 @@ impl RtpMapping { pub(crate) fn from_fbs_ref( mapping: rtp_parameters::RtpMappingRef<'_>, - ) -> Result> { + ) -> Result> { Ok(Self { codecs: mapping .codecs()? @@ -91,7 +91,7 @@ impl RtpMapping { mapped_payload_type: mapping?.mapped_payload_type()?, }) }) - .collect::, Box>>()?, + .collect::, Box>>()?, encodings: mapping .encodings()? .iter() @@ -107,7 +107,7 @@ impl RtpMapping { mapped_ssrc: mapping?.mapped_ssrc()?, }) }) - .collect::, Box>>()?, + .collect::, Box>>()?, }) } } diff --git a/rust/src/router/consumer.rs b/rust/src/router/consumer.rs index 8aa63ad83e..3914d40b2d 100644 --- a/rust/src/router/consumer.rs +++ b/rust/src/router/consumer.rs @@ -163,7 +163,9 @@ pub struct RtpStreamParams { } impl RtpStreamParams { - pub(crate) fn from_fbs_ref(params: rtp_stream::ParamsRef<'_>) -> Result> { + pub(crate) fn from_fbs_ref( + params: rtp_stream::ParamsRef<'_>, + ) -> Result> { Ok(Self { clock_rate: params.clock_rate()?, cname: params.cname()?.to_string(), @@ -197,7 +199,9 @@ pub struct RtxStreamParams { } impl RtxStreamParams { - pub(crate) fn from_fbs_ref(params: rtx_stream::ParamsRef<'_>) -> Result> { + pub(crate) fn from_fbs_ref( + params: rtx_stream::ParamsRef<'_>, + ) -> Result> { Ok(Self { clock_rate: params.clock_rate()?, cname: params.cname()?.to_string(), @@ -218,7 +222,9 @@ pub struct RtpStream { } impl RtpStream { - pub(crate) fn from_fbs_ref(dump: rtp_stream::DumpRef<'_>) -> Result> { + pub(crate) fn from_fbs_ref( + dump: rtp_stream::DumpRef<'_>, + ) -> Result> { Ok(Self { params: RtpStreamParams::from_fbs_ref(dump.params()?)?, score: dump.score()?, @@ -267,7 +273,7 @@ pub struct ConsumerDump { impl ConsumerDump { pub(crate) fn from_fbs_ref( dump: consumer::DumpResponseRef<'_>, - ) -> Result> { + ) -> Result> { let dump = dump.data(); Ok(Self { @@ -286,7 +292,7 @@ impl ConsumerDump { .trace_event_types()? .iter() .map(|trace_event_type| Ok(ConsumerTraceEventType::from_fbs(trace_event_type?))) - .collect::>>()?, + .collect::>>()?, r#type: ConsumerType::from_fbs(dump?.base()?.type_()?), consumable_rtp_encodings: dump? .base()? @@ -295,12 +301,12 @@ impl ConsumerDump { .map(|encoding_parameters| { RtpEncodingParameters::from_fbs_ref(encoding_parameters?) }) - .collect::>>()?, + .collect::>>()?, rtp_streams: dump? .rtp_streams()? .iter() .map(|stream| RtpStream::from_fbs_ref(stream?)) - .collect::>>()?, + .collect::>>()?, preferred_spatial_layer: dump?.preferred_spatial_layer()?, target_spatial_layer: dump?.target_spatial_layer()?, current_spatial_layer: dump?.current_spatial_layer()?, diff --git a/rust/src/router/data_consumer.rs b/rust/src/router/data_consumer.rs index c00c79cdae..e813f5e858 100644 --- a/rust/src/router/data_consumer.rs +++ b/rust/src/router/data_consumer.rs @@ -163,7 +163,9 @@ pub struct DataConsumerDump { } impl DataConsumerDump { - pub(crate) fn from_fbs(dump: data_consumer::DumpResponse) -> Result> { + pub(crate) fn from_fbs( + dump: data_consumer::DumpResponse, + ) -> Result> { Ok(Self { id: dump.id.parse()?, data_producer_id: dump.data_producer_id.parse()?, diff --git a/rust/src/router/data_producer.rs b/rust/src/router/data_producer.rs index fb6396e49d..590c4c8a6a 100644 --- a/rust/src/router/data_producer.rs +++ b/rust/src/router/data_producer.rs @@ -116,7 +116,9 @@ pub struct DataProducerDump { } impl DataProducerDump { - pub(crate) fn from_fbs(dump: data_producer::DumpResponse) -> Result> { + pub(crate) fn from_fbs( + dump: data_producer::DumpResponse, + ) -> Result> { Ok(Self { id: dump.id.parse()?, r#type: if dump.type_ == data_producer::Type::Sctp { diff --git a/rust/src/router/direct_transport.rs b/rust/src/router/direct_transport.rs index 817a37cd1a..38a6857cf0 100644 --- a/rust/src/router/direct_transport.rs +++ b/rust/src/router/direct_transport.rs @@ -75,7 +75,9 @@ pub struct DirectTransportDump { } impl DirectTransportDump { - pub(crate) fn from_fbs(dump: direct_transport::DumpResponse) -> Result> { + pub(crate) fn from_fbs( + dump: direct_transport::DumpResponse, + ) -> Result> { Ok(Self { id: dump.base.id.parse()?, direct: true, @@ -84,37 +86,37 @@ impl DirectTransportDump { .producer_ids .iter() .map(|producer_id| Ok(producer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, consumer_ids: dump .base .consumer_ids .iter() .map(|consumer_id| Ok(consumer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, map_ssrc_consumer_id: dump .base .map_ssrc_consumer_id .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, map_rtx_ssrc_consumer_id: dump .base .map_rtx_ssrc_consumer_id .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, data_producer_ids: dump .base .data_producer_ids .iter() .map(|data_producer_id| Ok(data_producer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, data_consumer_ids: dump .base .data_consumer_ids .iter() .map(|data_consumer_id| Ok(data_consumer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, recv_rtp_header_extensions: RecvRtpHeaderExtensions::from_fbs( dump.base.recv_rtp_header_extensions.as_ref(), ), @@ -182,7 +184,7 @@ pub struct DirectTransportStat { impl DirectTransportStat { pub(crate) fn from_fbs( stats: direct_transport::GetStatsResponse, - ) -> Result> { + ) -> Result> { Ok(Self { transport_id: stats.base.transport_id.parse()?, timestamp: stats.base.timestamp, diff --git a/rust/src/router/pipe_transport.rs b/rust/src/router/pipe_transport.rs index 633743bc19..613e12b465 100644 --- a/rust/src/router/pipe_transport.rs +++ b/rust/src/router/pipe_transport.rs @@ -106,7 +106,9 @@ pub struct PipeTransportDump { } impl PipeTransportDump { - pub(crate) fn from_fbs(dump: pipe_transport::DumpResponse) -> Result> { + pub(crate) fn from_fbs( + dump: pipe_transport::DumpResponse, + ) -> Result> { Ok(Self { // Common to all Transports. id: dump.base.id.parse()?, @@ -116,37 +118,37 @@ impl PipeTransportDump { .producer_ids .iter() .map(|producer_id| Ok(producer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, consumer_ids: dump .base .consumer_ids .iter() .map(|consumer_id| Ok(consumer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, map_ssrc_consumer_id: dump .base .map_ssrc_consumer_id .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, map_rtx_ssrc_consumer_id: dump .base .map_rtx_ssrc_consumer_id .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, data_producer_ids: dump .base .data_producer_ids .iter() .map(|data_producer_id| Ok(data_producer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, data_consumer_ids: dump .base .data_consumer_ids .iter() .map(|data_consumer_id| Ok(data_consumer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, recv_rtp_header_extensions: RecvRtpHeaderExtensions::from_fbs( dump.base.recv_rtp_header_extensions.as_ref(), ), @@ -223,7 +225,7 @@ pub struct PipeTransportStat { impl PipeTransportStat { pub(crate) fn from_fbs( stats: pipe_transport::GetStatsResponse, - ) -> Result> { + ) -> Result> { Ok(Self { transport_id: stats.base.transport_id.parse()?, timestamp: stats.base.timestamp, diff --git a/rust/src/router/plain_transport.rs b/rust/src/router/plain_transport.rs index 29e436f254..5c6aaa3206 100644 --- a/rust/src/router/plain_transport.rs +++ b/rust/src/router/plain_transport.rs @@ -127,7 +127,9 @@ pub struct PlainTransportDump { } impl PlainTransportDump { - pub(crate) fn from_fbs(dump: plain_transport::DumpResponse) -> Result> { + pub(crate) fn from_fbs( + dump: plain_transport::DumpResponse, + ) -> Result> { Ok(Self { // Common to all Transports. id: dump.base.id.parse()?, @@ -137,37 +139,37 @@ impl PlainTransportDump { .producer_ids .iter() .map(|producer_id| Ok(producer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, consumer_ids: dump .base .consumer_ids .iter() .map(|consumer_id| Ok(consumer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, map_ssrc_consumer_id: dump .base .map_ssrc_consumer_id .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, map_rtx_ssrc_consumer_id: dump .base .map_rtx_ssrc_consumer_id .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, data_producer_ids: dump .base .data_producer_ids .iter() .map(|data_producer_id| Ok(data_producer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, data_consumer_ids: dump .base .data_consumer_ids .iter() .map(|data_consumer_id| Ok(data_consumer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, recv_rtp_header_extensions: RecvRtpHeaderExtensions::from_fbs( dump.base.recv_rtp_header_extensions.as_ref(), ), @@ -251,7 +253,7 @@ pub struct PlainTransportStat { impl PlainTransportStat { pub(crate) fn from_fbs( stats: plain_transport::GetStatsResponse, - ) -> Result> { + ) -> Result> { Ok(Self { transport_id: stats.base.transport_id.parse()?, timestamp: stats.base.timestamp, diff --git a/rust/src/router/producer.rs b/rust/src/router/producer.rs index 1b9d1c7478..8b1a952e37 100644 --- a/rust/src/router/producer.rs +++ b/rust/src/router/producer.rs @@ -108,7 +108,9 @@ pub struct RtpStreamRecv { } impl RtpStreamRecv { - pub(crate) fn from_fbs_ref(dump: rtp_stream::DumpRef<'_>) -> Result> { + pub(crate) fn from_fbs_ref( + dump: rtp_stream::DumpRef<'_>, + ) -> Result> { Ok(Self { params: RtpStreamParams::from_fbs_ref(dump.params()?)?, score: dump.score()?, @@ -141,7 +143,7 @@ pub struct ProducerDump { impl ProducerDump { pub(crate) fn from_fbs_ref( dump: producer::DumpResponseRef<'_>, - ) -> Result> { + ) -> Result> { Ok(Self { id: dump.id()?.parse()?, kind: MediaKind::from_fbs(dump.kind()?), @@ -152,7 +154,7 @@ impl ProducerDump { .rtp_streams()? .iter() .map(|rtp_stream| RtpStreamRecv::from_fbs_ref(rtp_stream?)) - .collect::>>()?, + .collect::>>()?, trace_event_types: dump .trace_event_types()? .iter() diff --git a/rust/src/router/transport.rs b/rust/src/router/transport.rs index feb1d5d012..9e073d026c 100644 --- a/rust/src/router/transport.rs +++ b/rust/src/router/transport.rs @@ -122,23 +122,25 @@ pub struct RtpListener { } impl RtpListener { - pub(crate) fn from_fbs(rtp_listener: &transport::RtpListener) -> Result> { + pub(crate) fn from_fbs( + rtp_listener: &transport::RtpListener, + ) -> Result> { Ok(Self { mid_table: rtp_listener .mid_table .iter() .map(|key_value| Ok((key_value.key.to_string(), key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, rid_table: rtp_listener .rid_table .iter() .map(|key_value| Ok((key_value.key.to_string(), key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, ssrc_table: rtp_listener .ssrc_table .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, }) } } @@ -175,13 +177,15 @@ pub struct SctpListener { } impl SctpListener { - pub(crate) fn from_fbs(listener: &transport::SctpListener) -> Result> { + pub(crate) fn from_fbs( + listener: &transport::SctpListener, + ) -> Result> { Ok(Self { stream_id_table: listener .stream_id_table .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, }) } } diff --git a/rust/src/router/webrtc_transport.rs b/rust/src/router/webrtc_transport.rs index 7218c2a038..a50a9dfa31 100644 --- a/rust/src/router/webrtc_transport.rs +++ b/rust/src/router/webrtc_transport.rs @@ -213,7 +213,9 @@ pub struct WebRtcTransportDump { } impl WebRtcTransportDump { - pub(crate) fn from_fbs(dump: web_rtc_transport::DumpResponse) -> Result> { + pub(crate) fn from_fbs( + dump: web_rtc_transport::DumpResponse, + ) -> Result> { Ok(Self { // Common to all Transports. id: dump.base.id.parse()?, @@ -223,37 +225,37 @@ impl WebRtcTransportDump { .producer_ids .iter() .map(|producer_id| Ok(producer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, consumer_ids: dump .base .consumer_ids .iter() .map(|consumer_id| Ok(consumer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, map_ssrc_consumer_id: dump .base .map_ssrc_consumer_id .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, map_rtx_ssrc_consumer_id: dump .base .map_rtx_ssrc_consumer_id .iter() .map(|key_value| Ok((key_value.key, key_value.value.parse()?))) - .collect::>>()?, + .collect::>>()?, data_producer_ids: dump .base .data_producer_ids .iter() .map(|data_producer_id| Ok(data_producer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, data_consumer_ids: dump .base .data_consumer_ids .iter() .map(|data_consumer_id| Ok(data_consumer_id.parse()?)) - .collect::>>()?, + .collect::>>()?, recv_rtp_header_extensions: RecvRtpHeaderExtensions::from_fbs( dump.base.recv_rtp_header_extensions.as_ref(), ), @@ -342,7 +344,7 @@ pub struct WebRtcTransportStat { impl WebRtcTransportStat { pub(crate) fn from_fbs( stats: web_rtc_transport::GetStatsResponse, - ) -> Result> { + ) -> Result> { Ok(Self { transport_id: stats.base.transport_id.parse()?, timestamp: stats.base.timestamp, diff --git a/rust/src/rtp_parameters.rs b/rust/src/rtp_parameters.rs index e430b3a1f3..cefe8d8c1c 100644 --- a/rust/src/rtp_parameters.rs +++ b/rust/src/rtp_parameters.rs @@ -789,7 +789,7 @@ pub struct RtpParameters { impl RtpParameters { pub(crate) fn from_fbs_ref( rtp_parameters: rtp_parameters::RtpParametersRef<'_>, - ) -> Result> { + ) -> Result> { Ok(Self { mid: rtp_parameters.mid()?.map(|mid| mid.to_string()), codecs: rtp_parameters @@ -824,7 +824,7 @@ impl RtpParameters { }, )) }) - .collect::>>()?; + .collect::>>()?; let rtcp_feedback = codec? .rtcp_feedback()? .unwrap_or(planus::Vector::new_empty()) @@ -835,7 +835,7 @@ impl RtpParameters { rtcp_feedback?.parameter()?.unwrap_or_default(), )?) }) - .collect::>>()?; + .collect::>>()?; Ok(match MimeType::from_str(codec?.mime_type()?)? { MimeType::Audio(mime_type) => RtpCodecParameters::Audio { @@ -858,7 +858,7 @@ impl RtpParameters { }, }) }) - .collect::>>()?, + .collect::>>()?, header_extensions: rtp_parameters .header_extensions()? .into_iter() @@ -869,7 +869,7 @@ impl RtpParameters { encrypt: header_extension_parameters?.encrypt()?, }) }) - .collect::>>()?, + .collect::>>()?, encodings: rtp_parameters .encodings()? .into_iter() @@ -894,7 +894,7 @@ impl RtpParameters { max_bitrate: encoding?.max_bitrate()?, }) }) - .collect::>>()?, + .collect::>>()?, rtcp: RtcpParameters { cname: rtp_parameters .rtcp()? @@ -1310,7 +1310,7 @@ impl RtpEncodingParameters { pub(crate) fn from_fbs_ref( encoding_parameters: rtp_parameters::RtpEncodingParametersRef<'_>, - ) -> Result> { + ) -> Result> { Ok(Self { ssrc: encoding_parameters.ssrc()?, rid: encoding_parameters.rid()?.map(|rid| rid.to_string()), diff --git a/rust/src/worker.rs b/rust/src/worker.rs index 632cb08750..f233b72aa3 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -67,7 +67,7 @@ pub enum RequestError { NoData, /// Response conversion error. #[error("Response conversion error: {0}")] - ResponseConversion(Box), + ResponseConversion(Box), } /// Logging level for logs generated by the media worker thread (check the From 1e8eeb44f57a11e404bbd7f0bfeb1dbc89c5b2b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 7 Feb 2024 12:31:03 +0100 Subject: [PATCH 347/525] Update NPM eslint deps --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 964ae71b0f..9125be4acb 100644 --- a/package.json +++ b/package.json @@ -111,8 +111,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.11.16", - "@typescript-eslint/eslint-plugin": "^6.20.0", - "@typescript-eslint/parser": "^6.20.0", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.6.3", From f5438aab2be69414fe9723d8d4ab82ff7649054e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 12 Feb 2024 16:29:18 +0100 Subject: [PATCH 348/525] Update npm dev deps --- package-lock.json | 346 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 174 insertions(+), 174 deletions(-) diff --git a/package-lock.json b/package-lock.json index 54bb599fd3..962623e411 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,9 +21,9 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.16", - "@typescript-eslint/eslint-plugin": "^6.20.0", - "@typescript-eslint/parser": "^6.20.0", + "@types/node": "^20.11.17", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.6.3", @@ -1626,9 +1626,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "20.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", + "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1662,16 +1662,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz", - "integrity": "sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.20.0", - "@typescript-eslint/type-utils": "6.20.0", - "@typescript-eslint/utils": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1697,13 +1697,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", - "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1714,9 +1714,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", - "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1727,13 +1727,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", - "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1755,17 +1755,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", - "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.20.0", - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" }, "engines": { @@ -1780,12 +1780,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", - "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1821,15 +1821,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.20.0.tgz", - "integrity": "sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.20.0", - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/typescript-estree": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4" }, "engines": { @@ -1849,13 +1849,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", - "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1866,9 +1866,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", - "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1879,13 +1879,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", - "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1907,12 +1907,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", - "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1965,13 +1965,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz", - "integrity": "sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.20.0", - "@typescript-eslint/utils": "6.20.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1992,13 +1992,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", - "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2009,9 +2009,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", - "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2022,13 +2022,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", - "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2050,17 +2050,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", - "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.20.0", - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" }, "engines": { @@ -2075,12 +2075,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", - "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -7514,9 +7514,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "20.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", + "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7550,16 +7550,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz", - "integrity": "sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.20.0", - "@typescript-eslint/type-utils": "6.20.0", - "@typescript-eslint/utils": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7569,29 +7569,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", - "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" } }, "@typescript-eslint/types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", - "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", - "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7601,27 +7601,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", - "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.20.0", - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", - "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7646,42 +7646,42 @@ } }, "@typescript-eslint/parser": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.20.0.tgz", - "integrity": "sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.20.0", - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/typescript-estree": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", - "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" } }, "@typescript-eslint/types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", - "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", - "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7691,12 +7691,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", - "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7731,41 +7731,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz", - "integrity": "sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.20.0", - "@typescript-eslint/utils": "6.20.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", - "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "requires": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" } }, "@typescript-eslint/types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", - "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", - "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/visitor-keys": "6.20.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7775,27 +7775,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", - "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.20.0", - "@typescript-eslint/types": "6.20.0", - "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", - "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "requires": { - "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" } }, diff --git a/package.json b/package.json index 9125be4acb..2f9ca8c9f0 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.16", + "@types/node": "^20.11.17", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "eslint": "^8.56.0", From 7324348a355f9de9c41234ff45ac638b8d8c0e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 12 Feb 2024 18:41:12 +0100 Subject: [PATCH 349/525] [Node] Fix router.createWebRtcTransport() with listenIps (#1330) --- node/src/Router.ts | 4 ++-- node/src/test/test-WebRtcTransport.ts | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/node/src/Router.ts b/node/src/Router.ts index 42732654be..7b87818bf7 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -507,13 +507,13 @@ export class Router< const orderedProtocols: TransportProtocol[] = []; - if (enableUdp && (!enableTcp || preferUdp)) { + if (enableUdp && (preferUdp || !enableTcp || !preferTcp)) { orderedProtocols.push('udp'); if (enableTcp) { orderedProtocols.push('tcp'); } - } else if (enableTcp && (!enableUdp || (preferTcp && !preferUdp))) { + } else if (enableTcp && ((preferTcp && !preferUdp) || !enableUdp)) { orderedProtocols.push('tcp'); if (enableUdp) { diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 1e62a9dadb..72bfd48e4a 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -172,6 +172,31 @@ test('router.createWebRtcTransport() succeeds', async () => { expect(webRtcTransport.closed).toBe(true); }, 2000); +test('router.createWebRtcTransport() with deprecated listenIps succeeds', async () => { + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenIps: [{ ip: '127.0.0.1', announcedIp: undefined }], + enableUdp: true, + enableTcp: true, + preferUdp: false, + initialAvailableOutgoingBitrate: 1000000, + }); + + expect(Array.isArray(webRtcTransport.iceCandidates)).toBe(true); + expect(webRtcTransport.iceCandidates.length).toBe(2); + + const iceCandidates = webRtcTransport.iceCandidates; + + expect(iceCandidates[0].ip).toBe('127.0.0.1'); + expect(iceCandidates[0].protocol).toBe('udp'); + expect(iceCandidates[0].type).toBe('host'); + expect(iceCandidates[0].tcpType).toBeUndefined(); + expect(iceCandidates[1].ip).toBe('127.0.0.1'); + expect(iceCandidates[1].protocol).toBe('tcp'); + expect(iceCandidates[1].type).toBe('host'); + expect(iceCandidates[1].tcpType).toBe('passive'); + expect(iceCandidates[0].priority).toBeGreaterThan(iceCandidates[1].priority); +}, 2000); + test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore await expect(ctx.router!.createWebRtcTransport({})).rejects.toThrow( From 9151e241f3699a96d4408fa45f7cb1ef673c51dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 12 Feb 2024 18:44:43 +0100 Subject: [PATCH 350/525] 3.13.19 --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6d65148bb..8e81b85c00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### 3.13.19 + +- Node: Fix `router.createWebRtcTransport()` with `listenIps` ([PR #1330](https://github.com/versatica/mediasoup/pull/1330)). + ### 3.13.18 - Make transport-cc feedback work similarly to libwebrtc ([PR #1088](https://github.com/versatica/mediasoup/pull/1088) by @penguinol). diff --git a/package-lock.json b/package-lock.json index 962623e411..a38e00f1f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.18", + "version": "3.13.19", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.18", + "version": "3.13.19", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 2f9ca8c9f0..c005cbc7a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.18", + "version": "3.13.19", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 3efa2772e17558b71b1bd8659a4dfaa824b5e67f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 13 Feb 2024 12:26:09 +0100 Subject: [PATCH 351/525] npm-scripts.mjs: remove no longer needed eslint-disable-next-line --- npm-scripts.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 56405fea8e..2094e1dd55 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -223,7 +223,6 @@ async function run() { repo: GH_REPO, name: PKG.version, body: versionChanges, - // eslint-disable-next-line camelcase tag_name: PKG.version, draft: false, }); From 053177d09504f4f9ee63fb2826aee090c3ef936e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s-Combarro?= Date: Tue, 13 Feb 2024 16:39:48 +0100 Subject: [PATCH 352/525] Remove `no-async-promise-executor` linter disables (#1312) --- node/src/test/test-Consumer.ts | 19 +++--- node/src/test/test-DirectTransport.ts | 86 +++++++++++++-------------- node/src/test/test-node-sctp.ts | 3 +- 3 files changed, 52 insertions(+), 56 deletions(-) diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index 6d4c5f84ba..829ee29fe1 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -1,3 +1,4 @@ +import { once } from 'node:events'; import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; @@ -993,26 +994,24 @@ test('Consumer emits "producerpause" and "producerresume"', async () => { rtpCapabilities: ctx.consumerDeviceCapabilities, }); - // eslint-disable-next-line no-async-promise-executor - await new Promise(async resolve => { - audioConsumer.on('producerpause', resolve); + await Promise.all([ + once(audioConsumer, 'producerpause'), // Let's await for pause() to resolve to avoid aborted channel requests // due to worker closure. - await ctx.audioProducer!.pause(); - }); + ctx.audioProducer!.pause(), + ]); expect(audioConsumer.paused).toBe(false); expect(audioConsumer.producerPaused).toBe(true); - // eslint-disable-next-line no-async-promise-executor - await new Promise(async resolve => { - audioConsumer.on('producerresume', resolve); + await Promise.all([ + once(audioConsumer, 'producerresume'), // Let's await for resume() to resolve to avoid aborted channel requests // due to worker closure. - await ctx.audioProducer!.resume(); - }); + ctx.audioProducer!.resume(), + ]); expect(audioConsumer.paused).toBe(false); expect(audioConsumer.producerPaused).toBe(false); diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index f9c233a7d8..ac2f6ff8e8 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -126,8 +126,45 @@ test('dataProducer.send() succeeds', async () => { let numSentMessages = 0; let numReceivedMessages = 0; - // eslint-disable-next-line no-async-promise-executor - await new Promise(async (resolve, reject) => { + async function sendNextMessage(): Promise { + const id = ++numSentMessages; + let message: Buffer | string; + + if (id === pauseSendingAtMessage) { + await dataProducer.pause(); + } else if (id === resumeSendingAtMessage) { + await dataProducer.resume(); + } else if (id === pauseReceivingAtMessage) { + await dataConsumer.pause(); + } else if (id === resumeReceivingAtMessage) { + await dataConsumer.resume(); + } + + // Send string (WebRTC DataChannel string). + if (id < numMessages / 2) { + message = String(id); + } + // Send string (WebRTC DataChannel binary). + else { + message = Buffer.from(String(id)); + } + + dataProducer.send(message); + + const messageSize = Buffer.from(message).byteLength; + + sentMessageBytes += messageSize; + + if (!dataProducer.paused && !dataConsumer.paused) { + effectivelySentMessageBytes += messageSize; + } + + if (id < numMessages) { + void sendNextMessage(); + } + } + + await new Promise((resolve, reject) => { dataProducer.on('listenererror', (eventName, error) => { reject( new Error( @@ -144,46 +181,6 @@ test('dataProducer.send() succeeds', async () => { ); }); - await sendNextMessage(); - - async function sendNextMessage(): Promise { - const id = ++numSentMessages; - let message: Buffer | string; - - if (id === pauseSendingAtMessage) { - await dataProducer.pause(); - } else if (id === resumeSendingAtMessage) { - await dataProducer.resume(); - } else if (id === pauseReceivingAtMessage) { - await dataConsumer.pause(); - } else if (id === resumeReceivingAtMessage) { - await dataConsumer.resume(); - } - - // Send string (WebRTC DataChannel string). - if (id < numMessages / 2) { - message = String(id); - } - // Send string (WebRTC DataChannel binary). - else { - message = Buffer.from(String(id)); - } - - dataProducer.send(message); - - const messageSize = Buffer.from(message).byteLength; - - sentMessageBytes += messageSize; - - if (!dataProducer.paused && !dataConsumer.paused) { - effectivelySentMessageBytes += messageSize; - } - - if (id < numMessages) { - sendNextMessage(); - } - } - dataConsumer.on('message', (message, ppid) => { ++numReceivedMessages; @@ -212,6 +209,8 @@ test('dataProducer.send() succeeds', async () => { ); } }); + + void sendNextMessage(); }); expect(numSentMessages).toBe(numMessages); @@ -255,8 +254,7 @@ test('dataProducer.send() with subchannels succeeds', async () => { const receivedMessages1: string[] = []; const receivedMessages2: string[] = []; - // eslint-disable-next-line no-async-promise-executor - await new Promise(async resolve => { + await new Promise(resolve => { // Must be received by dataConsumer1 and dataConsumer2. dataProducer.send( 'both', diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index 380549b161..f5e402f082 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -122,8 +122,7 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn // It must be zero because it's the first DataConsumer on the plainTransport. expect(ctx.dataConsumer!.sctpStreamParameters?.streamId).toBe(0); - // eslint-disable-next-line no-async-promise-executor - await new Promise(async (resolve, reject) => { + await new Promise((resolve, reject) => { sendNextMessage(); async function sendNextMessage(): Promise { From 35422d978b73e744d2d5d6ce7aa0ed31c403fcf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 14 Feb 2024 18:29:45 +0100 Subject: [PATCH 353/525] Update NPM dev deps --- package-lock.json | 374 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 190 insertions(+), 190 deletions(-) diff --git a/package-lock.json b/package-lock.json index a38e00f1f0..1a81802f6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,11 +22,11 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.11.17", - "@typescript-eslint/eslint-plugin": "^6.21.0", - "@typescript-eslint/parser": "^6.21.0", + "@typescript-eslint/eslint-plugin": "^7.0.1", + "@typescript-eslint/parser": "^7.0.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.6.3", + "eslint-plugin-jest": "^27.8.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.0", @@ -1662,16 +1662,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.1.tgz", + "integrity": "sha512-OLvgeBv3vXlnnJGIAgCLYKjgMEU+wBGj07MQ/nxAaON+3mLzX7mJbhRYrVGiVvFiXtwFlkcBa/TtmglHy0UbzQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/type-utils": "7.0.1", + "@typescript-eslint/utils": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1687,8 +1687,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1697,13 +1697,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1714,9 +1714,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1727,13 +1727,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1755,17 +1755,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", "semver": "^7.5.4" }, "engines": { @@ -1776,16 +1776,16 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/types": "7.0.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1821,15 +1821,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.1.tgz", + "integrity": "sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4" }, "engines": { @@ -1840,7 +1840,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1849,13 +1849,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1866,9 +1866,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1879,13 +1879,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1907,12 +1907,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/types": "7.0.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1965,13 +1965,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.1.tgz", + "integrity": "sha512-YtT9UcstTG5Yqy4xtLiClm1ZpM/pWVGFnkAa90UfdkkZsR1eP2mR/1jbHeYp8Ay1l1JHPyGvoUYR6o3On5Nhmw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/utils": "7.0.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1983,7 +1983,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1992,13 +1992,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2009,9 +2009,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2022,13 +2022,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2050,17 +2050,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", "semver": "^7.5.4" }, "engines": { @@ -2071,16 +2071,16 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/types": "7.0.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3003,9 +3003,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.6.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz", - "integrity": "sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA==", + "version": "27.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.8.0.tgz", + "integrity": "sha512-347hVFiu4ZKMYl5xFp0X81gLNwBdno0dl0CMpUMjwuAux9X/M2a7z+ab2VHmPL6XCT87q8nv1vaVzhIO4TE/hw==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -3014,7 +3014,7 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", "eslint": "^7.0.0 || ^8.0.0", "jest": "*" }, @@ -5928,12 +5928,12 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", - "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -7550,16 +7550,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.1.tgz", + "integrity": "sha512-OLvgeBv3vXlnnJGIAgCLYKjgMEU+wBGj07MQ/nxAaON+3mLzX7mJbhRYrVGiVvFiXtwFlkcBa/TtmglHy0UbzQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/type-utils": "7.0.1", + "@typescript-eslint/utils": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7569,29 +7569,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" } }, "@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", "dev": true, "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7601,27 +7601,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/types": "7.0.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -7646,42 +7646,42 @@ } }, "@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.1.tgz", + "integrity": "sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" } }, "@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", "dev": true, "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7691,12 +7691,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/types": "7.0.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -7731,41 +7731,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.1.tgz", + "integrity": "sha512-YtT9UcstTG5Yqy4xtLiClm1ZpM/pWVGFnkAa90UfdkkZsR1eP2mR/1jbHeYp8Ay1l1JHPyGvoUYR6o3On5Nhmw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/utils": "7.0.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" } }, "@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", "dev": true, "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7775,27 +7775,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/types": "7.0.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -8459,9 +8459,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "27.6.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz", - "integrity": "sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA==", + "version": "27.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.8.0.tgz", + "integrity": "sha512-347hVFiu4ZKMYl5xFp0X81gLNwBdno0dl0CMpUMjwuAux9X/M2a7z+ab2VHmPL6XCT87q8nv1vaVzhIO4TE/hw==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" @@ -10495,9 +10495,9 @@ } }, "ts-api-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", - "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", "dev": true, "requires": {} }, diff --git a/package.json b/package.json index c005cbc7a9..57689dbc1b 100644 --- a/package.json +++ b/package.json @@ -111,11 +111,11 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.11.17", - "@typescript-eslint/eslint-plugin": "^6.21.0", - "@typescript-eslint/parser": "^6.21.0", + "@typescript-eslint/eslint-plugin": "^7.0.1", + "@typescript-eslint/parser": "^7.0.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.6.3", + "eslint-plugin-jest": "^27.8.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.0", From 595bffe12b1a3ce272aedce9e3d15afed7fd5a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 14 Feb 2024 18:37:08 +0100 Subject: [PATCH 354/525] IceServer.cpp: add some missing brackets in `case` blocks --- worker/src/RTC/IceServer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index 88e8b1af20..e486b4629b 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -44,16 +44,24 @@ namespace RTC switch (state) { case IceServer::IceState::NEW: + { return FBS::WebRtcTransport::IceState::NEW; + } case IceServer::IceState::CONNECTED: + { return FBS::WebRtcTransport::IceState::CONNECTED; + } case IceServer::IceState::COMPLETED: + { return FBS::WebRtcTransport::IceState::COMPLETED; + } case IceServer::IceState::DISCONNECTED: + { return FBS::WebRtcTransport::IceState::DISCONNECTED; + } } } From a90d0da031f5a00585d9d4151274b0ca6a94cc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 19 Feb 2024 15:00:02 +0100 Subject: [PATCH 355/525] liburing: print RLIMIT_MEMLOCK values upon ENOMEM (#1331) liburing: print RLIMIT_MEMLOCK values upon ENOMEM --- worker/src/DepLibUring.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/worker/src/DepLibUring.cpp b/worker/src/DepLibUring.cpp index bfd44aba4d..95d2b6631e 100644 --- a/worker/src/DepLibUring.cpp +++ b/worker/src/DepLibUring.cpp @@ -6,6 +6,7 @@ #include "MediaSoupErrors.hpp" #include "Utils.hpp" #include +#include #include /* Static variables. */ @@ -330,10 +331,25 @@ DepLibUring::LibUring::LibUring() { this->zeroCopyEnabled = false; - MS_WARN_TAG( - info, - "io_uring_register_buffers() failed due to low memlock limit (ulimit -l), disabling zero copy: %s", - std::strerror(error)); + struct rlimit l = {}; + + if (getrlimit(RLIMIT_MEMLOCK, std::addressof(l)) == -1) + { + MS_WARN_TAG(info, "getrlimit() failed: %s", std::strerror(errno)); + MS_WARN_TAG( + info, + "io_uring_register_buffers() failed due to low RLIMIT_MEMLOCK, disabling zero copy: %s", + std::strerror(error)); + } + else + { + MS_WARN_TAG( + info, + "io_uring_register_buffers() failed due to low RLIMIT_MEMLOCK (soft:%lu, hard:%lu), disabling zero copy: %s", + l.rlim_cur, + l.rlim_max, + std::strerror(error)); + } } else { From 51f8e1e5bfee3b705c30dbd6c6a28aaf89dd99cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 20 Feb 2024 11:13:33 +0100 Subject: [PATCH 356/525] CI: add mediasoup-worker-fuzzer.yaml (#1337) --- .../workflows/mediasoup-worker-fuzzer.yaml | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/mediasoup-worker-fuzzer.yaml diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml new file mode 100644 index 0000000000..5f4e5d953e --- /dev/null +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -0,0 +1,40 @@ +name: mediasoup-worker-fuzzer + +on: [pull_request, workflow_dispatch] + +concurrency: + # Cancel a currently running workflow from the same PR, branch or tag when a + # new workflow is triggered. + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + ci: + strategy: + matrix: + build: + - os: ubuntu-22.04 + cc: clang + cxx: clang++ + + runs-on: ${{ matrix.build.os }} + + env: + CC: ${{ matrix.build.cc }} + CXX: ${{ matrix.build.cxx }} + MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' + MEDIASOUP_LOCAL_DEV: 'true' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + # We need to install pip invoke manually. + - name: pip3 install invoke + run: pip3 install invoke + + # Build the mediasoup-worker-fuzzer binary (which uses libFuzzer). + - name: invoke -r worker fuzzer + run: invoke -r worker fuzzer + + # We don't run mediasoup-worker-fuzzer (maybe in the future). From b34a3b7316cd622edca587d4b5b7ea5de92c62f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 20 Feb 2024 11:33:54 +0100 Subject: [PATCH 357/525] cosmetic --- worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index 21f09c9e8f..efd9d591bc 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -294,7 +294,7 @@ namespace RTC { MS_TRACE(); - MS_ASSERT(baseSet, "base not set"); + MS_ASSERT(this->baseSet, "base not set"); MS_ASSERT(!IsFull(), "packet is full"); // If the wide sequence number of the new packet is lower than the latest seen, From a1cc5507fc4606f28c38f1e75a08577316812fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 20 Feb 2024 18:42:05 +0100 Subject: [PATCH 358/525] Fix regression (crash) in transport-cc feedback generation (#1339) Fixes #1336 --- CHANGELOG.md | 4 + .../include/RTC/RTCP/FeedbackRtpTransport.hpp | 4 + .../RTC/TransportCongestionControlServer.hpp | 5 +- worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 9 +- .../RTC/TransportCongestionControlServer.cpp | 109 +++++++++++------- 5 files changed, 88 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e81b85c00..45b24b01b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Next + +- Fix regression (crash) in transport-cc feedback generation ([PR #1339](https://github.com/versatica/mediasoup/pull/1339)). + ### 3.13.19 - Node: Fix `router.createWebRtcTransport()` with `listenIps` ([PR #1330](https://github.com/versatica/mediasoup/pull/1330)). diff --git a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp index 901df0c46c..fff4d3fbe0 100644 --- a/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp +++ b/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp @@ -212,6 +212,10 @@ namespace RTC ~FeedbackRtpTransportPacket() override; public: + bool IsBaseSet() const + { + return this->baseSet; + } void SetBase(uint16_t sequenceNumber, uint64_t timestamp); AddPacketResult AddPacket(uint16_t sequenceNumber, uint64_t timestamp, size_t maxRtcpPacketLen); // Just for locally generated packets. diff --git a/worker/include/RTC/TransportCongestionControlServer.hpp b/worker/include/RTC/TransportCongestionControlServer.hpp index 5cfd676796..af5e6d7482 100644 --- a/worker/include/RTC/TransportCongestionControlServer.hpp +++ b/worker/include/RTC/TransportCongestionControlServer.hpp @@ -58,10 +58,12 @@ namespace RTC void FillAndSendTransportCcFeedback(); private: - void SendTransportCcFeedback(); + // Returns true if a feedback packet was sent. + bool SendTransportCcFeedback(); void MayDropOldPacketArrivalTimes(uint16_t seqNum, uint64_t nowMs); void MaySendLimitationRembFeedback(uint64_t nowMs); void UpdatePacketLoss(double packetLoss); + void ResetTransportCcFeedback(uint8_t feedbackPacketCount); /* Pure virtual methods inherited from webrtc::RemoteBitrateEstimator::Listener. */ public: @@ -95,6 +97,7 @@ namespace RTC // Whether any packet with transport wide sequence number was received. bool transportWideSeqNumberReceived{ false }; uint16_t transportCcFeedbackWideSeqNumStart{ 0u }; + // Map of arrival timestamp (ms) indexed by wide seq number. std::map::SeqLowerThan> mapPacketArrivalTimes; }; } // namespace RTC diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index efd9d591bc..9d497677b4 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -282,6 +282,8 @@ namespace RTC { MS_TRACE(); + MS_ASSERT(!this->baseSet, "base already set"); + this->baseSet = true; this->baseSequenceNumber = sequenceNumber; this->referenceTime = static_cast((timestamp & 0x1FFFFFC0) / 64); @@ -297,8 +299,8 @@ namespace RTC MS_ASSERT(this->baseSet, "base not set"); MS_ASSERT(!IsFull(), "packet is full"); - // If the wide sequence number of the new packet is lower than the latest seen, - // ignore it. + // If the wide sequence number of the new packet is lower than the latest + // seen, ignore it. // NOTE: Not very spec compliant but libwebrtc does it. // Also ignore if the sequence number matches the latest seen. if (!RTC::SeqManager::IsSeqHigherThan(sequenceNumber, this->latestSequenceNumber)) @@ -340,7 +342,8 @@ namespace RTC // Delta in 16 bits signed. auto delta = static_cast(delta64); - // Check whether another chunks and corresponding delta infos could be added. + // Check whether another chunks and corresponding delta infos could be + // added. { // Fixed packet size. size_t size = FeedbackRtpPacket::GetSize(); diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index 6fe639e175..001bf6b9e0 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -33,10 +33,7 @@ namespace RTC case RTC::BweType::TRANSPORT_CC: { // Create a feedback packet. - this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket(0u, 0u)); - - // Set initial packet count. - this->transportCcFeedbackPacket->SetFeedbackPacketCount(this->transportCcFeedbackPacketCount); + ResetTransportCcFeedback(0u); // Create the feedback send periodic timer. this->transportCcFeedbackSendPeriodicTimer = new TimerHandle(this); @@ -94,7 +91,7 @@ namespace RTC this->transportCcFeedbackSendPeriodicTimer->Stop(); // Create a new feedback packet. - this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket(0u, 0u)); + ResetTransportCcFeedback(this->transportCcFeedbackPacketCount); break; } @@ -131,9 +128,10 @@ namespace RTC break; } - // We may receive packets with sequence number lower than the one in previous - // tcc feedback, these packets may have been reported as lost previously, - // therefore we need to reset the start sequence num for the next tcc feedback. + // We may receive packets with sequence number lower than the one in + // previous tcc feedback, these packets may have been reported as lost + // previously, therefore we need to reset the start sequence num for the + // next tcc feedback. if ( !this->transportWideSeqNumberReceived || RTC::SeqManager::IsSeqLowerThan( @@ -192,13 +190,23 @@ namespace RTC return; } - // Set base sequence num and reference time. - this->transportCcFeedbackPacket->SetBase(this->transportCcFeedbackWideSeqNumStart, it->second); - for (; it != this->mapPacketArrivalTimes.end(); ++it) { - auto result = - this->transportCcFeedbackPacket->AddPacket(it->first, it->second, this->maxRtcpPacketLen); + auto sequenceNumber = it->first; + auto timestamp = it->second; + + // If the base is not set in this packet let's set it. + // NOTE: This maybe needed many times during this loop since the current + // feedback packet maybe a fresh new one if the previous one was full (so + // already sent) or failed to be built. + if (!this->transportCcFeedbackPacket->IsBaseSet()) + { + // Set base sequence num and reference time. + this->transportCcFeedbackPacket->SetBase(this->transportCcFeedbackWideSeqNumStart, timestamp); + } + + auto result = this->transportCcFeedbackPacket->AddPacket( + sequenceNumber, timestamp, this->maxRtcpPacketLen); switch (result) { @@ -209,7 +217,15 @@ namespace RTC { MS_DEBUG_DEV("transport-cc feedback packet is full, sending feedback now"); - SendTransportCcFeedback(); + auto sent = SendTransportCcFeedback(); + + if (sent) + { + ++this->transportCcFeedbackPacketCount; + } + + // Create a new feedback packet. + ResetTransportCcFeedback(this->transportCcFeedbackPacketCount); } break; @@ -218,31 +234,39 @@ namespace RTC case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::MAX_SIZE_EXCEEDED: { // This should not happen. - MS_WARN_DEV("transport-cc feedback packet is exceeded"); + MS_WARN_TAG(rtcp, "transport-cc feedback packet is exceeded"); // Create a new feedback packet. - this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( - this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); + // NOTE: Do not increment packet count it since the previous ongoing + // feedback packet was not sent. + ResetTransportCcFeedback(this->transportCcFeedbackPacketCount); + + break; } case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::FATAL: { // Create a new feedback packet. - this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( - this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); - - // Use current packet count. - // NOTE: Do not increment it since the previous ongoing feedback - // packet was not sent. - this->transportCcFeedbackPacket->SetFeedbackPacketCount( - this->transportCcFeedbackPacketCount); + // NOTE: Do not increment packet count it since the previous ongoing + // feedback packet was not sent. + ResetTransportCcFeedback(this->transportCcFeedbackPacketCount); break; } } } - SendTransportCcFeedback(); + // It may happen that the packet is empty (no deltas) but in that case + // SendTransportCcFeedback() won't send it so we are safe. + auto sent = SendTransportCcFeedback(); + + if (sent) + { + ++this->transportCcFeedbackPacketCount; + } + + // Create a new feedback packet. + ResetTransportCcFeedback(this->transportCcFeedbackPacketCount); } void TransportCongestionControlServer::SetMaxIncomingBitrate(uint32_t bitrate) @@ -264,7 +288,7 @@ namespace RTC } } - inline void TransportCongestionControlServer::SendTransportCcFeedback() + bool TransportCongestionControlServer::SendTransportCcFeedback() { MS_TRACE(); @@ -272,7 +296,9 @@ namespace RTC if (!this->transportCcFeedbackPacket->IsSerializable()) { - return; + MS_WARN_TAG(rtcp, "couldn't send feedback-cc packet because it is not serializable"); + + return false; } auto latestWideSeqNumber = this->transportCcFeedbackPacket->GetLatestSequenceNumber(); @@ -298,17 +324,12 @@ namespace RTC this->UpdatePacketLoss(static_cast(lostPackets) / expectedPackets); } - // Create a new feedback packet. - this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( - this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); - - // Increment packet count. - this->transportCcFeedbackPacket->SetFeedbackPacketCount(++this->transportCcFeedbackPacketCount); this->transportCcFeedbackWideSeqNumStart = latestWideSeqNumber + 1; + + return true; } - inline void TransportCongestionControlServer::MayDropOldPacketArrivalTimes( - uint16_t seqNum, uint64_t nowMs) + void TransportCongestionControlServer::MayDropOldPacketArrivalTimes(uint16_t seqNum, uint64_t nowMs) { MS_TRACE(); @@ -330,7 +351,7 @@ namespace RTC } } - inline void TransportCongestionControlServer::MaySendLimitationRembFeedback(uint64_t nowMs) + void TransportCongestionControlServer::MaySendLimitationRembFeedback(uint64_t nowMs) { MS_TRACE(); @@ -402,7 +423,17 @@ namespace RTC this->packetLoss = totalPacketLoss / samples; } - inline void TransportCongestionControlServer::OnRembServerAvailableBitrate( + void TransportCongestionControlServer::ResetTransportCcFeedback(uint8_t feedbackPacketCount) + { + MS_TRACE(); + + this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( + this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); + + this->transportCcFeedbackPacket->SetFeedbackPacketCount(feedbackPacketCount); + } + + void TransportCongestionControlServer::OnRembServerAvailableBitrate( const webrtc::RemoteBitrateEstimator* /*rembServer*/, const std::vector& ssrcs, uint32_t availableBitrate) @@ -440,7 +471,7 @@ namespace RTC this->listener->OnTransportCongestionControlServerSendRtcpPacket(this, &packet); } - inline void TransportCongestionControlServer::OnTimer(TimerHandle* timer) + void TransportCongestionControlServer::OnTimer(TimerHandle* timer) { MS_TRACE(); From 32e83e3ac196c2cce6ea9bf3789ad1b77c141581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 20 Feb 2024 18:48:14 +0100 Subject: [PATCH 359/525] Add server side ICE consent checks to detect silent WebRTC disconnection (#1332) Fixes #1127 --- CHANGELOG.md | 1 + node/src/Router.ts | 4 +- node/src/WebRtcTransport.ts | 6 +- node/src/test/test-WebRtcTransport.ts | 8 +- rust/src/messages.rs | 3 + rust/src/router/webrtc_transport.rs | 5 + worker/Dockerfile | 4 +- worker/Dockerfile.alpine | 4 +- worker/fbs/webRtcTransport.fbs | 1 + worker/fuzzer/src/RTC/FuzzerStunPacket.cpp | 26 +- worker/include/RTC/IceServer.hpp | 58 +- worker/include/RTC/StunPacket.hpp | 25 +- worker/src/RTC/IceServer.cpp | 627 ++++++++++++++------- worker/src/RTC/KeyFrameRequestManager.cpp | 2 +- worker/src/RTC/StunPacket.cpp | 224 +++++--- worker/src/RTC/Transport.cpp | 4 +- worker/src/RTC/WebRtcServer.cpp | 2 +- worker/src/RTC/WebRtcTransport.cpp | 11 +- 18 files changed, 667 insertions(+), 348 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45b24b01b4..f90f3dd1fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Next +- Add server side ICE consent checks to detect silent WebRTC disconnections ([PR #1332](https://github.com/versatica/mediasoup/pull/1332)). - Fix regression (crash) in transport-cc feedback generation ([PR #1339](https://github.com/versatica/mediasoup/pull/1339)). ### 3.13.19 diff --git a/node/src/Router.ts b/node/src/Router.ts index 7b87818bf7..56245fe877 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -454,6 +454,7 @@ export class Router< numSctpStreams = { OS: 1024, MIS: 1024 }, maxSctpMessageSize = 262144, sctpSendBufferSize = 262144, + iceConsentTimeout = 30, appData, }: WebRtcTransportOptions): Promise< WebRtcTransport @@ -596,7 +597,8 @@ export class Router< enableUdp, enableTcp, preferUdp, - preferTcp + preferTcp, + iceConsentTimeout ); const requestOffset = new FbsRouter.CreateWebRtcTransportRequestT( diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index bdfb534e59..1e0a8d5b49 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -96,6 +96,11 @@ export type WebRtcTransportOptionsBase = { */ preferTcp?: boolean; + /** + * ICE consent timeout (in seconds). If 0 it is disabled. Default 30. + */ + iceConsentTimeout?: number; + /** * Initial available outgoing bitrate (in bps). Default 600000. */ @@ -836,7 +841,6 @@ function createConnectRequest({ // Serialize DtlsParameters. This can throw. const dtlsParametersOffset = serializeDtlsParameters(builder, dtlsParameters); - // Create request. return FbsWebRtcTransport.ConnectRequest.createConnectRequest( builder, dtlsParametersOffset diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 72bfd48e4a..c605c05cb5 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -299,12 +299,16 @@ test('webRtcTransport.connect() succeeds', async () => { }; await expect( - webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }) + webRtcTransport.connect({ + dtlsParameters: dtlsRemoteParameters, + }) ).resolves.toBeUndefined(); // Must fail if connected. await expect( - webRtcTransport.connect({ dtlsParameters: dtlsRemoteParameters }) + webRtcTransport.connect({ + dtlsParameters: dtlsRemoteParameters, + }) ).rejects.toThrow(Error); expect(webRtcTransport.dtlsParameters.role).toBe('server'); diff --git a/rust/src/messages.rs b/rust/src/messages.rs index c05eed1e08..d06fcaaf52 100644 --- a/rust/src/messages.rs +++ b/rust/src/messages.rs @@ -669,6 +669,7 @@ pub(crate) struct RouterCreateWebrtcTransportData { enable_tcp: bool, prefer_udp: bool, prefer_tcp: bool, + ice_consent_timeout: u8, enable_sctp: bool, num_sctp_streams: NumSctpStreams, max_sctp_message_size: u32, @@ -701,6 +702,7 @@ impl RouterCreateWebrtcTransportData { enable_tcp: webrtc_transport_options.enable_tcp, prefer_udp: webrtc_transport_options.prefer_udp, prefer_tcp: webrtc_transport_options.prefer_tcp, + ice_consent_timeout: webrtc_transport_options.ice_consent_timeout, enable_sctp: webrtc_transport_options.enable_sctp, num_sctp_streams: webrtc_transport_options.num_sctp_streams, max_sctp_message_size: webrtc_transport_options.max_sctp_message_size, @@ -726,6 +728,7 @@ impl RouterCreateWebrtcTransportData { enable_tcp: self.enable_tcp, prefer_udp: self.prefer_udp, prefer_tcp: self.prefer_tcp, + ice_consent_timeout: self.ice_consent_timeout, } } } diff --git a/rust/src/router/webrtc_transport.rs b/rust/src/router/webrtc_transport.rs index a50a9dfa31..e3f8c3babe 100644 --- a/rust/src/router/webrtc_transport.rs +++ b/rust/src/router/webrtc_transport.rs @@ -129,6 +129,9 @@ pub struct WebRtcTransportOptions { /// Prefer TCP. /// Default false. pub prefer_tcp: bool, + /// ICE consent timeout (in seconds). If 0 it is disabled. + /// Default 30. + pub ice_consent_timeout: u8, /// Create a SCTP association. /// Default false. pub enable_sctp: bool, @@ -155,6 +158,7 @@ impl WebRtcTransportOptions { enable_tcp: false, prefer_udp: false, prefer_tcp: false, + ice_consent_timeout: 30, enable_sctp: false, num_sctp_streams: NumSctpStreams::default(), max_sctp_message_size: 262_144, @@ -172,6 +176,7 @@ impl WebRtcTransportOptions { enable_tcp: true, prefer_udp: false, prefer_tcp: false, + ice_consent_timeout: 30, enable_sctp: false, num_sctp_streams: NumSctpStreams::default(), max_sctp_message_size: 262_144, diff --git a/worker/Dockerfile b/worker/Dockerfile index 37ab88d260..64ae430df2 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -26,8 +26,8 @@ ENV LANG="C.UTF-8" ENV CC="clang" ENV CXX="clang++" -ENV MEDIASOUP_LOCAL_DEV=true -ENV KEEP_BUILD_ARTIFACTS=1 +ENV MEDIASOUP_LOCAL_DEV="true" +ENV KEEP_BUILD_ARTIFACTS="1" WORKDIR /mediasoup diff --git a/worker/Dockerfile.alpine b/worker/Dockerfile.alpine index bde3577dcc..68cf11664d 100644 --- a/worker/Dockerfile.alpine +++ b/worker/Dockerfile.alpine @@ -9,8 +9,8 @@ ENV LANG="C.UTF-8" ENV CC="gcc" ENV CXX="g++" -ENV MEDIASOUP_LOCAL_DEV=true -ENV KEEP_BUILD_ARTIFACTS=1 +ENV MEDIASOUP_LOCAL_DEV="true" +ENV KEEP_BUILD_ARTIFACTS="1" WORKDIR /mediasoup diff --git a/worker/fbs/webRtcTransport.fbs b/worker/fbs/webRtcTransport.fbs index 4c12fb968c..4d66c7a511 100644 --- a/worker/fbs/webRtcTransport.fbs +++ b/worker/fbs/webRtcTransport.fbs @@ -23,6 +23,7 @@ table WebRtcTransportOptions { enable_tcp: bool = true; prefer_udp: bool = false; prefer_tcp: bool = false; + ice_consent_timeout: uint8 = 30; } enum FingerprintAlgorithm: uint8 { diff --git a/worker/fuzzer/src/RTC/FuzzerStunPacket.cpp b/worker/fuzzer/src/RTC/FuzzerStunPacket.cpp index 2110f8f0e1..37d567778d 100644 --- a/worker/fuzzer/src/RTC/FuzzerStunPacket.cpp +++ b/worker/fuzzer/src/RTC/FuzzerStunPacket.cpp @@ -1,6 +1,9 @@ #include "RTC/FuzzerStunPacket.hpp" #include "RTC/StunPacket.hpp" +static constexpr size_t StunSerializeBufferSize{ 65536 }; +thread_local static uint8_t StunSerializeBuffer[StunSerializeBufferSize]; + void Fuzzer::RTC::StunPacket::Fuzz(const uint8_t* data, size_t len) { if (!::RTC::StunPacket::IsStun(data, len)) @@ -21,6 +24,7 @@ void Fuzzer::RTC::StunPacket::Fuzz(const uint8_t* data, size_t len) packet->GetData(); packet->GetSize(); packet->SetUsername("foo", 3); + packet->SetPassword("lalala"); packet->SetPriority(123); packet->SetIceControlling(123); packet->SetIceControlled(123); @@ -37,13 +41,21 @@ void Fuzzer::RTC::StunPacket::Fuzz(const uint8_t* data, size_t len) packet->GetErrorCode(); packet->HasMessageIntegrity(); packet->HasFingerprint(); - packet->CheckAuthentication("foo", "bar"); - // TODO: packet->CreateSuccessResponse(); // This cannot be easily tested. - // TODO: packet->CreateErrorResponse(); // This cannot be easily tested. - packet->Authenticate("lalala"); - // TODO: Cannot test Serialize() because we don't know the exact required - // buffer size (setters above may change the total size). - // TODO: packet->Serialize(); + packet->CheckAuthentication("foo", "xxx"); + + if (packet->GetClass() == ::RTC::StunPacket::Class::REQUEST) + { + auto* successResponse = packet->CreateSuccessResponse(); + auto* errorResponse = packet->CreateErrorResponse(444); + + delete successResponse; + delete errorResponse; + } + + if (len < StunSerializeBufferSize - 1000) + { + packet->Serialize(StunSerializeBuffer); + } delete packet; } diff --git a/worker/include/RTC/IceServer.hpp b/worker/include/RTC/IceServer.hpp index bde22a4642..72d7710363 100644 --- a/worker/include/RTC/IceServer.hpp +++ b/worker/include/RTC/IceServer.hpp @@ -2,15 +2,17 @@ #define MS_RTC_ICE_SERVER_HPP #include "common.hpp" +#include "Utils.hpp" #include "FBS/webRtcTransport.h" #include "RTC/StunPacket.hpp" #include "RTC/TransportTuple.hpp" +#include "handles/TimerHandle.hpp" #include #include namespace RTC { - class IceServer + class IceServer : public TimerHandle::Listener { public: enum class IceState @@ -53,8 +55,12 @@ namespace RTC }; public: - IceServer(Listener* listener, const std::string& usernameFragment, const std::string& password); - ~IceServer(); + IceServer( + Listener* listener, + const std::string& usernameFragment, + const std::string& password, + uint8_t consentTimeoutSec); + ~IceServer() override; public: void ProcessStunPacket(RTC::StunPacket* packet, RTC::TransportTuple* tuple); @@ -74,28 +80,7 @@ namespace RTC { return this->selectedTuple; } - void RestartIce(const std::string& usernameFragment, const std::string& password) - { - if (!this->oldUsernameFragment.empty()) - { - this->listener->OnIceServerLocalUsernameFragmentRemoved(this, this->oldUsernameFragment); - } - - this->oldUsernameFragment = this->usernameFragment; - this->usernameFragment = usernameFragment; - - this->oldPassword = this->password; - this->password = password; - - this->remoteNomination = 0u; - - // Notify the listener. - this->listener->OnIceServerLocalUsernameFragmentAdded(this, usernameFragment); - - // NOTE: Do not call listener->OnIceServerLocalUsernameFragmentRemoved() - // yet with old usernameFragment. Wait until we receive a STUN packet - // with the new one. - } + void RestartIce(const std::string& usernameFragment, const std::string& password); bool IsValidTuple(const RTC::TransportTuple* tuple) const; void RemoveTuple(RTC::TransportTuple* tuple); /** @@ -105,6 +90,9 @@ namespace RTC void MayForceSelectedTuple(const RTC::TransportTuple* tuple); private: + void ProcessStunRequest(RTC::StunPacket* request, RTC::TransportTuple* tuple); + void ProcessStunIndication(RTC::StunPacket* indication); + void ProcessStunResponse(RTC::StunPacket* response); void HandleTuple( RTC::TransportTuple* tuple, bool hasUseCandidate, bool hasNomination, uint32_t nomination); /** @@ -120,19 +108,37 @@ namespace RTC * NOTE: The given tuple MUST be already stored within the list. */ void SetSelectedTuple(RTC::TransportTuple* storedTuple); + bool IsConsentCheckSupported() const + { + return this->consentTimeoutMs != 0u; + } + bool IsConsentCheckRunning() const + { + return (this->consentCheckTimer && this->consentCheckTimer->IsActive()); + } + void StartConsentCheck(); + void RestartConsentCheck(); + void StopConsentCheck(); + + /* Pure virtual methods inherited from TimerHandle::Listener. */ + public: + void OnTimer(TimerHandle* timer) override; private: // Passed by argument. Listener* listener{ nullptr }; - // Others. std::string usernameFragment; std::string password; + uint16_t consentTimeoutMs{ 30000u }; + // Others. std::string oldUsernameFragment; std::string oldPassword; IceState state{ IceState::NEW }; uint32_t remoteNomination{ 0u }; std::list tuples; RTC::TransportTuple* selectedTuple{ nullptr }; + TimerHandle* consentCheckTimer{ nullptr }; + uint64_t lastConsentRequestReceivedAtMs{ 0u }; }; } // namespace RTC diff --git a/worker/include/RTC/StunPacket.hpp b/worker/include/RTC/StunPacket.hpp index ab4846e237..1d781fff43 100644 --- a/worker/include/RTC/StunPacket.hpp +++ b/worker/include/RTC/StunPacket.hpp @@ -50,7 +50,7 @@ namespace RTC { OK = 0, UNAUTHORIZED = 1, - BAD_REQUEST = 2 + BAD_MESSAGE = 2 }; public: @@ -95,6 +95,10 @@ namespace RTC { return this->size; } + const uint8_t* GetTransactionId() const + { + return this->transactionId; + } void SetUsername(const char* username, size_t len) { this->username.assign(username, len); @@ -127,6 +131,10 @@ namespace RTC { this->errorCode = errorCode; } + void SetSoftware(const char* software, size_t len) + { + this->software.assign(software, len); + } void SetMessageIntegrity(const uint8_t* messageIntegrity) { this->messageIntegrity = messageIntegrity; @@ -139,6 +147,7 @@ namespace RTC { return this->username; } + void SetPassword(const std::string& password); uint32_t GetPriority() const { return this->priority; @@ -171,6 +180,10 @@ namespace RTC { return this->errorCode; } + std::string GetSoftware() const + { + return this->software; + } bool HasMessageIntegrity() const { return (this->messageIntegrity != nullptr); @@ -180,10 +193,11 @@ namespace RTC return this->hasFingerprint; } Authentication CheckAuthentication( - const std::string& localUsername, const std::string& localPassword); + // The first username fragment in the USERNAME attribute. + const std::string& usernameFragment1, + const std::string& password); StunPacket* CreateSuccessResponse(); StunPacket* CreateErrorResponse(uint16_t errorCode); - void Authenticate(const std::string& password); void Serialize(uint8_t* buffer); private: @@ -194,7 +208,8 @@ namespace RTC uint8_t* data{ nullptr }; // Pointer to binary data. size_t size{ 0u }; // The full message size (including header). // STUN attributes. - std::string username; // Less than 513 bytes. + std::string username; // Less than 513 bytes. + std::string password; uint32_t priority{ 0u }; // 4 bytes unsigned integer. uint64_t iceControlling{ 0u }; // 8 bytes unsigned integer. uint64_t iceControlled{ 0u }; // 8 bytes unsigned integer. @@ -205,7 +220,7 @@ namespace RTC bool hasFingerprint{ false }; // 4 bytes. const struct sockaddr* xorMappedAddress{ nullptr }; // 8 or 20 bytes. uint16_t errorCode{ 0u }; // 4 bytes (no reason phrase). - std::string password; + std::string software; // Less than 763 bytes. }; } // namespace RTC diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index e486b4629b..756cae8eb5 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -2,6 +2,7 @@ // #define MS_LOG_DEV_LEVEL 3 #include "RTC/IceServer.hpp" +#include "DepLibUV.hpp" #include "Logger.hpp" namespace RTC @@ -11,6 +12,8 @@ namespace RTC static constexpr size_t StunSerializeBufferSize{ 65536 }; thread_local static uint8_t StunSerializeBuffer[StunSerializeBufferSize]; static constexpr size_t MaxTuples{ 8 }; + static constexpr uint8_t ConsentCheckMinTimeoutSec{ 10u }; + static constexpr uint8_t ConsentCheckMaxTimeoutSec{ 60u }; /* Class methods. */ IceServer::IceState IceStateFromFbs(FBS::WebRtcTransport::IceState state) @@ -67,11 +70,40 @@ namespace RTC /* Instance methods. */ - IceServer::IceServer(Listener* listener, const std::string& usernameFragment, const std::string& password) + IceServer::IceServer( + Listener* listener, + const std::string& usernameFragment, + const std::string& password, + uint8_t consentTimeoutSec) : listener(listener), usernameFragment(usernameFragment), password(password) { MS_TRACE(); + if (consentTimeoutSec == 0u) + { + // 0 means disabled so it's a valid value. + } + else if (consentTimeoutSec < ConsentCheckMinTimeoutSec) + { + MS_WARN_TAG( + ice, + "consentTimeoutSec cannot be lower than %" PRIu8 " seconds, fixing it", + ConsentCheckMinTimeoutSec); + + consentTimeoutSec = ConsentCheckMinTimeoutSec; + } + else if (consentTimeoutSec > ConsentCheckMaxTimeoutSec) + { + MS_WARN_TAG( + ice, + "consentTimeoutSec cannot be higher than %" PRIu8 " seconds, fixing it", + ConsentCheckMaxTimeoutSec); + + consentTimeoutSec = ConsentCheckMaxTimeoutSec; + } + + this->consentTimeoutMs = consentTimeoutSec * 1000; + // Notify the listener. this->listener->OnIceServerLocalUsernameFragmentAdded(this, usernameFragment); } @@ -90,6 +122,7 @@ namespace RTC this->listener->OnIceServerLocalUsernameFragmentRemoved(this, this->oldUsernameFragment); } + // Clear all tuples. for (const auto& it : this->tuples) { auto* storedTuple = const_cast(std::addressof(it)); @@ -98,296 +131,383 @@ namespace RTC this->listener->OnIceServerTupleRemoved(this, storedTuple); } + // Clear all tuples. + // NOTE: Do it after notifying the listener since the listener may need to + // use/read the tuple being removed so we cannot free it yet. this->tuples.clear(); + + // Unset selected tuple. + this->selectedTuple = nullptr; + + // Delete the ICE consent check timer. + delete this->consentCheckTimer; + this->consentCheckTimer = nullptr; } void IceServer::ProcessStunPacket(RTC::StunPacket* packet, RTC::TransportTuple* tuple) { MS_TRACE(); - // Must be a Binding method. - if (packet->GetMethod() != RTC::StunPacket::Method::BINDING) + switch (packet->GetClass()) { - if (packet->GetClass() == RTC::StunPacket::Class::REQUEST) + case RTC::StunPacket::Class::REQUEST: { - MS_WARN_TAG( - ice, - "unknown method %#.3x in STUN Request => 400", - static_cast(packet->GetMethod())); + ProcessStunRequest(packet, tuple); - // Reply 400. - RTC::StunPacket* response = packet->CreateErrorResponse(400); + break; + } - response->Serialize(StunSerializeBuffer); - this->listener->OnIceServerSendStunPacket(this, response, tuple); + case RTC::StunPacket::Class::INDICATION: + { + ProcessStunIndication(packet); - delete response; + break; } - else + + case RTC::StunPacket::Class::SUCCESS_RESPONSE: + case RTC::StunPacket::Class::ERROR_RESPONSE: { - MS_WARN_TAG( - ice, - "ignoring STUN Indication or Response with unknown method %#.3x", - static_cast(packet->GetMethod())); + ProcessStunResponse(packet); + + break; } - return; + default: + { + MS_WARN_TAG(ice, "unknown STUN class %" PRIu16 ", discarded", packet->GetClass()); + } } + } - // Must use FINGERPRINT (optional for ICE STUN indications). - if (!packet->HasFingerprint() && packet->GetClass() != RTC::StunPacket::Class::INDICATION) + void IceServer::RestartIce(const std::string& usernameFragment, const std::string& password) + { + MS_TRACE(); + + if (!this->oldUsernameFragment.empty()) { - if (packet->GetClass() == RTC::StunPacket::Class::REQUEST) - { - MS_WARN_TAG(ice, "STUN Binding Request without FINGERPRINT => 400"); + this->listener->OnIceServerLocalUsernameFragmentRemoved(this, this->oldUsernameFragment); + } - // Reply 400. - RTC::StunPacket* response = packet->CreateErrorResponse(400); + this->oldUsernameFragment = this->usernameFragment; + this->usernameFragment = usernameFragment; - response->Serialize(StunSerializeBuffer); - this->listener->OnIceServerSendStunPacket(this, response, tuple); + this->oldPassword = this->password; + this->password = password; - delete response; - } - else + this->remoteNomination = 0u; + + // Notify the listener. + this->listener->OnIceServerLocalUsernameFragmentAdded(this, usernameFragment); + + // NOTE: Do not call listener->OnIceServerLocalUsernameFragmentRemoved() + // yet with old usernameFragment. Wait until we receive a STUN packet + // with the new one. + + // Restart ICE consent check (if running) to give some time to the + // client to establish ICE again. + if (IsConsentCheckSupported() && IsConsentCheckRunning()) + { + RestartConsentCheck(); + } + } + + bool IceServer::IsValidTuple(const RTC::TransportTuple* tuple) const + { + MS_TRACE(); + + return HasTuple(tuple) != nullptr; + } + + void IceServer::RemoveTuple(RTC::TransportTuple* tuple) + { + MS_TRACE(); + + RTC::TransportTuple* removedTuple{ nullptr }; + + // Find the removed tuple. + auto it = this->tuples.begin(); + + for (; it != this->tuples.end(); ++it) + { + RTC::TransportTuple* storedTuple = std::addressof(*it); + + if (storedTuple->Compare(tuple)) { - MS_WARN_TAG(ice, "ignoring STUN Binding Response without FINGERPRINT"); + removedTuple = storedTuple; + + break; } + } + // If not found, ignore. + if (!removedTuple) + { return; } - switch (packet->GetClass()) - { - case RTC::StunPacket::Class::REQUEST: - { - // USERNAME, MESSAGE-INTEGRITY and PRIORITY are required. - if (!packet->HasMessageIntegrity() || (packet->GetPriority() == 0u) || packet->GetUsername().empty()) - { - MS_WARN_TAG(ice, "mising required attributes in STUN Binding Request => 400"); + // Notify the listener. + this->listener->OnIceServerTupleRemoved(this, removedTuple); - // Reply 400. - RTC::StunPacket* response = packet->CreateErrorResponse(400); + // Remove it from the list of tuples. + // NOTE: Do it after notifying the listener since the listener may need to + // use/read the tuple being removed so we cannot free it yet. + this->tuples.erase(it); - response->Serialize(StunSerializeBuffer); - this->listener->OnIceServerSendStunPacket(this, response, tuple); + // If this is the selected tuple, do things. + if (removedTuple == this->selectedTuple) + { + this->selectedTuple = nullptr; - delete response; + // Mark the first tuple as selected tuple (if any) but only if state was + // 'connected' or 'completed'. + if ( + (this->state == IceState::CONNECTED || this->state == IceState::COMPLETED) && + this->tuples.begin() != this->tuples.end()) + { + SetSelectedTuple(std::addressof(*this->tuples.begin())); - return; + // Restart ICE consent check to let the client send new consent requests + // on the new selected tuple. + if (IsConsentCheckSupported()) + { + RestartConsentCheck(); } + } + // Or just emit 'disconnected'. + else + { + // Update state. + this->state = IceState::DISCONNECTED; - // Check authentication. - switch (packet->CheckAuthentication(this->usernameFragment, this->password)) - { - case RTC::StunPacket::Authentication::OK: - { - if (!this->oldUsernameFragment.empty() && !this->oldPassword.empty()) - { - MS_DEBUG_TAG(ice, "new ICE credentials applied"); + // Reset remote nomination. + this->remoteNomination = 0u; - // Notify the listener. - this->listener->OnIceServerLocalUsernameFragmentRemoved(this, this->oldUsernameFragment); + // Notify the listener. + this->listener->OnIceServerDisconnected(this); - this->oldUsernameFragment.clear(); - this->oldPassword.clear(); - } + if (IsConsentCheckSupported() && IsConsentCheckRunning()) + { + StopConsentCheck(); + } + } + } + } - break; - } + void IceServer::ProcessStunRequest(RTC::StunPacket* request, RTC::TransportTuple* tuple) + { + MS_TRACE(); - case RTC::StunPacket::Authentication::UNAUTHORIZED: - { - // We may have changed our usernameFragment and password, so check - // the old ones. - // clang-format off - if ( - !this->oldUsernameFragment.empty() && - !this->oldPassword.empty() && - packet->CheckAuthentication(this->oldUsernameFragment, this->oldPassword) == RTC::StunPacket::Authentication::OK - ) - // clang-format on - { - MS_DEBUG_TAG(ice, "using old ICE credentials"); + MS_DEBUG_DEV("processing STUN request"); - break; - } + // Must be a Binding method. + if (request->GetMethod() != RTC::StunPacket::Method::BINDING) + { + MS_WARN_TAG( + ice, + "STUN request with unknown method %#.3x => 400", + static_cast(request->GetMethod())); - MS_WARN_TAG(ice, "wrong authentication in STUN Binding Request => 401"); + // Reply 400. + RTC::StunPacket* response = request->CreateErrorResponse(400); - // Reply 401. - RTC::StunPacket* response = packet->CreateErrorResponse(401); + response->Serialize(StunSerializeBuffer); + this->listener->OnIceServerSendStunPacket(this, response, tuple); - response->Serialize(StunSerializeBuffer); - this->listener->OnIceServerSendStunPacket(this, response, tuple); + delete response; - delete response; + return; + } - return; - } + // Must have FINGERPRINT attribute. + if (!request->HasFingerprint()) + { + MS_WARN_TAG(ice, "STUN Binding request without FINGERPRINT attribute => 400"); - case RTC::StunPacket::Authentication::BAD_REQUEST: - { - MS_WARN_TAG(ice, "cannot check authentication in STUN Binding Request => 400"); + // Reply 400. + RTC::StunPacket* response = request->CreateErrorResponse(400); - // Reply 400. - RTC::StunPacket* response = packet->CreateErrorResponse(400); + response->Serialize(StunSerializeBuffer); + this->listener->OnIceServerSendStunPacket(this, response, tuple); - response->Serialize(StunSerializeBuffer); - this->listener->OnIceServerSendStunPacket(this, response, tuple); + delete response; - delete response; + return; + } - return; - } - } + // PRIORITY attribute is required. + if (request->GetPriority() == 0u) + { + MS_WARN_TAG(ice, "STUN Binding request without PRIORITY attribute => 400"); - // The remote peer must be ICE controlling. - if (packet->GetIceControlled()) - { - MS_WARN_TAG(ice, "peer indicates ICE-CONTROLLED in STUN Binding Request => 487"); + // Reply 400. + RTC::StunPacket* response = request->CreateErrorResponse(400); - // Reply 487 (Role Conflict). - RTC::StunPacket* response = packet->CreateErrorResponse(487); + response->Serialize(StunSerializeBuffer); + this->listener->OnIceServerSendStunPacket(this, response, tuple); - response->Serialize(StunSerializeBuffer); - this->listener->OnIceServerSendStunPacket(this, response, tuple); + delete response; - delete response; + return; + } - return; - } + // Check authentication. + switch (request->CheckAuthentication(this->usernameFragment, this->password)) + { + case RTC::StunPacket::Authentication::OK: + { + if (!this->oldUsernameFragment.empty() && !this->oldPassword.empty()) + { + MS_DEBUG_TAG(ice, "new ICE credentials applied"); - MS_DEBUG_DEV( - "processing STUN Binding Request [Priority:%" PRIu32 ", UseCandidate:%s]", - static_cast(packet->GetPriority()), - packet->HasUseCandidate() ? "true" : "false"); + // Notify the listener. + this->listener->OnIceServerLocalUsernameFragmentRemoved(this, this->oldUsernameFragment); - // Create a success response. - RTC::StunPacket* response = packet->CreateSuccessResponse(); + this->oldUsernameFragment.clear(); + this->oldPassword.clear(); + } - // Add XOR-MAPPED-ADDRESS. - response->SetXorMappedAddress(tuple->GetRemoteAddress()); + break; + } - // Authenticate the response. - if (this->oldPassword.empty()) - { - response->Authenticate(this->password); - } - else + case RTC::StunPacket::Authentication::UNAUTHORIZED: + { + // We may have changed our usernameFragment and password, so check the + // old ones. + // clang-format off + if ( + !this->oldUsernameFragment.empty() && + !this->oldPassword.empty() && + request->CheckAuthentication( + this->oldUsernameFragment, this->oldPassword + ) == RTC::StunPacket::Authentication::OK + ) + // clang-format on { - response->Authenticate(this->oldPassword); + MS_DEBUG_TAG(ice, "using old ICE credentials"); + + break; } - // Send back. + MS_WARN_TAG(ice, "wrong authentication in STUN Binding request => 401"); + + // Reply 401. + RTC::StunPacket* response = request->CreateErrorResponse(401); + response->Serialize(StunSerializeBuffer); this->listener->OnIceServerSendStunPacket(this, response, tuple); delete response; - uint32_t nomination{ 0u }; - - if (packet->HasNomination()) - { - nomination = packet->GetNomination(); - } - - // Handle the tuple. - HandleTuple(tuple, packet->HasUseCandidate(), packet->HasNomination(), nomination); - - break; + return; } - case RTC::StunPacket::Class::INDICATION: + case RTC::StunPacket::Authentication::BAD_MESSAGE: { - MS_DEBUG_TAG(ice, "STUN Binding Indication processed"); + MS_WARN_TAG(ice, "cannot check authentication in STUN Binding request => 400"); - break; - } - - case RTC::StunPacket::Class::SUCCESS_RESPONSE: - { - MS_DEBUG_TAG(ice, "STUN Binding Success Response processed"); + // Reply 400. + RTC::StunPacket* response = request->CreateErrorResponse(400); - break; - } + response->Serialize(StunSerializeBuffer); + this->listener->OnIceServerSendStunPacket(this, response, tuple); - case RTC::StunPacket::Class::ERROR_RESPONSE: - { - MS_DEBUG_TAG(ice, "STUN Binding Error Response processed"); + delete response; - break; + return; } } - } - bool IceServer::IsValidTuple(const RTC::TransportTuple* tuple) const - { - MS_TRACE(); + // The remote peer must be ICE controlling. + if (request->GetIceControlled()) + { + MS_WARN_TAG(ice, "peer indicates ICE-CONTROLLED in STUN Binding request => 487"); - return HasTuple(tuple) != nullptr; - } + // Reply 487 (Role Conflict). + RTC::StunPacket* response = request->CreateErrorResponse(487); - void IceServer::RemoveTuple(RTC::TransportTuple* tuple) - { - MS_TRACE(); + response->Serialize(StunSerializeBuffer); + this->listener->OnIceServerSendStunPacket(this, response, tuple); - RTC::TransportTuple* removedTuple{ nullptr }; + delete response; - // Find the removed tuple. - auto it = this->tuples.begin(); + return; + } - for (; it != this->tuples.end(); ++it) - { - RTC::TransportTuple* storedTuple = std::addressof(*it); + MS_DEBUG_DEV( + "valid STUN Binding request [priority:%" PRIu32 ", useCandidate:%s]", + static_cast(request->GetPriority()), + request->HasUseCandidate() ? "true" : "false"); - if (storedTuple->Compare(tuple)) - { - removedTuple = storedTuple; + // Create a success response. + RTC::StunPacket* response = request->CreateSuccessResponse(); - break; - } - } + // Add XOR-MAPPED-ADDRESS. + response->SetXorMappedAddress(tuple->GetRemoteAddress()); - // If not found, ignore. - if (!removedTuple) + // Authenticate the response. + if (this->oldPassword.empty()) { - return; + response->SetPassword(this->password); + } + else + { + response->SetPassword(this->oldPassword); } - // Notify the listener. - this->listener->OnIceServerTupleRemoved(this, removedTuple); + // Send back. + response->Serialize(StunSerializeBuffer); + this->listener->OnIceServerSendStunPacket(this, response, tuple); - // Remove it from the list of tuples. - // NOTE: Do it after notifying the listener since the listener may need to - // use/read the tuple being removed so we cannot free it yet. - this->tuples.erase(it); + delete response; - // If this is the selected tuple, do things. - if (removedTuple == this->selectedTuple) + uint32_t nomination{ 0u }; + + if (request->HasNomination()) { - this->selectedTuple = nullptr; + nomination = request->GetNomination(); + } - // Mark the first tuple as selected tuple (if any). - if (this->tuples.begin() != this->tuples.end()) + // Handle the tuple. + HandleTuple(tuple, request->HasUseCandidate(), request->HasNomination(), nomination); + + // If state is 'connected' or 'completed' after handling the tuple, then + // start or restart ICE consent check (if supported). + if (IsConsentCheckSupported() && (this->state == IceState::CONNECTED || this->state == IceState::COMPLETED)) + { + if (IsConsentCheckRunning()) { - SetSelectedTuple(std::addressof(*this->tuples.begin())); + RestartConsentCheck(); } - // Or just emit 'disconnected'. else { - // Update state. - this->state = IceState::DISCONNECTED; - - // Reset remote nomination. - this->remoteNomination = 0u; - - // Notify the listener. - this->listener->OnIceServerDisconnected(this); + StartConsentCheck(); } } } + void IceServer::ProcessStunIndication(RTC::StunPacket* indication) + { + MS_TRACE(); + + MS_DEBUG_DEV("STUN indication received, discarded"); + + // Nothig else to do. We just discard STUN indications. + } + + void IceServer::ProcessStunResponse(RTC::StunPacket* response) + { + MS_TRACE(); + + const std::string responseType = response->GetClass() == RTC::StunPacket::Class::SUCCESS_RESPONSE + ? "success" + : std::to_string(response->GetErrorCode()) + " error"; + + MS_DEBUG_DEV("processing STUN %s response received, discarded", responseType.c_str()); + + // Nothig else to do. We just discard STUN responses because we do not + // generate STUN requests. + } + void IceServer::MayForceSelectedTuple(const RTC::TransportTuple* tuple) { MS_TRACE(); @@ -408,7 +528,6 @@ namespace RTC return; } - // Mark it as selected tuple. SetSelectedTuple(storedTuple); } @@ -437,12 +556,12 @@ namespace RTC // Store the tuple. auto* storedTuple = AddTuple(tuple); - // Mark it as selected tuple. - SetSelectedTuple(storedTuple); - // Update state. this->state = IceState::CONNECTED; + // Mark it as selected tuple. + SetSelectedTuple(storedTuple); + // Notify the listener. this->listener->OnIceServerConnected(this); } @@ -461,12 +580,12 @@ namespace RTC hasNomination ? "true" : "false", nomination); - // Mark it as selected tuple. - SetSelectedTuple(storedTuple); - // Update state. this->state = IceState::COMPLETED; + // Mark it as selected tuple. + SetSelectedTuple(storedTuple); + // Update nomination. if (hasNomination && nomination > this->remoteNomination) { @@ -499,12 +618,12 @@ namespace RTC // Store the tuple. auto* storedTuple = AddTuple(tuple); - // Mark it as selected tuple. - SetSelectedTuple(storedTuple); - // Update state. this->state = IceState::CONNECTED; + // Mark it as selected tuple. + SetSelectedTuple(storedTuple); + // Notify the listener. this->listener->OnIceServerConnected(this); } @@ -523,12 +642,12 @@ namespace RTC hasNomination ? "true" : "false", nomination); - // Mark it as selected tuple. - SetSelectedTuple(storedTuple); - // Update state. this->state = IceState::COMPLETED; + // Mark it as selected tuple. + SetSelectedTuple(storedTuple); + // Update nomination. if (hasNomination && nomination > this->remoteNomination) { @@ -571,12 +690,12 @@ namespace RTC if ((hasNomination && nomination > this->remoteNomination) || !hasNomination) { - // Mark it as selected tuple. - SetSelectedTuple(storedTuple); - // Update state. this->state = IceState::COMPLETED; + // Mark it as selected tuple. + SetSelectedTuple(storedTuple); + // Update nomination. if (hasNomination && nomination > this->remoteNomination) { @@ -627,7 +746,7 @@ namespace RTC } } - inline RTC::TransportTuple* IceServer::AddTuple(RTC::TransportTuple* tuple) + RTC::TransportTuple* IceServer::AddTuple(RTC::TransportTuple* tuple) { MS_TRACE(); @@ -635,7 +754,7 @@ namespace RTC if (storedTuple) { - MS_DEBUG_DEV('tuple already exists'); + MS_DEBUG_DEV("tuple already exists"); return storedTuple; } @@ -695,7 +814,7 @@ namespace RTC return storedTuple; } - inline RTC::TransportTuple* IceServer::HasTuple(const RTC::TransportTuple* tuple) const + RTC::TransportTuple* IceServer::HasTuple(const RTC::TransportTuple* tuple) const { MS_TRACE(); @@ -719,7 +838,7 @@ namespace RTC return nullptr; } - inline void IceServer::SetSelectedTuple(RTC::TransportTuple* storedTuple) + void IceServer::SetSelectedTuple(RTC::TransportTuple* storedTuple) { MS_TRACE(); @@ -734,4 +853,88 @@ namespace RTC // Notify the listener. this->listener->OnIceServerSelectedTuple(this, this->selectedTuple); } + + void IceServer::StartConsentCheck() + { + MS_TRACE(); + + MS_ASSERT(IsConsentCheckSupported(), "ICE consent check not supported"); + MS_ASSERT(!IsConsentCheckRunning(), "ICE consent check already running"); + MS_ASSERT(this->selectedTuple, "no selected tuple"); + + // Create the ICE consent check timer if it doesn't exist. + if (!this->consentCheckTimer) + { + this->consentCheckTimer = new TimerHandle(this); + } + + this->consentCheckTimer->Start(this->consentTimeoutMs); + } + + void IceServer::RestartConsentCheck() + { + MS_TRACE(); + + MS_ASSERT(IsConsentCheckSupported(), "ICE consent check not supported"); + MS_ASSERT(IsConsentCheckRunning(), "ICE consent check not running"); + MS_ASSERT(this->selectedTuple, "no selected tuple"); + + this->consentCheckTimer->Restart(); + } + + void IceServer::StopConsentCheck() + { + MS_TRACE(); + + MS_ASSERT(IsConsentCheckSupported(), "ICE consent check not supported"); + MS_ASSERT(IsConsentCheckRunning(), "ICE consent check not running"); + + this->consentCheckTimer->Stop(); + } + + inline void IceServer::OnTimer(TimerHandle* timer) + { + MS_TRACE(); + + if (timer == this->consentCheckTimer) + { + MS_ASSERT(IsConsentCheckSupported(), "ICE consent check not supported"); + + // State must be 'connected' or 'completed'. + MS_ASSERT( + this->state == IceState::COMPLETED || this->state == IceState::CONNECTED, + "ICE consent check timer fired but state is neither 'completed' nor 'connected'"); + + // There should be a selected tuple. + MS_ASSERT(this->selectedTuple, "ICE consent check timer fired but there is not selected tuple"); + + MS_WARN_TAG(ice, "ICE consent expired due to timeout, moving to 'disconnected' state"); + + // Update state. + this->state = IceState::DISCONNECTED; + + // Reset remote nomination. + this->remoteNomination = 0u; + + // Clear all tuples. + for (const auto& it : this->tuples) + { + auto* storedTuple = const_cast(std::addressof(it)); + + // Notify the listener. + this->listener->OnIceServerTupleRemoved(this, storedTuple); + } + + // Clear all tuples. + // NOTE: Do it after notifying the listener since the listener may need to + // use/read the tuple being removed so we cannot free it yet. + this->tuples.clear(); + + // Unset selected tuple. + this->selectedTuple = nullptr; + + // Notify the listener. + this->listener->OnIceServerDisconnected(this); + } + } } // namespace RTC diff --git a/worker/src/RTC/KeyFrameRequestManager.cpp b/worker/src/RTC/KeyFrameRequestManager.cpp index 1112901b49..540414ae0c 100644 --- a/worker/src/RTC/KeyFrameRequestManager.cpp +++ b/worker/src/RTC/KeyFrameRequestManager.cpp @@ -4,7 +4,7 @@ #include "RTC/KeyFrameRequestManager.hpp" #include "Logger.hpp" -static constexpr uint32_t KeyFrameRetransmissionWaitTime{ 1000 }; +static constexpr uint32_t KeyFrameRetransmissionWaitTime{ 1000u }; /* PendingKeyFrameInfo methods. */ diff --git a/worker/src/RTC/StunPacket.cpp b/worker/src/RTC/StunPacket.cpp index 518ca8ff97..6747afebd1 100644 --- a/worker/src/RTC/StunPacket.cpp +++ b/worker/src/RTC/StunPacket.cpp @@ -24,23 +24,21 @@ namespace RTC return nullptr; } - /* - The message type field is decomposed further into the following - structure: - - 0 1 - 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - +--+--+-+-+-+-+-+-+-+-+-+-+-+-+ - |M |M |M|M|M|C|M|M|M|C|M|M|M|M| - |11|10|9|8|7|1|6|5|4|0|3|2|1|0| - +--+--+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 3: Format of STUN Message Type Field - - Here the bits in the message type field are shown as most significant - (M11) through least significant (M0). M11 through M0 represent a 12- - bit encoding of the method. C1 and C0 represent a 2-bit encoding of - the class. + /** + * The message type field is decomposed further into the following + * structure: + * + * 0 1 + * 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+-+-+-+-+-+-+-+-+-+-+-+-+ + * |M |M |M|M|M|C|M|M|M|C|M|M|M|M| + * |11|10|9|8|7|1|6|5|4|0|3|2|1|0| + * +--+--+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Here the bits in the message type field are shown as most significant + * (M11) through least significant (M0). M11 through M0 represent a 12-bit + * encoding of the method. C1 and C0 represent a 2-bit encoding of the + * class. */ // Get type field. @@ -49,7 +47,8 @@ namespace RTC // Get length field. const uint16_t msgLength = Utils::Byte::Get2Bytes(data, 2); - // length field must be total size minus header's 20 bytes, and must be multiple of 4 Bytes. + // length field must be total size minus header's 20 bytes, and must be + // multiple of 4 Bytes. if ((static_cast(msgLength) != len - 20) || ((msgLength & 0x03) != 0)) { MS_WARN_TAG( @@ -67,35 +66,38 @@ namespace RTC // Get STUN class. const uint16_t msgClass = ((data[0] & 0x01) << 1) | ((data[1] & 0x10) >> 4); - // Create a new StunPacket (data + 8 points to the received TransactionID field). + // Create a new StunPacket (data + 8 points to the received TransactionID + // field). auto* packet = new StunPacket( static_cast(msgClass), static_cast(msgMethod), data + 8, data, len); - /* - STUN Attributes - - After the STUN header are zero or more attributes. Each attribute - MUST be TLV encoded, with a 16-bit type, 16-bit length, and value. - Each STUN attribute MUST end on a 32-bit boundary. As mentioned - above, all fields in an attribute are transmitted most significant - bit first. - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Value (variable) .... - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /** + * STUN Attributes + * + * After the STUN header are zero or more attributes. Each attribute MUST + * be TLV encoded, with a 16-bit type, 16-bit length, and value. Each STUN + * attribute MUST end on a 32-bit boundary. As mentioned above, all fields + * in an attribute are transmitted most significant bit first. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Value (variable) .... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ // Start looking for attributes after STUN header (Byte #20). size_t pos{ 20 }; - // Flags (positions) for special MESSAGE-INTEGRITY and FINGERPRINT attributes. + // Flags (positions) for special MESSAGE-INTEGRITY and FINGERPRINT + // attributes. bool hasMessageIntegrity{ false }; bool hasFingerprint{ false }; - size_t fingerprintAttrPos; // Will point to the beginning of the attribute. - uint32_t fingerprint; // Holds the value of the FINGERPRINT attribute. + // Will point to the beginning of the attribute. + size_t fingerprintAttrPos; + // Holds the value of the FINGERPRINT attribute. + uint32_t fingerprint; // Ensure there are at least 4 remaining bytes (attribute with 0 length). while (pos + 4 <= len) @@ -285,6 +287,24 @@ namespace RTC break; } + case Attribute::SOFTWARE: + { + // Ensure attribute length is less than 763 bytes. + if (attrLength >= 763) + { + MS_WARN_TAG( + ice, "attribute SOFTWARE must be less than 763 bytes length, packet discarded"); + + delete packet; + return nullptr; + } + + packet->SetSoftware( + reinterpret_cast(attrValuePos), static_cast(attrLength)); + + break; + } + default:; } @@ -351,16 +371,16 @@ namespace RTC switch (this->klass) { case Class::REQUEST: - klass = "Request"; + klass = "request"; break; case Class::INDICATION: - klass = "Indication"; + klass = "indication"; break; case Class::SUCCESS_RESPONSE: - klass = "SuccessResponse"; + klass = "success response"; break; case Class::ERROR_RESPONSE: - klass = "ErrorResponse"; + klass = "error response"; break; } if (this->method == Method::BINDING) @@ -374,14 +394,11 @@ namespace RTC } MS_DUMP(" size: %zu bytes", this->size); - char transactionId[25]; + auto transactionId1 = Utils::Byte::Get4Bytes(this->transactionId, 0); + auto transactionId2 = Utils::Byte::Get8Bytes(this->transactionId, 4); - for (int i{ 0 }; i < 12; ++i) - { - // NOTE: n must be 3 because snprintf adds a \0 after printed chars. - std::snprintf(transactionId + (i * 2), 3, "%.2x", this->transactionId[i]); - } - MS_DUMP(" transactionId: %s", transactionId); + MS_DUMP(" transactionId (first 4 bytes): %" PRIu32, transactionId1); + MS_DUMP(" transactionId (last 8 bytes): %" PRIu64, transactionId2); if (this->errorCode != 0u) { MS_DUMP(" errorCode: %" PRIu16, this->errorCode); @@ -406,6 +423,10 @@ namespace RTC { MS_DUMP(" useCandidate"); } + if (!this->software.empty()) + { + MS_DUMP(" software: %s", this->software.c_str()); + } if (this->xorMappedAddress != nullptr) { int family; @@ -435,8 +456,21 @@ namespace RTC MS_DUMP(""); } + void StunPacket::SetPassword(const std::string& password) + { + // Just for request, indication and success response messages. + if (this->klass == Class::ERROR_RESPONSE) + { + MS_ERROR("cannot set password for error responses"); + + return; + } + + this->password = password; + } + StunPacket::Authentication StunPacket::CheckAuthentication( - const std::string& localUsername, const std::string& localPassword) + const std::string& usernameFragment1, const std::string& password) { MS_TRACE(); @@ -445,46 +479,82 @@ namespace RTC case Class::REQUEST: case Class::INDICATION: { - // Both USERNAME and MESSAGE-INTEGRITY must be present. - if (!this->messageIntegrity || this->username.empty()) + // usernameFragment1 must be given. + if (usernameFragment1.empty()) + { + MS_WARN_TAG(ice, "usernameFragment1 not given, cannot authenticate request or indication"); + + return Authentication::BAD_MESSAGE; + } + + // USERNAME attribute must be present. + if (this->username.empty()) + { + MS_WARN_TAG(ice, "missing USERNAME attribute, cannot authenticate request or indication"); + + return Authentication::BAD_MESSAGE; + } + + // MESSAGE-INTEGRITY attribute must be present. + if (!this->messageIntegrity) { - return Authentication::BAD_REQUEST; + MS_WARN_TAG( + ice, "missing MESSAGE-INTEGRITY attribute, cannot authenticate request or indication"); + + return Authentication::BAD_MESSAGE; } - // Check that USERNAME attribute begins with our local username plus ":". - const size_t localUsernameLen = localUsername.length(); + // Check that the USERNAME attribute begins with the first username + // fragment plus ":". + const size_t usernameFragment1Len = usernameFragment1.length(); if ( - this->username.length() <= localUsernameLen || this->username.at(localUsernameLen) != ':' || - (this->username.compare(0, localUsernameLen, localUsername) != 0)) + this->username.length() <= usernameFragment1Len || + this->username.at(usernameFragment1Len) != ':' || + this->username.compare(0, usernameFragment1Len, usernameFragment1) != 0) { return Authentication::UNAUTHORIZED; } break; } - // This method cannot check authentication in received responses (as we - // are ICE-Lite and don't generate requests). + case Class::SUCCESS_RESPONSE: case Class::ERROR_RESPONSE: { - MS_ERROR("cannot check authentication for a STUN response"); + // MESSAGE-INTEGRITY attribute must be present. + if (!this->messageIntegrity) + { + MS_WARN_TAG(ice, "missing MESSAGE-INTEGRITY attribute, cannot authenticate response"); - return Authentication::BAD_REQUEST; + return Authentication::BAD_MESSAGE; + } + + break; + } + + default: + { + MS_WARN_TAG(ice, "unknown STUN class %" PRIu16 ", cannot authenticate", this->klass); + + return Authentication::BAD_MESSAGE; } } - // If there is FINGERPRINT it must be discarded for MESSAGE-INTEGRITY calculation, - // so the header length field must be modified (and later restored). + // If there is FINGERPRINT it must be discarded for MESSAGE-INTEGRITY + // calculation, so the header length field must be modified (and later + // restored). if (this->hasFingerprint) { - // Set the header length field: full size - header length (20) - FINGERPRINT length (8). + // Set the header length field: full size - header length (20) - + // FINGERPRINT length (8). Utils::Byte::Set2Bytes(this->data, 2, static_cast(this->size - 20 - 8)); } - // Calculate the HMAC-SHA1 of the message according to MESSAGE-INTEGRITY rules. - const uint8_t* computedMessageIntegrity = Utils::Crypto::GetHmacSha1( - localPassword, this->data, (this->messageIntegrity - 4) - this->data); + // Calculate the HMAC-SHA1 of the message according to MESSAGE-INTEGRITY + // rules. + const uint8_t* computedMessageIntegrity = + Utils::Crypto::GetHmacSha1(password, this->data, (this->messageIntegrity - 4) - this->data); Authentication result; @@ -513,7 +583,7 @@ namespace RTC MS_ASSERT( this->klass == Class::REQUEST, - "attempt to create a success response for a non Request STUN packet"); + "attempt to create a success response for a non request STUN packet"); return new StunPacket(Class::SUCCESS_RESPONSE, this->method, this->transactionId, nullptr, 0); } @@ -524,7 +594,7 @@ namespace RTC MS_ASSERT( this->klass == Class::REQUEST, - "attempt to create an error response for a non Request STUN packet"); + "attempt to create an error response for a non request STUN packet"); auto* response = new StunPacket(Class::ERROR_RESPONSE, this->method, this->transactionId, nullptr, 0); @@ -534,19 +604,6 @@ namespace RTC return response; } - void StunPacket::Authenticate(const std::string& password) - { - // Just for Request, Indication and SuccessResponse messages. - if (this->klass == Class::ERROR_RESPONSE) - { - MS_ERROR("cannot set password for ErrorResponse messages"); - - return; - } - - this->password = password; - } - void StunPacket::Serialize(uint8_t* buffer) { MS_TRACE(); @@ -807,7 +864,8 @@ namespace RTC Utils::Byte::Set2Bytes(buffer, 2, static_cast(this->size - 20 - 8)); } - // Calculate the HMAC-SHA1 of the packet according to MESSAGE-INTEGRITY rules. + // Calculate the HMAC-SHA1 of the packet according to MESSAGE-INTEGRITY + // rules. const uint8_t* computedMessageIntegrity = Utils::Crypto::GetHmacSha1(this->password, buffer, pos); diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 830b31ddb7..ea5426970f 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -3083,8 +3083,8 @@ namespace RTC /* * The interval between RTCP packets is varied randomly over the range - * [1.0,1.5] times the calculated interval to avoid unintended synchronization - * of all participants. + * [1.0, 1.5] times the calculated interval to avoid unintended + * synchronization of all participants. */ interval *= static_cast(Utils::Crypto::GetRandomUInt(10, 15)) / 10; diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index bd1c095c13..362b43d455 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -499,7 +499,7 @@ namespace RTC if (this->mapTupleWebRtcTransport.find(tuple->hash) == this->mapTupleWebRtcTransport.end()) { - MS_WARN_TAG(ice, "tuple hash not found in the table"); + MS_DEBUG_TAG(ice, "tuple hash not found in the table"); return; } diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index c718c1179a..a5deb26fe0 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -160,9 +160,11 @@ namespace RTC iceLocalPreferenceDecrement += 100; } + auto iceConsentTimeout = options->iceConsentTimeout(); + // Create a ICE server. this->iceServer = new RTC::IceServer( - this, Utils::Crypto::GetRandomString(32), Utils::Crypto::GetRandomString(32)); + this, Utils::Crypto::GetRandomString(32), Utils::Crypto::GetRandomString(32), iceConsentTimeout); // Create a DTLS transport. this->dtlsTransport = new RTC::DtlsTransport(this); @@ -227,9 +229,11 @@ namespace RTC MS_THROW_TYPE_ERROR("empty iceCandidates"); } + auto iceConsentTimeout = options->iceConsentTimeout(); + // Create a ICE server. this->iceServer = new RTC::IceServer( - this, Utils::Crypto::GetRandomString(32), Utils::Crypto::GetRandomString(32)); + this, Utils::Crypto::GetRandomString(32), Utils::Crypto::GetRandomString(32), iceConsentTimeout); // Create a DTLS transport. this->dtlsTransport = new RTC::DtlsTransport(this); @@ -435,7 +439,8 @@ namespace RTC MS_THROW_ERROR("connect() already called"); } - const auto* body = request->data->body_as(); + const auto* body = request->data->body_as(); + const auto* dtlsParameters = body->dtlsParameters(); RTC::DtlsTransport::Fingerprint dtlsRemoteFingerprint; From 928cda9e4de6efdae31977ace0be9724a0eb1d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 20 Feb 2024 19:19:35 +0100 Subject: [PATCH 360/525] Update NPM dev deps --- package-lock.json | 360 +++++++++++++++++++++++----------------------- package.json | 8 +- 2 files changed, 184 insertions(+), 184 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a81802f6e..3b089ed5f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,12 +21,12 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.17", - "@typescript-eslint/eslint-plugin": "^7.0.1", - "@typescript-eslint/parser": "^7.0.1", + "@types/node": "^20.11.19", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.8.0", + "eslint-plugin-jest": "^27.9.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.0", @@ -1626,9 +1626,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", - "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", + "version": "20.11.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", + "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1662,16 +1662,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.1.tgz", - "integrity": "sha512-OLvgeBv3vXlnnJGIAgCLYKjgMEU+wBGj07MQ/nxAaON+3mLzX7mJbhRYrVGiVvFiXtwFlkcBa/TtmglHy0UbzQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.2.tgz", + "integrity": "sha512-/XtVZJtbaphtdrWjr+CJclaCVGPtOdBpFEnvtNf/jRV0IiEemRrL0qABex/nEt8isYcnFacm3nPHYQwL+Wb7qg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.0.1", - "@typescript-eslint/type-utils": "7.0.1", - "@typescript-eslint/utils": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/type-utils": "7.0.2", + "@typescript-eslint/utils": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1697,13 +1697,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", - "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", + "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1" + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1714,9 +1714,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", - "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", + "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1727,13 +1727,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", - "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", + "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1755,17 +1755,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", + "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.1", - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", "semver": "^7.5.4" }, "engines": { @@ -1780,12 +1780,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", - "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", + "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/types": "7.0.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1821,15 +1821,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.1.tgz", - "integrity": "sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.2.tgz", + "integrity": "sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.0.1", - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/typescript-estree": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4" }, "engines": { @@ -1849,13 +1849,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", - "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", + "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1" + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1866,9 +1866,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", - "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", + "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1879,13 +1879,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", - "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", + "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1907,12 +1907,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", - "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", + "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/types": "7.0.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1965,13 +1965,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.1.tgz", - "integrity": "sha512-YtT9UcstTG5Yqy4xtLiClm1ZpM/pWVGFnkAa90UfdkkZsR1eP2mR/1jbHeYp8Ay1l1JHPyGvoUYR6o3On5Nhmw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.2.tgz", + "integrity": "sha512-IKKDcFsKAYlk8Rs4wiFfEwJTQlHcdn8CLwLaxwd6zb8HNiMcQIFX9sWax2k4Cjj7l7mGS5N1zl7RCHOVwHq2VQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.0.1", - "@typescript-eslint/utils": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/utils": "7.0.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1992,13 +1992,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", - "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", + "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1" + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2009,9 +2009,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", - "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", + "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2022,13 +2022,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", - "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", + "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2050,17 +2050,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", + "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.1", - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", "semver": "^7.5.4" }, "engines": { @@ -2075,12 +2075,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", - "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", + "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/types": "7.0.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3003,9 +3003,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.8.0.tgz", - "integrity": "sha512-347hVFiu4ZKMYl5xFp0X81gLNwBdno0dl0CMpUMjwuAux9X/M2a7z+ab2VHmPL6XCT87q8nv1vaVzhIO4TE/hw==", + "version": "27.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", + "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -7514,9 +7514,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", - "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", + "version": "20.11.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", + "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7550,16 +7550,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.1.tgz", - "integrity": "sha512-OLvgeBv3vXlnnJGIAgCLYKjgMEU+wBGj07MQ/nxAaON+3mLzX7mJbhRYrVGiVvFiXtwFlkcBa/TtmglHy0UbzQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.2.tgz", + "integrity": "sha512-/XtVZJtbaphtdrWjr+CJclaCVGPtOdBpFEnvtNf/jRV0IiEemRrL0qABex/nEt8isYcnFacm3nPHYQwL+Wb7qg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.0.1", - "@typescript-eslint/type-utils": "7.0.1", - "@typescript-eslint/utils": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/type-utils": "7.0.2", + "@typescript-eslint/utils": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7569,29 +7569,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", - "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", + "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1" + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2" } }, "@typescript-eslint/types": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", - "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", + "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", - "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", + "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7601,27 +7601,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", + "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.1", - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", - "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", + "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/types": "7.0.2", "eslint-visitor-keys": "^3.4.1" } }, @@ -7646,42 +7646,42 @@ } }, "@typescript-eslint/parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.1.tgz", - "integrity": "sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.2.tgz", + "integrity": "sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.0.1", - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/typescript-estree": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", - "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", + "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1" + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2" } }, "@typescript-eslint/types": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", - "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", + "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", - "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", + "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7691,12 +7691,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", - "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", + "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/types": "7.0.2", "eslint-visitor-keys": "^3.4.1" } }, @@ -7731,41 +7731,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.1.tgz", - "integrity": "sha512-YtT9UcstTG5Yqy4xtLiClm1ZpM/pWVGFnkAa90UfdkkZsR1eP2mR/1jbHeYp8Ay1l1JHPyGvoUYR6o3On5Nhmw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.2.tgz", + "integrity": "sha512-IKKDcFsKAYlk8Rs4wiFfEwJTQlHcdn8CLwLaxwd6zb8HNiMcQIFX9sWax2k4Cjj7l7mGS5N1zl7RCHOVwHq2VQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.0.1", - "@typescript-eslint/utils": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/utils": "7.0.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", - "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", + "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1" + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2" } }, "@typescript-eslint/types": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", - "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", + "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", - "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", + "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7775,27 +7775,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", + "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.1", - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", - "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", + "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/types": "7.0.2", "eslint-visitor-keys": "^3.4.1" } }, @@ -8459,9 +8459,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "27.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.8.0.tgz", - "integrity": "sha512-347hVFiu4ZKMYl5xFp0X81gLNwBdno0dl0CMpUMjwuAux9X/M2a7z+ab2VHmPL6XCT87q8nv1vaVzhIO4TE/hw==", + "version": "27.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", + "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" diff --git a/package.json b/package.json index 57689dbc1b..c3f719cf52 100644 --- a/package.json +++ b/package.json @@ -110,12 +110,12 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.17", - "@typescript-eslint/eslint-plugin": "^7.0.1", - "@typescript-eslint/parser": "^7.0.1", + "@types/node": "^20.11.19", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.8.0", + "eslint-plugin-jest": "^27.9.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.0", From 780bd7a3f2d5fb9358259367e8655caf7ddc798e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 20 Feb 2024 19:22:37 +0100 Subject: [PATCH 361/525] 3.13.20 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f90f3dd1fa..035a8f8841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### Next +### 3.13.20 - Add server side ICE consent checks to detect silent WebRTC disconnections ([PR #1332](https://github.com/versatica/mediasoup/pull/1332)). - Fix regression (crash) in transport-cc feedback generation ([PR #1339](https://github.com/versatica/mediasoup/pull/1339)). diff --git a/package-lock.json b/package-lock.json index 3b089ed5f3..68cbfb37cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.19", + "version": "3.13.20", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.19", + "version": "3.13.20", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index c3f719cf52..c429646220 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.19", + "version": "3.13.20", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 74934dec78e63fdcd972aa87f1a257d9893974bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 21 Feb 2024 14:31:34 +0100 Subject: [PATCH 362/525] CI: Really run fuzzer for 5 minutes (#1338) --- .../workflows/mediasoup-worker-fuzzer.yaml | 4 +- worker/Dockerfile | 3 ++ worker/Dockerfile.alpine | 3 ++ worker/scripts/run-fuzzer.sh | 38 +++++++++++++++++++ worker/tasks.py | 16 +++++--- 5 files changed, 57 insertions(+), 7 deletions(-) create mode 100755 worker/scripts/run-fuzzer.sh diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index 5f4e5d953e..211754342f 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -37,4 +37,6 @@ jobs: - name: invoke -r worker fuzzer run: invoke -r worker fuzzer - # We don't run mediasoup-worker-fuzzer (maybe in the future). + # Run mediasoup-worker-fuzzer for 5 minutes. + - name: run-fuzzer.sh 300 + run: cd worker && ./scripts/run-fuzzer.sh 300 diff --git a/worker/Dockerfile b/worker/Dockerfile index 64ae430df2..674291f118 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -28,6 +28,9 @@ ENV CXX="clang++" ENV MEDIASOUP_LOCAL_DEV="true" ENV KEEP_BUILD_ARTIFACTS="1" +# Disable liburing due to this bug: +# https://github.com/versatica/mediasoup/issues/1334 +ENV MESON_ARGS="-Dms_disable_liburing=true" WORKDIR /mediasoup diff --git a/worker/Dockerfile.alpine b/worker/Dockerfile.alpine index 68cf11664d..04689b61f0 100644 --- a/worker/Dockerfile.alpine +++ b/worker/Dockerfile.alpine @@ -11,6 +11,9 @@ ENV CXX="g++" ENV MEDIASOUP_LOCAL_DEV="true" ENV KEEP_BUILD_ARTIFACTS="1" +# Disable liburing due to this bug: +# https://github.com/versatica/mediasoup/issues/1334 +ENV MESON_ARGS="-Dms_disable_liburing=true" WORKDIR /mediasoup diff --git a/worker/scripts/run-fuzzer.sh b/worker/scripts/run-fuzzer.sh new file mode 100755 index 0000000000..bc9c5321b6 --- /dev/null +++ b/worker/scripts/run-fuzzer.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +WORKER_PWD=${PWD} +DURATION_SEC=$1 + +current_dir_name=${WORKER_PWD##*/} +if [ "${current_dir_name}" != "worker" ] ; then + echo "run-fuzzer.sh [ERROR] $(basename $0) must be called from mediasoup/worker directory" >&2 + exit 1 +fi + +if [ "$#" -eq 0 ] ; then + echo "run-fuzzer.sh [ERROR] duration (in seconds) must be fiven as argument" >&2 + exit 1 +fi + +invoke fuzzer-run-all & + +MEDIASOUP_WORKER_FUZZER_PID=$! + +i=${DURATION_SEC} + +until [ ${i} -eq 0 ] +do + echo "run-fuzzer.sh [INFO] ${i} seconds left" + if ! kill -0 ${MEDIASOUP_WORKER_FUZZER_PID} &> /dev/null ; then + echo "run-fuzzer.sh [ERROR] mediasoup-worker-fuzzer died" >&2 + exit 1 + else + ((i=i-1)) + sleep 1 + fi +done + +echo "run-fuzzer.sh [INFO] mediasoup-worker-fuzzer is still running after given ${DURATION_SEC} seconds so no fuzzer issues so far" + +kill -SIGTERM ${MEDIASOUP_WORKER_FUZZER_PID} &> /dev/null +exit 0 diff --git a/worker/tasks.py b/worker/tasks.py index a99f74cf5c..728e7cf962 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -23,7 +23,7 @@ import inspect; import shutil; # We import this from a custom location and pylint doesn't know. -from invoke import task; # pylint: disable=import-error +from invoke import task, call; # pylint: disable=import-error MEDIASOUP_BUILDTYPE = os.getenv('MEDIASOUP_BUILDTYPE') or 'Release'; WORKER_DIR = os.path.dirname(os.path.abspath( @@ -135,14 +135,14 @@ def meson_ninja(ctx): @task(pre=[meson_ninja]) -def setup(ctx): +def setup(ctx, meson_args=MESON_ARGS): """ Run meson setup """ if MEDIASOUP_BUILDTYPE == 'Release': with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true {MESON_ARGS} "{BUILD_DIR}"', + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true {meson_args} "{BUILD_DIR}"', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -150,7 +150,7 @@ def setup(ctx): elif MEDIASOUP_BUILDTYPE == 'Debug': with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug {MESON_ARGS} "{BUILD_DIR}"', + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug {meson_args} "{BUILD_DIR}"', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -158,7 +158,7 @@ def setup(ctx): else: with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( - f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release {MESON_ARGS} "{BUILD_DIR}"', + f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release {meson_args} "{BUILD_DIR}"', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -464,11 +464,15 @@ def tidy(ctx): ); -@task(pre=[setup, flatc]) +@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=address'), flatc]) def fuzzer(ctx): """ Build the mediasoup-worker-fuzzer binary (which uses libFuzzer) """ + + # NOTE: We need to pass '-Db_sanitize=address' to enable fuzzer in all Meson + # subprojects, so we pass it to the setup() task. + with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-fuzzer', From 45964b2697f9e22f5ff89bd86561106d069a4ddc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:42:14 +0100 Subject: [PATCH 363/525] Bump the npm_and_yarn group across 1 directories with 1 update (#1341) Bumps the npm_and_yarn group with 1 update in the /. directory: [ip](https://github.com/indutny/node-ip). Updates `ip` from 1.1.8 to 1.1.9 - [Commits](https://github.com/indutny/node-ip/compare/v1.1.8...v1.1.9) --- updated-dependencies: - dependency-name: ip dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 68cbfb37cc..c16855716f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3749,9 +3749,9 @@ "dev": true }, "node_modules/ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", "dev": true }, "node_modules/is-arrayish": { @@ -8951,9 +8951,9 @@ "dev": true }, "ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", "dev": true }, "is-arrayish": { From af2ae379d45b2028002ca4b863b48793aa557f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 21 Feb 2024 18:01:44 +0100 Subject: [PATCH 364/525] Revert PR #1156 "Make DTLS fragment stay within MTU size range" because it causes a memory leak (#1342) --- CHANGELOG.md | 4 + worker/include/RTC/DtlsTransport.hpp | 3 +- worker/src/RTC/DtlsTransport.cpp | 117 +++++++++++++++------------ 3 files changed, 71 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 035a8f8841..3713af892d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Next + +- Revert ([PR #1156](https://github.com/versatica/mediasoup/pull/1156)) "Make DTLS fragment stay within MTU size range" because it causes a memory leak ([PR #1342](https://github.com/versatica/mediasoup/pull/1342)). + ### 3.13.20 - Add server side ICE consent checks to detect silent WebRTC disconnections ([PR #1332](https://github.com/versatica/mediasoup/pull/1332)). diff --git a/worker/include/RTC/DtlsTransport.hpp b/worker/include/RTC/DtlsTransport.hpp index 27f4bd847f..0d50c3eb07 100644 --- a/worker/include/RTC/DtlsTransport.hpp +++ b/worker/include/RTC/DtlsTransport.hpp @@ -152,8 +152,6 @@ namespace RTC return this->localRole; } void SendApplicationData(const uint8_t* data, size_t len); - // This method must be public since it's called within an OpenSSL callback. - void SendDtlsData(const uint8_t* data, size_t len); private: bool IsRunning() const @@ -175,6 +173,7 @@ namespace RTC } void Reset(); bool CheckStatus(int returnCode); + void SendPendingOutgoingDtlsData(); bool SetTimeout(); bool ProcessHandshake(); bool CheckRemoteFingerprint(); diff --git a/worker/src/RTC/DtlsTransport.cpp b/worker/src/RTC/DtlsTransport.cpp index 3199c6aed4..3bb8a9657c 100644 --- a/worker/src/RTC/DtlsTransport.cpp +++ b/worker/src/RTC/DtlsTransport.cpp @@ -61,30 +61,6 @@ inline static unsigned int onSslDtlsTimer(SSL* /*ssl*/, unsigned int timerUs) } } -inline static long onSslBioOut( - BIO* bio, - int operationType, - const char* argp, - size_t len, - int /*argi*/, - long /*argl*/, - int ret, - size_t* /*processed*/) -{ - const long resultOfcallback = (operationType == BIO_CB_RETURN) ? static_cast(ret) : 1; - - if (operationType == BIO_CB_WRITE && argp && len > 0) - { - MS_DEBUG_DEV("%zu bytes of DTLS data ready to be sent", len); - - auto* dtlsTransport = reinterpret_cast(BIO_get_callback_arg(bio)); - - dtlsTransport->SendDtlsData(reinterpret_cast(argp), len); - } - - return resultOfcallback; -} - namespace RTC { /* Static. */ @@ -730,11 +706,12 @@ namespace RTC goto error; } - BIO_set_callback_ex(this->sslBioToNetwork, onSslBioOut); - BIO_set_callback_arg(this->sslBioToNetwork, reinterpret_cast(this)); SSL_set_bio(this->ssl, this->sslBioFromNetwork, this->sslBioToNetwork); - // Set the MTU so that we don't send packets that are too large with no fragmentation. + // Set the MTU so that we don't send packets that are too large with no + // fragmentation. + // TODO: This is not honored, see issue: + // https://github.com/versatica/mediasoup/issues/1100 SSL_set_mtu(this->ssl, DtlsMtu); DTLS_set_link_mtu(this->ssl, DtlsMtu); @@ -778,6 +755,7 @@ namespace RTC { // Send close alert to the peer. SSL_shutdown(this->ssl); + SendPendingOutgoingDtlsData(); } if (this->ssl) @@ -900,6 +878,7 @@ namespace RTC SSL_set_connect_state(this->ssl); SSL_do_handshake(this->ssl); + SendPendingOutgoingDtlsData(); SetTimeout(); break; @@ -970,6 +949,9 @@ namespace RTC // Must call SSL_read() to process received DTLS data. read = SSL_read(this->ssl, static_cast(DtlsTransport::sslReadBuffer), SslReadBufferSize); + // Send data if it's ready. + SendPendingOutgoingDtlsData(); + // Check SSL status and return if it is bad/closed. if (!CheckStatus(read)) { @@ -985,7 +967,8 @@ namespace RTC // Application data received. Notify to the listener. if (read > 0) { - // It is allowed to receive DTLS data even before validating remote fingerprint. + // It is allowed to receive DTLS data even before validating remote + // fingerprint. if (!this->handshakeDone) { MS_WARN_TAG(dtls, "ignoring application data received while DTLS handshake not done"); @@ -1003,7 +986,8 @@ namespace RTC { MS_TRACE(); - // We cannot send data to the peer if its remote fingerprint is not validated. + // We cannot send data to the peer if its remote fingerprint is not + // validated. if (this->state != DtlsState::CONNECTED) { MS_WARN_TAG(dtls, "cannot send application data while DTLS is not fully connected"); @@ -1036,14 +1020,9 @@ namespace RTC MS_WARN_TAG( dtls, "OpenSSL SSL_write() wrote less (%d bytes) than given data (%zu bytes)", written, len); } - } - - void DtlsTransport::SendDtlsData(const uint8_t* data, size_t len) - { - MS_TRACE(); - // Notify the listener. - this->listener->OnDtlsTransportSendData(this, data, len); + // Send data. + SendPendingOutgoingDtlsData(); } void DtlsTransport::Reset() @@ -1062,8 +1041,9 @@ namespace RTC // Stop the DTLS timer. this->timer->Stop(); - // NOTE: We need to reset the SSL instance so we need to "shutdown" it, but we - // don't want to send a Close Alert to the peer. However this is gonna happen. + // NOTE: We need to reset the SSL instance so we need to "shutdown" it, but + // we don't want to send a Close Alert to the peer, so just don't call + // SendPendingOutgoingDTLSData(). SSL_shutdown(this->ssl); this->localRole.reset(); @@ -1083,7 +1063,7 @@ namespace RTC } } - inline bool DtlsTransport::CheckStatus(int returnCode) + bool DtlsTransport::CheckStatus(int returnCode) { MS_TRACE(); @@ -1200,7 +1180,37 @@ namespace RTC } } - inline bool DtlsTransport::SetTimeout() + void DtlsTransport::SendPendingOutgoingDtlsData() + { + MS_TRACE(); + + if (BIO_eof(this->sslBioToNetwork)) + { + return; + } + + int64_t read; + char* data{ nullptr }; + + read = BIO_get_mem_data(this->sslBioToNetwork, &data); // NOLINT + + if (read <= 0) + { + return; + } + + MS_DEBUG_DEV("%" PRIu64 " bytes of DTLS data ready to sent to the peer", read); + + // Notify the listener. + this->listener->OnDtlsTransportSendData( + this, reinterpret_cast(data), static_cast(read)); + + // Clear the BIO buffer. + // NOTE: the (void) avoids the -Wunused-value warning. + (void)BIO_reset(this->sslBioToNetwork); + } + + bool DtlsTransport::SetTimeout() { MS_TRACE(); @@ -1235,7 +1245,8 @@ namespace RTC return true; } - // NOTE: Don't start the timer again if the timeout is greater than 30 seconds. + // NOTE: Don't start the timer again if the timeout is greater than 30 + // seconds. else { MS_WARN_TAG(dtls, "DTLS timeout too high (%" PRIu64 "ms), resetting DLTS", timeoutMs); @@ -1250,7 +1261,7 @@ namespace RTC } } - inline bool DtlsTransport::ProcessHandshake() + bool DtlsTransport::ProcessHandshake() { MS_TRACE(); @@ -1292,7 +1303,7 @@ namespace RTC return false; } - inline bool DtlsTransport::CheckRemoteFingerprint() + bool DtlsTransport::CheckRemoteFingerprint() { MS_TRACE(); @@ -1386,8 +1397,8 @@ namespace RTC BIO* bio = BIO_new(BIO_s_mem()); // Ensure the underlying BUF_MEM structure is also freed. - // NOTE: Avoid stupid "warning: value computed is not used [-Wunused-value]" since - // BIO_set_close() always returns 1. + // NOTE: Avoid stupid "warning: value computed is not used [-Wunused-value]" + // since BIO_set_close() always returns 1. (void)BIO_set_close(bio, BIO_CLOSE); ret = PEM_write_bio_X509(bio, certificate); @@ -1424,7 +1435,7 @@ namespace RTC return true; } - inline void DtlsTransport::ExtractSrtpKeys(RTC::SrtpSession::CryptoSuite srtpCryptoSuite) + void DtlsTransport::ExtractSrtpKeys(RTC::SrtpSession::CryptoSuite srtpCryptoSuite) { MS_TRACE(); @@ -1529,7 +1540,7 @@ namespace RTC delete[] srtpRemoteMasterKey; } - inline std::optional DtlsTransport::GetNegotiatedSrtpCryptoSuite() + std::optional DtlsTransport::GetNegotiatedSrtpCryptoSuite() { MS_TRACE(); @@ -1563,7 +1574,7 @@ namespace RTC return negotiatedSrtpCryptoSuite; } - inline void DtlsTransport::OnSslInfo(int where, int ret) + void DtlsTransport::OnSslInfo(int where, int ret) { MS_TRACE(); @@ -1646,11 +1657,12 @@ namespace RTC this->handshakeDoneNow = true; } - // NOTE: checking SSL_get_shutdown(this->ssl) & SSL_RECEIVED_SHUTDOWN here upon - // receipt of a close alert does not work (the flag is set after this callback). + // NOTE: checking SSL_get_shutdown(this->ssl) & SSL_RECEIVED_SHUTDOWN here + // upon receipt of a close alert does not work (the flag is set after this + // callback). } - inline void DtlsTransport::OnTimer(TimerHandle* /*timer*/) + void DtlsTransport::OnTimer(TimerHandle* /*timer*/) { MS_TRACE(); @@ -1670,6 +1682,9 @@ namespace RTC if (ret == 1) { + // If required, send DTLS data. + SendPendingOutgoingDtlsData(); + // Set the DTLS timer again. SetTimeout(); } From f9f75facd1c64aff1689705161d5678501bcd384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 21 Feb 2024 18:20:24 +0100 Subject: [PATCH 365/525] 3.13.22 --- CHANGELOG.md | 6 +++++- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3713af892d..3404784291 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog -### Next +### 3.13.22 + +- Fix wrong publication of mediasoup NPM 3.13.21. + +### 3.13.21 - Revert ([PR #1156](https://github.com/versatica/mediasoup/pull/1156)) "Make DTLS fragment stay within MTU size range" because it causes a memory leak ([PR #1342](https://github.com/versatica/mediasoup/pull/1342)). diff --git a/package-lock.json b/package-lock.json index c16855716f..d77c4bdbd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.20", + "version": "3.13.22", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.20", + "version": "3.13.22", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index c429646220..54a8fd3a1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.20", + "version": "3.13.22", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 5547e44d8d72d8b4dcf76e64e14813ac20ea0738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 21 Feb 2024 21:22:53 +0100 Subject: [PATCH 366/525] Remove the liburing workaround in Dockerfiles since we can mount a case sensitive disk in macOS: https://github.com/versatica/mediasoup/issues/1334#issuecomment-1957831658 --- worker/Dockerfile | 3 --- worker/Dockerfile.alpine | 3 --- 2 files changed, 6 deletions(-) diff --git a/worker/Dockerfile b/worker/Dockerfile index 674291f118..64ae430df2 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -28,9 +28,6 @@ ENV CXX="clang++" ENV MEDIASOUP_LOCAL_DEV="true" ENV KEEP_BUILD_ARTIFACTS="1" -# Disable liburing due to this bug: -# https://github.com/versatica/mediasoup/issues/1334 -ENV MESON_ARGS="-Dms_disable_liburing=true" WORKDIR /mediasoup diff --git a/worker/Dockerfile.alpine b/worker/Dockerfile.alpine index 04689b61f0..68cf11664d 100644 --- a/worker/Dockerfile.alpine +++ b/worker/Dockerfile.alpine @@ -11,9 +11,6 @@ ENV CXX="g++" ENV MEDIASOUP_LOCAL_DEV="true" ENV KEEP_BUILD_ARTIFACTS="1" -# Disable liburing due to this bug: -# https://github.com/versatica/mediasoup/issues/1334 -ENV MESON_ARGS="-Dms_disable_liburing=true" WORKDIR /mediasoup From fca4f5b11bc18cc0b5e055177770c26bfdecb397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 22 Feb 2024 16:55:19 +0100 Subject: [PATCH 367/525] cosmetic: add some 'clang-format off' in DtlsTransport.cpp --- worker/src/RTC/DtlsTransport.cpp | 34 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/worker/src/RTC/DtlsTransport.cpp b/worker/src/RTC/DtlsTransport.cpp index 3bb8a9657c..c88977bdc7 100644 --- a/worker/src/RTC/DtlsTransport.cpp +++ b/worker/src/RTC/DtlsTransport.cpp @@ -12,23 +12,25 @@ #include // std::snprintf(), std::fopen() #include // std::memcpy(), std::strcmp() -#define LOG_OPENSSL_ERROR(desc) \ - do \ - { \ - if (ERR_peek_error() == 0) \ - { \ - MS_ERROR("OpenSSL error [desc:'%s']", desc); \ - } \ - else \ - { \ - int64_t err; \ - while ((err = ERR_get_error()) != 0) \ - { \ - MS_ERROR("OpenSSL error [desc:'%s', error:'%s']", desc, ERR_error_string(err, nullptr)); \ - } \ - ERR_clear_error(); \ - } \ +// clang-format off +#define LOG_OPENSSL_ERROR(desc) \ + do \ + { \ + if (ERR_peek_error() == 0) \ + { \ + MS_ERROR("OpenSSL error [desc:'%s']", desc); \ + } \ + else \ + { \ + int64_t err; \ + while ((err = ERR_get_error()) != 0) \ + { \ + MS_ERROR("OpenSSL error [desc:'%s', error:'%s']", desc, ERR_error_string(err, nullptr)); \ + } \ + ERR_clear_error(); \ + } \ } while (false) +// clang-format on /* Static methods for OpenSSL callbacks. */ From 7e1a995eaf6464664402360e1934b8e9805b9111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 22 Feb 2024 17:14:24 +0100 Subject: [PATCH 368/525] cosmetic: apply consistent tabulation (no tabulation) to values in Dump() methods --- worker/src/RTC/Codecs/H264.cpp | 12 ++--- worker/src/RTC/Codecs/H264_SVC.cpp | 14 ++--- worker/src/RTC/Codecs/Opus.cpp | 6 +-- worker/src/RTC/Codecs/VP8.cpp | 34 ++++++------ worker/src/RTC/Codecs/VP9.cpp | 30 +++++------ worker/src/RTC/RTCP/Bye.cpp | 4 +- worker/src/RTC/RTCP/Feedback.cpp | 6 +-- worker/src/RTC/RTCP/FeedbackPsFir.cpp | 4 +- worker/src/RTC/RTCP/FeedbackPsLei.cpp | 2 +- worker/src/RTC/RTCP/FeedbackPsRemb.cpp | 4 +- worker/src/RTC/RTCP/FeedbackPsRpsi.cpp | 6 +-- worker/src/RTC/RTCP/FeedbackPsSli.cpp | 6 +-- worker/src/RTC/RTCP/FeedbackPsTst.cpp | 6 +-- worker/src/RTC/RTCP/FeedbackPsVbcm.cpp | 8 +-- worker/src/RTC/RTCP/FeedbackRtpEcn.cpp | 14 ++--- worker/src/RTC/RTCP/FeedbackRtpNack.cpp | 4 +- worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp | 6 +-- worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 14 ++--- worker/src/RTC/RTCP/ReceiverReport.cpp | 14 ++--- worker/src/RTC/RTCP/Sdes.cpp | 8 +-- worker/src/RTC/RTCP/SenderReport.cpp | 12 ++--- worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp | 12 ++--- .../src/RTC/RTCP/XrReceiverReferenceTime.cpp | 10 ++-- worker/src/RTC/RtpPacket.cpp | 53 +++++++++---------- worker/src/RTC/StunPacket.cpp | 4 +- worker/src/RTC/TransportTuple.cpp | 12 ++--- worker/src/handles/TcpConnectionHandle.cpp | 10 ++-- worker/src/handles/TcpServerHandle.cpp | 10 ++-- worker/src/handles/UdpSocketHandle.cpp | 6 +-- 29 files changed, 163 insertions(+), 168 deletions(-) diff --git a/worker/src/RTC/Codecs/H264.cpp b/worker/src/RTC/Codecs/H264.cpp index fef2c1d56e..63bff4dcab 100644 --- a/worker/src/RTC/Codecs/H264.cpp +++ b/worker/src/RTC/Codecs/H264.cpp @@ -161,7 +161,7 @@ namespace RTC { MS_TRACE(); - MS_DUMP(""); + MS_DUMP(""); MS_DUMP( " s:%" PRIu8 "|e:%" PRIu8 "|i:%" PRIu8 "|d:%" PRIu8 "|b:%" PRIu8, this->s, @@ -171,18 +171,18 @@ namespace RTC this->b); if (this->hasTid) { - MS_DUMP(" tid : %" PRIu8, this->tid); + MS_DUMP(" tid: %" PRIu8, this->tid); } if (this->hasLid) { - MS_DUMP(" lid : %" PRIu8, this->lid); + MS_DUMP(" lid: %" PRIu8, this->lid); } if (this->hasTl0picidx) { - MS_DUMP(" tl0picidx : %" PRIu8, this->tl0picidx); + MS_DUMP(" tl0picidx: %" PRIu8, this->tl0picidx); } - MS_DUMP(" isKeyFrame : %s", this->isKeyFrame ? "true" : "false"); - MS_DUMP(""); + MS_DUMP(" isKeyFrame: %s", this->isKeyFrame ? "true" : "false"); + MS_DUMP(""); } H264::PayloadDescriptorHandler::PayloadDescriptorHandler(H264::PayloadDescriptor* payloadDescriptor) diff --git a/worker/src/RTC/Codecs/H264_SVC.cpp b/worker/src/RTC/Codecs/H264_SVC.cpp index f4ff7fc319..f67b1fae86 100644 --- a/worker/src/RTC/Codecs/H264_SVC.cpp +++ b/worker/src/RTC/Codecs/H264_SVC.cpp @@ -251,7 +251,7 @@ namespace RTC { MS_TRACE(); - MS_DUMP(""); + MS_DUMP(""); MS_DUMP( " s:%" PRIu8 "|e:%" PRIu8 "|i:%" PRIu8 "|d:%" PRIu8 "|b:%" PRIu8, this->s, @@ -259,12 +259,12 @@ namespace RTC this->i, this->d, this->b); - MS_DUMP(" hasSlIndex : %s", this->hasSlIndex ? "true" : "false"); - MS_DUMP(" hasTlIndex : %s", this->hasTlIndex ? "true" : "false"); - MS_DUMP(" tl0picidx : %" PRIu8, this->tl0picidx); - MS_DUMP(" noIntLayerPredFlag : %" PRIu8, this->noIntLayerPredFlag); - MS_DUMP(" isKeyFrame : %s", this->isKeyFrame ? "true" : "false"); - MS_DUMP(""); + MS_DUMP(" hasSlIndex: %s", this->hasSlIndex ? "true" : "false"); + MS_DUMP(" hasTlIndex: %s", this->hasTlIndex ? "true" : "false"); + MS_DUMP(" tl0picidx: %" PRIu8, this->tl0picidx); + MS_DUMP(" noIntLayerPredFlag: %" PRIu8, this->noIntLayerPredFlag); + MS_DUMP(" isKeyFrame: %s", this->isKeyFrame ? "true" : "false"); + MS_DUMP(""); } H264_SVC::PayloadDescriptorHandler::PayloadDescriptorHandler( diff --git a/worker/src/RTC/Codecs/Opus.cpp b/worker/src/RTC/Codecs/Opus.cpp index 90dd986d4d..4ff265ec1b 100644 --- a/worker/src/RTC/Codecs/Opus.cpp +++ b/worker/src/RTC/Codecs/Opus.cpp @@ -45,9 +45,9 @@ namespace RTC { MS_TRACE(); - MS_DUMP(""); - MS_DUMP(" isDtx : %s", this->isDtx ? "true" : "false"); - MS_DUMP(""); + MS_DUMP(""); + MS_DUMP(" isDtx: %s", this->isDtx ? "true" : "false"); + MS_DUMP(""); } Opus::PayloadDescriptorHandler::PayloadDescriptorHandler(Opus::PayloadDescriptor* payloadDescriptor) diff --git a/worker/src/RTC/Codecs/VP8.cpp b/worker/src/RTC/Codecs/VP8.cpp index bab206bd04..0c336ce1b3 100644 --- a/worker/src/RTC/Codecs/VP8.cpp +++ b/worker/src/RTC/Codecs/VP8.cpp @@ -167,25 +167,25 @@ namespace RTC { MS_TRACE(); - MS_DUMP(""); + MS_DUMP(""); MS_DUMP( " i:%" PRIu8 "|l:%" PRIu8 "|t:%" PRIu8 "|k:%" PRIu8, this->i, this->l, this->t, this->k); - MS_DUMP(" extended : %" PRIu8, this->extended); - MS_DUMP(" nonReference : %" PRIu8, this->nonReference); - MS_DUMP(" start : %" PRIu8, this->start); - MS_DUMP(" partitionIndex : %" PRIu8, this->partitionIndex); - MS_DUMP(" pictureId : %" PRIu16, this->pictureId); - MS_DUMP(" tl0PictureIndex : %" PRIu8, this->tl0PictureIndex); - MS_DUMP(" tlIndex : %" PRIu8, this->tlIndex); - MS_DUMP(" y : %" PRIu8, this->y); - MS_DUMP(" keyIndex : %" PRIu8, this->keyIndex); - MS_DUMP(" isKeyFrame : %s", this->isKeyFrame ? "true" : "false"); - MS_DUMP(" hasPictureId : %s", this->hasPictureId ? "true" : "false"); - MS_DUMP(" hasOneBytePictureId : %s", this->hasOneBytePictureId ? "true" : "false"); - MS_DUMP(" hasTwoBytesPictureId : %s", this->hasTwoBytesPictureId ? "true" : "false"); - MS_DUMP(" hasTl0PictureIndex : %s", this->hasTl0PictureIndex ? "true" : "false"); - MS_DUMP(" hasTlIndex : %s", this->hasTlIndex ? "true" : "false"); - MS_DUMP(""); + MS_DUMP(" extended: %" PRIu8, this->extended); + MS_DUMP(" nonReference: %" PRIu8, this->nonReference); + MS_DUMP(" start: %" PRIu8, this->start); + MS_DUMP(" partitionIndex: %" PRIu8, this->partitionIndex); + MS_DUMP(" pictureId: %" PRIu16, this->pictureId); + MS_DUMP(" tl0PictureIndex: %" PRIu8, this->tl0PictureIndex); + MS_DUMP(" tlIndex: %" PRIu8, this->tlIndex); + MS_DUMP(" y: %" PRIu8, this->y); + MS_DUMP(" keyIndex: %" PRIu8, this->keyIndex); + MS_DUMP(" isKeyFrame: %s", this->isKeyFrame ? "true" : "false"); + MS_DUMP(" hasPictureId: %s", this->hasPictureId ? "true" : "false"); + MS_DUMP(" hasOneBytePictureId: %s", this->hasOneBytePictureId ? "true" : "false"); + MS_DUMP(" hasTwoBytesPictureId: %s", this->hasTwoBytesPictureId ? "true" : "false"); + MS_DUMP(" hasTl0PictureIndex: %s", this->hasTl0PictureIndex ? "true" : "false"); + MS_DUMP(" hasTlIndex: %s", this->hasTlIndex ? "true" : "false"); + MS_DUMP(""); } void VP8::PayloadDescriptor::Encode(uint8_t* data, uint16_t pictureId, uint8_t tl0PictureIndex) const diff --git a/worker/src/RTC/Codecs/VP9.cpp b/worker/src/RTC/Codecs/VP9.cpp index 7f4b2d7c00..646ca8d72a 100644 --- a/worker/src/RTC/Codecs/VP9.cpp +++ b/worker/src/RTC/Codecs/VP9.cpp @@ -146,7 +146,7 @@ namespace RTC { MS_TRACE(); - MS_DUMP(""); + MS_DUMP(""); MS_DUMP( " i:%" PRIu8 "|p:%" PRIu8 "|l:%" PRIu8 "|f:%" PRIu8 "|b:%" PRIu8 "|e:%" PRIu8 "|v:%" PRIu8, this->i, @@ -156,20 +156,20 @@ namespace RTC this->b, this->e, this->v); - MS_DUMP(" pictureId : %" PRIu16, this->pictureId); - MS_DUMP(" slIndex : %" PRIu8, this->slIndex); - MS_DUMP(" tlIndex : %" PRIu8, this->tlIndex); - MS_DUMP(" tl0PictureIndex : %" PRIu8, this->tl0PictureIndex); - MS_DUMP(" interLayerDependency : %" PRIu8, this->interLayerDependency); - MS_DUMP(" switchingUpPoint : %" PRIu8, this->switchingUpPoint); - MS_DUMP(" isKeyFrame : %s", this->isKeyFrame ? "true" : "false"); - MS_DUMP(" hasPictureId : %s", this->hasPictureId ? "true" : "false"); - MS_DUMP(" hasOneBytePictureId : %s", this->hasOneBytePictureId ? "true" : "false"); - MS_DUMP(" hasTwoBytesPictureId : %s", this->hasTwoBytesPictureId ? "true" : "false"); - MS_DUMP(" hasTl0PictureIndex : %s", this->hasTl0PictureIndex ? "true" : "false"); - MS_DUMP(" hasSlIndex : %s", this->hasSlIndex ? "true" : "false"); - MS_DUMP(" hasTlIndex : %s", this->hasTlIndex ? "true" : "false"); - MS_DUMP(""); + MS_DUMP(" pictureId: %" PRIu16, this->pictureId); + MS_DUMP(" slIndex: %" PRIu8, this->slIndex); + MS_DUMP(" tlIndex: %" PRIu8, this->tlIndex); + MS_DUMP(" tl0PictureIndex: %" PRIu8, this->tl0PictureIndex); + MS_DUMP(" interLayerDependency: %" PRIu8, this->interLayerDependency); + MS_DUMP(" switchingUpPoint: %" PRIu8, this->switchingUpPoint); + MS_DUMP(" isKeyFrame: %s", this->isKeyFrame ? "true" : "false"); + MS_DUMP(" hasPictureId: %s", this->hasPictureId ? "true" : "false"); + MS_DUMP(" hasOneBytePictureId: %s", this->hasOneBytePictureId ? "true" : "false"); + MS_DUMP(" hasTwoBytesPictureId: %s", this->hasTwoBytesPictureId ? "true" : "false"); + MS_DUMP(" hasTl0PictureIndex: %s", this->hasTl0PictureIndex ? "true" : "false"); + MS_DUMP(" hasSlIndex: %s", this->hasSlIndex ? "true" : "false"); + MS_DUMP(" hasTlIndex: %s", this->hasTlIndex ? "true" : "false"); + MS_DUMP(""); } VP9::PayloadDescriptorHandler::PayloadDescriptorHandler(VP9::PayloadDescriptor* payloadDescriptor) diff --git a/worker/src/RTC/RTCP/Bye.cpp b/worker/src/RTC/RTCP/Bye.cpp index 94772b5eed..beea0f4273 100644 --- a/worker/src/RTC/RTCP/Bye.cpp +++ b/worker/src/RTC/RTCP/Bye.cpp @@ -94,11 +94,11 @@ namespace RTC MS_DUMP(""); for (auto ssrc : this->ssrcs) { - MS_DUMP(" ssrc : %" PRIu32, ssrc); + MS_DUMP(" ssrc: %" PRIu32, ssrc); } if (!this->reason.empty()) { - MS_DUMP(" reason : %s", this->reason.c_str()); + MS_DUMP(" reason: %s", this->reason.c_str()); } MS_DUMP(""); } diff --git a/worker/src/RTC/RTCP/Feedback.cpp b/worker/src/RTC/RTCP/Feedback.cpp index 4286556457..907322dee9 100644 --- a/worker/src/RTC/RTCP/Feedback.cpp +++ b/worker/src/RTC/RTCP/Feedback.cpp @@ -87,9 +87,9 @@ namespace RTC { MS_TRACE(); - MS_DUMP(" sender ssrc : %" PRIu32, GetSenderSsrc()); - MS_DUMP(" media ssrc : %" PRIu32, GetMediaSsrc()); - MS_DUMP(" size : %zu", this->GetSize()); + MS_DUMP(" sender ssrc: %" PRIu32, GetSenderSsrc()); + MS_DUMP(" media ssrc: %" PRIu32, GetMediaSsrc()); + MS_DUMP(" size: %zu", this->GetSize()); } /* Specialization for Ps class. */ diff --git a/worker/src/RTC/RTCP/FeedbackPsFir.cpp b/worker/src/RTC/RTCP/FeedbackPsFir.cpp index ee69ac635c..d39ff4aed9 100644 --- a/worker/src/RTC/RTCP/FeedbackPsFir.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsFir.cpp @@ -41,8 +41,8 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" ssrc : %" PRIu32, this->GetSsrc()); - MS_DUMP(" sequence number : %" PRIu8, this->GetSequenceNumber()); + MS_DUMP(" ssrc: %" PRIu32, this->GetSsrc()); + MS_DUMP(" sequence number: %" PRIu8, this->GetSequenceNumber()); MS_DUMP(""); } } // namespace RTCP diff --git a/worker/src/RTC/RTCP/FeedbackPsLei.cpp b/worker/src/RTC/RTCP/FeedbackPsLei.cpp index 8ecc265461..147c469993 100644 --- a/worker/src/RTC/RTCP/FeedbackPsLei.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsLei.cpp @@ -34,7 +34,7 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" ssrc : %" PRIu32, this->GetSsrc()); + MS_DUMP(" ssrc: %" PRIu32, this->GetSsrc()); MS_DUMP(""); } } // namespace RTCP diff --git a/worker/src/RTC/RTCP/FeedbackPsRemb.cpp b/worker/src/RTC/RTCP/FeedbackPsRemb.cpp index a4855984ba..cef3adcc45 100644 --- a/worker/src/RTC/RTCP/FeedbackPsRemb.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsRemb.cpp @@ -147,10 +147,10 @@ namespace RTC MS_DUMP(""); FeedbackPsPacket::Dump(); - MS_DUMP(" bitrate (bps) : %" PRIu64, this->bitrate); + MS_DUMP(" bitrate (bps): %" PRIu64, this->bitrate); for (auto ssrc : this->ssrcs) { - MS_DUMP(" ssrc : %" PRIu32, ssrc); + MS_DUMP(" ssrc: %" PRIu32, ssrc); } MS_DUMP(""); } diff --git a/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp b/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp index 0ec4c0a63b..746e7b4e7a 100644 --- a/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp @@ -77,9 +77,9 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" padding bits : %" PRIu8, this->header->paddingBits); - MS_DUMP(" payload type : %" PRIu8, this->GetPayloadType()); - MS_DUMP(" length : %zu", this->GetLength()); + MS_DUMP(" padding bits %" PRIu8, this->header->paddingBits); + MS_DUMP(" payload type: %" PRIu8, this->GetPayloadType()); + MS_DUMP(" length: %zu", this->GetLength()); MS_DUMP(""); } } // namespace RTCP diff --git a/worker/src/RTC/RTCP/FeedbackPsSli.cpp b/worker/src/RTC/RTCP/FeedbackPsSli.cpp index 085b60e330..feeb2854e8 100644 --- a/worker/src/RTC/RTCP/FeedbackPsSli.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsSli.cpp @@ -39,9 +39,9 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" first : %" PRIu16, this->first); - MS_DUMP(" number : %" PRIu16, this->number); - MS_DUMP(" picture id : %" PRIu8, this->pictureId); + MS_DUMP(" first: %" PRIu16, this->first); + MS_DUMP(" number: %" PRIu16, this->number); + MS_DUMP(" picture id: %" PRIu8, this->pictureId); MS_DUMP(""); } } // namespace RTCP diff --git a/worker/src/RTC/RTCP/FeedbackPsTst.cpp b/worker/src/RTC/RTCP/FeedbackPsTst.cpp index 72160665f6..25cf5f69bd 100644 --- a/worker/src/RTC/RTCP/FeedbackPsTst.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsTst.cpp @@ -41,9 +41,9 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" ssrc : %" PRIu32, this->GetSsrc()); - MS_DUMP(" sequence number : %" PRIu32, this->GetSequenceNumber()); - MS_DUMP(" index : %" PRIu32, this->GetIndex()); + MS_DUMP(" ssrc: %" PRIu32, this->GetSsrc()); + MS_DUMP(" sequence number: %" PRIu32, this->GetSequenceNumber()); + MS_DUMP(" index: %" PRIu32, this->GetIndex()); MS_DUMP(""); } diff --git a/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp b/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp index b40029467c..590e810f76 100644 --- a/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp +++ b/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp @@ -51,10 +51,10 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" ssrc : %" PRIu32, this->GetSsrc()); - MS_DUMP(" sequence number : %" PRIu8, this->GetSequenceNumber()); - MS_DUMP(" payload type : %" PRIu8, this->GetPayloadType()); - MS_DUMP(" length : %" PRIu16, this->GetLength()); + MS_DUMP(" ssrc: %" PRIu32, this->GetSsrc()); + MS_DUMP(" sequence number: %" PRIu8, this->GetSequenceNumber()); + MS_DUMP(" payload type: %" PRIu8, this->GetPayloadType()); + MS_DUMP(" length: %" PRIu16, this->GetLength()); MS_DUMP(""); } } // namespace RTCP diff --git a/worker/src/RTC/RTCP/FeedbackRtpEcn.cpp b/worker/src/RTC/RTCP/FeedbackRtpEcn.cpp index a6adc3d91a..26f6105480 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpEcn.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpEcn.cpp @@ -24,13 +24,13 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" sequence number : %" PRIu32, this->GetSequenceNumber()); - MS_DUMP(" ect0 counter : %" PRIu32, this->GetEct0Counter()); - MS_DUMP(" ect1 counter : %" PRIu32, this->GetEct1Counter()); - MS_DUMP(" ecn ce counter : %" PRIu16, this->GetEcnCeCounter()); - MS_DUMP(" not ect counter : %" PRIu16, this->GetNotEctCounter()); - MS_DUMP(" lost packets : %" PRIu16, this->GetLostPackets()); - MS_DUMP(" duplicated packets : %" PRIu16, this->GetDuplicatedPackets()); + MS_DUMP(" sequence number: %" PRIu32, this->GetSequenceNumber()); + MS_DUMP(" ect0 counter: %" PRIu32, this->GetEct0Counter()); + MS_DUMP(" ect1 counter: %" PRIu32, this->GetEct1Counter()); + MS_DUMP(" ecn ce counter: %" PRIu16, this->GetEcnCeCounter()); + MS_DUMP(" not ect counter: %" PRIu16, this->GetNotEctCounter()); + MS_DUMP(" lost packets: %" PRIu16, this->GetLostPackets()); + MS_DUMP(" duplicated packets: %" PRIu16, this->GetDuplicatedPackets()); MS_DUMP(""); } } // namespace RTCP diff --git a/worker/src/RTC/RTCP/FeedbackRtpNack.cpp b/worker/src/RTC/RTCP/FeedbackRtpNack.cpp index d119044d8a..c3876051e4 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpNack.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpNack.cpp @@ -37,8 +37,8 @@ namespace RTC std::bitset<16> nackBitset(this->GetLostPacketBitmask()); MS_DUMP(""); - MS_DUMP(" pid : %" PRIu16, this->GetPacketId()); - MS_DUMP(" bpl : %s", nackBitset.to_string().c_str()); + MS_DUMP(" pid: %" PRIu16, this->GetPacketId()); + MS_DUMP(" bpl: %s", nackBitset.to_string().c_str()); MS_DUMP(""); } } // namespace RTCP diff --git a/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp b/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp index fe998f8975..f443e64c42 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTmmb.cpp @@ -68,9 +68,9 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" ssrc : %" PRIu32, this->GetSsrc()); - MS_DUMP(" bitrate : %" PRIu64, this->GetBitrate()); - MS_DUMP(" overhead : %" PRIu16, this->GetOverhead()); + MS_DUMP(" ssrc: %" PRIu32, this->GetSsrc()); + MS_DUMP(" bitrate: %" PRIu64, this->GetBitrate()); + MS_DUMP(" overhead: %" PRIu16, this->GetOverhead()); MS_DUMP(""); } diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index 9d497677b4..7463403991 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -179,11 +179,11 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" base sequence : %" PRIu16, this->baseSequenceNumber); - MS_DUMP(" packet status count : %" PRIu16, this->packetStatusCount); - MS_DUMP(" reference time : %" PRIi32, this->referenceTime); - MS_DUMP(" feedback packet count : %" PRIu8, this->feedbackPacketCount); - MS_DUMP(" size : %zu", GetSize()); + MS_DUMP(" base sequence: %" PRIu16, this->baseSequenceNumber); + MS_DUMP(" packet status count: %" PRIu16, this->packetStatusCount); + MS_DUMP(" reference time: %" PRIi32, this->referenceTime); + MS_DUMP(" feedback packet count: %" PRIu8, this->feedbackPacketCount); + MS_DUMP(" size: %zu", GetSize()); for (auto* chunk : this->chunks) { @@ -728,8 +728,8 @@ namespace RTC MS_TRACE(); MS_DUMP(" "); - MS_DUMP(" status : %s", FeedbackRtpTransportPacket::status2String[this->status].c_str()); - MS_DUMP(" count : %" PRIu16, this->count); + MS_DUMP(" status: %s", FeedbackRtpTransportPacket::status2String[this->status].c_str()); + MS_DUMP(" count: %" PRIu16, this->count); MS_DUMP(" "); } diff --git a/worker/src/RTC/RTCP/ReceiverReport.cpp b/worker/src/RTC/RTCP/ReceiverReport.cpp index de873b340c..e90938a6f6 100644 --- a/worker/src/RTC/RTCP/ReceiverReport.cpp +++ b/worker/src/RTC/RTCP/ReceiverReport.cpp @@ -37,13 +37,13 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" ssrc : %" PRIu32, GetSsrc()); - MS_DUMP(" fraction lost : %" PRIu8, GetFractionLost()); - MS_DUMP(" total lost : %" PRIu32, GetTotalLost()); - MS_DUMP(" last seq : %" PRIu32, GetLastSeq()); - MS_DUMP(" jitter : %" PRIu32, GetJitter()); - MS_DUMP(" lsr : %" PRIu32, GetLastSenderReport()); - MS_DUMP(" dlsr : %" PRIu32, GetDelaySinceLastSenderReport()); + MS_DUMP(" ssrc: %" PRIu32, GetSsrc()); + MS_DUMP(" fraction lost: %" PRIu8, GetFractionLost()); + MS_DUMP(" total lost: %" PRIu32, GetTotalLost()); + MS_DUMP(" last seq: %" PRIu32, GetLastSeq()); + MS_DUMP(" jitter: %" PRIu32, GetJitter()); + MS_DUMP(" lsr: %" PRIu32, GetLastSenderReport()); + MS_DUMP(" dlsr: %" PRIu32, GetDelaySinceLastSenderReport()); MS_DUMP(""); } diff --git a/worker/src/RTC/RTCP/Sdes.cpp b/worker/src/RTC/RTCP/Sdes.cpp index 3d5e9fe373..7c7d9c1ef8 100644 --- a/worker/src/RTC/RTCP/Sdes.cpp +++ b/worker/src/RTC/RTCP/Sdes.cpp @@ -92,9 +92,9 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" type : %s", SdesItem::Type2String(this->GetType()).c_str()); - MS_DUMP(" length : %" PRIu8, this->header->length); - MS_DUMP(" value : %.*s", this->header->length, this->header->value); + MS_DUMP(" type: %s", SdesItem::Type2String(this->GetType()).c_str()); + MS_DUMP(" length: %" PRIu8, this->header->length); + MS_DUMP(" value: %.*s", this->header->length, this->header->value); MS_DUMP(""); } @@ -240,7 +240,7 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" ssrc : %" PRIu32, this->ssrc); + MS_DUMP(" ssrc: %" PRIu32, this->ssrc); for (auto* item : this->items) { item->Dump(); diff --git a/worker/src/RTC/RTCP/SenderReport.cpp b/worker/src/RTC/RTCP/SenderReport.cpp index ed51124b88..2b0eb9d265 100644 --- a/worker/src/RTC/RTCP/SenderReport.cpp +++ b/worker/src/RTC/RTCP/SenderReport.cpp @@ -36,12 +36,12 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" ssrc : %" PRIu32, GetSsrc()); - MS_DUMP(" ntp sec : %" PRIu32, GetNtpSec()); - MS_DUMP(" ntp frac : %" PRIu32, GetNtpFrac()); - MS_DUMP(" rtp ts : %" PRIu32, GetRtpTs()); - MS_DUMP(" packet count : %" PRIu32, GetPacketCount()); - MS_DUMP(" octet count : %" PRIu32, GetOctetCount()); + MS_DUMP(" ssrc: %" PRIu32, GetSsrc()); + MS_DUMP(" ntp sec: %" PRIu32, GetNtpSec()); + MS_DUMP(" ntp frac: %" PRIu32, GetNtpFrac()); + MS_DUMP(" rtp ts: %" PRIu32, GetRtpTs()); + MS_DUMP(" packet count: %" PRIu32, GetPacketCount()); + MS_DUMP(" octet count: %" PRIu32, GetOctetCount()); MS_DUMP(""); } diff --git a/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp b/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp index 5b3a9b5dd4..beb6cc083f 100644 --- a/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp +++ b/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp @@ -38,9 +38,9 @@ namespace RTC MS_TRACE(); MS_DUMP(" "); - MS_DUMP(" ssrc : %" PRIu32, GetSsrc()); - MS_DUMP(" lrr : %" PRIu32, GetLastReceiverReport()); - MS_DUMP(" dlrr : %" PRIu32, GetDelaySinceLastReceiverReport()); + MS_DUMP(" ssrc: %" PRIu32, GetSsrc()); + MS_DUMP(" lrr: %" PRIu32, GetLastReceiverReport()); + MS_DUMP(" dlrr: %" PRIu32, GetDelaySinceLastReceiverReport()); MS_DUMP(" "); } @@ -117,10 +117,10 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" block type : %" PRIu8, (uint8_t)this->type); - MS_DUMP(" reserved : 0"); + MS_DUMP(" block type: %" PRIu8, (uint8_t)this->type); + MS_DUMP(" reserved: 0"); MS_DUMP( - " length : %" PRIu16, + " length: %" PRIu16, static_cast((SsrcInfo::BodySize * this->ssrcInfos.size() / 4))); for (auto* ssrcInfo : this->ssrcInfos) { diff --git a/worker/src/RTC/RTCP/XrReceiverReferenceTime.cpp b/worker/src/RTC/RTCP/XrReceiverReferenceTime.cpp index 3a93026bf2..948c5c8884 100644 --- a/worker/src/RTC/RTCP/XrReceiverReferenceTime.cpp +++ b/worker/src/RTC/RTCP/XrReceiverReferenceTime.cpp @@ -35,11 +35,11 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" block type : %" PRIu8, static_cast(this->type)); - MS_DUMP(" reserved : 0"); - MS_DUMP(" length : 2"); - MS_DUMP(" ntp sec : %" PRIu32, GetNtpSec()); - MS_DUMP(" ntp frac : %" PRIu32, GetNtpFrac()); + MS_DUMP(" block type: %" PRIu8, static_cast(this->type)); + MS_DUMP(" reserved: 0"); + MS_DUMP(" length: 2"); + MS_DUMP(" ntp sec: %" PRIu32, GetNtpSec()); + MS_DUMP(" ntp frac: %" PRIu32, GetNtpFrac()); MS_DUMP(""); } diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index ef05d24a41..c38f1eefd4 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -166,21 +166,21 @@ namespace RTC MS_TRACE(); MS_DUMP(""); - MS_DUMP(" padding : %s", this->header->padding ? "true" : "false"); + MS_DUMP(" padding: %s", this->header->padding ? "true" : "false"); if (HasHeaderExtension()) { MS_DUMP( - " header extension : id:%" PRIu16 ", length:%zu", + " header extension: id:%" PRIu16 ", length:%zu", GetHeaderExtensionId(), GetHeaderExtensionLength()); } if (HasOneByteExtensions()) { - MS_DUMP(" RFC5285 ext style : One-Byte Header"); + MS_DUMP(" RFC5285 ext style: One-Byte Header"); } if (HasTwoBytesExtensions()) { - MS_DUMP(" RFC5285 ext style : Two-Bytes Header"); + MS_DUMP(" RFC5285 ext style: Two-Bytes Header"); } if (HasOneByteExtensions() || HasTwoBytesExtensions()) { @@ -213,7 +213,7 @@ namespace RTC extIds.begin(), extIds.end() - 1, std::ostream_iterator(extIdsStream, ",")); extIdsStream << extIds.back(); - MS_DUMP(" RFC5285 ext ids : %s", extIdsStream.str().c_str()); + MS_DUMP(" RFC5285 ext ids: %s", extIdsStream.str().c_str()); } } if (this->midExtensionId != 0u) @@ -222,8 +222,7 @@ namespace RTC if (ReadMid(mid)) { - MS_DUMP( - " mid : extId:%" PRIu8 ", value:'%s'", this->midExtensionId, mid.c_str()); + MS_DUMP(" mid: extId:%" PRIu8 ", value:'%s'", this->midExtensionId, mid.c_str()); } } if (this->ridExtensionId != 0u) @@ -232,8 +231,7 @@ namespace RTC if (ReadRid(rid)) { - MS_DUMP( - " rid : extId:%" PRIu8 ", value:'%s'", this->ridExtensionId, rid.c_str()); + MS_DUMP(" rid: extId:%" PRIu8 ", value:'%s'", this->ridExtensionId, rid.c_str()); } } if (this->rridExtensionId != 0u) @@ -242,13 +240,12 @@ namespace RTC if (ReadRid(rid)) { - MS_DUMP( - " rrid : extId:%" PRIu8 ", value:'%s'", this->rridExtensionId, rid.c_str()); + MS_DUMP(" rrid: extId:%" PRIu8 ", value:'%s'", this->rridExtensionId, rid.c_str()); } } if (this->absSendTimeExtensionId != 0u) { - MS_DUMP(" absSendTime : extId:%" PRIu8, this->absSendTimeExtensionId); + MS_DUMP(" absSendTime: extId:%" PRIu8, this->absSendTimeExtensionId); } if (this->transportWideCc01ExtensionId != 0u) { @@ -257,7 +254,7 @@ namespace RTC if (ReadTransportWideCc01(wideSeqNumber)) { MS_DUMP( - " transportWideCc01 : extId:%" PRIu8 ", value:%" PRIu16, + " transportWideCc01: extId:%" PRIu8 ", value:%" PRIu16, this->transportWideCc01ExtensionId, wideSeqNumber); } @@ -265,11 +262,11 @@ namespace RTC // Remove once it becomes RFC. if (this->frameMarking07ExtensionId != 0u) { - MS_DUMP(" frameMarking07 : extId:%" PRIu8, this->frameMarking07ExtensionId); + MS_DUMP(" frameMarking07: extId:%" PRIu8, this->frameMarking07ExtensionId); } if (this->frameMarkingExtensionId != 0u) { - MS_DUMP(" frameMarking : extId:%" PRIu8, this->frameMarkingExtensionId); + MS_DUMP(" frameMarking: extId:%" PRIu8, this->frameMarkingExtensionId); } if (this->ssrcAudioLevelExtensionId != 0u) { @@ -279,7 +276,7 @@ namespace RTC if (ReadSsrcAudioLevel(volume, voice)) { MS_DUMP( - " ssrcAudioLevel : extId:%" PRIu8 ", volume:%" PRIu8 ", voice:%s", + " ssrcAudioLevel: extId:%" PRIu8 ", volume:%" PRIu8 ", voice:%s", this->ssrcAudioLevelExtensionId, volume, voice ? "true" : "false"); @@ -294,27 +291,27 @@ namespace RTC if (ReadVideoOrientation(camera, flip, rotation)) { MS_DUMP( - " videoOrientation : extId:%" PRIu8 ", camera:%s, flip:%s, rotation:%" PRIu16, + " videoOrientation: extId:%" PRIu8 ", camera:%s, flip:%s, rotation:%" PRIu16, this->videoOrientationExtensionId, camera ? "true" : "false", flip ? "true" : "false", rotation); } } - MS_DUMP(" csrc count : %" PRIu8, this->header->csrcCount); - MS_DUMP(" marker : %s", HasMarker() ? "true" : "false"); - MS_DUMP(" payload type : %" PRIu8, GetPayloadType()); - MS_DUMP(" sequence number : %" PRIu16, GetSequenceNumber()); - MS_DUMP(" timestamp : %" PRIu32, GetTimestamp()); - MS_DUMP(" ssrc : %" PRIu32, GetSsrc()); - MS_DUMP(" payload size : %zu bytes", GetPayloadLength()); + MS_DUMP(" csrc count: %" PRIu8, this->header->csrcCount); + MS_DUMP(" marker: %s", HasMarker() ? "true" : "false"); + MS_DUMP(" payload type: %" PRIu8, GetPayloadType()); + MS_DUMP(" sequence number: %" PRIu16, GetSequenceNumber()); + MS_DUMP(" timestamp: %" PRIu32, GetTimestamp()); + MS_DUMP(" ssrc: %" PRIu32, GetSsrc()); + MS_DUMP(" payload size: %zu bytes", GetPayloadLength()); if (this->header->padding != 0u) { - MS_DUMP(" padding size : %" PRIu8 " bytes", this->payloadPadding); + MS_DUMP(" padding size: %" PRIu8 " bytes", this->payloadPadding); } - MS_DUMP(" packet size : %zu bytes", GetSize()); - MS_DUMP(" spatial layer : %" PRIu8, GetSpatialLayer()); - MS_DUMP(" temporal layer : %" PRIu8, GetTemporalLayer()); + MS_DUMP(" packet size: %zu bytes", GetSize()); + MS_DUMP(" spatial layer: %" PRIu8, GetSpatialLayer()); + MS_DUMP(" temporal layer: %" PRIu8, GetTemporalLayer()); MS_DUMP(""); } diff --git a/worker/src/RTC/StunPacket.cpp b/worker/src/RTC/StunPacket.cpp index 6747afebd1..24ab54c89c 100644 --- a/worker/src/RTC/StunPacket.cpp +++ b/worker/src/RTC/StunPacket.cpp @@ -421,7 +421,7 @@ namespace RTC } if (this->hasUseCandidate) { - MS_DUMP(" useCandidate"); + MS_DUMP(" useCandidate: yes"); } if (!this->software.empty()) { @@ -450,7 +450,7 @@ namespace RTC } if (this->hasFingerprint) { - MS_DUMP(" has fingerprint"); + MS_DUMP(" fingerprint: yes"); } MS_DUMP(""); diff --git a/worker/src/RTC/TransportTuple.cpp b/worker/src/RTC/TransportTuple.cpp index 3055e8c2a9..33720bf689 100644 --- a/worker/src/RTC/TransportTuple.cpp +++ b/worker/src/RTC/TransportTuple.cpp @@ -74,22 +74,22 @@ namespace RTC Utils::IP::GetAddressInfo(GetLocalAddress(), family, ip, port); - MS_DUMP(" localIp : %s", ip.c_str()); - MS_DUMP(" localPort : %" PRIu16, port); + MS_DUMP(" localIp: %s", ip.c_str()); + MS_DUMP(" localPort: %" PRIu16, port); Utils::IP::GetAddressInfo(GetRemoteAddress(), family, ip, port); - MS_DUMP(" remoteIp : %s", ip.c_str()); - MS_DUMP(" remotePort : %" PRIu16, port); + MS_DUMP(" remoteIp: %s", ip.c_str()); + MS_DUMP(" remotePort: %" PRIu16, port); switch (GetProtocol()) { case Protocol::UDP: - MS_DUMP(" protocol : udp"); + MS_DUMP(" protocol: udp"); break; case Protocol::TCP: - MS_DUMP(" protocol : tcp"); + MS_DUMP(" protocol: tcp"); break; } diff --git a/worker/src/handles/TcpConnectionHandle.cpp b/worker/src/handles/TcpConnectionHandle.cpp index ae2ded0d9c..56d9e10004 100644 --- a/worker/src/handles/TcpConnectionHandle.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -145,11 +145,11 @@ void TcpConnectionHandle::Close() void TcpConnectionHandle::Dump() const { MS_DUMP(""); - MS_DUMP(" localIp : %s", this->localIp.c_str()); - MS_DUMP(" localPort : %" PRIu16, static_cast(this->localPort)); - MS_DUMP(" remoteIp : %s", this->peerIp.c_str()); - MS_DUMP(" remotePort : %" PRIu16, static_cast(this->peerPort)); - MS_DUMP(" closed : %s", !this->closed ? "open" : "closed"); + MS_DUMP(" localIp: %s", this->localIp.c_str()); + MS_DUMP(" localPort: %" PRIu16, static_cast(this->localPort)); + MS_DUMP(" remoteIp: %s", this->peerIp.c_str()); + MS_DUMP(" remotePort: %" PRIu16, static_cast(this->peerPort)); + MS_DUMP(" closed: %s", this->closed ? "yes" : "no"); MS_DUMP(""); } diff --git a/worker/src/handles/TcpServerHandle.cpp b/worker/src/handles/TcpServerHandle.cpp index 217f0aee90..c6cf895110 100644 --- a/worker/src/handles/TcpServerHandle.cpp +++ b/worker/src/handles/TcpServerHandle.cpp @@ -96,12 +96,10 @@ void TcpServerHandle::Close() void TcpServerHandle::Dump() const { MS_DUMP(""); - MS_DUMP( - " [TCP, local:%s :%" PRIu16 ", status:%s, connections:%zu]", - this->localIp.c_str(), - static_cast(this->localPort), - (!this->closed) ? "open" : "closed", - this->connections.size()); + MS_DUMP(" localIp: %s", this->localIp.c_str()); + MS_DUMP(" localPort: %" PRIu16, static_cast(this->localPort)); + MS_DUMP(" num connections: %zu", this->connections.size()); + MS_DUMP(" closed: %s", this->closed ? "yes" : "no"); MS_DUMP(""); } diff --git a/worker/src/handles/UdpSocketHandle.cpp b/worker/src/handles/UdpSocketHandle.cpp index b544794e34..416dac18cf 100644 --- a/worker/src/handles/UdpSocketHandle.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -135,9 +135,9 @@ void UdpSocketHandle::Close() void UdpSocketHandle::Dump() const { MS_DUMP(""); - MS_DUMP(" localIp : %s", this->localIp.c_str()); - MS_DUMP(" localPort : %" PRIu16, static_cast(this->localPort)); - MS_DUMP(" closed : %s", !this->closed ? "open" : "closed"); + MS_DUMP(" localIp: %s", this->localIp.c_str()); + MS_DUMP(" localPort: %" PRIu16, static_cast(this->localPort)); + MS_DUMP(" closed: %s", this->closed ? "yes" : "no"); MS_DUMP(""); } From 968320c49ed9b5d828ba3c25c8a87b5039369a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 22 Feb 2024 17:15:22 +0100 Subject: [PATCH 369/525] cosmetic: DtlsTransport::Dump() method --- worker/src/RTC/DtlsTransport.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/worker/src/RTC/DtlsTransport.cpp b/worker/src/RTC/DtlsTransport.cpp index c88977bdc7..f85d108c94 100644 --- a/worker/src/RTC/DtlsTransport.cpp +++ b/worker/src/RTC/DtlsTransport.cpp @@ -834,9 +834,9 @@ namespace RTC } MS_DUMP(""); - MS_DUMP(" state : %s", state.c_str()); - MS_DUMP(" role : %s", role.c_str()); - MS_DUMP(" handshake done: : %s", this->handshakeDone ? "yes" : "no"); + MS_DUMP(" state: %s", state.c_str()); + MS_DUMP(" role: %s", role.c_str()); + MS_DUMP(" handshake done: %s", this->handshakeDone ? "yes" : "no"); MS_DUMP(""); } From 99e933fe9f3bcf4e918f27485a31bae0c9d766f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 23 Feb 2024 12:33:38 +0100 Subject: [PATCH 370/525] Update NPM dev deps --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index d77c4bdbd9..1816dfc278 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.19", + "@types/node": "^20.11.20", "@typescript-eslint/eslint-plugin": "^7.0.2", "@typescript-eslint/parser": "^7.0.2", "eslint": "^8.56.0", @@ -1626,9 +1626,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", - "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", + "version": "20.11.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", + "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -7514,9 +7514,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", - "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", + "version": "20.11.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", + "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", "dev": true, "requires": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index 54a8fd3a1b..178a4fede2 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.19", + "@types/node": "^20.11.20", "@typescript-eslint/eslint-plugin": "^7.0.2", "@typescript-eslint/parser": "^7.0.2", "eslint": "^8.56.0", From 7652e7683ff158409678e303d7b374ee15c45f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 23 Feb 2024 12:45:00 +0100 Subject: [PATCH 371/525] Settings::PrintConfiguration(): remove tabs --- worker/src/Settings.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/worker/src/Settings.cpp b/worker/src/Settings.cpp index abde2f9c07..a989bc44e5 100644 --- a/worker/src/Settings.cpp +++ b/worker/src/Settings.cpp @@ -273,23 +273,20 @@ void Settings::PrintConfiguration() MS_DEBUG_TAG(info, ""); MS_DEBUG_TAG( - info, - " logLevel : %s", - Settings::LogLevel2String[Settings::configuration.logLevel].c_str()); - MS_DEBUG_TAG(info, " logTags : %s", logTagsStream.str().c_str()); - MS_DEBUG_TAG(info, " rtcMinPort : %" PRIu16, Settings::configuration.rtcMinPort); - MS_DEBUG_TAG(info, " rtcMaxPort : %" PRIu16, Settings::configuration.rtcMaxPort); + info, " logLevel: %s", Settings::LogLevel2String[Settings::configuration.logLevel].c_str()); + MS_DEBUG_TAG(info, " logTags: %s", logTagsStream.str().c_str()); + MS_DEBUG_TAG(info, " rtcMinPort: %" PRIu16, Settings::configuration.rtcMinPort); + MS_DEBUG_TAG(info, " rtcMaxPort: %" PRIu16, Settings::configuration.rtcMaxPort); if (!Settings::configuration.dtlsCertificateFile.empty()) { MS_DEBUG_TAG( - info, " dtlsCertificateFile : %s", Settings::configuration.dtlsCertificateFile.c_str()); - MS_DEBUG_TAG( - info, " dtlsPrivateKeyFile : %s", Settings::configuration.dtlsPrivateKeyFile.c_str()); + info, " dtlsCertificateFile: %s", Settings::configuration.dtlsCertificateFile.c_str()); + MS_DEBUG_TAG(info, " dtlsPrivateKeyFile: %s", Settings::configuration.dtlsPrivateKeyFile.c_str()); } if (!Settings::configuration.libwebrtcFieldTrials.empty()) { MS_DEBUG_TAG( - info, " libwebrtcFieldTrials : %s", Settings::configuration.libwebrtcFieldTrials.c_str()); + info, " libwebrtcFieldTrials: %s", Settings::configuration.libwebrtcFieldTrials.c_str()); } MS_DEBUG_TAG(info, ""); From 898c760fe01b9f704f7d4cadbe7d6350f37ba3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 27 Feb 2024 13:11:25 +0100 Subject: [PATCH 372/525] Update NPM dev deps --- package-lock.json | 398 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 202 insertions(+), 202 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1816dfc278..b5794f979e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,9 +22,9 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.11.20", - "@typescript-eslint/eslint-plugin": "^7.0.2", - "@typescript-eslint/parser": "^7.0.2", - "eslint": "^8.56.0", + "@typescript-eslint/eslint-plugin": "^7.1.0", + "@typescript-eslint/parser": "^7.1.0", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", "eslint-plugin-prettier": "^5.1.3", @@ -768,22 +768,22 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -804,9 +804,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -1662,16 +1662,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.2.tgz", - "integrity": "sha512-/XtVZJtbaphtdrWjr+CJclaCVGPtOdBpFEnvtNf/jRV0IiEemRrL0qABex/nEt8isYcnFacm3nPHYQwL+Wb7qg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz", + "integrity": "sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/type-utils": "7.0.2", - "@typescript-eslint/utils": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/type-utils": "7.1.0", + "@typescript-eslint/utils": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1697,13 +1697,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", - "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", + "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2" + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1714,9 +1714,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", - "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", + "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1727,13 +1727,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", - "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", + "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1755,17 +1755,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", - "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", + "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.0", "semver": "^7.5.4" }, "engines": { @@ -1780,12 +1780,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", - "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", + "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/types": "7.1.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1821,15 +1821,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.2.tgz", - "integrity": "sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.0.tgz", + "integrity": "sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4" }, "engines": { @@ -1849,13 +1849,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", - "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", + "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2" + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1866,9 +1866,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", - "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", + "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1879,13 +1879,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", - "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", + "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1907,12 +1907,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", - "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", + "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/types": "7.1.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1965,13 +1965,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.2.tgz", - "integrity": "sha512-IKKDcFsKAYlk8Rs4wiFfEwJTQlHcdn8CLwLaxwd6zb8HNiMcQIFX9sWax2k4Cjj7l7mGS5N1zl7RCHOVwHq2VQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz", + "integrity": "sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.0.2", - "@typescript-eslint/utils": "7.0.2", + "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/utils": "7.1.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1992,13 +1992,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", - "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", + "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2" + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2009,9 +2009,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", - "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", + "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2022,13 +2022,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", - "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", + "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2050,17 +2050,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", - "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", + "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.0", "semver": "^7.5.4" }, "engines": { @@ -2075,12 +2075,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", - "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", + "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/types": "7.1.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2936,16 +2936,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -6811,19 +6811,19 @@ } }, "@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true }, "@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" } }, @@ -6834,9 +6834,9 @@ "dev": true }, "@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "@istanbuljs/load-nyc-config": { @@ -7550,16 +7550,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.2.tgz", - "integrity": "sha512-/XtVZJtbaphtdrWjr+CJclaCVGPtOdBpFEnvtNf/jRV0IiEemRrL0qABex/nEt8isYcnFacm3nPHYQwL+Wb7qg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz", + "integrity": "sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/type-utils": "7.0.2", - "@typescript-eslint/utils": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/type-utils": "7.1.0", + "@typescript-eslint/utils": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7569,29 +7569,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", - "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", + "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2" + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0" } }, "@typescript-eslint/types": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", - "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", + "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", - "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", + "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7601,27 +7601,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", - "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", + "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", - "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", + "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/types": "7.1.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7646,42 +7646,42 @@ } }, "@typescript-eslint/parser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.2.tgz", - "integrity": "sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.0.tgz", + "integrity": "sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", - "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", + "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2" + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0" } }, "@typescript-eslint/types": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", - "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", + "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", - "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", + "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7691,12 +7691,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", - "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", + "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/types": "7.1.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7731,41 +7731,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.2.tgz", - "integrity": "sha512-IKKDcFsKAYlk8Rs4wiFfEwJTQlHcdn8CLwLaxwd6zb8HNiMcQIFX9sWax2k4Cjj7l7mGS5N1zl7RCHOVwHq2VQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz", + "integrity": "sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.0.2", - "@typescript-eslint/utils": "7.0.2", + "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/utils": "7.1.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", - "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", + "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2" + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0" } }, "@typescript-eslint/types": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", - "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", + "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", - "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", + "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7775,27 +7775,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", - "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", + "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", - "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", + "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/types": "7.1.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -8388,16 +8388,16 @@ "dev": true }, "eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", diff --git a/package.json b/package.json index 178a4fede2..339938fba8 100644 --- a/package.json +++ b/package.json @@ -111,9 +111,9 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.11.20", - "@typescript-eslint/eslint-plugin": "^7.0.2", - "@typescript-eslint/parser": "^7.0.2", - "eslint": "^8.56.0", + "@typescript-eslint/eslint-plugin": "^7.1.0", + "@typescript-eslint/parser": "^7.1.0", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", "eslint-plugin-prettier": "^5.1.3", From 9af2a269cf4407b6446011450fc9e3e78d46cadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 27 Feb 2024 17:02:06 +0100 Subject: [PATCH 373/525] Fix DTLS packets do not honor configured DTLS MTU (attempt 3) (#1345) --- CHANGELOG.md | 4 + worker/include/RTC/DtlsTransport.hpp | 3 +- worker/src/RTC/DtlsTransport.cpp | 138 ++++++++++++++++----------- 3 files changed, 86 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3404784291..e24f5e536c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Next + +- Fix DTLS packets do not honor configured DTLS MTU (attempt 3) ([PR #1345](https://github.com/versatica/mediasoup/pull/1345)). + ### 3.13.22 - Fix wrong publication of mediasoup NPM 3.13.21. diff --git a/worker/include/RTC/DtlsTransport.hpp b/worker/include/RTC/DtlsTransport.hpp index 0d50c3eb07..27f4bd847f 100644 --- a/worker/include/RTC/DtlsTransport.hpp +++ b/worker/include/RTC/DtlsTransport.hpp @@ -152,6 +152,8 @@ namespace RTC return this->localRole; } void SendApplicationData(const uint8_t* data, size_t len); + // This method must be public since it's called within an OpenSSL callback. + void SendDtlsData(const uint8_t* data, size_t len); private: bool IsRunning() const @@ -173,7 +175,6 @@ namespace RTC } void Reset(); bool CheckStatus(int returnCode); - void SendPendingOutgoingDtlsData(); bool SetTimeout(); bool ProcessHandshake(); bool CheckRemoteFingerprint(); diff --git a/worker/src/RTC/DtlsTransport.cpp b/worker/src/RTC/DtlsTransport.cpp index f85d108c94..b3458c901b 100644 --- a/worker/src/RTC/DtlsTransport.cpp +++ b/worker/src/RTC/DtlsTransport.cpp @@ -47,15 +47,49 @@ inline static void onSslInfo(const SSL* ssl, int where, int ret) static_cast(SSL_get_ex_data(ssl, 0))->OnSslInfo(where, ret); } +/** + * This callback is called by OpenSSL when it wants to send DTLS data to the + * endpoint. Such a data could be a full DTLS message, various DTLS messages, + * a DTLS message fragment, various DTLS message fragments or a combination of + * these. It's guaranteed (by observation) that |len| argument corresponds to + * the entire content of our BIO mem buffer |this->sslBioToNetwork| and it + * never exceeds our |DtlsMtu| limit. + */ +inline static long onSslBioOut( + BIO* bio, + int operationType, + const char* argp, + size_t len, + int /*argi*/, + long /*argl*/, + int ret, + size_t* /*processed*/) +{ + long resultOfcallback = (operationType == BIO_CB_RETURN) ? static_cast(ret) : 1; + + // This callback is called twice for write operations: + // - First one with operationType = BIO_CB_WRITE. + // - Second one with operationType = BIO_CB_RETURN | BIO_CB_WRITE. + // We only care about the former. + if ((operationType == BIO_CB_WRITE) && argp && len > 0) + { + auto* dtlsTransport = reinterpret_cast(BIO_get_callback_arg(bio)); + + dtlsTransport->SendDtlsData(reinterpret_cast(argp), len); + } + + return resultOfcallback; +} + inline static unsigned int onSslDtlsTimer(SSL* /*ssl*/, unsigned int timerUs) { - if (timerUs == 0) + if (timerUs == 0u) { - return 100000; + return 100000u; } - else if (timerUs >= 4000000) + else if (timerUs >= 4000000u) { - return 4000000; + return 4000000u; } else { @@ -71,15 +105,15 @@ namespace RTC static constexpr int DtlsMtu{ 1350 }; static constexpr int SslReadBufferSize{ 65536 }; // AES-HMAC: http://tools.ietf.org/html/rfc3711 - static constexpr size_t SrtpMasterKeyLength{ 16 }; - static constexpr size_t SrtpMasterSaltLength{ 14 }; + static constexpr size_t SrtpMasterKeyLength{ 16u }; + static constexpr size_t SrtpMasterSaltLength{ 14u }; static constexpr size_t SrtpMasterLength{ SrtpMasterKeyLength + SrtpMasterSaltLength }; // AES-GCM: http://tools.ietf.org/html/rfc7714 - static constexpr size_t SrtpAesGcm256MasterKeyLength{ 32 }; - static constexpr size_t SrtpAesGcm256MasterSaltLength{ 12 }; + static constexpr size_t SrtpAesGcm256MasterKeyLength{ 32u }; + static constexpr size_t SrtpAesGcm256MasterSaltLength{ 12u }; static constexpr size_t SrtpAesGcm256MasterLength{ SrtpAesGcm256MasterKeyLength + SrtpAesGcm256MasterSaltLength }; - static constexpr size_t SrtpAesGcm128MasterKeyLength{ 16 }; - static constexpr size_t SrtpAesGcm128MasterSaltLength{ 12 }; + static constexpr size_t SrtpAesGcm128MasterKeyLength{ 16u }; + static constexpr size_t SrtpAesGcm128MasterSaltLength{ 12u }; static constexpr size_t SrtpAesGcm128MasterLength{ SrtpAesGcm128MasterKeyLength + SrtpAesGcm128MasterSaltLength }; // clang-format on @@ -708,15 +742,19 @@ namespace RTC goto error; } - SSL_set_bio(this->ssl, this->sslBioFromNetwork, this->sslBioToNetwork); - // Set the MTU so that we don't send packets that are too large with no // fragmentation. - // TODO: This is not honored, see issue: - // https://github.com/versatica/mediasoup/issues/1100 SSL_set_mtu(this->ssl, DtlsMtu); DTLS_set_link_mtu(this->ssl, DtlsMtu); + // We want to monitor OpenSSL write operations into our |sslBioToNetwork| + // buffer so we can immediately send those DTLS bytes (containing full DTLS + // messages, or valid DTLS fragment messages, or combination of them) to + // the endpoint, and hence we honor the configured DTLS MTU. + BIO_set_callback_ex(this->sslBioToNetwork, onSslBioOut); + BIO_set_callback_arg(this->sslBioToNetwork, reinterpret_cast(this)); + SSL_set_bio(this->ssl, this->sslBioFromNetwork, this->sslBioToNetwork); + // Set callback handler for setting DTLS timer interval. DTLS_set_timer_cb(this->ssl, onSslDtlsTimer); @@ -757,7 +795,6 @@ namespace RTC { // Send close alert to the peer. SSL_shutdown(this->ssl); - SendPendingOutgoingDtlsData(); } if (this->ssl) @@ -880,7 +917,6 @@ namespace RTC SSL_set_connect_state(this->ssl); SSL_do_handshake(this->ssl); - SendPendingOutgoingDtlsData(); SetTimeout(); break; @@ -951,9 +987,6 @@ namespace RTC // Must call SSL_read() to process received DTLS data. read = SSL_read(this->ssl, static_cast(DtlsTransport::sslReadBuffer), SslReadBufferSize); - // Send data if it's ready. - SendPendingOutgoingDtlsData(); - // Check SSL status and return if it is bad/closed. if (!CheckStatus(read)) { @@ -1022,9 +1055,31 @@ namespace RTC MS_WARN_TAG( dtls, "OpenSSL SSL_write() wrote less (%d bytes) than given data (%zu bytes)", written, len); } + } + + /** + * This method is called within our |onSslBioOut| callback above. As told + * there, it's guaranteed that OpenSSL invokes that callback with all the + * bytes currently written in our BIO mem buffer |this->sslBioToNetwork| so + * we can safely reset/clear that buffer once we have sent the data to the + * endpoint. + */ + void DtlsTransport::SendDtlsData(const uint8_t* data, size_t len) + { + MS_TRACE(); + + MS_DEBUG_DEV("%zu bytes of DTLS data ready to be sent", len); - // Send data. - SendPendingOutgoingDtlsData(); + // Notify the listener. + this->listener->OnDtlsTransportSendData(this, data, len); + + // Clear the BIO buffer. + auto ret = BIO_reset(this->sslBioToNetwork); + + if (ret != 1) + { + MS_ERROR("BIO_reset() failed [ret:%d]", ret); + } } void DtlsTransport::Reset() @@ -1044,8 +1099,9 @@ namespace RTC this->timer->Stop(); // NOTE: We need to reset the SSL instance so we need to "shutdown" it, but - // we don't want to send a Close Alert to the peer, so just don't call - // SendPendingOutgoingDTLSData(). + // we don't want to send a DTLS Close Alert to the peer. However this is + // gonna happen since SSL_shutdown() will trigger a DTLS Close Alert and + // we'll have our onSslBioOut() callback called to deliver it. SSL_shutdown(this->ssl); this->localRole.reset(); @@ -1069,10 +1125,9 @@ namespace RTC { MS_TRACE(); - int err; const bool wasHandshakeDone = this->handshakeDone; - err = SSL_get_error(this->ssl, returnCode); + int err = SSL_get_error(this->ssl, returnCode); switch (err) { @@ -1182,36 +1237,6 @@ namespace RTC } } - void DtlsTransport::SendPendingOutgoingDtlsData() - { - MS_TRACE(); - - if (BIO_eof(this->sslBioToNetwork)) - { - return; - } - - int64_t read; - char* data{ nullptr }; - - read = BIO_get_mem_data(this->sslBioToNetwork, &data); // NOLINT - - if (read <= 0) - { - return; - } - - MS_DEBUG_DEV("%" PRIu64 " bytes of DTLS data ready to sent to the peer", read); - - // Notify the listener. - this->listener->OnDtlsTransportSendData( - this, reinterpret_cast(data), static_cast(read)); - - // Clear the BIO buffer. - // NOTE: the (void) avoids the -Wunused-value warning. - (void)BIO_reset(this->sslBioToNetwork); - } - bool DtlsTransport::SetTimeout() { MS_TRACE(); @@ -1684,9 +1709,6 @@ namespace RTC if (ret == 1) { - // If required, send DTLS data. - SendPendingOutgoingDtlsData(); - // Set the DTLS timer again. SetTimeout(); } From c293b40497fd662da403eb64592669689e95edc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 27 Feb 2024 17:05:11 +0100 Subject: [PATCH 374/525] 3.13.23 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e24f5e536c..d0337b36ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### Next +### 3.13.23 - Fix DTLS packets do not honor configured DTLS MTU (attempt 3) ([PR #1345](https://github.com/versatica/mediasoup/pull/1345)). diff --git a/package-lock.json b/package-lock.json index b5794f979e..b69a6dafbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.22", + "version": "3.13.23", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.22", + "version": "3.13.23", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 339938fba8..ee4cfe6dfc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.22", + "version": "3.13.23", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From a6ba853b32ee24be400797ebd2199b81e7be558a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 28 Feb 2024 11:00:16 +0100 Subject: [PATCH 375/525] Make gcc happy by casting `enum class Class : uint16_t` to uint16_t when printing --- worker/src/RTC/IceServer.cpp | 3 ++- worker/src/RTC/StunPacket.cpp | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index 756cae8eb5..f2ddc8e224 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -174,7 +174,8 @@ namespace RTC default: { - MS_WARN_TAG(ice, "unknown STUN class %" PRIu16 ", discarded", packet->GetClass()); + MS_WARN_TAG( + ice, "unknown STUN class %" PRIu16 ", discarded", static_cast(packet->GetClass())); } } } diff --git a/worker/src/RTC/StunPacket.cpp b/worker/src/RTC/StunPacket.cpp index 24ab54c89c..518f8d8789 100644 --- a/worker/src/RTC/StunPacket.cpp +++ b/worker/src/RTC/StunPacket.cpp @@ -535,7 +535,10 @@ namespace RTC default: { - MS_WARN_TAG(ice, "unknown STUN class %" PRIu16 ", cannot authenticate", this->klass); + MS_WARN_TAG( + ice, + "unknown STUN class %" PRIu16 ", cannot authenticate", + static_cast(this->klass)); return Authentication::BAD_MESSAGE; } From 1e9e6f032d4325f63f3e61e70766df2537234caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 28 Feb 2024 15:40:57 +0100 Subject: [PATCH 376/525] Add DTLS fuzzer (#1346) --- doc/Fuzzer.md | 15 ++- .../include/RTC/FuzzerDtlsTransport.hpp | 39 ++++++ worker/fuzzer/src/RTC/FuzzerDtlsTransport.cpp | 118 ++++++++++++++++++ worker/fuzzer/src/fuzzer.cpp | 27 +++- worker/meson.build | 3 +- 5 files changed, 192 insertions(+), 10 deletions(-) create mode 100644 worker/fuzzer/include/RTC/FuzzerDtlsTransport.hpp create mode 100644 worker/fuzzer/src/RTC/FuzzerDtlsTransport.cpp diff --git a/doc/Fuzzer.md b/doc/Fuzzer.md index d993e43684..0e94468faa 100644 --- a/doc/Fuzzer.md +++ b/doc/Fuzzer.md @@ -39,10 +39,11 @@ For memory leak detection enable the following environment variable: The mediasoup-worker fuzzer reads some custom environment variables to decide which kind of fuzzing perform: -- `MS_FUZZ_STUN=1`: Do STUN fuzzing. -- `MS_FUZZ_RTP=1`: Do RTP fuzzing. -- `MS_FUZZ_RTCP=1`: Do RTCP fuzzing. -- `MS_FUZZ_UTILS=1`: Do C++ utils fuzzing. +- `MS_FUZZ_STUN=1`: Enable STUN fuzzer. +- `MS_FUZZ_DTLS=1`: Enable DTLS fuzzer. +- `MS_FUZZ_RTP=1`: Enable RTP fuzzer. +- `MS_FUZZ_RTCP=1`: Enable RTCP fuzzer. +- `MS_FUZZ_UTILS=1`: Enable C++ utils fuzzer. - If none of them is given, then **all** fuzzers are enabled. The log level can also be set by setting the `MS_FUZZ_LOG_LEVEL` environment variable to "debug", "warn" or "error" (it is "none" if unset). @@ -55,6 +56,12 @@ The log level can also be set by setting the `MS_FUZZ_LOG_LEVEL` environment var MS_FUZZ_STUN=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus ``` +- Detect memory leaks and just fuzz DTLS: + +```bash +MS_FUZZ_DTLS=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus +``` + - Detect memory leaks and just fuzz RTP: ```bash diff --git a/worker/fuzzer/include/RTC/FuzzerDtlsTransport.hpp b/worker/fuzzer/include/RTC/FuzzerDtlsTransport.hpp new file mode 100644 index 0000000000..f5f6baa780 --- /dev/null +++ b/worker/fuzzer/include/RTC/FuzzerDtlsTransport.hpp @@ -0,0 +1,39 @@ +#ifndef MS_FUZZER_RTC_DTLS_TRANSPORT_HPP +#define MS_FUZZER_RTC_DTLS_TRANSPORT_HPP + +#include "common.hpp" +#include "RTC/DtlsTransport.hpp" + +namespace Fuzzer +{ + namespace RTC + { + namespace DtlsTransport + { + class DtlsTransportListener : public ::RTC::DtlsTransport::Listener + { + /* Pure virtual methods inherited from RTC::DtlsTransport::Listener. */ + public: + void OnDtlsTransportConnecting(const ::RTC::DtlsTransport* dtlsTransport) override; + void OnDtlsTransportConnected( + const ::RTC::DtlsTransport* dtlsTransport, + ::RTC::SrtpSession::CryptoSuite srtpCryptoSuite, + uint8_t* srtpLocalKey, + size_t srtpLocalKeyLen, + uint8_t* srtpRemoteKey, + size_t srtpRemoteKeyLen, + std::string& remoteCert) override; + void OnDtlsTransportFailed(const ::RTC::DtlsTransport* dtlsTransport) override; + void OnDtlsTransportClosed(const ::RTC::DtlsTransport* dtlsTransport) override; + void OnDtlsTransportSendData( + const ::RTC::DtlsTransport* dtlsTransport, const uint8_t* data, size_t len) override; + void OnDtlsTransportApplicationDataReceived( + const ::RTC::DtlsTransport* dtlsTransport, const uint8_t* data, size_t len) override; + }; + + void Fuzz(const uint8_t* data, size_t len); + } // namespace DtlsTransport + } // namespace RTC +} // namespace Fuzzer + +#endif diff --git a/worker/fuzzer/src/RTC/FuzzerDtlsTransport.cpp b/worker/fuzzer/src/RTC/FuzzerDtlsTransport.cpp new file mode 100644 index 0000000000..91e1993897 --- /dev/null +++ b/worker/fuzzer/src/RTC/FuzzerDtlsTransport.cpp @@ -0,0 +1,118 @@ +#define MS_CLASS "Fuzzer::RTC::DtlsTransport" +// #define MS_LOG_DEV_LEVEL 3 + +#include "RTC/FuzzerDtlsTransport.hpp" +#include "Logger.hpp" +#include "Utils.hpp" + +// DtlsTransport singleton. It's reset every time DTLS handshake fails or DTLS +// is closed. +thread_local static ::RTC::DtlsTransport* dtlsTransportSingleton{ nullptr }; +// DtlsTransport Listener singleton. It's reset every time the DtlsTransport +// singletonDTLS is reset. +thread_local static Fuzzer::RTC::DtlsTransport::DtlsTransportListener* dtlsTransportListenerSingleton{ + nullptr +}; + +void Fuzzer::RTC::DtlsTransport::Fuzz(const uint8_t* data, size_t len) +{ + if (!::RTC::DtlsTransport::IsDtls(data, len)) + { + return; + } + + if (!dtlsTransportSingleton) + { + MS_DEBUG_DEV("no DtlsTransport singleton, creating it"); + + delete dtlsTransportListenerSingleton; + dtlsTransportListenerSingleton = new DtlsTransportListener(); + + dtlsTransportSingleton = new ::RTC::DtlsTransport(dtlsTransportListenerSingleton); + + ::RTC::DtlsTransport::Role localRole; + ::RTC::DtlsTransport::Fingerprint dtlsRemoteFingerprint; + + // Local DTLS role must be 'server' or 'client'. Choose it based on + // randomness of first given byte. + if (data[0] / 2 == 0) + { + localRole = ::RTC::DtlsTransport::Role::SERVER; + } + else + { + localRole = ::RTC::DtlsTransport::Role::CLIENT; + } + + // Remote DTLS fingerprint random generation. + // NOTE: Use a random integer in range 1..5 since FingerprintAlgorithm enum + // has 5 possible values starting with value 1. + dtlsRemoteFingerprint.algorithm = + static_cast<::RTC::DtlsTransport::FingerprintAlgorithm>(::Utils::Crypto::GetRandomUInt(1u, 5u)); + + dtlsRemoteFingerprint.value = + ::Utils::Crypto::GetRandomString(::Utils::Crypto::GetRandomUInt(3u, 20u)); + + dtlsTransportSingleton->Run(localRole); + dtlsTransportSingleton->SetRemoteFingerprint(dtlsRemoteFingerprint); + } + + dtlsTransportSingleton->ProcessDtlsData(data, len); + + // DTLS may have failed or closed after ProcessDtlsData(). If so, unset it. + if ( + dtlsTransportSingleton->GetState() == ::RTC::DtlsTransport::DtlsState::FAILED || + dtlsTransportSingleton->GetState() == ::RTC::DtlsTransport::DtlsState::CLOSED) + { + MS_DEBUG_DEV("DtlsTransport singleton state is 'failed' or 'closed', unsetting it"); + + delete dtlsTransportSingleton; + dtlsTransportSingleton = nullptr; + } + else + { + dtlsTransportSingleton->SendApplicationData(data, len); + } +} + +void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportConnecting( + const ::RTC::DtlsTransport* /*dtlsTransport*/) +{ + MS_DEBUG_DEV("DtlsTransport singleton connecting"); +} + +void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportConnected( + const ::RTC::DtlsTransport* /*dtlsTransport*/, + ::RTC::SrtpSession::CryptoSuite /*srtpCryptoSuite*/, + uint8_t* /*srtpLocalKey*/, + size_t /*srtpLocalKeyLen*/, + uint8_t* /*srtpRemoteKey*/, + size_t /*srtpRemoteKeyLen*/, + std::string& /*remoteCert*/) +{ + MS_DEBUG_DEV("DtlsTransport singleton connected"); +} + +void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportFailed( + const ::RTC::DtlsTransport* /*dtlsTransport*/) +{ + MS_DEBUG_DEV("DtlsTransport singleton failed"); +} + +void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportClosed( + const ::RTC::DtlsTransport* /*dtlsTransport*/) +{ + MS_DEBUG_DEV("DtlsTransport singleton closed"); +} + +void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportSendData( + const ::RTC::DtlsTransport* /*dtlsTransport*/, const uint8_t* /*data*/, size_t /*len*/) +{ + MS_DEBUG_DEV("DtlsTransport singleton wants to send data"); +} + +void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportApplicationDataReceived( + const ::RTC::DtlsTransport* /*dtlsTransport*/, const uint8_t* /*data*/, size_t /*len*/) +{ + MS_DEBUG_DEV("DtlsTransport singleton received application data"); +} diff --git a/worker/fuzzer/src/fuzzer.cpp b/worker/fuzzer/src/fuzzer.cpp index 26e3ee6957..403ef2c417 100644 --- a/worker/fuzzer/src/fuzzer.cpp +++ b/worker/fuzzer/src/fuzzer.cpp @@ -9,6 +9,8 @@ #include "LogLevel.hpp" #include "Settings.hpp" #include "Utils.hpp" +#include "RTC/DtlsTransport.hpp" +#include "RTC/FuzzerDtlsTransport.hpp" #include "RTC/FuzzerRtpPacket.hpp" #include "RTC/FuzzerRtpRetransmissionBuffer.hpp" #include "RTC/FuzzerRtpStreamSend.hpp" @@ -22,6 +24,7 @@ #include bool fuzzStun = false; +bool fuzzDtls = false; bool fuzzRtp = false; bool fuzzRtcp = false; bool fuzzUtils = false; @@ -41,6 +44,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) Fuzzer::RTC::StunPacket::Fuzz(data, len); } + if (fuzzDtls) + { + Fuzzer::RTC::DtlsTransport::Fuzz(data, len); + } + if (fuzzRtp) { Fuzzer::RTC::RtpPacket::Fuzz(data, len); @@ -85,35 +93,43 @@ int Init() } // Select what to fuzz. + if (std::getenv("MS_FUZZ_STUN") && std::string(std::getenv("MS_FUZZ_STUN")) == "1") { - std::cout << "[fuzzer] STUN fuzzers enabled" << std::endl; + std::cout << "[fuzzer] STUN fuzzer enabled" << std::endl; fuzzStun = true; } + if (std::getenv("MS_FUZZ_DTLS") && std::string(std::getenv("MS_FUZZ_DTLS")) == "1") + { + std::cout << "[fuzzer] DTLS fuzzer enabled" << std::endl; + + fuzzDtls = true; + } if (std::getenv("MS_FUZZ_RTP") && std::string(std::getenv("MS_FUZZ_RTP")) == "1") { - std::cout << "[fuzzer] RTP fuzzers enabled" << std::endl; + std::cout << "[fuzzer] RTP fuzzer enabled" << std::endl; fuzzRtp = true; } if (std::getenv("MS_FUZZ_RTCP") && std::string(std::getenv("MS_FUZZ_RTCP")) == "1") { - std::cout << "[fuzzer] RTCP fuzzers enabled" << std::endl; + std::cout << "[fuzzer] RTCP fuzzer enabled" << std::endl; fuzzRtcp = true; } if (std::getenv("MS_FUZZ_UTILS") && std::string(std::getenv("MS_FUZZ_UTILS")) == "1") { - std::cout << "[fuzzer] Utils fuzzers enabled" << std::endl; + std::cout << "[fuzzer] Utils fuzzer enabled" << std::endl; fuzzUtils = true; } - if (!fuzzUtils && !fuzzStun && !fuzzRtcp && !fuzzRtp) + if (!fuzzStun && !fuzzDtls && !fuzzRtcp && !fuzzRtp && !fuzzUtils) { std::cout << "[fuzzer] all fuzzers enabled" << std::endl; fuzzStun = true; + fuzzDtls = true; fuzzRtp = true; fuzzRtcp = true; fuzzUtils = true; @@ -128,6 +144,7 @@ int Init() DepUsrSCTP::ClassInit(); DepLibWebRTC::ClassInit(); Utils::Crypto::ClassInit(); + ::RTC::DtlsTransport::ClassInit(); return 0; } diff --git a/worker/meson.build b/worker/meson.build index 77125be6e0..bc4ff9eb00 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -431,11 +431,12 @@ executable( sources: common_sources + [ 'fuzzer/src/fuzzer.cpp', 'fuzzer/src/FuzzerUtils.cpp', - 'fuzzer/src/RTC/FuzzerStunPacket.cpp', + 'fuzzer/src/RTC/FuzzerDtlsTransport.cpp', 'fuzzer/src/RTC/FuzzerRtpPacket.cpp', 'fuzzer/src/RTC/FuzzerRtpRetransmissionBuffer.cpp', 'fuzzer/src/RTC/FuzzerRtpStreamSend.cpp', 'fuzzer/src/RTC/FuzzerSeqManager.cpp', + 'fuzzer/src/RTC/FuzzerStunPacket.cpp', 'fuzzer/src/RTC/FuzzerTrendCalculator.cpp', 'fuzzer/src/RTC/RTCP/FuzzerBye.cpp', 'fuzzer/src/RTC/RTCP/FuzzerFeedbackPs.cpp', From d1e6f668b81518265bb0eaeefc765d3b90e29323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 1 Mar 2024 11:48:10 +0100 Subject: [PATCH 377/525] Fix missing bitrateByLayer field in stats of RtpRecvStream in Node (#1349) --- CHANGELOG.md | 4 ++++ node/src/RtpStream.ts | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0337b36ac..026c5162e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Next + +- Node: Fix missing `bitrateByLayer` field in stats of `RtpRecvStream` in Node ([PR #1349](https://github.com/versatica/mediasoup/pull/1349)). + ### 3.13.23 - Fix DTLS packets do not honor configured DTLS MTU (attempt 3) ([PR #1345](https://github.com/versatica/mediasoup/pull/1345)). diff --git a/node/src/RtpStream.ts b/node/src/RtpStream.ts index af0296bb61..47acfd44a0 100644 --- a/node/src/RtpStream.ts +++ b/node/src/RtpStream.ts @@ -1,13 +1,15 @@ import * as FbsRtpStream from './fbs/rtp-stream'; import * as FbsRtpParameters from './fbs/rtp-parameters'; +type BitrateByLayer = { [key: string]: number }; + export type RtpStreamRecvStats = BaseRtpStreamStats & { type: string; jitter: number; packetCount: number; byteCount: number; bitrate: number; - bitrateByLayer?: any; + bitrateByLayer: BitrateByLayer; }; export type RtpStreamSendStats = BaseRtpStreamStats & { @@ -118,7 +120,7 @@ function parseBaseStreamStats( }; } -function parseBitrateByLayer(binary: FbsRtpStream.RecvStats): any { +function parseBitrateByLayer(binary: FbsRtpStream.RecvStats): BitrateByLayer { if (binary.bitrateByLayerLength() === 0) { return {}; } @@ -131,4 +133,6 @@ function parseBitrateByLayer(binary: FbsRtpStream.RecvStats): any { bitRateByLayer[layer] = Number(bitrate); } + + return bitRateByLayer; } From 0e1eb9deafaef70cea31ac5105b7676c2fbd0e5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 00:42:43 +0100 Subject: [PATCH 378/525] Bump the cargo group group with 1 update (#1350) --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 815ea73405..b354e488c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1272,9 +1272,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" @@ -1447,9 +1447,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", From af7fb8ca079a380da381e335547fe8cb2bc84e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 5 Mar 2024 11:30:57 +0100 Subject: [PATCH 379/525] Update NPM dev deps --- package-lock.json | 346 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 176 insertions(+), 176 deletions(-) diff --git a/package-lock.json b/package-lock.json index b69a6dafbf..cb0ca861eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,9 +21,9 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.20", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", + "@types/node": "^20.11.24", + "@typescript-eslint/eslint-plugin": "^7.1.1", + "@typescript-eslint/parser": "^7.1.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", @@ -1626,9 +1626,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", - "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", + "version": "20.11.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", + "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1662,16 +1662,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz", - "integrity": "sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", + "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/type-utils": "7.1.0", - "@typescript-eslint/utils": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/type-utils": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1697,13 +1697,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", - "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0" + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1714,9 +1714,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", - "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1727,13 +1727,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", - "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1755,17 +1755,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", - "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", + "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", "semver": "^7.5.4" }, "engines": { @@ -1780,12 +1780,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", - "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/types": "7.1.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1821,15 +1821,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.0.tgz", - "integrity": "sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", + "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/typescript-estree": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4" }, "engines": { @@ -1849,13 +1849,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", - "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0" + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1866,9 +1866,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", - "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1879,13 +1879,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", - "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1907,12 +1907,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", - "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/types": "7.1.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1965,13 +1965,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz", - "integrity": "sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", + "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.1.0", - "@typescript-eslint/utils": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/utils": "7.1.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1992,13 +1992,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", - "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0" + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2009,9 +2009,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", - "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2022,13 +2022,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", - "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2050,17 +2050,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", - "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", + "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", "semver": "^7.5.4" }, "engines": { @@ -2075,12 +2075,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", - "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/types": "7.1.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -7514,9 +7514,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", - "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", + "version": "20.11.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", + "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7550,16 +7550,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz", - "integrity": "sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", + "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/type-utils": "7.1.0", - "@typescript-eslint/utils": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/type-utils": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7569,29 +7569,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", - "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0" + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" } }, "@typescript-eslint/types": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", - "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", - "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7601,27 +7601,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", - "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", + "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", - "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/types": "7.1.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -7646,42 +7646,42 @@ } }, "@typescript-eslint/parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.0.tgz", - "integrity": "sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", + "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/typescript-estree": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", - "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0" + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" } }, "@typescript-eslint/types": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", - "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", - "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7691,12 +7691,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", - "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/types": "7.1.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -7731,41 +7731,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz", - "integrity": "sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", + "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.1.0", - "@typescript-eslint/utils": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/utils": "7.1.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", - "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0" + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" } }, "@typescript-eslint/types": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", - "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", - "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7775,27 +7775,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", - "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", + "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", - "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/types": "7.1.1", "eslint-visitor-keys": "^3.4.1" } }, diff --git a/package.json b/package.json index ee4cfe6dfc..3f06384927 100644 --- a/package.json +++ b/package.json @@ -110,9 +110,9 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.20", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", + "@types/node": "^20.11.24", + "@typescript-eslint/eslint-plugin": "^7.1.1", + "@typescript-eslint/parser": "^7.1.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", From f330dffdd591849d934978e2d84841100ade6054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 7 Mar 2024 11:14:13 +0100 Subject: [PATCH 380/525] Update libuv to 1.48.0 --- CHANGELOG.md | 1 + worker/subprojects/libuv.wrap | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 026c5162e0..10fe06bb0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Next - Node: Fix missing `bitrateByLayer` field in stats of `RtpRecvStream` in Node ([PR #1349](https://github.com/versatica/mediasoup/pull/1349)). +- Update worker dependency libuv to 1.48.0. ### 3.13.23 diff --git a/worker/subprojects/libuv.wrap b/worker/subprojects/libuv.wrap index 53ef63575e..94f0018009 100644 --- a/worker/subprojects/libuv.wrap +++ b/worker/subprojects/libuv.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = libuv-v1.47.0 -source_url = https://dist.libuv.org/dist/v1.47.0/libuv-v1.47.0.tar.gz -source_filename = libuv-v1.47.0.tar.gz -source_hash = 20c37a4ca77a2107879473c6c8fa0dc1350e80045df98bfbe78f7cd6d7dd2965 -patch_filename = libuv_1.47.0-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/libuv_1.47.0-1/get_patch -patch_hash = 7362dfca01c8ddf89a60a4a05faa8a1fc7976b8b57aa6e3c54630e329a418b8f -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libuv_1.47.0-1/libuv-v1.47.0.tar.gz -wrapdb_version = 1.47.0-1 +directory = libuv-v1.48.0 +source_url = https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz +source_filename = libuv-v1.48.0.tar.gz +source_hash = 7f1db8ac368d89d1baf163bac1ea5fe5120697a73910c8ae6b2fffb3551d59fb +patch_filename = libuv_1.48.0-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/libuv_1.48.0-1/get_patch +patch_hash = 27b18917c914a5d6dfb459073710e9bfb6b2962d69d4e0bad5bc7b1173482be7 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libuv_1.48.0-1/libuv-v1.48.0.tar.gz +wrapdb_version = 1.48.0-1 [provide] libuv = libuv_dep From e39044bfcb7c82339697e3dad5dd677426dc8dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 8 Mar 2024 09:20:49 +0100 Subject: [PATCH 381/525] Fuzzer codecs (#1355) --- doc/Fuzzer.md | 7 +++ .../fuzzer/include/RTC/Codecs/FuzzerH264.hpp | 20 ++++++++ .../include/RTC/Codecs/FuzzerH264_SVC.hpp | 20 ++++++++ .../fuzzer/include/RTC/Codecs/FuzzerOpus.hpp | 20 ++++++++ .../fuzzer/include/RTC/Codecs/FuzzerVP8.hpp | 20 ++++++++ .../fuzzer/include/RTC/Codecs/FuzzerVP9.hpp | 20 ++++++++ ...h-7e7caf72377ad55d353719f28febb5238eadfc9e | 1 + ...h-9cc885b84ba02d766f422c6512ead3808ded0189 | Bin 0 -> 4 bytes worker/fuzzer/src/RTC/Codecs/FuzzerH264.cpp | 14 ++++++ .../fuzzer/src/RTC/Codecs/FuzzerH264_SVC.cpp | 14 ++++++ worker/fuzzer/src/RTC/Codecs/FuzzerOpus.cpp | 14 ++++++ worker/fuzzer/src/RTC/Codecs/FuzzerVP8.cpp | 14 ++++++ worker/fuzzer/src/RTC/Codecs/FuzzerVP9.cpp | 14 ++++++ worker/fuzzer/src/fuzzer.cpp | 44 +++++++++++++----- worker/include/RTC/Codecs/H264.hpp | 1 + worker/meson.build | 5 ++ worker/src/RTC/Codecs/H264_SVC.cpp | 11 +++++ 17 files changed, 228 insertions(+), 11 deletions(-) create mode 100644 worker/fuzzer/include/RTC/Codecs/FuzzerH264.hpp create mode 100644 worker/fuzzer/include/RTC/Codecs/FuzzerH264_SVC.hpp create mode 100644 worker/fuzzer/include/RTC/Codecs/FuzzerOpus.hpp create mode 100644 worker/fuzzer/include/RTC/Codecs/FuzzerVP8.hpp create mode 100644 worker/fuzzer/include/RTC/Codecs/FuzzerVP9.hpp create mode 100644 worker/fuzzer/reports/crash-7e7caf72377ad55d353719f28febb5238eadfc9e create mode 100644 worker/fuzzer/reports/crash-9cc885b84ba02d766f422c6512ead3808ded0189 create mode 100644 worker/fuzzer/src/RTC/Codecs/FuzzerH264.cpp create mode 100644 worker/fuzzer/src/RTC/Codecs/FuzzerH264_SVC.cpp create mode 100644 worker/fuzzer/src/RTC/Codecs/FuzzerOpus.cpp create mode 100644 worker/fuzzer/src/RTC/Codecs/FuzzerVP8.cpp create mode 100644 worker/fuzzer/src/RTC/Codecs/FuzzerVP9.cpp diff --git a/doc/Fuzzer.md b/doc/Fuzzer.md index 0e94468faa..9514743f42 100644 --- a/doc/Fuzzer.md +++ b/doc/Fuzzer.md @@ -43,6 +43,7 @@ The mediasoup-worker fuzzer reads some custom environment variables to decide wh - `MS_FUZZ_DTLS=1`: Enable DTLS fuzzer. - `MS_FUZZ_RTP=1`: Enable RTP fuzzer. - `MS_FUZZ_RTCP=1`: Enable RTCP fuzzer. +- `MS_FUZZ_CODECS=1`: Enable audio/video codecs fuzzer. - `MS_FUZZ_UTILS=1`: Enable C++ utils fuzzer. - If none of them is given, then **all** fuzzers are enabled. @@ -74,6 +75,12 @@ MS_FUZZ_RTP=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-wor MS_FUZZ_RTCP=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus ``` +- Detect memory leaks and just fuzz audio/video codecs: + +```bash +MS_FUZZ_CODECS=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus +``` + - Detect memory leaks and just fuzz mediasoup-worker C++ utils: ```bash diff --git a/worker/fuzzer/include/RTC/Codecs/FuzzerH264.hpp b/worker/fuzzer/include/RTC/Codecs/FuzzerH264.hpp new file mode 100644 index 0000000000..21a2364365 --- /dev/null +++ b/worker/fuzzer/include/RTC/Codecs/FuzzerH264.hpp @@ -0,0 +1,20 @@ +#ifndef MS_FUZZER_RTC_CODECS_H264_HPP +#define MS_FUZZER_RTC_CODECS_H264_HPP + +#include "common.hpp" + +namespace Fuzzer +{ + namespace RTC + { + namespace Codecs + { + namespace H264 + { + void Fuzz(const uint8_t* data, size_t len); + } + } // namespace Codecs + } // namespace RTC +} // namespace Fuzzer + +#endif diff --git a/worker/fuzzer/include/RTC/Codecs/FuzzerH264_SVC.hpp b/worker/fuzzer/include/RTC/Codecs/FuzzerH264_SVC.hpp new file mode 100644 index 0000000000..d72125dc5d --- /dev/null +++ b/worker/fuzzer/include/RTC/Codecs/FuzzerH264_SVC.hpp @@ -0,0 +1,20 @@ +#ifndef MS_FUZZER_RTC_CODECS_H264_SVC_HPP +#define MS_FUZZER_RTC_CODECS_H264_SVC_HPP + +#include "common.hpp" + +namespace Fuzzer +{ + namespace RTC + { + namespace Codecs + { + namespace H264_SVC + { + void Fuzz(const uint8_t* data, size_t len); + } + } // namespace Codecs + } // namespace RTC +} // namespace Fuzzer + +#endif diff --git a/worker/fuzzer/include/RTC/Codecs/FuzzerOpus.hpp b/worker/fuzzer/include/RTC/Codecs/FuzzerOpus.hpp new file mode 100644 index 0000000000..2e52616600 --- /dev/null +++ b/worker/fuzzer/include/RTC/Codecs/FuzzerOpus.hpp @@ -0,0 +1,20 @@ +#ifndef MS_FUZZER_RTC_CODECS_OPUS_HPP +#define MS_FUZZER_RTC_CODECS_OPUS_HPP + +#include "common.hpp" + +namespace Fuzzer +{ + namespace RTC + { + namespace Codecs + { + namespace Opus + { + void Fuzz(const uint8_t* data, size_t len); + } + } // namespace Codecs + } // namespace RTC +} // namespace Fuzzer + +#endif diff --git a/worker/fuzzer/include/RTC/Codecs/FuzzerVP8.hpp b/worker/fuzzer/include/RTC/Codecs/FuzzerVP8.hpp new file mode 100644 index 0000000000..dfa87efec8 --- /dev/null +++ b/worker/fuzzer/include/RTC/Codecs/FuzzerVP8.hpp @@ -0,0 +1,20 @@ +#ifndef MS_FUZZER_RTC_CODECS_VP8_HPP +#define MS_FUZZER_RTC_CODECS_VP8_HPP + +#include "common.hpp" + +namespace Fuzzer +{ + namespace RTC + { + namespace Codecs + { + namespace VP8 + { + void Fuzz(const uint8_t* data, size_t len); + } + } // namespace Codecs + } // namespace RTC +} // namespace Fuzzer + +#endif diff --git a/worker/fuzzer/include/RTC/Codecs/FuzzerVP9.hpp b/worker/fuzzer/include/RTC/Codecs/FuzzerVP9.hpp new file mode 100644 index 0000000000..93743cbeae --- /dev/null +++ b/worker/fuzzer/include/RTC/Codecs/FuzzerVP9.hpp @@ -0,0 +1,20 @@ +#ifndef MS_FUZZER_RTC_CODECS_VP9_HPP +#define MS_FUZZER_RTC_CODECS_VP9_HPP + +#include "common.hpp" + +namespace Fuzzer +{ + namespace RTC + { + namespace Codecs + { + namespace VP9 + { + void Fuzz(const uint8_t* data, size_t len); + } + } // namespace Codecs + } // namespace RTC +} // namespace Fuzzer + +#endif diff --git a/worker/fuzzer/reports/crash-7e7caf72377ad55d353719f28febb5238eadfc9e b/worker/fuzzer/reports/crash-7e7caf72377ad55d353719f28febb5238eadfc9e new file mode 100644 index 0000000000..e570989278 --- /dev/null +++ b/worker/fuzzer/reports/crash-7e7caf72377ad55d353719f28febb5238eadfc9e @@ -0,0 +1 @@ +88t \ No newline at end of file diff --git a/worker/fuzzer/reports/crash-9cc885b84ba02d766f422c6512ead3808ded0189 b/worker/fuzzer/reports/crash-9cc885b84ba02d766f422c6512ead3808ded0189 new file mode 100644 index 0000000000000000000000000000000000000000..e450f03ee831d124112a2d8b13460847777e845a GIT binary patch literal 4 LcmcCuVK4yz0VDu% literal 0 HcmV?d00001 diff --git a/worker/fuzzer/src/RTC/Codecs/FuzzerH264.cpp b/worker/fuzzer/src/RTC/Codecs/FuzzerH264.cpp new file mode 100644 index 0000000000..48404e41e8 --- /dev/null +++ b/worker/fuzzer/src/RTC/Codecs/FuzzerH264.cpp @@ -0,0 +1,14 @@ +#include "RTC/Codecs/FuzzerH264.hpp" +#include "RTC/Codecs/H264.hpp" + +void Fuzzer::RTC::Codecs::H264::Fuzz(const uint8_t* data, size_t len) +{ + ::RTC::Codecs::H264::PayloadDescriptor* descriptor = ::RTC::Codecs::H264::Parse(data, len); + + if (!descriptor) + { + return; + } + + delete descriptor; +} diff --git a/worker/fuzzer/src/RTC/Codecs/FuzzerH264_SVC.cpp b/worker/fuzzer/src/RTC/Codecs/FuzzerH264_SVC.cpp new file mode 100644 index 0000000000..b0af2e6012 --- /dev/null +++ b/worker/fuzzer/src/RTC/Codecs/FuzzerH264_SVC.cpp @@ -0,0 +1,14 @@ +#include "RTC/Codecs/FuzzerH264_SVC.hpp" +#include "RTC/Codecs/H264_SVC.hpp" + +void Fuzzer::RTC::Codecs::H264_SVC::Fuzz(const uint8_t* data, size_t len) +{ + ::RTC::Codecs::H264_SVC::PayloadDescriptor* descriptor = ::RTC::Codecs::H264_SVC::Parse(data, len); + + if (!descriptor) + { + return; + } + + delete descriptor; +} diff --git a/worker/fuzzer/src/RTC/Codecs/FuzzerOpus.cpp b/worker/fuzzer/src/RTC/Codecs/FuzzerOpus.cpp new file mode 100644 index 0000000000..188762c8b8 --- /dev/null +++ b/worker/fuzzer/src/RTC/Codecs/FuzzerOpus.cpp @@ -0,0 +1,14 @@ +#include "RTC/Codecs/FuzzerOpus.hpp" +#include "RTC/Codecs/Opus.hpp" + +void Fuzzer::RTC::Codecs::Opus::Fuzz(const uint8_t* data, size_t len) +{ + ::RTC::Codecs::Opus::PayloadDescriptor* descriptor = ::RTC::Codecs::Opus::Parse(data, len); + + if (!descriptor) + { + return; + } + + delete descriptor; +} diff --git a/worker/fuzzer/src/RTC/Codecs/FuzzerVP8.cpp b/worker/fuzzer/src/RTC/Codecs/FuzzerVP8.cpp new file mode 100644 index 0000000000..a628bd5e11 --- /dev/null +++ b/worker/fuzzer/src/RTC/Codecs/FuzzerVP8.cpp @@ -0,0 +1,14 @@ +#include "RTC/Codecs/FuzzerVP8.hpp" +#include "RTC/Codecs/VP8.hpp" + +void Fuzzer::RTC::Codecs::VP8::Fuzz(const uint8_t* data, size_t len) +{ + ::RTC::Codecs::VP8::PayloadDescriptor* descriptor = ::RTC::Codecs::VP8::Parse(data, len); + + if (!descriptor) + { + return; + } + + delete descriptor; +} diff --git a/worker/fuzzer/src/RTC/Codecs/FuzzerVP9.cpp b/worker/fuzzer/src/RTC/Codecs/FuzzerVP9.cpp new file mode 100644 index 0000000000..c10a177a79 --- /dev/null +++ b/worker/fuzzer/src/RTC/Codecs/FuzzerVP9.cpp @@ -0,0 +1,14 @@ +#include "RTC/Codecs/FuzzerVP9.hpp" +#include "RTC/Codecs/VP9.hpp" + +void Fuzzer::RTC::Codecs::VP9::Fuzz(const uint8_t* data, size_t len) +{ + ::RTC::Codecs::VP9::PayloadDescriptor* descriptor = ::RTC::Codecs::VP9::Parse(data, len); + + if (!descriptor) + { + return; + } + + delete descriptor; +} diff --git a/worker/fuzzer/src/fuzzer.cpp b/worker/fuzzer/src/fuzzer.cpp index 403ef2c417..d51422b103 100644 --- a/worker/fuzzer/src/fuzzer.cpp +++ b/worker/fuzzer/src/fuzzer.cpp @@ -9,6 +9,11 @@ #include "LogLevel.hpp" #include "Settings.hpp" #include "Utils.hpp" +#include "RTC/Codecs/FuzzerH264.hpp" +#include "RTC/Codecs/FuzzerH264_SVC.hpp" +#include "RTC/Codecs/FuzzerOpus.hpp" +#include "RTC/Codecs/FuzzerVP8.hpp" +#include "RTC/Codecs/FuzzerVP9.hpp" #include "RTC/DtlsTransport.hpp" #include "RTC/FuzzerDtlsTransport.hpp" #include "RTC/FuzzerRtpPacket.hpp" @@ -23,11 +28,12 @@ #include #include -bool fuzzStun = false; -bool fuzzDtls = false; -bool fuzzRtp = false; -bool fuzzRtcp = false; -bool fuzzUtils = false; +bool fuzzStun = false; +bool fuzzDtls = false; +bool fuzzRtp = false; +bool fuzzRtcp = false; +bool fuzzCodecs = false; +bool fuzzUtils = false; int Init(); @@ -62,6 +68,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) Fuzzer::RTC::RTCP::Packet::Fuzz(data, len); } + if (fuzzCodecs) + { + Fuzzer::RTC::Codecs::Opus::Fuzz(data, len); + Fuzzer::RTC::Codecs::VP8::Fuzz(data, len); + Fuzzer::RTC::Codecs::VP9::Fuzz(data, len); + Fuzzer::RTC::Codecs::H264::Fuzz(data, len); + Fuzzer::RTC::Codecs::H264_SVC::Fuzz(data, len); + } + if (fuzzUtils) { Fuzzer::Utils::Fuzz(data, len); @@ -118,21 +133,28 @@ int Init() fuzzRtcp = true; } + if (std::getenv("MS_FUZZ_CODECS") && std::string(std::getenv("MS_FUZZ_CODECS")) == "1") + { + std::cout << "[fuzzer] codecs fuzzer enabled" << std::endl; + + fuzzCodecs = true; + } if (std::getenv("MS_FUZZ_UTILS") && std::string(std::getenv("MS_FUZZ_UTILS")) == "1") { std::cout << "[fuzzer] Utils fuzzer enabled" << std::endl; fuzzUtils = true; } - if (!fuzzStun && !fuzzDtls && !fuzzRtcp && !fuzzRtp && !fuzzUtils) + if (!fuzzStun && !fuzzDtls && !fuzzRtp && !fuzzRtcp && !fuzzCodecs && !fuzzUtils) { std::cout << "[fuzzer] all fuzzers enabled" << std::endl; - fuzzStun = true; - fuzzDtls = true; - fuzzRtp = true; - fuzzRtcp = true; - fuzzUtils = true; + fuzzStun = true; + fuzzDtls = true; + fuzzRtp = true; + fuzzRtcp = true; + fuzzCodecs = true; + fuzzUtils = true; } Settings::configuration.logLevel = logLevel; diff --git a/worker/include/RTC/Codecs/H264.hpp b/worker/include/RTC/Codecs/H264.hpp index 788c86aa0e..8fda3227de 100644 --- a/worker/include/RTC/Codecs/H264.hpp +++ b/worker/include/RTC/Codecs/H264.hpp @@ -28,6 +28,7 @@ namespace RTC uint8_t tid{ 0 }; // Temporal layer id. uint8_t lid{ 0 }; // Spatial layer id. uint8_t tl0picidx{ 0 }; // TL0PICIDX + // Parsed values. bool hasLid{ false }; bool hasTid{ false }; diff --git a/worker/meson.build b/worker/meson.build index bc4ff9eb00..f4d24f5958 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -438,6 +438,11 @@ executable( 'fuzzer/src/RTC/FuzzerSeqManager.cpp', 'fuzzer/src/RTC/FuzzerStunPacket.cpp', 'fuzzer/src/RTC/FuzzerTrendCalculator.cpp', + 'fuzzer/src/RTC/Codecs/FuzzerOpus.cpp', + 'fuzzer/src/RTC/Codecs/FuzzerVP8.cpp', + 'fuzzer/src/RTC/Codecs/FuzzerVP9.cpp', + 'fuzzer/src/RTC/Codecs/FuzzerH264.cpp', + 'fuzzer/src/RTC/Codecs/FuzzerH264_SVC.cpp', 'fuzzer/src/RTC/RTCP/FuzzerBye.cpp', 'fuzzer/src/RTC/RTCP/FuzzerFeedbackPs.cpp', 'fuzzer/src/RTC/RTCP/FuzzerFeedbackPsAfb.cpp', diff --git a/worker/src/RTC/Codecs/H264_SVC.cpp b/worker/src/RTC/Codecs/H264_SVC.cpp index f67b1fae86..05e43ec318 100644 --- a/worker/src/RTC/Codecs/H264_SVC.cpp +++ b/worker/src/RTC/Codecs/H264_SVC.cpp @@ -166,7 +166,10 @@ namespace RTC // Single NAL unit packet. // IDR (instantaneous decoding picture). case 5: + { payloadDescriptor->isKeyFrame = true; + } + case 1: { payloadDescriptor->slIndex = 0; @@ -177,9 +180,15 @@ namespace RTC break; } + case 14: case 20: { + if (len <= 1) + { + return nullptr; + } + size_t offset{ 1 }; uint8_t byte = data[offset]; @@ -210,6 +219,7 @@ namespace RTC break; } + case 7: { payloadDescriptor->isKeyFrame = isStartBit ? true : false; @@ -217,6 +227,7 @@ namespace RTC break; } } + return payloadDescriptor; } From 564b3ac6498dcba2bbfe9b53709bc3d573eb537e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 8 Mar 2024 10:34:46 +0100 Subject: [PATCH 382/525] Update FlatBuffers to 24.3.6-1 (fix cannot set temporal layer 0) (#1348) --- CHANGELOG.md | 3 +- node/src/test/test-Consumer.ts | 40 +++++++++++++++++--- npm-scripts.mjs | 23 ++++++++++-- package-lock.json | 39 +++++++++++++++---- package.json | 4 +- rust/tests/integration/consumer.rs | 58 +++++++++++++++++++++++++++-- worker/subprojects/flatbuffers.wrap | 18 ++++----- 7 files changed, 154 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10fe06bb0f..d9148cb203 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Node: Fix missing `bitrateByLayer` field in stats of `RtpRecvStream` in Node ([PR #1349](https://github.com/versatica/mediasoup/pull/1349)). - Update worker dependency libuv to 1.48.0. +- Update worker FlatBuffers to 24.3.6-1 (fix cannot set temporal layer 0) ([PR #1348](https://github.com/versatica/mediasoup/pull/1348)). ### 3.13.23 @@ -123,7 +124,7 @@ ### 3.13.0 -- Switch from JSON based messages to `flatbuffers` ([PR #1064](https://github.com/versatica/mediasoup/pull/1064)). +- Switch from JSON based messages to FlatBuffers ([PR #1064](https://github.com/versatica/mediasoup/pull/1064)). - Add `ListenInfo` in all transports and send/recv buffer size options ([PR #1084](https://github.com/versatica/mediasoup/pull/1084)). - Add optional `rtcpListenInfo` in `PlainTransportOptions` ([PR #1099](https://github.com/versatica/mediasoup/pull/1099)). - Add pause/resume API in `DataProducer` and `DataConsumer` ([PR #1104](https://github.com/versatica/mediasoup/pull/1104)). diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index 829ee29fe1..ee643c7a25 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -123,10 +123,10 @@ const ctx: TestContext = { }, ], encodings: [ - { ssrc: 22222222, rtx: { ssrc: 22222223 } }, - { ssrc: 22222224, rtx: { ssrc: 22222225 } }, - { ssrc: 22222226, rtx: { ssrc: 22222227 } }, - { ssrc: 22222228, rtx: { ssrc: 22222229 } }, + { ssrc: 22222222, scalabilityMode: 'L1T5', rtx: { ssrc: 22222223 } }, + { ssrc: 22222224, scalabilityMode: 'L1T5', rtx: { ssrc: 22222225 } }, + { ssrc: 22222226, scalabilityMode: 'L1T5', rtx: { ssrc: 22222227 } }, + { ssrc: 22222228, scalabilityMode: 'L1T5', rtx: { ssrc: 22222229 } }, ], rtcp: { cname: 'FOOBAR', @@ -343,7 +343,7 @@ test('transport.consume() succeeds', async () => { producerId: ctx.videoProducer!.id, rtpCapabilities: ctx.consumerDeviceCapabilities, paused: true, - preferredLayers: { spatialLayer: 12 }, + preferredLayers: { spatialLayer: 12, temporalLayer: 0 }, appData: { baz: 'LOL' }, }); @@ -729,7 +729,7 @@ test('consumer.dump() succeeds', async () => { rtx: { ssrc: videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc, }, - scalabilityMode: 'L4T1', + scalabilityMode: 'L4T5', }, ]); expect(Array.isArray(dump2.consumableRtpEncodings)).toBe(true); @@ -737,21 +737,25 @@ test('consumer.dump() succeeds', async () => { expect(dump2.consumableRtpEncodings![0]).toEqual( expect.objectContaining({ ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[0].ssrc, + scalabilityMode: 'L1T5', }) ); expect(dump2.consumableRtpEncodings![1]).toEqual( expect.objectContaining({ ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[1].ssrc, + scalabilityMode: 'L1T5', }) ); expect(dump2.consumableRtpEncodings![2]).toEqual( expect.objectContaining({ ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[2].ssrc, + scalabilityMode: 'L1T5', }) ); expect(dump2.consumableRtpEncodings![3]).toEqual( expect.objectContaining({ ssrc: ctx.videoProducer!.consumableRtpParameters.encodings?.[3].ssrc, + scalabilityMode: 'L1T5', }) ); expect(dump2.supportedCodecPayloadTypes).toEqual([103]); @@ -870,8 +874,32 @@ test('consumer.setPreferredLayers() succeed', async () => { expect(videoConsumer.preferredLayers).toEqual({ spatialLayer: 2, + temporalLayer: 3, + }); + + await videoConsumer.setPreferredLayers({ spatialLayer: 3 }); + + expect(videoConsumer.preferredLayers).toEqual({ + spatialLayer: 3, + temporalLayer: 4, + }); + + await videoConsumer.setPreferredLayers({ spatialLayer: 3, temporalLayer: 0 }); + + expect(videoConsumer.preferredLayers).toEqual({ + spatialLayer: 3, temporalLayer: 0, }); + + await videoConsumer.setPreferredLayers({ + spatialLayer: 66, + temporalLayer: 66, + }); + + expect(videoConsumer.preferredLayers).toEqual({ + spatialLayer: 3, + temporalLayer: 4, + }); }, 2000); test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError', async () => { diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 2094e1dd55..7cdffa32e4 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -5,13 +5,15 @@ import * as path from 'node:path'; import { execSync } from 'node:child_process'; import fetch from 'node-fetch'; import tar from 'tar'; +import * as ini from 'ini'; -const PKG = JSON.parse(fs.readFileSync('./package.json').toString()); +const PKG = JSON.parse( + fs.readFileSync('./package.json', { encoding: 'utf-8' }) +); const IS_WINDOWS = os.platform() === 'win32'; const MAYOR_VERSION = PKG.version.split('.')[0]; const PYTHON = getPython(); const PIP_INVOKE_DIR = path.resolve('worker/pip_invoke'); -const FLATBUFFERS_VERSION = '23.3.3'; const WORKER_RELEASE_DIR = 'worker/out/Release'; const WORKER_RELEASE_BIN = IS_WINDOWS ? 'mediasoup-worker.exe' @@ -362,6 +364,18 @@ function flatcNode() { const buildType = process.env.MEDIASOUP_BUILDTYPE || 'Release'; const extension = IS_WINDOWS ? '.exe' : ''; + const flatbuffersWrapFilePath = path.join( + 'worker', + 'subprojects', + 'flatbuffers.wrap' + ); + const flatbuffersWrap = ini.parse( + fs.readFileSync(flatbuffersWrapFilePath, { + encoding: 'utf-8', + }) + ); + const flatbuffersDir = flatbuffersWrap['wrap-file']['directory']; + const flatc = path.resolve( path.join( 'worker', @@ -369,10 +383,11 @@ function flatcNode() { buildType, 'build', 'subprojects', - `flatbuffers-${FLATBUFFERS_VERSION}`, + flatbuffersDir, `flatc${extension}` ) ); + const out = path.resolve(path.join('node', 'src')); for (const dirent of fs.readdirSync(path.join('worker', 'fbs'), { @@ -601,7 +616,7 @@ async function getVersionChanges() { // NOTE: Load dep on demand since it's a devDependency. const marked = await import('marked'); - const changelog = fs.readFileSync('./CHANGELOG.md').toString(); + const changelog = fs.readFileSync('./CHANGELOG.md', { encoding: 'utf-8' }); const entries = marked.lexer(changelog); for (let idx = 0; idx < entries.length; ++idx) { diff --git a/package-lock.json b/package-lock.json index cb0ca861eb..f0668b33b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,11 @@ "hasInstallScript": true, "license": "ISC", "dependencies": { + "@types/ini": "^4.1.0", "debug": "^4.3.4", - "flatbuffers": "^23.5.26", + "flatbuffers": "^24.3.6", "h264-profile-level-id": "^2.0.0", + "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0" @@ -1580,6 +1582,11 @@ "@types/node": "*" } }, + "node_modules/@types/ini": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@types/ini/-/ini-4.1.0.tgz", + "integrity": "sha512-mTehMtc+xtnWBBvqizcqYCktKDBH2WChvx1GU3Sfe4PysFDXiNe+1YwtpVX1MDtCa4NQrSPw2+3HmvXHY3gt1w==" + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -3408,9 +3415,9 @@ } }, "node_modules/flatbuffers": { - "version": "23.5.26", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.5.26.tgz", - "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==" + "version": "24.3.6", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.6.tgz", + "integrity": "sha512-R+LI8mP4YvuHfX3lUgKVmF/Y95hlxBtxQS7+zmYBSa9xvpxLvzQDQuTxIhrOCmnbsF71vk1NCZ7h9k0VYBa1PA==" }, "node_modules/flatted": { "version": "3.2.7", @@ -3748,6 +3755,14 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ini": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", + "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/ip": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", @@ -7468,6 +7483,11 @@ "@types/node": "*" } }, + "@types/ini": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@types/ini/-/ini-4.1.0.tgz", + "integrity": "sha512-mTehMtc+xtnWBBvqizcqYCktKDBH2WChvx1GU3Sfe4PysFDXiNe+1YwtpVX1MDtCa4NQrSPw2+3HmvXHY3gt1w==" + }, "@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -8717,9 +8737,9 @@ } }, "flatbuffers": { - "version": "23.5.26", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.5.26.tgz", - "integrity": "sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==" + "version": "24.3.6", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.6.tgz", + "integrity": "sha512-R+LI8mP4YvuHfX3lUgKVmF/Y95hlxBtxQS7+zmYBSa9xvpxLvzQDQuTxIhrOCmnbsF71vk1NCZ7h9k0VYBa1PA==" }, "flatted": { "version": "3.2.7", @@ -8950,6 +8970,11 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "ini": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", + "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==" + }, "ip": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", diff --git a/package.json b/package.json index 3f06384927..7a14c80c24 100644 --- a/package.json +++ b/package.json @@ -99,9 +99,11 @@ ] }, "dependencies": { + "@types/ini": "^4.1.0", "debug": "^4.3.4", - "flatbuffers": "^23.5.26", + "flatbuffers": "^24.3.6", "h264-profile-level-id": "^2.0.0", + "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^6.2.0" diff --git a/rust/tests/integration/consumer.rs b/rust/tests/integration/consumer.rs index 35fdaa214e..ed2fdbc3b0 100644 --- a/rust/tests/integration/consumer.rs +++ b/rust/tests/integration/consumer.rs @@ -159,21 +159,25 @@ fn video_producer_options() -> ProducerOptions { encodings: vec![ RtpEncodingParameters { ssrc: Some(22222222), + scalability_mode: "L1T5".parse().unwrap(), rtx: Some(RtpEncodingParametersRtx { ssrc: 22222223 }), ..RtpEncodingParameters::default() }, RtpEncodingParameters { ssrc: Some(22222224), + scalability_mode: "L1T5".parse().unwrap(), rtx: Some(RtpEncodingParametersRtx { ssrc: 22222225 }), ..RtpEncodingParameters::default() }, RtpEncodingParameters { ssrc: Some(22222226), + scalability_mode: "L1T5".parse().unwrap(), rtx: Some(RtpEncodingParametersRtx { ssrc: 22222227 }), ..RtpEncodingParameters::default() }, RtpEncodingParameters { ssrc: Some(22222228), + scalability_mode: "L1T5".parse().unwrap(), rtx: Some(RtpEncodingParametersRtx { ssrc: 22222229 }), ..RtpEncodingParameters::default() }, @@ -499,7 +503,7 @@ fn consume_succeeds() { options.paused = true; options.preferred_layers = Some(ConsumerLayers { spatial_layer: 12, - temporal_layer: None, + temporal_layer: Some(0), }); options.app_data = AppData::new(ConsumerAppData { baz: "LOL" }); options @@ -1091,7 +1095,7 @@ fn dump_succeeds() { .unwrap() .rtx, dtx: None, - scalability_mode: "L4T1".parse().unwrap(), + scalability_mode: "L4T5".parse().unwrap(), rid: None, max_bitrate: None, }], @@ -1110,7 +1114,7 @@ fn dump_succeeds() { rtx: None, max_bitrate: None, dtx: None, - scalability_mode: ScalabilityMode::None, + scalability_mode: "L1T5".parse().unwrap(), }) .collect::>() ); @@ -1324,9 +1328,57 @@ fn set_preferred_layers_succeeds() { video_consumer.preferred_layers(), Some(ConsumerLayers { spatial_layer: 2, + temporal_layer: Some(3), + }) + ); + + video_consumer + .set_preferred_layers(ConsumerLayers { + spatial_layer: 3, + temporal_layer: None, + }) + .await + .expect("Failed to set preferred layers consumer"); + + assert_eq!( + video_consumer.preferred_layers(), + Some(ConsumerLayers { + spatial_layer: 3, + temporal_layer: Some(4), + }) + ); + + video_consumer + .set_preferred_layers(ConsumerLayers { + spatial_layer: 3, + temporal_layer: Some(0), + }) + .await + .expect("Failed to set preferred layers consumer"); + + assert_eq!( + video_consumer.preferred_layers(), + Some(ConsumerLayers { + spatial_layer: 3, temporal_layer: Some(0), }) ); + + video_consumer + .set_preferred_layers(ConsumerLayers { + spatial_layer: 66, + temporal_layer: Some(66), + }) + .await + .expect("Failed to set preferred layers consumer"); + + assert_eq!( + video_consumer.preferred_layers(), + Some(ConsumerLayers { + spatial_layer: 3, + temporal_layer: Some(4), + }) + ); } }); } diff --git a/worker/subprojects/flatbuffers.wrap b/worker/subprojects/flatbuffers.wrap index 630611bdb1..57cca8ca88 100644 --- a/worker/subprojects/flatbuffers.wrap +++ b/worker/subprojects/flatbuffers.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = flatbuffers-23.3.3 -source_url = https://github.com/google/flatbuffers/archive/v23.3.3.tar.gz -source_filename = flatbuffers-23.3.3.tar.gz -source_hash = 8aff985da30aaab37edf8e5b02fda33ed4cbdd962699a8e2af98fdef306f4e4d -patch_filename = flatbuffers_23.3.3-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/flatbuffers_23.3.3-1/get_patch -patch_hash = fa5faa75a99d1161be532a5d5db19543c15cb193d116d24827a251fc03488a14 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/flatbuffers_23.3.3-1/flatbuffers-23.3.3.tar.gz -wrapdb_version = 23.3.3-1 +directory = flatbuffers-24.3.6 +source_url = https://github.com/google/flatbuffers/archive/v24.3.6.tar.gz +source_filename = flatbuffers-24.3.6.tar.gz +source_hash = 5d8bfbf5b1b4c47f516e7673677f0e8db0efd32f262f7a14c3fd5ff67e2bd8fc +patch_filename = flatbuffers_24.3.6-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/flatbuffers_24.3.6-1/get_patch +patch_hash = bc0e1035a67ae74b1f862491fe2b0fd49b2889d989508143fff0a45508421bd7 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/flatbuffers_24.3.6-1/flatbuffers-24.3.6.tar.gz +wrapdb_version = 24.3.6-1 [provide] flatbuffers = flatbuffers_dep From 2972ca228232886fe90ace37b8c87f1c65853ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 8 Mar 2024 10:36:27 +0100 Subject: [PATCH 383/525] Update NPM deps --- package-lock.json | 56 +++++++++++++++++++++++------------------------ package.json | 8 +++---- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0668b33b2..7dfdaf5856 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "dependencies": { "@types/ini": "^4.1.0", "debug": "^4.3.4", - "flatbuffers": "^24.3.6", + "flatbuffers": "^24.3.7", "h264-profile-level-id": "^2.0.0", "ini": "^4.1.2", "node-fetch": "^3.3.2", @@ -23,7 +23,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.24", + "@types/node": "^20.11.25", "@typescript-eslint/eslint-plugin": "^7.1.1", "@typescript-eslint/parser": "^7.1.1", "eslint": "^8.57.0", @@ -31,13 +31,13 @@ "eslint-plugin-jest": "^27.9.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^12.0.0", + "marked": "^12.0.1", "open-cli": "^8.0.0", "pick-port": "^2.0.1", "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.3.3" + "typescript": "^5.4.2" }, "engines": { "node": ">=16" @@ -1633,9 +1633,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3415,9 +3415,9 @@ } }, "node_modules/flatbuffers": { - "version": "24.3.6", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.6.tgz", - "integrity": "sha512-R+LI8mP4YvuHfX3lUgKVmF/Y95hlxBtxQS7+zmYBSa9xvpxLvzQDQuTxIhrOCmnbsF71vk1NCZ7h9k0VYBa1PA==" + "version": "24.3.7", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.7.tgz", + "integrity": "sha512-GB19A5cyEvOVeQw3D72zXG/5rWXhGo+BhQj5YbXwOi9tV0IorjWKu1PyoW80FSNtii/YBAxHLuu54/ww0pPceQ==" }, "node_modules/flatted": { "version": "3.2.7", @@ -4746,9 +4746,9 @@ } }, "node_modules/marked": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.0.tgz", - "integrity": "sha512-Vkwtq9rLqXryZnWaQc86+FHLC6tr/fycMfYAhiOIXkrNmeGAyhSxjqu0Rs1i0bBqw5u0S7+lV9fdH2ZSVaoa0w==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.1.tgz", + "integrity": "sha512-Y1/V2yafOcOdWQCX0XpAKXzDakPOpn6U0YLxTJs3cww6VxOzZV1BTOOYWLvH3gX38cq+iLwljHHTnMtlDfg01Q==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -6052,9 +6052,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -7534,9 +7534,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -8737,9 +8737,9 @@ } }, "flatbuffers": { - "version": "24.3.6", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.6.tgz", - "integrity": "sha512-R+LI8mP4YvuHfX3lUgKVmF/Y95hlxBtxQS7+zmYBSa9xvpxLvzQDQuTxIhrOCmnbsF71vk1NCZ7h9k0VYBa1PA==" + "version": "24.3.7", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.7.tgz", + "integrity": "sha512-GB19A5cyEvOVeQw3D72zXG/5rWXhGo+BhQj5YbXwOi9tV0IorjWKu1PyoW80FSNtii/YBAxHLuu54/ww0pPceQ==" }, "flatted": { "version": "3.2.7", @@ -9713,9 +9713,9 @@ } }, "marked": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.0.tgz", - "integrity": "sha512-Vkwtq9rLqXryZnWaQc86+FHLC6tr/fycMfYAhiOIXkrNmeGAyhSxjqu0Rs1i0bBqw5u0S7+lV9fdH2ZSVaoa0w==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.1.tgz", + "integrity": "sha512-Y1/V2yafOcOdWQCX0XpAKXzDakPOpn6U0YLxTJs3cww6VxOzZV1BTOOYWLvH3gX38cq+iLwljHHTnMtlDfg01Q==", "dev": true }, "meow": { @@ -10579,9 +10579,9 @@ "dev": true }, "typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true }, "undici-types": { diff --git a/package.json b/package.json index 7a14c80c24..0956c0aba8 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "dependencies": { "@types/ini": "^4.1.0", "debug": "^4.3.4", - "flatbuffers": "^24.3.6", + "flatbuffers": "^24.3.7", "h264-profile-level-id": "^2.0.0", "ini": "^4.1.2", "node-fetch": "^3.3.2", @@ -112,7 +112,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.24", + "@types/node": "^20.11.25", "@typescript-eslint/eslint-plugin": "^7.1.1", "@typescript-eslint/parser": "^7.1.1", "eslint": "^8.57.0", @@ -120,12 +120,12 @@ "eslint-plugin-jest": "^27.9.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^12.0.0", + "marked": "^12.0.1", "open-cli": "^8.0.0", "pick-port": "^2.0.1", "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.3.3" + "typescript": "^5.4.2" } } From 8d757bc51afcc8553117cd10580fce2a81b28299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 8 Mar 2024 10:38:42 +0100 Subject: [PATCH 384/525] 3.13.24 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9148cb203..a22380b77f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### Next +### 3.13.24 - Node: Fix missing `bitrateByLayer` field in stats of `RtpRecvStream` in Node ([PR #1349](https://github.com/versatica/mediasoup/pull/1349)). - Update worker dependency libuv to 1.48.0. diff --git a/package-lock.json b/package-lock.json index 7dfdaf5856..2deb89f16c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.23", + "version": "3.13.24", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.23", + "version": "3.13.24", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 0956c0aba8..8d9f9b5ce6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.23", + "version": "3.13.24", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From fe0f7c40ec2aa6e17823c36247aa27a87568feed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 26 Mar 2024 10:42:20 +0100 Subject: [PATCH 385/525] Add fuzzer for RateCalculator class (#1358) --- .../include/RTC/FuzzerRateCalculator.hpp | 17 +++++++ .../fuzzer/src/RTC/FuzzerRateCalculator.cpp | 47 +++++++++++++++++++ worker/fuzzer/src/fuzzer.cpp | 6 ++- worker/meson.build | 1 + worker/src/RTC/RateCalculator.cpp | 5 +- 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 worker/fuzzer/include/RTC/FuzzerRateCalculator.hpp create mode 100644 worker/fuzzer/src/RTC/FuzzerRateCalculator.cpp diff --git a/worker/fuzzer/include/RTC/FuzzerRateCalculator.hpp b/worker/fuzzer/include/RTC/FuzzerRateCalculator.hpp new file mode 100644 index 0000000000..c7386bb3db --- /dev/null +++ b/worker/fuzzer/include/RTC/FuzzerRateCalculator.hpp @@ -0,0 +1,17 @@ +#ifndef MS_FUZZER_RTC_RATE_CALCULATOR_HPP +#define MS_FUZZER_RTC_RATE_CALCULATOR_HPP + +#include "common.hpp" + +namespace Fuzzer +{ + namespace RTC + { + namespace RateCalculator + { + void Fuzz(const uint8_t* data, size_t len); + } + } // namespace RTC +} // namespace Fuzzer + +#endif diff --git a/worker/fuzzer/src/RTC/FuzzerRateCalculator.cpp b/worker/fuzzer/src/RTC/FuzzerRateCalculator.cpp new file mode 100644 index 0000000000..380e146c05 --- /dev/null +++ b/worker/fuzzer/src/RTC/FuzzerRateCalculator.cpp @@ -0,0 +1,47 @@ +#include "RTC/FuzzerRateCalculator.hpp" +#include "DepLibUV.hpp" +#include "Utils.hpp" +#include "RTC/RateCalculator.hpp" +#include "RTC/RtpPacket.hpp" // RTC::MtuSize + +static ::RTC::RateCalculator rateCalculator; +static uint64_t nowMs; + +// This Init() function must be declared static, otherwise linking will fail if +// another source file defines same non static Init() function. +static int Init(); + +void Fuzzer::RTC::RateCalculator::Fuzz(const uint8_t* data, size_t len) +{ + // Trick to initialize our stuff just once. + static int unused = Init(); + + // Avoid [-Wunused-variable]. + unused++; + + // We need at least 2 bytes of |data|. + if (len < 2) + { + return; + } + + auto size = + static_cast(Utils::Crypto::GetRandomUInt(0u, static_cast(::RTC::MtuSize))); + + nowMs += Utils::Crypto::GetRandomUInt(0u, 1000u); + + rateCalculator.Update(size, nowMs); + + // Only get rate from time to time. + if (Utils::Byte::Get2Bytes(data, 0) % 100 == 0) + { + rateCalculator.GetRate(nowMs); + } +} + +int Init() +{ + nowMs = DepLibUV::GetTimeMs(); + + return 0; +} diff --git a/worker/fuzzer/src/fuzzer.cpp b/worker/fuzzer/src/fuzzer.cpp index d51422b103..7c5c4dc996 100644 --- a/worker/fuzzer/src/fuzzer.cpp +++ b/worker/fuzzer/src/fuzzer.cpp @@ -16,6 +16,7 @@ #include "RTC/Codecs/FuzzerVP9.hpp" #include "RTC/DtlsTransport.hpp" #include "RTC/FuzzerDtlsTransport.hpp" +#include "RTC/FuzzerRateCalculator.hpp" #include "RTC/FuzzerRtpPacket.hpp" #include "RTC/FuzzerRtpRetransmissionBuffer.hpp" #include "RTC/FuzzerRtpStreamSend.hpp" @@ -35,7 +36,9 @@ bool fuzzRtcp = false; bool fuzzCodecs = false; bool fuzzUtils = false; -int Init(); +// This Init() function must be declared static, otherwise linking will fail if +// another source file defines same non static Init() function. +static int Init(); extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { @@ -61,6 +64,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) Fuzzer::RTC::RtpStreamSend::Fuzz(data, len); Fuzzer::RTC::RtpRetransmissionBuffer::Fuzz(data, len); Fuzzer::RTC::SeqManager::Fuzz(data, len); + Fuzzer::RTC::RateCalculator::Fuzz(data, len); } if (fuzzRtcp) diff --git a/worker/meson.build b/worker/meson.build index f4d24f5958..1be338815b 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -432,6 +432,7 @@ executable( 'fuzzer/src/fuzzer.cpp', 'fuzzer/src/FuzzerUtils.cpp', 'fuzzer/src/RTC/FuzzerDtlsTransport.cpp', + 'fuzzer/src/RTC/FuzzerRateCalculator.cpp', 'fuzzer/src/RTC/FuzzerRtpPacket.cpp', 'fuzzer/src/RTC/FuzzerRtpRetransmissionBuffer.cpp', 'fuzzer/src/RTC/FuzzerRtpStreamSend.cpp', diff --git a/worker/src/RTC/RateCalculator.cpp b/worker/src/RTC/RateCalculator.cpp index 6d0e9f709c..eb78248a74 100644 --- a/worker/src/RTC/RateCalculator.cpp +++ b/worker/src/RTC/RateCalculator.cpp @@ -36,7 +36,10 @@ namespace RTC MS_ASSERT( this->newestItemIndex != this->oldestItemIndex || this->oldestItemIndex == -1, - "newest index overlaps with the oldest one"); + "newest index overlaps with the oldest one [newestItemIndex:%" PRId32 + ", oldestItemIndex:%" PRId32 "]", + this->newestItemIndex, + this->oldestItemIndex); // Set the newest item. BufferItem& item = this->buffer[this->newestItemIndex]; From 94686fdeab8bd3fa8e09a4d3e85a410b652a3b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 26 Mar 2024 11:10:00 +0100 Subject: [PATCH 386/525] Update NPM devs --- package-lock.json | 422 +++++++++++++++++++++++----------------------- package.json | 12 +- 2 files changed, 217 insertions(+), 217 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2deb89f16c..033d70f529 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,20 +12,20 @@ "dependencies": { "@types/ini": "^4.1.0", "debug": "^4.3.4", - "flatbuffers": "^24.3.7", + "flatbuffers": "^24.3.25", "h264-profile-level-id": "^2.0.0", "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.2.0" + "tar": "^6.2.1" }, "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.25", - "@typescript-eslint/eslint-plugin": "^7.1.1", - "@typescript-eslint/parser": "^7.1.1", + "@types/node": "^20.11.30", + "@typescript-eslint/eslint-plugin": "^7.4.0", + "@typescript-eslint/parser": "^7.4.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", @@ -37,7 +37,7 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.2" + "typescript": "^5.4.3" }, "engines": { "node": ">=16" @@ -1633,9 +1633,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", - "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1669,16 +1669,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", - "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz", + "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/type-utils": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/type-utils": "7.4.0", + "@typescript-eslint/utils": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1687,7 +1687,7 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1704,16 +1704,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", + "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1721,12 +1721,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", + "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1734,13 +1734,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", + "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1749,7 +1749,7 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1762,21 +1762,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", + "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/typescript-estree": "7.4.0", "semver": "^7.5.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1787,16 +1787,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", + "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/types": "7.4.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1828,19 +1828,19 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", - "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz", + "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1856,16 +1856,16 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", + "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1873,12 +1873,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", + "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1886,13 +1886,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", + "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1901,7 +1901,7 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1914,16 +1914,16 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", + "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/types": "7.4.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1972,18 +1972,18 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", - "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz", + "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/utils": "7.4.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1999,16 +1999,16 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", + "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -2016,12 +2016,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", + "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -2029,13 +2029,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", + "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2044,7 +2044,7 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -2057,21 +2057,21 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", + "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/typescript-estree": "7.4.0", "semver": "^7.5.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -2082,16 +2082,16 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", + "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/types": "7.4.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -3415,9 +3415,9 @@ } }, "node_modules/flatbuffers": { - "version": "24.3.7", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.7.tgz", - "integrity": "sha512-GB19A5cyEvOVeQw3D72zXG/5rWXhGo+BhQj5YbXwOi9tV0IorjWKu1PyoW80FSNtii/YBAxHLuu54/ww0pPceQ==" + "version": "24.3.25", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.25.tgz", + "integrity": "sha512-3HDgPbgiwWMI9zVB7VYBHaMrbOO7Gm0v+yD2FV/sCKj+9NDeVL7BOBYUuhWAQGKWOzBo8S9WdMvV0eixO233XQ==" }, "node_modules/flatted": { "version": "3.2.7", @@ -5812,9 +5812,9 @@ "dev": true }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -6052,9 +6052,9 @@ } }, "node_modules/typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -7534,9 +7534,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", - "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7570,16 +7570,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", - "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz", + "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/type-utils": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/type-utils": "7.4.0", + "@typescript-eslint/utils": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7589,29 +7589,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", + "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0" } }, "@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", + "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", + "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7621,27 +7621,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", + "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/typescript-estree": "7.4.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", + "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/types": "7.4.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7666,42 +7666,42 @@ } }, "@typescript-eslint/parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", - "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz", + "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", + "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0" } }, "@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", + "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", + "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7711,12 +7711,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", + "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/types": "7.4.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7751,41 +7751,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", - "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz", + "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/utils": "7.4.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", + "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0" } }, "@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", + "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", + "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7795,27 +7795,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", + "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/typescript-estree": "7.4.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", + "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/types": "7.4.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -8737,9 +8737,9 @@ } }, "flatbuffers": { - "version": "24.3.7", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.7.tgz", - "integrity": "sha512-GB19A5cyEvOVeQw3D72zXG/5rWXhGo+BhQj5YbXwOi9tV0IorjWKu1PyoW80FSNtii/YBAxHLuu54/ww0pPceQ==" + "version": "24.3.25", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.25.tgz", + "integrity": "sha512-3HDgPbgiwWMI9zVB7VYBHaMrbOO7Gm0v+yD2FV/sCKj+9NDeVL7BOBYUuhWAQGKWOzBo8S9WdMvV0eixO233XQ==" }, "flatted": { "version": "3.2.7", @@ -10427,9 +10427,9 @@ } }, "tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -10579,9 +10579,9 @@ "dev": true }, "typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", "dev": true }, "undici-types": { diff --git a/package.json b/package.json index 8d9f9b5ce6..f361d60b02 100644 --- a/package.json +++ b/package.json @@ -101,20 +101,20 @@ "dependencies": { "@types/ini": "^4.1.0", "debug": "^4.3.4", - "flatbuffers": "^24.3.7", + "flatbuffers": "^24.3.25", "h264-profile-level-id": "^2.0.0", "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.2.0" + "tar": "^6.2.1" }, "devDependencies": { "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.25", - "@typescript-eslint/eslint-plugin": "^7.1.1", - "@typescript-eslint/parser": "^7.1.1", + "@types/node": "^20.11.30", + "@typescript-eslint/eslint-plugin": "^7.4.0", + "@typescript-eslint/parser": "^7.4.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", @@ -126,6 +126,6 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.2" + "typescript": "^5.4.3" } } From 6306c52465d2c02f7f70554588ad3112d8943937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 27 Mar 2024 20:07:22 +0100 Subject: [PATCH 387/525] fix #1360 --- .../congestion_controller/goog_cc/trendline_estimator.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index dedb33d3f9..90b80c97ef 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -224,8 +224,11 @@ void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) { MS_DEBUG_DEV("hypothesis_: BandwidthUsage::kBwOverusing"); #if MS_LOG_DEV_LEVEL == 3 - for (auto& kv : delay_hist_) { - MS_DEBUG_DEV("arrival_time_ms - first_arrival_time_ms_:%f, smoothed_delay_:%f", kv.first, kv.second); + for (auto& packetTiming : delay_hist_) { + MS_DEBUG_DEV( + "packetTiming [arrival_time_ms:%f, smoothed_delay_ms:%f, raw_delay_ms:%f", + packetTiming.arrival_time_ms, packetTiming.smoothed_delay_ms, packetTiming.raw_delay_ms + ); } #endif } From c2de0ddd9aebd3456f4c882d8e5bb4f65e511f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 27 Mar 2024 20:08:47 +0100 Subject: [PATCH 388/525] Fix #1361 --- worker/src/RTC/SctpAssociation.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/worker/src/RTC/SctpAssociation.cpp b/worker/src/RTC/SctpAssociation.cpp index 499ec2a053..e78745b4d5 100644 --- a/worker/src/RTC/SctpAssociation.cpp +++ b/worker/src/RTC/SctpAssociation.cpp @@ -460,7 +460,6 @@ namespace RTC if (sctpSendBufferFull) { MS_DEBUG_DEV( - sctp, "error sending SCTP message [sid:%" PRIu16 ", ppid:%" PRIu32 ", message size:%zu]: %s", parameters.streamId, ppid, From f6e3fa47f6b008cd54538ed3a280ddd811fbc720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 30 Mar 2024 22:44:33 +0100 Subject: [PATCH 389/525] Update NPM dev deps --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 033d70f529..5011e3ce8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.30", + "@types/node": "^20.12.2", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", "eslint": "^8.57.0", @@ -1633,9 +1633,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.11.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", - "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "version": "20.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", + "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -7534,9 +7534,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.11.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", - "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "version": "20.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", + "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", "dev": true, "requires": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index f361d60b02..33596e6c28 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "@octokit/rest": "^20.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.11.30", + "@types/node": "^20.12.2", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", "eslint": "^8.57.0", From a13ec828d99bac98896fa50903a41182961bbcf4 Mon Sep 17 00:00:00 2001 From: Liu <34062520+liuzhenyilang@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:19:23 +0800 Subject: [PATCH 390/525] Fix: modify comments about packet loss rate calculation (#1362) Co-authored-by: liuzhen890106@163.com --- worker/src/RTC/TransportCongestionControlClient.cpp | 2 +- worker/src/RTC/TransportCongestionControlServer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index e6622b75e6..c8f82b64d3 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -241,7 +241,7 @@ namespace RTC void TransportCongestionControlClient::UpdatePacketLoss(double packetLoss) { - // Add the score into the histogram. + // Add the lost into the histogram. if (this->packetLossHistory.size() == PacketLossHistogramLength) { this->packetLossHistory.pop_front(); diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index 001bf6b9e0..c5d21de37a 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -397,7 +397,7 @@ namespace RTC void TransportCongestionControlServer::UpdatePacketLoss(double packetLoss) { - // Add the score into the histogram. + // Add the lost into the histogram. if (this->packetLossHistory.size() == PacketLossHistogramLength) { this->packetLossHistory.pop_front(); From cafe45642ef0eadc30e26729ed0575345abb1e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 2 Apr 2024 12:39:41 +0200 Subject: [PATCH 391/525] CI: Install PIP invoke package with --break-system-packages (#1364) --- .github/workflows/mediasoup-worker-fuzzer.yaml | 6 ++++++ .github/workflows/mediasoup-worker.yaml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index 211754342f..c72c3e89b6 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -32,6 +32,12 @@ jobs: # We need to install pip invoke manually. - name: pip3 install invoke run: pip3 install invoke + if: runner.os != 'macOS' + + # In macOS we need to specify this option. + - name: pip3 install --break-system-packages invoke + run: pip3 install --break-system-packages invoke + if: runner.os == 'macOS' # Build the mediasoup-worker-fuzzer binary (which uses libFuzzer). - name: invoke -r worker fuzzer diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 0ff40d5497..99c256e487 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -67,6 +67,12 @@ jobs: # We need to install pip invoke manually. - name: pip3 install invoke run: pip3 install invoke + if: runner.os != 'macOS' + + # In macOS we need to specify this option. + - name: pip3 install --break-system-packages invoke + run: pip3 install --break-system-packages invoke + if: runner.os == 'macOS' # We need to install npm deps of worker/scripts/package.json. - name: npm ci --prefix worker/scripts From 4408526d1987a0923564a8e8ec9af415d9fc6bb6 Mon Sep 17 00:00:00 2001 From: Arush Kurundodi <69193694+arcinston@users.noreply.github.com> Date: Tue, 2 Apr 2024 18:08:17 +0530 Subject: [PATCH 392/525] add arm64 prebuilt workers for linux (#1363) --- .github/workflows/mediasoup-node.yaml | 9 ++++++++ .github/workflows/mediasoup-rust.yaml | 22 +++++++++++-------- .../workflows/mediasoup-worker-fuzzer.yaml | 4 ++++ .../workflows/mediasoup-worker-prebuild.yaml | 10 +++++++++ .github/workflows/mediasoup-worker.yaml | 16 ++++++++++++++ 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 1c66a6e855..0b5d7c420b 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -19,6 +19,15 @@ jobs: node: 18 - os: ubuntu-22.04 node: 20 + - os: ubuntu-20.04 + node: 16 + arch: arm64 + - os: ubuntu-20.04 + node: 18 + arch: arm64 + - os: ubuntu-22.04 + node: 20 + arch: arm64 - os: macos-12 node: 18 - os: macos-14 diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index 5622ccc573..c2f449c010 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -15,14 +15,18 @@ jobs: ci: strategy: matrix: - os: - - ubuntu-20.04 - - ubuntu-22.04 - - macos-12 - - macos-14 - - windows-2022 - - runs-on: ${{ matrix.os }} + ci: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: ubuntu-20.04 + arch: arm64 + - os: ubuntu-22.04 + arch: arm64 + - os: macos-12 + - os: macos-14 + - os: windows-2022 + + runs-on: ${{ matrix.ci.os }} env: KEEP_BUILD_ARTIFACTS: '1' @@ -37,7 +41,7 @@ jobs: path: | ~/.cargo/registry ~/.cargo/git - key: ${{ matrix.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} + key: ${{ matrix.ci.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - name: cargo fmt run: cargo fmt --all -- --check diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index c72c3e89b6..6662e144ac 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -16,6 +16,10 @@ jobs: - os: ubuntu-22.04 cc: clang cxx: clang++ + - os: ubuntu-22.04 + cc: clang + cxx: clang++ + arch: arm64 runs-on: ${{ matrix.build.os }} diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 4b6f61c532..e6616f033d 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -22,6 +22,16 @@ jobs: - os: ubuntu-22.04 cc: gcc cxx: g++ + # Worker prebuild for Linux on arm64. + - os: ubuntu-20.04 + cc: gcc + cxx: g++ + arch: arm64 + # Worker prebuild for Linux on arm64. + - os: ubuntu-22.04 + cc: gcc + cxx: g++ + arch: arm64 - os: macos-12 cc: clang cxx: clang++ diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 99c256e487..6851658a8f 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -25,6 +25,22 @@ jobs: - os: ubuntu-22.04 cc: clang cxx: clang++ + - os: ubuntu-20.04 + cc: gcc + cxx: g++ + arch: arm64 + - os: ubuntu-20.04 + cc: clang + cxx: clang++ + arch: arm64 + - os: ubuntu-22.04 + cc: gcc + cxx: g++ + arch: arm64 + - os: ubuntu-22.04 + cc: clang + cxx: clang++ + arch: arm64 - os: macos-12 cc: gcc cxx: g++ From 4d3f5c552f39cedb77cc3a38eed4a726ab9b250a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 2 Apr 2024 19:10:16 +0200 Subject: [PATCH 393/525] Update NPM dev deps --- package-lock.json | 332 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 168 insertions(+), 168 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5011e3ce8d..e65843070c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,8 +24,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.2", - "@typescript-eslint/eslint-plugin": "^7.4.0", - "@typescript-eslint/parser": "^7.4.0", + "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/parser": "^7.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", @@ -1669,16 +1669,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz", - "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", + "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/type-utils": "7.4.0", - "@typescript-eslint/utils": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/type-utils": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1704,13 +1704,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1721,9 +1721,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1734,13 +1734,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1762,17 +1762,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" }, "engines": { @@ -1787,12 +1787,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1828,15 +1828,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz", - "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", + "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4" }, "engines": { @@ -1856,13 +1856,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1873,9 +1873,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1886,13 +1886,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1914,12 +1914,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1972,13 +1972,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz", - "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/utils": "7.4.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1999,13 +1999,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2016,9 +2016,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2029,13 +2029,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2057,17 +2057,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" }, "engines": { @@ -2082,12 +2082,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -7570,16 +7570,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz", - "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", + "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/type-utils": "7.4.0", - "@typescript-eslint/utils": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/type-utils": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7589,29 +7589,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" } }, "@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7621,27 +7621,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7666,42 +7666,42 @@ } }, "@typescript-eslint/parser": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz", - "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", + "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" } }, "@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7711,12 +7711,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7751,41 +7751,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz", - "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/utils": "7.4.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" } }, "@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7795,27 +7795,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" } }, diff --git a/package.json b/package.json index 33596e6c28..ea960acec9 100644 --- a/package.json +++ b/package.json @@ -113,8 +113,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.2", - "@typescript-eslint/eslint-plugin": "^7.4.0", - "@typescript-eslint/parser": "^7.4.0", + "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/parser": "^7.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", From 8389947c3c6f1a3bbac75efa6285c81dd917ed65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Apr 2024 11:46:40 +0200 Subject: [PATCH 394/525] Node tests: pass to utils.deepFreeze() --- node/src/test/test-ActiveSpeakerObserver.ts | 2 +- node/src/test/test-AudioLevelObserver.ts | 2 +- node/src/test/test-Consumer.ts | 182 ++++++++++---------- node/src/test/test-DataConsumer.ts | 2 +- node/src/test/test-DataProducer.ts | 4 +- node/src/test/test-PipeTransport.ts | 114 ++++++------ node/src/test/test-PlainTransport.ts | 2 +- node/src/test/test-Producer.ts | 6 +- node/src/test/test-Router.ts | 2 +- node/src/test/test-WebRtcTransport.ts | 2 +- node/src/test/test-multiopus.ts | 76 ++++---- 11 files changed, 200 insertions(+), 194 deletions(-) diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index 2f31ff5379..b4f2689fd0 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -8,7 +8,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index f981d59df9..7d4fe82592 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -8,7 +8,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index ee643c7a25..0d3a4a056e 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -24,7 +24,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', @@ -51,7 +51,7 @@ const ctx: TestContext = { }, }, ]), - audioProducerOptions: utils.deepFreeze({ + audioProducerOptions: utils.deepFreeze({ kind: 'audio', rtpParameters: { mid: 'AUDIO', @@ -86,7 +86,7 @@ const ctx: TestContext = { }, appData: { foo: 1, bar: '2' }, }), - videoProducerOptions: utils.deepFreeze({ + videoProducerOptions: utils.deepFreeze({ kind: 'video', rtpParameters: { mid: 'VIDEO', @@ -134,95 +134,97 @@ const ctx: TestContext = { }, appData: { foo: 1, bar: '2' }, }), - consumerDeviceCapabilities: utils.deepFreeze({ - codecs: [ - { - mimeType: 'audio/opus', - kind: 'audio', - preferredPayloadType: 100, - clockRate: 48000, - channels: 2, - rtcpFeedback: [{ type: 'nack', parameter: '' }], - }, - { - mimeType: 'video/H264', - kind: 'video', - preferredPayloadType: 101, - clockRate: 90000, - parameters: { - 'level-asymmetry-allowed': 1, - 'packetization-mode': 1, - 'profile-level-id': '4d0032', + consumerDeviceCapabilities: utils.deepFreeze( + { + codecs: [ + { + mimeType: 'audio/opus', + kind: 'audio', + preferredPayloadType: 100, + clockRate: 48000, + channels: 2, + rtcpFeedback: [{ type: 'nack', parameter: '' }], }, - rtcpFeedback: [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb', parameter: '' }, - ], - }, - { - mimeType: 'video/rtx', - kind: 'video', - preferredPayloadType: 102, - clockRate: 90000, - parameters: { - apt: 101, + { + mimeType: 'video/H264', + kind: 'video', + preferredPayloadType: 101, + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb', parameter: '' }, + ], }, - rtcpFeedback: [], - }, - ], - headerExtensions: [ - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId: 1, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId: 1, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', - preferredId: 2, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId: 4, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId: 4, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId: 10, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'urn:3gpp:video-orientation', - preferredId: 11, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'urn:ietf:params:rtp-hdrext:toffset', - preferredId: 12, - preferredEncrypt: false, - }, - ], - }), + { + mimeType: 'video/rtx', + kind: 'video', + preferredPayloadType: 102, + clockRate: 90000, + parameters: { + apt: 101, + }, + rtcpFeedback: [], + }, + ], + headerExtensions: [ + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', + preferredId: 2, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId: 4, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId: 4, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:3gpp:video-orientation', + preferredId: 11, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:toffset', + preferredId: 12, + preferredEncrypt: false, + }, + ], + } + ), }; beforeEach(async () => { diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index d37ab10c30..163f4d4e19 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -12,7 +12,7 @@ type TestContext = { }; const ctx: TestContext = { - dataProducerOptions: utils.deepFreeze({ + dataProducerOptions: utils.deepFreeze({ sctpStreamParameters: { streamId: 12345, ordered: false, diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index 54362f4381..c5dddaacba 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -11,7 +11,7 @@ type TestContext = { }; const ctx: TestContext = { - dataProducerOptions1: utils.deepFreeze({ + dataProducerOptions1: utils.deepFreeze({ sctpStreamParameters: { streamId: 666, }, @@ -19,7 +19,7 @@ const ctx: TestContext = { protocol: 'bar', appData: { foo: 1, bar: '2' }, }), - dataProducerOptions2: utils.deepFreeze({ + dataProducerOptions2: utils.deepFreeze({ sctpStreamParameters: { streamId: 777, maxRetransmits: 3, diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 7be3294d07..3b9052374d 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -22,7 +22,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', @@ -35,7 +35,7 @@ const ctx: TestContext = { clockRate: 90000, }, ]), - audioProducerOptions: utils.deepFreeze({ + audioProducerOptions: utils.deepFreeze({ kind: 'audio', rtpParameters: { mid: 'AUDIO', @@ -64,7 +64,7 @@ const ctx: TestContext = { }, appData: { foo: 'bar1' }, }), - videoProducerOptions: utils.deepFreeze({ + videoProducerOptions: utils.deepFreeze({ kind: 'video', rtpParameters: { mid: 'VIDEO', @@ -102,7 +102,7 @@ const ctx: TestContext = { }, appData: { foo: 'bar2' }, }), - dataProducerOptions: utils.deepFreeze({ + dataProducerOptions: utils.deepFreeze({ sctpStreamParameters: { streamId: 666, ordered: false, @@ -111,59 +111,61 @@ const ctx: TestContext = { label: 'foo', protocol: 'bar', }), - consumerDeviceCapabilities: utils.deepFreeze({ - codecs: [ - { - kind: 'audio', - mimeType: 'audio/opus', - preferredPayloadType: 100, - clockRate: 48000, - channels: 2, - }, - { - kind: 'video', - mimeType: 'video/VP8', - preferredPayloadType: 101, - clockRate: 90000, - rtcpFeedback: [ - { type: 'nack' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'transport-cc' }, - ], - }, - { - kind: 'video', - mimeType: 'video/rtx', - preferredPayloadType: 102, - clockRate: 90000, - parameters: { - apt: 101, + consumerDeviceCapabilities: utils.deepFreeze( + { + codecs: [ + { + kind: 'audio', + mimeType: 'audio/opus', + preferredPayloadType: 100, + clockRate: 48000, + channels: 2, }, - rtcpFeedback: [], - }, - ], - headerExtensions: [ - { - kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId: 4, - preferredEncrypt: false, - direction: 'sendrecv', - }, - { - kind: 'video', - uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - preferredId: 5, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId: 10, - preferredEncrypt: false, - }, - ], - }), + { + kind: 'video', + mimeType: 'video/VP8', + preferredPayloadType: 101, + clockRate: 90000, + rtcpFeedback: [ + { type: 'nack' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'transport-cc' }, + ], + }, + { + kind: 'video', + mimeType: 'video/rtx', + preferredPayloadType: 102, + clockRate: 90000, + parameters: { + apt: 101, + }, + rtcpFeedback: [], + }, + ], + headerExtensions: [ + { + kind: 'video', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + preferredId: 4, + preferredEncrypt: false, + direction: 'sendrecv', + }, + { + kind: 'video', + uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + preferredId: 5, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + }, + ], + } + ), }; beforeEach(async () => { diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index 097cc2b91f..6588fe55cb 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -12,7 +12,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index 18cc7eaa90..d6fe900cf4 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -20,7 +20,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', @@ -48,7 +48,7 @@ const ctx: TestContext = { rtcpFeedback: [], // Will be ignored. }, ]), - audioProducerOptions: utils.deepFreeze({ + audioProducerOptions: utils.deepFreeze({ kind: 'audio', rtpParameters: { mid: 'AUDIO', @@ -83,7 +83,7 @@ const ctx: TestContext = { }, appData: { foo: 1, bar: '2' }, }), - videoProducerOptions: utils.deepFreeze({ + videoProducerOptions: utils.deepFreeze({ kind: 'video', rtpParameters: { mid: 'VIDEO', diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index b5f989bfe4..d904883509 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -8,7 +8,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index c605c05cb5..129a33a19b 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -18,7 +18,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index cf7ea964f1..2b419271bf 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -12,7 +12,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/multiopus', @@ -27,7 +27,7 @@ const ctx: TestContext = { }, }, ]), - audioProducerOptions: utils.deepFreeze({ + audioProducerOptions: utils.deepFreeze({ kind: 'audio', rtpParameters: { mid: 'AUDIO', @@ -57,42 +57,44 @@ const ctx: TestContext = { ], }, }), - consumerDeviceCapabilities: utils.deepFreeze({ - codecs: [ - { - mimeType: 'audio/multiopus', - kind: 'audio', - preferredPayloadType: 100, - clockRate: 48000, - channels: 6, - parameters: { - channel_mapping: '0,4,1,2,3,5', - num_streams: 4, - coupled_streams: 2, + consumerDeviceCapabilities: utils.deepFreeze( + { + codecs: [ + { + mimeType: 'audio/multiopus', + kind: 'audio', + preferredPayloadType: 100, + clockRate: 48000, + channels: 6, + parameters: { + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 2, + }, }, - }, - ], - headerExtensions: [ - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId: 1, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId: 4, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId: 10, - preferredEncrypt: false, - }, - ], - }), + ], + headerExtensions: [ + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId: 4, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + }, + ], + } + ), }; beforeEach(async () => { From cd475ac36e409b43084a40fbe1a6889c8fc1b9e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 5 Apr 2024 11:01:17 +0200 Subject: [PATCH 395/525] cosmetic --- worker/src/Worker.cpp | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 1bd5468f88..2dd3cb2b6f 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -216,6 +216,18 @@ flatbuffers::Offset Worker::FillBufferResour uvRusage.ru_nivcsw); } +RTC::WebRtcServer* Worker::GetWebRtcServer(const std::string& webRtcServerId) const +{ + auto it = this->mapWebRtcServers.find(webRtcServerId); + + if (it == this->mapWebRtcServers.end()) + { + MS_THROW_ERROR("WebRtcServer not found"); + } + + return it->second; +} + RTC::Router* Worker::GetRouter(const std::string& routerId) const { MS_TRACE(); @@ -246,19 +258,7 @@ void Worker::CheckNoRouter(const std::string& routerId) const } } -RTC::WebRtcServer* Worker::GetWebRtcServer(const std::string& webRtcServerId) const -{ - auto it = this->mapWebRtcServers.find(webRtcServerId); - - if (it == this->mapWebRtcServers.end()) - { - MS_THROW_ERROR("WebRtcServer not found"); - } - - return it->second; -} - -inline void Worker::HandleRequest(Channel::ChannelRequest* request) +void Worker::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); @@ -449,7 +449,7 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) } } -inline void Worker::HandleNotification(Channel::ChannelNotification* notification) +void Worker::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); @@ -478,7 +478,7 @@ inline void Worker::HandleNotification(Channel::ChannelNotification* notificatio } } -inline void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) +void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) { MS_TRACE_STD(); @@ -492,7 +492,7 @@ inline void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) Close(); } -inline void Worker::OnSignal(SignalHandle* /*signalHandle*/, int signum) +void Worker::OnSignal(SignalHandle* /*signalHandle*/, int signum) { MS_TRACE(); @@ -538,8 +538,7 @@ inline void Worker::OnSignal(SignalHandle* /*signalHandle*/, int signum) } } -inline RTC::WebRtcServer* Worker::OnRouterNeedWebRtcServer( - RTC::Router* /*router*/, std::string& webRtcServerId) +RTC::WebRtcServer* Worker::OnRouterNeedWebRtcServer(RTC::Router* /*router*/, std::string& webRtcServerId) { MS_TRACE(); From f7b96b87f6462c614e48ea9e8d768fa7f27f2ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 5 Apr 2024 11:50:51 +0200 Subject: [PATCH 396/525] cosmetic --- worker/include/Utils.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/worker/include/Utils.hpp b/worker/include/Utils.hpp index 4e2d0ba15f..53bb2d3cde 100644 --- a/worker/include/Utils.hpp +++ b/worker/include/Utils.hpp @@ -28,7 +28,10 @@ namespace Utils static bool CompareAddresses(const struct sockaddr* addr1, const struct sockaddr* addr2) { // Compare family. - if (addr1->sa_family != addr2->sa_family || (addr1->sa_family != AF_INET && addr1->sa_family != AF_INET6)) + if ( + addr1->sa_family != addr2->sa_family || + (addr1->sa_family != AF_INET && addr1->sa_family != AF_INET6) || + (addr2->sa_family != AF_INET && addr2->sa_family != AF_INET6)) { return false; } From dd691ff289fb3ef97bf96b9bb9cd5c4c31eab0e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 5 Apr 2024 14:42:02 +0200 Subject: [PATCH 397/525] cosmetic --- worker/include/RTC/TransportTuple.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 9366ba5d54..19750caf99 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -130,7 +130,7 @@ namespace RTC { if (this->protocol == Protocol::UDP) { - return (const struct sockaddr*)this->udpRemoteAddr; + return static_cast(this->udpRemoteAddr); } else { From 16e430486dd331a8eb65385a0ec9f22a64639458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Apr 2024 13:46:45 +0200 Subject: [PATCH 398/525] Require Node >= 18 (#1367) --- .github/workflows/mediasoup-node.yaml | 8 +- CHANGELOG.md | 4 + package-lock.json | 994 ++++++++++---------------- package.json | 10 +- worker/scripts/package-lock.json | 113 +-- worker/scripts/package.json | 2 +- 6 files changed, 409 insertions(+), 722 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 0b5d7c420b..bf643d7caf 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -13,15 +13,10 @@ jobs: strategy: matrix: ci: - - os: ubuntu-20.04 - node: 16 - os: ubuntu-20.04 node: 18 - os: ubuntu-22.04 node: 20 - - os: ubuntu-20.04 - node: 16 - arch: arm64 - os: ubuntu-20.04 node: 18 arch: arm64 @@ -59,9 +54,8 @@ jobs: restore-keys: | ${{ matrix.ci.os }}-node- - # NOTE: Add --force since some dev dependencies require Node >= 18. - name: npm ci - run: npm ci --force --foreground-scripts + run: npm ci --foreground-scripts - name: npm run lint:node run: npm run lint:node diff --git a/CHANGELOG.md b/CHANGELOG.md index a22380b77f..8de44463fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Require Node.js >= 18 ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). + ### 3.13.24 - Node: Fix missing `bitrateByLayer` field in stats of `RtpRecvStream` in Node ([PR #1349](https://github.com/versatica/mediasoup/pull/1349)). diff --git a/package-lock.json b/package-lock.json index e65843070c..4531ca93d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,15 +20,15 @@ "tar": "^6.2.1" }, "devDependencies": { - "@octokit/rest": "^20.0.2", + "@octokit/rest": "^20.1.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.2", + "@types/node": "^20.12.5", "@typescript-eslint/eslint-plugin": "^7.5.0", "@typescript-eslint/parser": "^7.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jest": "^28.2.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.1", @@ -37,10 +37,10 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.3" + "typescript": "^5.4.4" }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "type": "opencollective", @@ -806,9 +806,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -1305,16 +1305,16 @@ } }, "node_modules/@octokit/core": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", - "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", + "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", "dev": true, "dependencies": { "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.0.0", - "@octokit/request": "^8.0.2", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, @@ -1323,13 +1323,12 @@ } }, "node_modules/@octokit/endpoint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", - "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", + "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", "dev": true, "dependencies": { - "@octokit/types": "^11.0.0", - "is-plain-object": "^5.0.0", + "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -1337,13 +1336,13 @@ } }, "node_modules/@octokit/graphql": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", - "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", + "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", "dev": true, "dependencies": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^11.0.0", + "@octokit/request": "^8.3.0", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -1351,39 +1350,39 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", - "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-21.2.0.tgz", + "integrity": "sha512-xx+Xd6I7rYvul/hgUDqv6TeGX0IOGnhSg9IOeYgd/uI7IAqUy6DE2B6Ipv2M4mWoxaMcWjIzgTIcv8pMO3F3vw==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", - "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", + "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", "dev": true, "dependencies": { - "@octokit/types": "^12.0.0" + "@octokit/types": "^12.6.0" }, "engines": { "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=5" + "@octokit/core": "5" } }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^19.0.0" + "@octokit/openapi-types": "^20.0.0" } }, "node_modules/@octokit/plugin-request-log": { @@ -1399,45 +1398,44 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", - "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", "dev": true, "dependencies": { - "@octokit/types": "^12.0.0" + "@octokit/types": "^12.6.0" }, "engines": { "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=5" + "@octokit/core": "5" } }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", "dev": true }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^19.0.0" + "@octokit/openapi-types": "^20.0.0" } }, "node_modules/@octokit/request": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", - "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.3.1.tgz", + "integrity": "sha512-fin4cl5eHN5Ybmb/gtn7YZ+ycyUlcyqqkg5lfxeSChqj7sUt6TNaJPehREi+0PABKLREYL8pfaUhH3TicEWNoA==", "dev": true, "dependencies": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.1.0", - "is-plain-object": "^5.0.0", + "@octokit/endpoint": "^9.0.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -1445,12 +1443,12 @@ } }, "node_modules/@octokit/request-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", - "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", + "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", "dev": true, "dependencies": { - "@octokit/types": "^11.0.0", + "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, @@ -1459,27 +1457,27 @@ } }, "node_modules/@octokit/rest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", - "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", + "version": "20.1.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.0.tgz", + "integrity": "sha512-STVO3itHQLrp80lvcYB2UIKoeil5Ctsgd2s1AM+du3HqZIR35ZH7WE9HLwUOLXH0myA0y3AGNPo8gZtcgIbw0g==", "dev": true, "dependencies": { - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/core": "^5.0.2", + "@octokit/plugin-paginate-rest": "^9.1.5", "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + "@octokit/plugin-rest-endpoint-methods": "^10.2.0" }, "engines": { "node": ">= 18" } }, "node_modules/@octokit/types": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", - "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.1.0.tgz", + "integrity": "sha512-nBwAFOYqVUUJ2AZFK4ZzESQptaAVqdTDKk8gE0Xr0o99WuPDSrhUC38x0F40xD9OUxXhOOuZKWNNVVLPSHQDvQ==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^18.0.0" + "@octokit/openapi-types": "^21.0.0" } }, "node_modules/@pkgr/core": { @@ -1633,9 +1631,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.12.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", - "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", + "version": "20.12.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz", + "integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1720,6 +1718,33 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", @@ -1955,87 +1980,43 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", - "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2044,7 +2025,7 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -2056,49 +2037,7 @@ } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", - "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -2107,7 +2046,7 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", @@ -2122,83 +2061,17 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -2212,9 +2085,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3010,19 +2883,19 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "version": "28.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz", + "integrity": "sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^5.10.0" + "@typescript-eslint/utils": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", "jest": "*" }, "peerDependenciesMeta": { @@ -3034,6 +2907,31 @@ } } }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, "node_modules/eslint-plugin-prettier": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", @@ -3065,31 +2963,6 @@ } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", @@ -3105,13 +2978,16 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { - "node": ">=4.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { @@ -3156,15 +3032,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -3177,7 +3044,7 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -3186,15 +3053,6 @@ "node": ">=4.0" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3402,12 +3260,13 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -3420,9 +3279,9 @@ "integrity": "sha512-3HDgPbgiwWMI9zVB7VYBHaMrbOO7Gm0v+yD2FV/sCKj+9NDeVL7BOBYUuhWAQGKWOzBo8S9WdMvV0eixO233XQ==" }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/formdata-polyfill": { @@ -3568,9 +3427,9 @@ } }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3877,15 +3736,6 @@ "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4609,6 +4459,12 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -4639,6 +4495,15 @@ "node": ">=6" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -5997,27 +5862,6 @@ } } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -6052,9 +5896,9 @@ } }, "node_modules/typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", + "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -6086,9 +5930,9 @@ } }, "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", "dev": true }, "node_modules/update-browserslist-db": { @@ -6849,9 +6693,9 @@ "dev": true }, "@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "@istanbuljs/load-nyc-config": { @@ -7243,70 +7087,69 @@ "dev": true }, "@octokit/core": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", - "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", + "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", "dev": true, "requires": { "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.0.0", - "@octokit/request": "^8.0.2", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" } }, "@octokit/endpoint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", - "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", + "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", "dev": true, "requires": { - "@octokit/types": "^11.0.0", - "is-plain-object": "^5.0.0", + "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" } }, "@octokit/graphql": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", - "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", + "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", "dev": true, "requires": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^11.0.0", + "@octokit/request": "^8.3.0", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/openapi-types": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", - "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-21.2.0.tgz", + "integrity": "sha512-xx+Xd6I7rYvul/hgUDqv6TeGX0IOGnhSg9IOeYgd/uI7IAqUy6DE2B6Ipv2M4mWoxaMcWjIzgTIcv8pMO3F3vw==", "dev": true }, "@octokit/plugin-paginate-rest": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", - "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", + "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", "dev": true, "requires": { - "@octokit/types": "^12.0.0" + "@octokit/types": "^12.6.0" }, "dependencies": { "@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", "dev": true }, "@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", "dev": true, "requires": { - "@octokit/openapi-types": "^19.0.0" + "@octokit/openapi-types": "^20.0.0" } } } @@ -7319,74 +7162,73 @@ "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", - "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", "dev": true, "requires": { - "@octokit/types": "^12.0.0" + "@octokit/types": "^12.6.0" }, "dependencies": { "@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", "dev": true }, "@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", "dev": true, "requires": { - "@octokit/openapi-types": "^19.0.0" + "@octokit/openapi-types": "^20.0.0" } } } }, "@octokit/request": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", - "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.3.1.tgz", + "integrity": "sha512-fin4cl5eHN5Ybmb/gtn7YZ+ycyUlcyqqkg5lfxeSChqj7sUt6TNaJPehREi+0PABKLREYL8pfaUhH3TicEWNoA==", "dev": true, "requires": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.1.0", - "is-plain-object": "^5.0.0", + "@octokit/endpoint": "^9.0.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/request-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", - "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", + "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", "dev": true, "requires": { - "@octokit/types": "^11.0.0", + "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", "once": "^1.4.0" } }, "@octokit/rest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", - "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", + "version": "20.1.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.0.tgz", + "integrity": "sha512-STVO3itHQLrp80lvcYB2UIKoeil5Ctsgd2s1AM+du3HqZIR35ZH7WE9HLwUOLXH0myA0y3AGNPo8gZtcgIbw0g==", "dev": true, "requires": { - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/core": "^5.0.2", + "@octokit/plugin-paginate-rest": "^9.1.5", "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + "@octokit/plugin-rest-endpoint-methods": "^10.2.0" } }, "@octokit/types": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", - "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.1.0.tgz", + "integrity": "sha512-nBwAFOYqVUUJ2AZFK4ZzESQptaAVqdTDKk8gE0Xr0o99WuPDSrhUC38x0F40xD9OUxXhOOuZKWNNVVLPSHQDvQ==", "dev": true, "requires": { - "@octokit/openapi-types": "^18.0.0" + "@octokit/openapi-types": "^21.0.0" } }, "@pkgr/core": { @@ -7534,9 +7376,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.12.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", - "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", + "version": "20.12.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz", + "integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7598,6 +7440,18 @@ "@typescript-eslint/visitor-keys": "7.5.0" } }, + "@typescript-eslint/type-utils": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + } + }, "@typescript-eslint/types": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", @@ -7741,84 +7595,37 @@ } }, "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" } }, - "@typescript-eslint/type-utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", - "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/utils": "7.5.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" - } - }, - "@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", - "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "semver": "^7.5.4" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" - } - }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -7839,51 +7646,14 @@ } } }, - "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - } - }, "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" } }, "@ungap/structured-clone": { @@ -7893,9 +7663,9 @@ "dev": true }, "acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true }, "acorn-jsx": { @@ -8451,24 +8221,6 @@ "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "text-table": "^0.2.0" - }, - "dependencies": { - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "eslint-config-prettier": { @@ -8479,12 +8231,29 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "version": "28.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz", + "integrity": "sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g==", "dev": true, "requires": { - "@typescript-eslint/utils": "^5.10.0" + "@typescript-eslint/utils": "^6.0.0" + }, + "dependencies": { + "@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + } + } } }, "eslint-plugin-prettier": { @@ -8498,13 +8267,13 @@ } }, "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" } }, "eslint-visitor-keys": { @@ -8537,14 +8306,6 @@ "dev": true, "requires": { "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "esrecurse": { @@ -8554,20 +8315,12 @@ "dev": true, "requires": { "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, "esutils": { @@ -8727,12 +8480,13 @@ } }, "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "requires": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, @@ -8742,9 +8496,9 @@ "integrity": "sha512-3HDgPbgiwWMI9zVB7VYBHaMrbOO7Gm0v+yD2FV/sCKj+9NDeVL7BOBYUuhWAQGKWOzBo8S9WdMvV0eixO233XQ==" }, "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "formdata-polyfill": { @@ -8846,9 +8600,9 @@ } }, "globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -9050,12 +8804,6 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -9606,6 +9354,12 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -9630,6 +9384,15 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -10542,21 +10305,6 @@ "yargs-parser": "^21.0.1" } }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -10579,9 +10327,9 @@ "dev": true }, "typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", + "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", "dev": true }, "undici-types": { @@ -10600,9 +10348,9 @@ } }, "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", "dev": true }, "update-browserslist-db": { diff --git a/package.json b/package.json index ea960acec9..87fa1f789d 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "npm-scripts.mjs" ], "engines": { - "node": ">=16" + "node": ">=18" }, "keywords": [ "webrtc", @@ -109,15 +109,15 @@ "tar": "^6.2.1" }, "devDependencies": { - "@octokit/rest": "^20.0.2", + "@octokit/rest": "^20.1.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.2", + "@types/node": "^20.12.5", "@typescript-eslint/eslint-plugin": "^7.5.0", "@typescript-eslint/parser": "^7.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jest": "^28.2.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.1", @@ -126,6 +126,6 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.3" + "typescript": "^5.4.4" } } diff --git a/worker/scripts/package-lock.json b/worker/scripts/package-lock.json index 9f468b26cc..71d690bdba 100644 --- a/worker/scripts/package-lock.json +++ b/worker/scripts/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "dependencies": { "clang-format": "^1.8.0", - "glob": "^10.3.10" + "glob": "^10.3.12" } }, "node_modules/@isaacs/cliui": { @@ -277,15 +277,15 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" }, "bin": { "glob": "dist/esm/bin.mjs" @@ -356,41 +356,13 @@ } }, "node_modules/lru-cache": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", - "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", - "dependencies": { - "semver": "^7.3.5" - }, + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "engines": { "node": "14 || >=16.14" } }, - "node_modules/lru-cache/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lru-cache/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -443,11 +415,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { @@ -624,11 +596,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } }, "dependencies": { @@ -831,15 +798,15 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", "requires": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" } }, "has": { @@ -887,30 +854,9 @@ } }, "lru-cache": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", - "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", - "requires": { - "semver": "^7.3.5" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==" }, "minimatch": { "version": "9.0.3", @@ -949,11 +895,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, @@ -1076,11 +1022,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/worker/scripts/package.json b/worker/scripts/package.json index eb4827cf34..2831c80c0d 100644 --- a/worker/scripts/package.json +++ b/worker/scripts/package.json @@ -8,6 +8,6 @@ }, "dependencies": { "clang-format": "^1.8.0", - "glob": "^10.3.10" + "glob": "^10.3.12" } } From 62d2731a933b79b2c391aa44b28e95d368da27d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Apr 2024 16:24:07 +0200 Subject: [PATCH 399/525] TransportListenInfo: Add portRange (deprecate worker port range) (#1365) --- CHANGELOG.md | 7 +- node/src/Channel.ts | 7 +- node/src/Router.ts | 16 +- node/src/Transport.ts | 90 ++- node/src/WebRtcServer.ts | 3 +- node/src/Worker.ts | 6 +- node/src/test/test-WebRtcTransport.ts | 69 +- rust/benches/producer.rs | 1 + rust/examples/echo.rs | 1 + rust/examples/multiopus.rs | 2 + rust/examples/svc-simulcast.rs | 1 + rust/examples/videoroom.rs | 1 + rust/src/data_structures.rs | 14 +- rust/src/router.rs | 8 + rust/src/router/consumer/tests.rs | 1 + rust/src/router/data_consumer/tests.rs | 3 + rust/src/router/data_producer/tests.rs | 1 + rust/src/router/pipe_transport/tests.rs | 1 + rust/src/router/plain_transport/tests.rs | 1 + rust/src/router/producer/tests.rs | 1 + rust/src/router/webrtc_transport/tests.rs | 5 + rust/src/webrtc_server/tests.rs | 1 + rust/src/worker.rs | 18 +- rust/tests/integration/consumer.rs | 1 + rust/tests/integration/data_consumer.rs | 4 + rust/tests/integration/data_producer.rs | 2 + rust/tests/integration/multiopus.rs | 1 + rust/tests/integration/pipe_transport.rs | 7 + rust/tests/integration/plain_transport.rs | 16 + rust/tests/integration/producer.rs | 1 + rust/tests/integration/smoke.rs | 2 + rust/tests/integration/webrtc_server.rs | 11 + rust/tests/integration/webrtc_transport.rs | 81 ++ rust/tests/integration/worker.rs | 4 +- worker/fbs/transport.fbs | 6 + worker/include/RTC/PortManager.hpp | 69 +- .../include/RTC/RTCP/XrDelaySinceLastRr.hpp | 6 +- .../RTC/RTCP/XrReceiverReferenceTime.hpp | 6 +- worker/include/RTC/TcpServer.hpp | 8 +- worker/include/RTC/Transport.hpp | 7 + worker/include/RTC/TransportTuple.hpp | 74 +- worker/include/RTC/UdpSocket.hpp | 9 +- .../include/handles/TcpConnectionHandle.hpp | 2 +- worker/include/handles/TcpServerHandle.hpp | 2 +- worker/include/handles/UdpSocketHandle.hpp | 2 +- worker/src/RTC/PipeTransport.cpp | 30 +- worker/src/RTC/PlainTransport.cpp | 62 +- worker/src/RTC/PortManager.cpp | 711 ++++++++++-------- worker/src/RTC/TcpServer.cpp | 20 +- worker/src/RTC/TransportTuple.cpp | 73 ++ worker/src/RTC/UdpSocket.cpp | 22 +- worker/src/RTC/WebRtcServer.cpp | 57 +- worker/src/RTC/WebRtcTransport.cpp | 57 +- worker/src/Worker.cpp | 1 + 54 files changed, 1063 insertions(+), 549 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8de44463fa..a3462be0dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### NEXT +- `TransportListenInfo`: Add `portRange` (deprecate worker port range) ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). - Require Node.js >= 18 ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). ### 3.13.24 @@ -54,8 +55,8 @@ ### 3.13.14 - Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). -- `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). -- `ListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). +- `TransportListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). +- `TransportListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). - Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). - Add RTCP Sender Report trace event ([PR #1267](https://github.com/versatica/mediasoup/pull/1267) by @GithubUser8080). @@ -129,7 +130,7 @@ ### 3.13.0 - Switch from JSON based messages to FlatBuffers ([PR #1064](https://github.com/versatica/mediasoup/pull/1064)). -- Add `ListenInfo` in all transports and send/recv buffer size options ([PR #1084](https://github.com/versatica/mediasoup/pull/1084)). +- Add `TransportListenInfo` in all transports and send/recv buffer size options ([PR #1084](https://github.com/versatica/mediasoup/pull/1084)). - Add optional `rtcpListenInfo` in `PlainTransportOptions` ([PR #1099](https://github.com/versatica/mediasoup/pull/1099)). - Add pause/resume API in `DataProducer` and `DataConsumer` ([PR #1104](https://github.com/versatica/mediasoup/pull/1104)). - DataChannel subchannels feature ([PR #1152](https://github.com/versatica/mediasoup/pull/1152)). diff --git a/node/src/Channel.ts b/node/src/Channel.ts index fca87950f9..d0b9664707 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -1,5 +1,6 @@ import * as os from 'node:os'; import { Duplex } from 'node:stream'; +import { info, warn } from 'node:console'; import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; @@ -156,8 +157,7 @@ export class Channel extends EnhancedEventEmitter { } default: { - // eslint-disable-next-line no-console - console.warn( + warn( `worker[pid:${pid}] unexpected data: ${payload.toString( 'utf8', 1 @@ -482,8 +482,7 @@ export class Channel extends EnhancedEventEmitter { // 'X' (a dump log). case 'X': { - // eslint-disable-next-line no-console - console.log(logData.slice(1)); + info(logData.slice(1)); break; } diff --git a/node/src/Router.ts b/node/src/Router.ts index 56245fe877..e0d61f6f91 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -8,7 +8,8 @@ import { TransportListenInfo, TransportListenIp, TransportProtocol, - TransportSocketFlags, + portRangeToFbs, + socketFlagsToFbs, } from './Transport'; import { WebRtcTransport, @@ -560,6 +561,7 @@ export class Router< listenInfo.ip, listenInfo.announcedAddress ?? listenInfo.announcedIp, listenInfo.port, + portRangeToFbs(listenInfo.portRange), socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, listenInfo.recvBufferSize @@ -748,6 +750,7 @@ export class Router< listenInfo!.ip, listenInfo!.announcedAddress ?? listenInfo!.announcedIp, listenInfo!.port, + portRangeToFbs(listenInfo!.portRange), socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, listenInfo!.recvBufferSize @@ -760,6 +763,7 @@ export class Router< rtcpListenInfo.ip, rtcpListenInfo.announcedAddress ?? rtcpListenInfo.announcedIp, rtcpListenInfo.port, + portRangeToFbs(rtcpListenInfo.portRange), socketFlagsToFbs(rtcpListenInfo.flags), rtcpListenInfo.sendBufferSize, rtcpListenInfo.recvBufferSize @@ -900,6 +904,7 @@ export class Router< listenInfo!.ip, listenInfo!.announcedAddress ?? listenInfo!.announcedIp, listenInfo!.port, + portRangeToFbs(listenInfo!.portRange), socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, listenInfo!.recvBufferSize @@ -1569,12 +1574,3 @@ export function parseRouterDumpResponse( ), }; } - -export function socketFlagsToFbs( - flags: TransportSocketFlags = {} -): FbsTransport.SocketFlagsT { - return new FbsTransport.SocketFlagsT( - Boolean(flags.ipv6Only), - Boolean(flags.udpReusePort) - ); -} diff --git a/node/src/Transport.ts b/node/src/Transport.ts index de25523662..64299f9ca2 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -90,6 +90,11 @@ export type TransportListenInfo = { */ port?: number; + /** + * Listening port range. If given then |port| will be ignored. + */ + portRange?: TransportPortRange; + /** * Socket flags. */ @@ -128,6 +133,20 @@ export type TransportListenIp = { */ export type TransportProtocol = 'udp' | 'tcp'; +/** + * Port range.. + */ +export type TransportPortRange = { + /** + * Lowest port in the range. + */ + min: number; + /** + * Highest port in the range. + */ + max: number; +}; + /** * UDP/TCP socket flags. */ @@ -1274,36 +1293,19 @@ export class Transport< } } -function transportTraceEventTypeToFbs( - eventType: TransportTraceEventType -): FbsTransport.TraceEventType { - switch (eventType) { - case 'probation': { - return FbsTransport.TraceEventType.PROBATION; - } - - case 'bwe': { - return FbsTransport.TraceEventType.BWE; - } - - default: { - throw new TypeError(`invalid TransportTraceEventType: ${eventType}`); - } - } +export function portRangeToFbs( + portRange: TransportPortRange = { min: 0, max: 0 } +): FbsTransport.PortRangeT { + return new FbsTransport.PortRangeT(portRange.min, portRange.max); } -function transportTraceEventTypeFromFbs( - eventType: FbsTransport.TraceEventType -): TransportTraceEventType { - switch (eventType) { - case FbsTransport.TraceEventType.PROBATION: { - return 'probation'; - } - - case FbsTransport.TraceEventType.BWE: { - return 'bwe'; - } - } +export function socketFlagsToFbs( + flags: TransportSocketFlags = {} +): FbsTransport.SocketFlagsT { + return new FbsTransport.SocketFlagsT( + Boolean(flags.ipv6Only), + Boolean(flags.udpReusePort) + ); } export function parseSctpState(fbsSctpState: FbsSctpState): SctpState { @@ -1527,6 +1529,38 @@ function parseRecvRtpHeaderExtensions( }; } +function transportTraceEventTypeToFbs( + eventType: TransportTraceEventType +): FbsTransport.TraceEventType { + switch (eventType) { + case 'probation': { + return FbsTransport.TraceEventType.PROBATION; + } + + case 'bwe': { + return FbsTransport.TraceEventType.BWE; + } + + default: { + throw new TypeError(`invalid TransportTraceEventType: ${eventType}`); + } + } +} + +function transportTraceEventTypeFromFbs( + eventType: FbsTransport.TraceEventType +): TransportTraceEventType { + switch (eventType) { + case FbsTransport.TraceEventType.PROBATION: { + return 'probation'; + } + + case FbsTransport.TraceEventType.BWE: { + return 'bwe'; + } + } +} + function parseBweTraceInfo(binary: FbsTransport.BweTraceInfo): { desiredBitrate: number; effectiveDesiredBitrate: number; diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index bfe2714007..c13f83c35d 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -23,8 +23,7 @@ export type WebRtcServerOptions = }; /** - * @deprecated - * Use TransportListenInfo instead. + * @deprecated Use TransportListenInfo instead. */ export type WebRtcServerListenInfo = TransportListenInfo; diff --git a/node/src/Worker.ts b/node/src/Worker.ts index ad9838ce4a..cce310e810 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -6,8 +6,9 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import * as ortc from './ortc'; import { Channel } from './Channel'; -import { Router, RouterOptions, socketFlagsToFbs } from './Router'; +import { Router, RouterOptions } from './Router'; import { WebRtcServer, WebRtcServerOptions } from './WebRtcServer'; +import { portRangeToFbs, socketFlagsToFbs } from './Transport'; import { RtpCodecCapability } from './RtpParameters'; import { AppData } from './types'; import * as utils from './utils'; @@ -50,11 +51,13 @@ export type WorkerSettings = { /** * Minimun RTC port for ICE, DTLS, RTP, etc. Default 10000. + * @deprecated Use |portRange| in TransportListenInfo object instead. */ rtcMinPort?: number; /** * Maximum RTC port for ICE, DTLS, RTP, etc. Default 59999. + * @deprecated Use |portRange| in TransportListenInfo object instead. */ rtcMaxPort?: number; @@ -701,6 +704,7 @@ export class Worker< listenInfo.ip, listenInfo.announcedAddress ?? listenInfo.announcedIp, listenInfo.port, + portRangeToFbs(listenInfo.portRange), socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, listenInfo.recvBufferSize diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 129a33a19b..109b15499b 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -197,6 +197,57 @@ test('router.createWebRtcTransport() with deprecated listenIps succeeds', async expect(iceCandidates[0].priority).toBeGreaterThan(iceCandidates[1].priority); }, 2000); +test('router.createWebRtcTransport() with fixed port succeeds', async () => { + const port = await pickPort({ + type: 'tcp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [ + // NOTE: udpReusePort flag will be ignored since protocol is TCP. + { protocol: 'tcp', ip: '127.0.0.1', port, flags: { udpReusePort: true } }, + ], + }); + + expect(webRtcTransport.iceCandidates[0].port).toEqual(port); +}, 2000); + +test('router.createWebRtcTransport() with portRange succeeds', async () => { + const portRange = { min: 11111, max: 11112 }; + + const webRtcTransport1 = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', portRange }], + }); + + const iceCandidate1 = webRtcTransport1.iceCandidates[0]; + + expect(iceCandidate1.ip).toBe('127.0.0.1'); + expect( + iceCandidate1.port >= portRange.min && iceCandidate1.port <= portRange.max + ).toBe(true); + expect(iceCandidate1.protocol).toBe('udp'); + + const webRtcTransport2 = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', portRange }], + }); + + const iceCandidate2 = webRtcTransport2.iceCandidates[0]; + + expect(iceCandidate2.ip).toBe('127.0.0.1'); + expect( + iceCandidate1.port >= portRange.min && iceCandidate1.port <= portRange.max + ).toBe(true); + expect(iceCandidate2.protocol).toBe('udp'); + + // No more available ports so it must fail. + await expect( + ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', portRange }], + }) + ).rejects.toThrow(Error); +}, 2000); + test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore await expect(ctx.router!.createWebRtcTransport({})).rejects.toThrow( @@ -701,24 +752,6 @@ test('WebRtcTransport methods reject if closed', async () => { await expect(webRtcTransport.restartIce()).rejects.toThrow(Error); }, 2000); -test('router.createWebRtcTransport() with fixed port succeeds', async () => { - const port = await pickPort({ - type: 'tcp', - ip: '127.0.0.1', - reserveTimeout: 0, - }); - const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [ - // NOTE: udpReusePort flag will be ignored since protocol is TCP. - { protocol: 'tcp', ip: '127.0.0.1', port, flags: { udpReusePort: true } }, - ], - }); - - expect(webRtcTransport.iceCandidates[0].port).toEqual(port); - - webRtcTransport.close(); -}, 2000); - test('WebRtcTransport emits "routerclose" if Router is closed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenIps: ['127.0.0.1'], diff --git a/rust/benches/producer.rs b/rust/benches/producer.rs index 8d05625a26..260a00f189 100644 --- a/rust/benches/producer.rs +++ b/rust/benches/producer.rs @@ -67,6 +67,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/examples/echo.rs b/rust/examples/echo.rs index d8d751f55f..98a39e582d 100644 --- a/rust/examples/echo.rs +++ b/rust/examples/echo.rs @@ -187,6 +187,7 @@ impl EchoConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/examples/multiopus.rs b/rust/examples/multiopus.rs index d78e8fd859..9f959c1999 100644 --- a/rust/examples/multiopus.rs +++ b/rust/examples/multiopus.rs @@ -150,6 +150,7 @@ impl EchoConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -236,6 +237,7 @@ impl EchoConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/examples/svc-simulcast.rs b/rust/examples/svc-simulcast.rs index 4bf34bbf6c..b33b4f095d 100644 --- a/rust/examples/svc-simulcast.rs +++ b/rust/examples/svc-simulcast.rs @@ -207,6 +207,7 @@ impl SvcSimulcastConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/examples/videoroom.rs b/rust/examples/videoroom.rs index 379958534e..d475372735 100644 --- a/rust/examples/videoroom.rs +++ b/rust/examples/videoroom.rs @@ -501,6 +501,7 @@ mod participant { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index 807dee3990..3019b6ed1f 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -13,7 +13,7 @@ use std::any::Any; use std::borrow::Cow; use std::fmt; use std::net::IpAddr; -use std::ops::{Deref, DerefMut}; +use std::ops::{Deref, DerefMut, RangeInclusive}; use std::sync::Arc; /// Container for arbitrary data attached to mediasoup entities. @@ -52,7 +52,7 @@ impl AppData { /// # Notes on usage /// If you use "0.0.0.0" or "::" as ip value, then you need to also provide /// `announced_address`. -#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ListenInfo { /// Network protocol. @@ -66,6 +66,9 @@ pub struct ListenInfo { /// Listening port. #[serde(skip_serializing_if = "Option::is_none")] pub port: Option, + /// Listening port range. If given then |port| will be ignored. + #[serde(skip_serializing_if = "Option::is_none")] + pub port_range: Option>, /// Socket flags. #[serde(skip_serializing_if = "Option::is_none")] pub flags: Option, @@ -90,6 +93,13 @@ impl ListenInfo { .as_ref() .map(|address| address.to_string()), port: self.port.unwrap_or(0), + port_range: match &self.port_range { + Some(port_range) => Box::new(transport::PortRange { + min: *port_range.start(), + max: *port_range.end(), + }), + None => Box::new(transport::PortRange { min: 0, max: 0 }), + }, flags: Box::new(self.flags.unwrap_or_default().to_fbs()), send_buffer_size: self.send_buffer_size.unwrap_or(0), recv_buffer_size: self.recv_buffer_size.unwrap_or(0), diff --git a/rust/src/router.rs b/rust/src/router.rs index c1259c3174..95049e18fa 100644 --- a/rust/src/router.rs +++ b/rust/src/router.rs @@ -147,6 +147,7 @@ impl PipeToRouterOptions { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -610,6 +611,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -698,6 +700,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -764,6 +767,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -975,6 +979,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -1018,6 +1023,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -1204,6 +1210,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -1236,6 +1243,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, diff --git a/rust/src/router/consumer/tests.rs b/rust/src/router/consumer/tests.rs index 0055fc3262..eaf36003db 100644 --- a/rust/src/router/consumer/tests.rs +++ b/rust/src/router/consumer/tests.rs @@ -87,6 +87,7 @@ async fn init() -> (Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/data_consumer/tests.rs b/rust/src/router/data_consumer/tests.rs index b04a0a81b8..5edcb94537 100644 --- a/rust/src/router/data_consumer/tests.rs +++ b/rust/src/router/data_consumer/tests.rs @@ -41,6 +41,7 @@ async fn init() -> (Router, DataProducer) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -75,6 +76,7 @@ fn data_producer_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -129,6 +131,7 @@ fn transport_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/data_producer/tests.rs b/rust/src/router/data_producer/tests.rs index 349a0909d4..5b910f570e 100644 --- a/rust/src/router/data_producer/tests.rs +++ b/rust/src/router/data_producer/tests.rs @@ -41,6 +41,7 @@ async fn init() -> (Router, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/pipe_transport/tests.rs b/rust/src/router/pipe_transport/tests.rs index 7a3864cfd5..ef09da4a40 100644 --- a/rust/src/router/pipe_transport/tests.rs +++ b/rust/src/router/pipe_transport/tests.rs @@ -103,6 +103,7 @@ async fn init() -> (Router, Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/plain_transport/tests.rs b/rust/src/router/plain_transport/tests.rs index e10654f8cf..496d25a9bd 100644 --- a/rust/src/router/plain_transport/tests.rs +++ b/rust/src/router/plain_transport/tests.rs @@ -42,6 +42,7 @@ fn router_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/producer/tests.rs b/rust/src/router/producer/tests.rs index 68b73f4292..c4941e4f58 100644 --- a/rust/src/router/producer/tests.rs +++ b/rust/src/router/producer/tests.rs @@ -72,6 +72,7 @@ async fn init() -> (Router, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/webrtc_transport/tests.rs b/rust/src/router/webrtc_transport/tests.rs index 75ea2726b1..86a7518797 100644 --- a/rust/src/router/webrtc_transport/tests.rs +++ b/rust/src/router/webrtc_transport/tests.rs @@ -57,6 +57,7 @@ fn create_with_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -66,6 +67,7 @@ fn create_with_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port2), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -235,6 +237,7 @@ fn router_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -277,6 +280,7 @@ fn webrtc_server_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -286,6 +290,7 @@ fn webrtc_server_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port2), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/webrtc_server/tests.rs b/rust/src/webrtc_server/tests.rs index 468be2ba85..63fb7d2c50 100644 --- a/rust/src/webrtc_server/tests.rs +++ b/rust/src/webrtc_server/tests.rs @@ -38,6 +38,7 @@ fn worker_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/worker.rs b/rust/src/worker.rs index f233b72aa3..60a08b67f0 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -179,8 +179,8 @@ pub struct WorkerSettings { /// Log tags for debugging. Check the meaning of each available tag in the /// [Debugging](https://mediasoup.org/documentation/v3/mediasoup/debugging/) documentation. pub log_tags: Vec, - /// RTC ports range for ICE, DTLS, RTP, etc. Default 10000..=59999. - pub rtc_ports_range: RangeInclusive, + /// RTC port range for ICE, DTLS, RTP, etc. Default 10000..=59999. + pub rtc_port_range: RangeInclusive, /// DTLS certificate and private key. /// /// If `None`, a certificate is dynamically created. @@ -218,7 +218,7 @@ impl Default for WorkerSettings { WorkerLogTag::Sctp, WorkerLogTag::Message, ], - rtc_ports_range: 10000..=59999, + rtc_port_range: 10000..=59999, dtls_files: None, libwebrtc_field_trials: None, thread_initializer: None, @@ -232,7 +232,7 @@ impl fmt::Debug for WorkerSettings { let WorkerSettings { log_level, log_tags, - rtc_ports_range, + rtc_port_range, dtls_files, libwebrtc_field_trials, thread_initializer, @@ -242,7 +242,7 @@ impl fmt::Debug for WorkerSettings { f.debug_struct("WorkerSettings") .field("log_level", &log_level) .field("log_tags", &log_tags) - .field("rtc_ports_range", &rtc_ports_range) + .field("rtc_port_range", &rtc_port_range) .field("dtls_files", &dtls_files) .field("libwebrtc_field_trials", &libwebrtc_field_trials) .field( @@ -353,7 +353,7 @@ impl Inner { WorkerSettings { log_level, log_tags, - rtc_ports_range, + rtc_port_range, dtls_files, libwebrtc_field_trials, thread_initializer, @@ -371,14 +371,14 @@ impl Inner { spawn_args.push(format!("--logTag={}", log_tag.as_str())); } - if rtc_ports_range.is_empty() { + if rtc_port_range.is_empty() { return Err(io::Error::new( io::ErrorKind::InvalidInput, "Invalid RTC ports range", )); } - spawn_args.push(format!("--rtcMinPort={}", rtc_ports_range.start())); - spawn_args.push(format!("--rtcMaxPort={}", rtc_ports_range.end())); + spawn_args.push(format!("--rtcMinPort={}", rtc_port_range.start())); + spawn_args.push(format!("--rtcMaxPort={}", rtc_port_range.end())); if let Some(dtls_files) = dtls_files { spawn_args.push(format!( diff --git a/rust/tests/integration/consumer.rs b/rust/tests/integration/consumer.rs index ed2fdbc3b0..e1abdf88e6 100644 --- a/rust/tests/integration/consumer.rs +++ b/rust/tests/integration/consumer.rs @@ -356,6 +356,7 @@ async fn init() -> ( ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/data_consumer.rs b/rust/tests/integration/data_consumer.rs index 609837fd9e..1ded846105 100644 --- a/rust/tests/integration/data_consumer.rs +++ b/rust/tests/integration/data_consumer.rs @@ -68,6 +68,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, DataProducer) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -100,6 +101,7 @@ fn consume_data_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -210,6 +212,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -575,6 +578,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/data_producer.rs b/rust/tests/integration/data_producer.rs index 3fe27a394b..409a70eade 100644 --- a/rust/tests/integration/data_producer.rs +++ b/rust/tests/integration/data_producer.rs @@ -54,6 +54,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -73,6 +74,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/multiopus.rs b/rust/tests/integration/multiopus.rs index 0bcc1ea97d..5479be2077 100644 --- a/rust/tests/integration/multiopus.rs +++ b/rust/tests/integration/multiopus.rs @@ -135,6 +135,7 @@ async fn init() -> (Router, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/pipe_transport.rs b/rust/tests/integration/pipe_transport.rs index aff1990092..bf7bd01e80 100644 --- a/rust/tests/integration/pipe_transport.rs +++ b/rust/tests/integration/pipe_transport.rs @@ -261,6 +261,7 @@ async fn init() -> ( ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -606,6 +607,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -641,6 +643,7 @@ fn create_with_fixed_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -665,6 +668,7 @@ fn create_with_enable_rtx_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -778,6 +782,7 @@ fn create_with_enable_srtp_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -834,6 +839,7 @@ fn create_with_invalid_srtp_parameters_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -1161,6 +1167,7 @@ fn pipe_to_router_called_twice_generates_single_pair() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/plain_transport.rs b/rust/tests/integration/plain_transport.rs index 2edadb74ee..3fe38ed4a8 100644 --- a/rust/tests/integration/plain_transport.rs +++ b/rust/tests/integration/plain_transport.rs @@ -96,6 +96,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -135,6 +136,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -211,6 +213,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -222,6 +225,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(rtcp_port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -292,6 +296,7 @@ fn create_with_fixed_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -316,6 +321,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -350,6 +356,7 @@ fn create_enable_srtp_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -416,6 +423,7 @@ fn create_non_bindable_ip() { ip: "8.8.8.8".parse().unwrap(), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -442,6 +450,7 @@ fn create_two_transports_binding_to_same_ip_port_with_udp_reuse_port_flag_succee ip: multicast_ip, announced_address: None, port: Some(port), + port_range: None, // NOTE: ipv6Only flag will be ignored since ip is IPv4. flags: Some(SocketFlags { ipv6_only: true, @@ -461,6 +470,7 @@ fn create_two_transports_binding_to_same_ip_port_with_udp_reuse_port_flag_succee ip: multicast_ip, announced_address: None, port: Some(port), + port_range: None, flags: Some(SocketFlags { ipv6_only: false, udp_reuse_port: true, @@ -493,6 +503,7 @@ fn create_two_transports_binding_to_same_ip_port_without_udp_reuse_port_flag_fai ip: multicast_ip, announced_address: None, port: Some(port), + port_range: None, flags: Some(SocketFlags { ipv6_only: false, udp_reuse_port: false, @@ -511,6 +522,7 @@ fn create_two_transports_binding_to_same_ip_port_without_udp_reuse_port_flag_fai ip: multicast_ip, announced_address: None, port: Some(port), + port_range: None, flags: Some(SocketFlags { ipv6_only: false, udp_reuse_port: false, @@ -538,6 +550,7 @@ fn get_stats_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -598,6 +611,7 @@ fn connect_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -674,6 +688,7 @@ fn connect_wrong_arguments() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -715,6 +730,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/producer.rs b/rust/tests/integration/producer.rs index 44197df4e6..2fb6ac9276 100644 --- a/rust/tests/integration/producer.rs +++ b/rust/tests/integration/producer.rs @@ -207,6 +207,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/smoke.rs b/rust/tests/integration/smoke.rs index 1c0c48890f..20f3bff81c 100644 --- a/rust/tests/integration/smoke.rs +++ b/rust/tests/integration/smoke.rs @@ -88,6 +88,7 @@ fn smoke() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -275,6 +276,7 @@ fn smoke() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/webrtc_server.rs b/rust/tests/integration/webrtc_server.rs index c647d8a9bd..a052d0653b 100644 --- a/rust/tests/integration/webrtc_server.rs +++ b/rust/tests/integration/webrtc_server.rs @@ -64,6 +64,7 @@ fn create_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -73,6 +74,7 @@ fn create_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("foo.bar.org".to_string()), port: Some(port2), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -160,6 +162,7 @@ fn create_webrtc_server_without_specifying_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -169,6 +172,7 @@ fn create_webrtc_server_without_specifying_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("1.2.3.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -243,6 +247,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -252,6 +257,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)), announced_address: None, port: Some(port2), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -276,6 +282,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -285,6 +292,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), announced_address: Some("1.2.3.4".to_string()), port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -309,6 +317,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -324,6 +333,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -353,6 +363,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/webrtc_transport.rs b/rust/tests/integration/webrtc_transport.rs index c1e9b4bffb..e59caab44c 100644 --- a/rust/tests/integration/webrtc_transport.rs +++ b/rust/tests/integration/webrtc_transport.rs @@ -100,6 +100,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -138,6 +139,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -147,6 +149,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::UNSPECIFIED), announced_address: Some("foo1.bar.org".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -156,6 +159,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -267,6 +271,7 @@ fn create_with_fixed_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -279,6 +284,70 @@ fn create_with_fixed_port_succeeds() { }); } +#[test] +fn create_with_port_range_succeeds() { + future::block_on(async move { + let (_worker, router) = init().await; + let port_range = 11111..=11112; + + let transport1 = router + .create_webrtc_transport({ + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_address: Some("9.9.9.1".to_string()), + port: None, + port_range: Some(port_range.clone()), + flags: None, + send_buffer_size: None, + recv_buffer_size: None, + })) + }) + .await + .expect("Failed to create WebRTC transport"); + + let port1 = transport1.ice_candidates().get(0).unwrap().port; + assert!(port1 >= *port_range.start() && port1 <= *port_range.end()); + + let transport2 = router + .create_webrtc_transport({ + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_address: Some("9.9.9.1".to_string()), + port: None, + port_range: Some(port_range.clone()), + flags: None, + send_buffer_size: None, + recv_buffer_size: None, + })) + }) + .await + .expect("Failed to create WebRTC transport"); + + let port2 = transport2.ice_candidates().get(0).unwrap().port; + assert!(port2 >= *port_range.start() && port2 <= *port_range.end()); + + assert!(matches!( + router + .create_webrtc_transport({ + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_address: Some("9.9.9.1".to_string()), + port: None, + port_range: Some(port_range.clone()), + flags: None, + send_buffer_size: None, + recv_buffer_size: None, + })) + }) + .await, + Err(RequestError::Response { .. }), + )); + }); +} + #[test] fn weak() { future::block_on(async move { @@ -291,6 +360,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -322,6 +392,7 @@ fn create_non_bindable_ip() { ip: "8.8.8.8".parse().unwrap(), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -345,6 +416,7 @@ fn get_stats_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -397,6 +469,7 @@ fn connect_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -447,6 +520,7 @@ fn set_max_incoming_bitrate_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -480,6 +554,7 @@ fn set_max_outgoing_bitrate_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -513,6 +588,7 @@ fn set_min_outgoing_bitrate_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -546,6 +622,7 @@ fn set_max_outgoing_bitrate_fails_if_value_is_lower_than_current_min_limit() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -584,6 +661,7 @@ fn set_min_outgoing_bitrate_fails_if_value_is_higher_than_current_max_limit() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -622,6 +700,7 @@ fn restart_ice_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -658,6 +737,7 @@ fn enable_trace_event_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -734,6 +814,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/worker.rs b/rust/tests/integration/worker.rs index ad0a3d7d9a..9f905ae888 100644 --- a/rust/tests/integration/worker.rs +++ b/rust/tests/integration/worker.rs @@ -42,7 +42,7 @@ fn create_worker_succeeds() { settings.log_level = WorkerLogLevel::Debug; settings.log_tags = vec![WorkerLogTag::Info]; - settings.rtc_ports_range = 0..=9999; + settings.rtc_port_range = 0..=9999; settings.dtls_files = Some(WorkerDtlsFiles { certificate: "tests/integration/data/dtls-cert.pem".into(), private_key: "tests/integration/data/dtls-key.pem".into(), @@ -79,7 +79,7 @@ fn create_worker_wrong_settings() { // Intentionally incorrect range #[allow(clippy::reversed_empty_ranges)] { - settings.rtc_ports_range = 1000..=999; + settings.rtc_port_range = 1000..=999; } settings diff --git a/worker/fbs/transport.fbs b/worker/fbs/transport.fbs index fee932d964..655db6389e 100644 --- a/worker/fbs/transport.fbs +++ b/worker/fbs/transport.fbs @@ -13,6 +13,11 @@ enum Protocol: uint8 { TCP } +table PortRange { + min: uint16 = 0; + max: uint16 = 0; +} + table SocketFlags { ipv6_only: bool = false; udp_reuse_port: bool = false; @@ -23,6 +28,7 @@ table ListenInfo { ip: string (required); announced_address: string; port: uint16 = 0; + port_range: PortRange (required); flags: SocketFlags (required); send_buffer_size: uint32 = 0; recv_buffer_size: uint32 = 0; diff --git a/worker/include/RTC/PortManager.hpp b/worker/include/RTC/PortManager.hpp index f8c102b6b9..3e8c6aa9da 100644 --- a/worker/include/RTC/PortManager.hpp +++ b/worker/include/RTC/PortManager.hpp @@ -2,7 +2,6 @@ #define MS_RTC_PORT_MANAGER_HPP #include "common.hpp" -#include "Settings.hpp" #include "RTC/Transport.hpp" #include #include @@ -14,50 +13,72 @@ namespace RTC class PortManager { private: - enum class Transport : uint8_t + enum class Protocol : uint8_t { UDP = 1, TCP }; - public: - static uv_udp_t* BindUdp(std::string& ip, RTC::Transport::SocketFlags& flags) + private: + struct PortRange { - return reinterpret_cast(Bind(Transport::UDP, ip, flags)); - } + explicit PortRange(uint16_t numPorts, uint16_t minPort) + : ports(numPorts, false), minPort(minPort) + { + } + + std::vector ports; + uint16_t minPort{ 0u }; + uint16_t numUsedPorts{ 0u }; + }; + + public: static uv_udp_t* BindUdp(std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) { - return reinterpret_cast(Bind(Transport::UDP, ip, port, flags)); + return reinterpret_cast(Bind(Protocol::UDP, ip, port, flags)); } - static uv_tcp_t* BindTcp(std::string& ip, RTC::Transport::SocketFlags& flags) + static uv_udp_t* BindUdp( + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& hash) { - return reinterpret_cast(Bind(Transport::TCP, ip, flags)); + return reinterpret_cast(Bind(Protocol::UDP, ip, minPort, maxPort, flags, hash)); } static uv_tcp_t* BindTcp(std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) { - return reinterpret_cast(Bind(Transport::TCP, ip, port, flags)); + return reinterpret_cast(Bind(Protocol::TCP, ip, port, flags)); } - static void UnbindUdp(std::string& ip, uint16_t port) + static uv_tcp_t* BindTcp( + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& hash) { - return Unbind(Transport::UDP, ip, port); - } - static void UnbindTcp(std::string& ip, uint16_t port) - { - return Unbind(Transport::TCP, ip, port); + return reinterpret_cast(Bind(Protocol::TCP, ip, minPort, maxPort, flags, hash)); } + static void Unbind(uint64_t hash, uint16_t port); + static void Dump(); private: - static uv_handle_t* Bind(Transport transport, std::string& ip, RTC::Transport::SocketFlags& flags); static uv_handle_t* Bind( - Transport transport, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); - static void Unbind(Transport transport, std::string& ip, uint16_t port); - static std::vector& GetPorts(Transport transport, const std::string& ip); - static uint8_t ConvertSocketFlags( - RTC::Transport::SocketFlags& flags, Transport transport, int family); + Protocol protocol, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); + static uv_handle_t* Bind( + Protocol protocol, + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& hash); + static uint64_t GeneratePortRangeHash( + Protocol protocol, sockaddr_storage* bindAddr, uint16_t minPort, uint16_t maxPort); + static PortRange& GetOrCreatePortRange(uint64_t hash, uint16_t minPort, uint16_t maxPort); + static uint8_t ConvertSocketFlags(RTC::Transport::SocketFlags& flags, Protocol protocol, int family); private: - thread_local static absl::flat_hash_map> mapUdpIpPorts; - thread_local static absl::flat_hash_map> mapTcpIpPorts; + thread_local static absl::flat_hash_map mapPortRanges; }; } // namespace RTC diff --git a/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp b/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp index fa77eff277..eac430e28d 100644 --- a/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp +++ b/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp @@ -143,9 +143,9 @@ namespace RTC /* Pure virtual methods inherited from ExtendedReportBlock. */ public: - virtual void Dump() const override; - virtual size_t Serialize(uint8_t* buffer) override; - virtual size_t GetSize() const override + void Dump() const override; + size_t Serialize(uint8_t* buffer) override; + size_t GetSize() const override { size_t size{ 4u }; // Common header. diff --git a/worker/include/RTC/RTCP/XrReceiverReferenceTime.hpp b/worker/include/RTC/RTCP/XrReceiverReferenceTime.hpp index ecafaf1ad0..0083618588 100644 --- a/worker/include/RTC/RTCP/XrReceiverReferenceTime.hpp +++ b/worker/include/RTC/RTCP/XrReceiverReferenceTime.hpp @@ -68,9 +68,9 @@ namespace RTC /* Pure virtual methods inherited from ExtendedReportBlock. */ public: - virtual void Dump() const override; - virtual size_t Serialize(uint8_t* buffer) override; - virtual size_t GetSize() const override + void Dump() const override; + size_t Serialize(uint8_t* buffer) override; + size_t GetSize() const override { size_t size{ 4 }; // Common header. diff --git a/worker/include/RTC/TcpServer.hpp b/worker/include/RTC/TcpServer.hpp index 6d1aeb7376..383ae16ef4 100644 --- a/worker/include/RTC/TcpServer.hpp +++ b/worker/include/RTC/TcpServer.hpp @@ -28,13 +28,16 @@ namespace RTC Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, + uint16_t port, RTC::Transport::SocketFlags& flags); TcpServer( Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, - uint16_t port, - RTC::Transport::SocketFlags& flags); + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& portRangeHash); ~TcpServer() override; /* Pure virtual methods inherited from ::TcpServerHandle. */ @@ -47,6 +50,7 @@ namespace RTC Listener* listener{ nullptr }; RTC::TcpConnection::Listener* connListener{ nullptr }; bool fixedPort{ false }; + uint64_t portRangeHash{ 0u }; }; } // namespace RTC diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index 1b0baaa9c3..3448555a59 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -125,11 +125,18 @@ namespace RTC bool udpReusePort{ false }; }; + struct PortRange + { + uint16_t min{ 0u }; + uint16_t max{ 0u }; + }; + struct ListenInfo { std::string ip; std::string announcedAddress; uint16_t port{ 0u }; + PortRange portRange; SocketFlags flags; uint32_t sendBufferSize{ 0u }; uint32_t recvBufferSize{ 0u }; diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 19750caf99..8df96d10ce 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -17,7 +17,7 @@ namespace RTC using onSendCallback = const std::function; public: - enum class Protocol + enum class Protocol : uint8_t { UDP = 1, TCP @@ -163,77 +163,7 @@ namespace RTC } private: - /* - * Hash for IPv4 - * - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | PORT | IP | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | IP | |F|P| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Hash for IPv6 - * - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | PORT | IP[0] ^ IP[1] ^ IP[2] ^ IP[3]| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | IP[0] >> 16 |F|P| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - void SetHash() - { - const struct sockaddr* remoteSockAddr = GetRemoteAddress(); - - switch (remoteSockAddr->sa_family) - { - case AF_INET: - { - const auto* remoteSockAddrIn = reinterpret_cast(remoteSockAddr); - - const uint64_t address = ntohl(remoteSockAddrIn->sin_addr.s_addr); - const uint64_t port = (ntohs(remoteSockAddrIn->sin_port)); - - this->hash = port << 48; - this->hash |= address << 16; - this->hash |= 0x0000; // AF_INET. - - break; - } - - case AF_INET6: - { - const auto* remoteSockAddrIn6 = - reinterpret_cast(remoteSockAddr); - const auto* a = - reinterpret_cast(std::addressof(remoteSockAddrIn6->sin6_addr)); - - const auto address1 = a[0] ^ a[1] ^ a[2] ^ a[3]; - const auto address2 = a[0]; - const uint64_t port = ntohs(remoteSockAddrIn6->sin6_port); - - this->hash = port << 48; - this->hash |= static_cast(address1) << 16; - this->hash |= address2 >> 16 & 0xFFFC; - this->hash |= 0x0002; // AF_INET6. - - break; - } - } - - // Override least significant bit with protocol information: - // - If UDP, start with 0. - // - If TCP, start with 1. - if (this->protocol == Protocol::UDP) - { - this->hash |= 0x0000; - } - else - { - this->hash |= 0x0001; - } - } + void SetHash(); public: uint64_t hash{ 0u }; diff --git a/worker/include/RTC/UdpSocket.hpp b/worker/include/RTC/UdpSocket.hpp index ad9bde10d6..3a15f9cc0b 100644 --- a/worker/include/RTC/UdpSocket.hpp +++ b/worker/include/RTC/UdpSocket.hpp @@ -22,8 +22,14 @@ namespace RTC }; public: - UdpSocket(Listener* listener, std::string& ip, RTC::Transport::SocketFlags& flags); UdpSocket(Listener* listener, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); + UdpSocket( + Listener* listener, + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& portRangeHash); ~UdpSocket() override; /* Pure virtual methods inherited from ::UdpSocketHandle. */ @@ -34,6 +40,7 @@ namespace RTC // Passed by argument. Listener* listener{ nullptr }; bool fixedPort{ false }; + uint64_t portRangeHash{ 0u }; }; } // namespace RTC diff --git a/worker/include/handles/TcpConnectionHandle.hpp b/worker/include/handles/TcpConnectionHandle.hpp index 073602d305..76c92e3512 100644 --- a/worker/include/handles/TcpConnectionHandle.hpp +++ b/worker/include/handles/TcpConnectionHandle.hpp @@ -54,7 +54,7 @@ class TcpConnectionHandle { return this->closed; } - virtual void Dump() const; + void Dump() const; void Setup( Listener* listener, struct sockaddr_storage* localAddr, diff --git a/worker/include/handles/TcpServerHandle.hpp b/worker/include/handles/TcpServerHandle.hpp index 6d0fa9d1f9..e82c92a9a5 100644 --- a/worker/include/handles/TcpServerHandle.hpp +++ b/worker/include/handles/TcpServerHandle.hpp @@ -18,7 +18,7 @@ class TcpServerHandle : public TcpConnectionHandle::Listener public: void Close(); - virtual void Dump() const; + void Dump() const; const struct sockaddr* GetLocalAddress() const { return reinterpret_cast(&this->localAddr); diff --git a/worker/include/handles/UdpSocketHandle.hpp b/worker/include/handles/UdpSocketHandle.hpp index 2b7a708105..084690e76e 100644 --- a/worker/include/handles/UdpSocketHandle.hpp +++ b/worker/include/handles/UdpSocketHandle.hpp @@ -47,7 +47,7 @@ class UdpSocketHandle { return this->closed; } - virtual void Dump() const; + void Dump() const; void Send( const uint8_t* data, size_t len, const struct sockaddr* addr, UdpSocketHandle::onSendCallback* cb); const struct sockaddr* GetLocalAddress() const diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index 07fc5b538b..257b328ef1 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -53,6 +53,8 @@ namespace RTC } this->listenInfo.port = options->listenInfo()->port(); + this->listenInfo.portRange.min = options->listenInfo()->portRange()->min(); + this->listenInfo.portRange.max = options->listenInfo()->portRange()->max(); this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); this->listenInfo.flags.ipv6Only = options->listenInfo()->flags()->ipv6Only(); @@ -68,15 +70,37 @@ namespace RTC try { - // This may throw. - if (this->listenInfo.port != 0) + if (this->listenInfo.portRange.min != 0 && this->listenInfo.portRange.max != 0) + { + uint64_t portRangeHash{ 0u }; + + this->udpSocket = new RTC::UdpSocket( + this, + this->listenInfo.ip, + this->listenInfo.portRange.min, + this->listenInfo.portRange.max, + this->listenInfo.flags, + portRangeHash); + } + else if (this->listenInfo.port != 0) { this->udpSocket = new RTC::UdpSocket( this, this->listenInfo.ip, this->listenInfo.port, this->listenInfo.flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.flags); + uint64_t portRangeHash{ 0u }; + + this->udpSocket = new RTC::UdpSocket( + this, + this->listenInfo.ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + this->listenInfo.flags, + portRangeHash); } if (this->listenInfo.sendBufferSize != 0) diff --git a/worker/src/RTC/PlainTransport.cpp b/worker/src/RTC/PlainTransport.cpp index 2c8c14dfc4..3cb5a5b676 100644 --- a/worker/src/RTC/PlainTransport.cpp +++ b/worker/src/RTC/PlainTransport.cpp @@ -4,6 +4,7 @@ #include "RTC/PlainTransport.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Settings.hpp" #include "Utils.hpp" namespace RTC @@ -54,6 +55,8 @@ namespace RTC } this->listenInfo.port = options->listenInfo()->port(); + this->listenInfo.portRange.min = options->listenInfo()->portRange()->min(); + this->listenInfo.portRange.max = options->listenInfo()->portRange()->max(); this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); this->listenInfo.flags.ipv6Only = options->listenInfo()->flags()->ipv6Only(); @@ -85,6 +88,8 @@ namespace RTC } this->rtcpListenInfo.port = options->rtcpListenInfo()->port(); + this->rtcpListenInfo.portRange.min = options->rtcpListenInfo()->portRange()->min(); + this->rtcpListenInfo.portRange.max = options->rtcpListenInfo()->portRange()->max(); this->rtcpListenInfo.sendBufferSize = options->rtcpListenInfo()->sendBufferSize(); this->rtcpListenInfo.recvBufferSize = options->rtcpListenInfo()->recvBufferSize(); this->rtcpListenInfo.flags.ipv6Only = options->rtcpListenInfo()->flags()->ipv6Only(); @@ -143,15 +148,37 @@ namespace RTC try { - // This may throw. - if (this->listenInfo.port != 0) + if (this->listenInfo.portRange.min != 0 && this->listenInfo.portRange.max != 0) + { + uint64_t portRangeHash{ 0u }; + + this->udpSocket = new RTC::UdpSocket( + this, + this->listenInfo.ip, + this->listenInfo.portRange.min, + this->listenInfo.portRange.max, + this->listenInfo.flags, + portRangeHash); + } + else if (this->listenInfo.port != 0) { this->udpSocket = new RTC::UdpSocket( this, this->listenInfo.ip, this->listenInfo.port, this->listenInfo.flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.flags); + uint64_t portRangeHash{ 0u }; + + this->udpSocket = new RTC::UdpSocket( + this, + this->listenInfo.ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + this->listenInfo.flags, + portRangeHash); } if (this->listenInfo.sendBufferSize != 0) @@ -168,16 +195,37 @@ namespace RTC if (!this->rtcpMux) { - // This may throw. - if (this->rtcpListenInfo.port != 0) + if (this->rtcpListenInfo.portRange.min != 0 && this->rtcpListenInfo.portRange.max != 0) + { + uint64_t portRangeHash{ 0u }; + + this->rtcpUdpSocket = new RTC::UdpSocket( + this, + this->rtcpListenInfo.ip, + this->rtcpListenInfo.portRange.min, + this->rtcpListenInfo.portRange.max, + this->rtcpListenInfo.flags, + portRangeHash); + } + else if (this->rtcpListenInfo.port != 0) { this->rtcpUdpSocket = new RTC::UdpSocket( this, this->rtcpListenInfo.ip, this->rtcpListenInfo.port, this->rtcpListenInfo.flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - this->rtcpUdpSocket = - new RTC::UdpSocket(this, this->rtcpListenInfo.ip, this->rtcpListenInfo.flags); + uint64_t portRangeHash{ 0u }; + + this->rtcpUdpSocket = new RTC::UdpSocket( + this, + this->rtcpListenInfo.ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + this->rtcpListenInfo.flags, + portRangeHash); } if (this->rtcpListenInfo.sendBufferSize != 0) diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index a2247bf256..557596dc04 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -33,12 +33,12 @@ namespace RTC { /* Class variables. */ - thread_local absl::flat_hash_map> PortManager::mapUdpIpPorts; - thread_local absl::flat_hash_map> PortManager::mapTcpIpPorts; + thread_local absl::flat_hash_map PortManager::mapPortRanges; /* Class methods. */ - uv_handle_t* PortManager::Bind(Transport transport, std::string& ip, RTC::Transport::SocketFlags& flags) + uv_handle_t* PortManager::Bind( + Protocol protocol, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) { MS_TRACE(); @@ -50,27 +50,22 @@ namespace RTC struct sockaddr_storage bindAddr { }; - size_t portIdx; - std::vector& ports = PortManager::GetPorts(transport, ip); - size_t attempt{ 0u }; - const size_t numAttempts = ports.size(); uv_handle_t* uvHandle{ nullptr }; - uint16_t port; - std::string transportStr; - const uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); + std::string protocolStr; + const uint8_t bitFlags = ConvertSocketFlags(flags, protocol, family); - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { - transportStr.assign("udp"); + protocolStr.assign("udp"); break; } - case Transport::TCP: + case Protocol::TCP: { - transportStr.assign("tcp"); + protocolStr.assign("tcp"); break; } @@ -109,9 +104,233 @@ namespace RTC } } + // Set the port into the sockaddr struct. + switch (family) + { + case AF_INET: + { + (reinterpret_cast(&bindAddr))->sin_port = htons(port); + + break; + } + + case AF_INET6: + { + (reinterpret_cast(&bindAddr))->sin6_port = htons(port); + + break; + } + } + + // Try to bind on it. + switch (protocol) + { + case Protocol::UDP: + { + uvHandle = reinterpret_cast(new uv_udp_t()); + err = uv_udp_init_ex( + DepLibUV::GetLoop(), reinterpret_cast(uvHandle), UV_UDP_RECVMMSG); + + break; + } + + case Protocol::TCP: + { + uvHandle = reinterpret_cast(new uv_tcp_t()); + err = uv_tcp_init(DepLibUV::GetLoop(), reinterpret_cast(uvHandle)); + + break; + } + } + + if (err != 0) + { + switch (protocol) + { + case Protocol::UDP: + { + delete reinterpret_cast(uvHandle); + + MS_THROW_ERROR("uv_udp_init_ex() failed: %s", uv_strerror(err)); + + break; + } + + case Protocol::TCP: + { + delete reinterpret_cast(uvHandle); + + MS_THROW_ERROR("uv_tcp_init() failed: %s", uv_strerror(err)); + + break; + } + } + } + + switch (protocol) + { + case Protocol::UDP: + { + err = uv_udp_bind( + reinterpret_cast(uvHandle), + reinterpret_cast(&bindAddr), + bitFlags); + + if (err != 0) + { + // If it failed, close the handle and check the reason. + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseUdp)); + + MS_THROW_ERROR( + "uv_udp_bind() failed [protocol:%s, ip:'%s', port:%" PRIu16 "]: %s", + protocolStr.c_str(), + ip.c_str(), + port, + uv_strerror(err)); + } + + break; + } + + case Protocol::TCP: + { + err = uv_tcp_bind( + reinterpret_cast(uvHandle), + reinterpret_cast(&bindAddr), + bitFlags); + + if (err != 0) + { + // If it failed, close the handle and check the reason. + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); + + MS_THROW_ERROR( + "uv_tcp_bind() failed [protocol:%s, ip:'%s', port:%" PRIu16 "]: %s", + protocolStr.c_str(), + ip.c_str(), + port, + uv_strerror(err)); + } + + // uv_tcp_bind() may succeed even if later uv_listen() fails, so + // double check it. + err = uv_listen( + reinterpret_cast(uvHandle), + 256, + static_cast(onFakeConnection)); + + if (err != 0) + { + // If it failed, close the handle and check the reason. + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); + + MS_THROW_ERROR( + "uv_listen() failed [protocol:%s, ip:'%s', port:%" PRIu16 "]: %s", + protocolStr.c_str(), + ip.c_str(), + port, + uv_strerror(err)); + } + + break; + } + } + + MS_DEBUG_DEV( + "bind succeeded [protocol:%s, ip:'%s', port:%" PRIu16 "]", protocolStr.c_str(), ip.c_str(), port); + + return static_cast(uvHandle); + } + + uv_handle_t* PortManager::Bind( + Protocol protocol, + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& hash) + { + MS_TRACE(); + + if (maxPort < minPort) + { + MS_THROW_TYPE_ERROR("maxPort cannot be less than minPort"); + } + + // First normalize the IP. This may throw if invalid IP. + Utils::IP::NormalizeIp(ip); + + int err; + const int family = Utils::IP::GetFamily(ip); + struct sockaddr_storage bindAddr + { + }; + std::string protocolStr; + + switch (protocol) + { + case Protocol::UDP: + { + protocolStr.assign("udp"); + + break; + } + + case Protocol::TCP: + { + protocolStr.assign("tcp"); + + break; + } + } + + switch (family) + { + case AF_INET: + { + err = uv_ip4_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); + + if (err != 0) + { + MS_THROW_ERROR("uv_ip4_addr() failed: %s", uv_strerror(err)); + } + + break; + } + + case AF_INET6: + { + err = uv_ip6_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); + + if (err != 0) + { + MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); + } + + break; + } + + // This cannot happen. + default: + { + MS_THROW_ERROR("unknown IP family"); + } + } + + hash = GeneratePortRangeHash(protocol, std::addressof(bindAddr), minPort, maxPort); + + auto& portRange = PortManager::GetOrCreatePortRange(hash, minPort, maxPort); + const size_t numPorts = portRange.ports.size(); + const size_t numAttempts = numPorts; + size_t attempt{ 0u }; + size_t portIdx; + uint16_t port; + uv_handle_t* uvHandle{ nullptr }; + const uint8_t bitFlags = ConvertSocketFlags(flags, protocol, family); + // Choose a random port index to start from. - portIdx = static_cast(Utils::Crypto::GetRandomUInt( - static_cast(0), static_cast(ports.size() - 1))); + portIdx = static_cast( + Utils::Crypto::GetRandomUInt(static_cast(0), static_cast(numPorts - 1))); // Iterate all ports until getting one available. Fail if none found and also // if bind() fails N times in theoretically available ports. @@ -124,32 +343,32 @@ namespace RTC if (attempt > numAttempts) { MS_THROW_ERROR( - "no more available ports [transport:%s, ip:'%s', numAttempt:%zu]", - transportStr.c_str(), + "no more available ports [protocol:%s, ip:'%s', numAttempt:%zu]", + protocolStr.c_str(), ip.c_str(), numAttempts); } // Increase current port index. - portIdx = (portIdx + 1) % ports.size(); + portIdx = (portIdx + 1) % numPorts; // So the corresponding port is the vector position plus the RTC minimum port. - port = static_cast(portIdx + Settings::configuration.rtcMinPort); + port = static_cast(portIdx + minPort); MS_DEBUG_DEV( - "testing port [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + "testing port [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", + protocolStr.c_str(), ip.c_str(), port, attempt, numAttempts); // Check whether this port is not available. - if (ports[portIdx]) + if (portRange.ports[portIdx]) { MS_DEBUG_DEV( - "port in use, trying again [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + "port in use, trying again [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -180,9 +399,9 @@ namespace RTC } // Try to bind on it. - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { uvHandle = reinterpret_cast(new uv_udp_t()); err = uv_udp_init_ex( @@ -191,7 +410,7 @@ namespace RTC break; } - case Transport::TCP: + case Protocol::TCP: { uvHandle = reinterpret_cast(new uv_tcp_t()); err = uv_tcp_init(DepLibUV::GetLoop(), reinterpret_cast(uvHandle)); @@ -202,9 +421,9 @@ namespace RTC if (err != 0) { - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { delete reinterpret_cast(uvHandle); @@ -213,7 +432,7 @@ namespace RTC break; } - case Transport::TCP: + case Protocol::TCP: { delete reinterpret_cast(uvHandle); @@ -224,9 +443,9 @@ namespace RTC } } - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { err = uv_udp_bind( reinterpret_cast(uvHandle), @@ -236,8 +455,8 @@ namespace RTC if (err != 0) { MS_WARN_DEV( - "uv_udp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", - transportStr.c_str(), + "uv_udp_bind() failed [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -248,7 +467,7 @@ namespace RTC break; } - case Transport::TCP: + case Protocol::TCP: { err = uv_tcp_bind( reinterpret_cast(uvHandle), @@ -258,8 +477,8 @@ namespace RTC if (err != 0) { MS_WARN_DEV( - "uv_tcp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", - transportStr.c_str(), + "uv_tcp_bind() failed [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -277,8 +496,8 @@ namespace RTC static_cast(onFakeConnection)); MS_WARN_DEV( - "uv_listen() failed [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", - transportStr.c_str(), + "uv_listen() failed [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -297,16 +516,16 @@ namespace RTC } // If it failed, close the handle and check the reason. - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { uv_close(reinterpret_cast(uvHandle), static_cast(onCloseUdp)); break; }; - case Transport::TCP: + case Protocol::TCP: { uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); @@ -320,9 +539,9 @@ namespace RTC case UV_EMFILE: { MS_THROW_ERROR( - "port bind failed due to too many open files [transport:%s, ip:'%s', port:%" PRIu16 + "port bind failed due to too many open files [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -335,9 +554,9 @@ namespace RTC case UV_EADDRNOTAVAIL: { MS_THROW_ERROR( - "port bind failed due to address not available [transport:%s, ip:'%s', port:%" PRIu16 + "port bind failed due to address not available [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -354,11 +573,14 @@ namespace RTC } // If here, we got an available port. Mark it as unavailable. - ports[portIdx] = true; + portRange.ports[portIdx] = true; + + // Increase number of used ports in the range. + portRange.numUsedPorts++; MS_DEBUG_DEV( - "bind succeeded [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + "bind succeeded [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -367,337 +589,164 @@ namespace RTC return static_cast(uvHandle); } - uv_handle_t* PortManager::Bind( - Transport transport, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) + void PortManager::Unbind(uint64_t hash, uint16_t port) { MS_TRACE(); - // First normalize the IP. This may throw if invalid IP. - Utils::IP::NormalizeIp(ip); - - int err; - const int family = Utils::IP::GetFamily(ip); - struct sockaddr_storage bindAddr - { - }; - uv_handle_t* uvHandle{ nullptr }; - std::string transportStr; - const uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); + auto it = PortManager::mapPortRanges.find(hash); - switch (transport) + // This should not happen. + if (it == PortManager::mapPortRanges.end()) { - case Transport::UDP: - { - transportStr.assign("udp"); - - break; - } - - case Transport::TCP: - { - transportStr.assign("tcp"); + MS_ERROR("hash %" PRIu64 " doesn't exist in the map", hash); - break; - } + return; } - switch (family) - { - case AF_INET: - { - err = uv_ip4_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); - - if (err != 0) - { - MS_THROW_ERROR("uv_ip4_addr() failed: %s", uv_strerror(err)); - } - - break; - } + auto& portRange = it->second; + const auto portIdx = static_cast(port - portRange.minPort); - case AF_INET6: - { - err = uv_ip6_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); + // This should not happen. + MS_ASSERT(portRange.ports.at(portIdx) == true, "port %" PRIu16 " is not used", port); + MS_ASSERT(portRange.numUsedPorts > 0u, "number of used ports is 0"); - if (err != 0) - { - MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); - } + // Mark the port as available. + portRange.ports[portIdx] = false; - break; - } + // Decrease number of used ports in the range. + portRange.numUsedPorts--; - // This cannot happen. - default: - { - MS_THROW_ERROR("unknown IP family"); - } - } - - // Set the port into the sockaddr struct. - switch (family) + // Remove vector if there are no used ports. + if (portRange.numUsedPorts == 0u) { - case AF_INET: - { - (reinterpret_cast(&bindAddr))->sin_port = htons(port); - - break; - } - - case AF_INET6: - { - (reinterpret_cast(&bindAddr))->sin6_port = htons(port); - - break; - } + PortManager::mapPortRanges.erase(it); } + } - // Try to bind on it. - switch (transport) - { - case Transport::UDP: - { - uvHandle = reinterpret_cast(new uv_udp_t()); - err = uv_udp_init_ex( - DepLibUV::GetLoop(), reinterpret_cast(uvHandle), UV_UDP_RECVMMSG); - - break; - } - - case Transport::TCP: - { - uvHandle = reinterpret_cast(new uv_tcp_t()); - err = uv_tcp_init(DepLibUV::GetLoop(), reinterpret_cast(uvHandle)); - - break; - } - } + void PortManager::Dump() + { + MS_DUMP(""); - if (err != 0) + for (auto& kv : PortManager::mapPortRanges) { - switch (transport) - { - case Transport::UDP: - { - delete reinterpret_cast(uvHandle); - - MS_THROW_ERROR("uv_udp_init_ex() failed: %s", uv_strerror(err)); - - break; - } + auto hash = kv.first; + auto portRange = kv.second; + + MS_DUMP(" "); + MS_DUMP(" hash: %" PRIu64, hash); + MS_DUMP(" minPort: %" PRIu16, portRange.minPort); + MS_DUMP(" maxPort: %zu", portRange.minPort + portRange.ports.size() - 1); + MS_DUMP(" numUsedPorts: %" PRIu16, portRange.numUsedPorts); + MS_DUMP(" "); + } - case Transport::TCP: - { - delete reinterpret_cast(uvHandle); + MS_DUMP(""); + } - MS_THROW_ERROR("uv_tcp_init() failed: %s", uv_strerror(err)); + /* + * Hash for IPv4. + * + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MIN PORT | MAX PORT | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IP | IP >> 2 |F|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Hash for IPv6. + * + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MIN PORT | MAX PORT | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | same >> 2 |F|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + uint64_t PortManager::GeneratePortRangeHash( + Protocol protocol, sockaddr_storage* bindAddr, uint16_t minPort, uint16_t maxPort) + { + MS_TRACE(); - break; - } - } - } + uint64_t hash{ 0u }; - switch (transport) + switch (bindAddr->ss_family) { - case Transport::UDP: + case AF_INET: { - err = uv_udp_bind( - reinterpret_cast(uvHandle), - reinterpret_cast(&bindAddr), - bitFlags); + auto* bindAddrIn = reinterpret_cast(bindAddr); - if (err != 0) - { - // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onCloseUdp)); + // We want it in network order. + const uint64_t address = bindAddrIn->sin_addr.s_addr; - MS_THROW_ERROR( - "uv_udp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 "]: %s", - transportStr.c_str(), - ip.c_str(), - port, - uv_strerror(err)); - } + hash = static_cast(minPort) << 48; + hash = static_cast(maxPort) << 32; + hash |= (address >> 2) << 2; + hash |= 0x0000; // AF_INET. break; } - case Transport::TCP: + case AF_INET6: { - err = uv_tcp_bind( - reinterpret_cast(uvHandle), - reinterpret_cast(&bindAddr), - bitFlags); + auto* bindAddrIn6 = reinterpret_cast(bindAddr); + auto* a = reinterpret_cast(std::addressof(bindAddrIn6->sin6_addr)); - if (err != 0) - { - // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); + const auto address = a[0] ^ a[1] ^ a[2] ^ a[3]; - MS_THROW_ERROR( - "uv_tcp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 "]: %s", - transportStr.c_str(), - ip.c_str(), - port, - uv_strerror(err)); - } - - // uv_tcp_bind() may succeed even if later uv_listen() fails, so - // double check it. - err = uv_listen( - reinterpret_cast(uvHandle), - 256, - static_cast(onFakeConnection)); - - if (err != 0) - { - // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); - - MS_THROW_ERROR( - "uv_listen() failed [transport:%s, ip:'%s', port:%" PRIu16 "]: %s", - transportStr.c_str(), - ip.c_str(), - port, - uv_strerror(err)); - } + hash = static_cast(minPort) << 48; + hash = static_cast(maxPort) << 32; + hash |= static_cast(address) << 16; + hash |= (static_cast(address) >> 2) << 2; + hash |= 0x0002; // AF_INET6. break; } } - MS_DEBUG_DEV( - "bind succeeded [transport:%s, ip:'%s', port:%" PRIu16 "]", - transportStr.c_str(), - ip.c_str(), - port); - - return static_cast(uvHandle); - } - - void PortManager::Unbind(Transport transport, std::string& ip, uint16_t port) - { - MS_TRACE(); - - if ( - (static_cast(port) < Settings::configuration.rtcMinPort) || - (static_cast(port) > Settings::configuration.rtcMaxPort)) + // Override least significant bit with protocol information: + // - If UDP, start with 0. + // - If TCP, start with 1. + if (protocol == Protocol::UDP) { - MS_ERROR("given port %" PRIu16 " is out of range", port); - - return; + hash |= 0x0000; } - - const size_t portIdx = static_cast(port) - Settings::configuration.rtcMinPort; - - switch (transport) + else { - case Transport::UDP: - { - auto it = PortManager::mapUdpIpPorts.find(ip); - - if (it == PortManager::mapUdpIpPorts.end()) - { - return; - } - - auto& ports = it->second; - - // Mark the port as available. - ports[portIdx] = false; - - break; - } - - case Transport::TCP: - { - auto it = PortManager::mapTcpIpPorts.find(ip); - - if (it == PortManager::mapTcpIpPorts.end()) - { - return; - } - - auto& ports = it->second; - - // Mark the port as available. - ports[portIdx] = false; - - break; - } + hash |= 0x0001; } + + return hash; } - std::vector& PortManager::GetPorts(Transport transport, const std::string& ip) + PortManager::PortRange& PortManager::GetOrCreatePortRange( + uint64_t hash, uint16_t minPort, uint16_t maxPort) { MS_TRACE(); - // Make GCC happy so it does not print: - // "control reaches end of non-void function [-Wreturn-type]" - static std::vector emptyPorts; + auto it = PortManager::mapPortRanges.find(hash); - switch (transport) + // If the hash is already handled, return its port range. + if (it != PortManager::mapPortRanges.end()) { - case Transport::UDP: - { - auto it = PortManager::mapUdpIpPorts.find(ip); - - // If the IP is already handled, return its ports vector. - if (it != PortManager::mapUdpIpPorts.end()) - { - auto& ports = it->second; - - return ports; - } - - // Otherwise add an entry in the map and return it. - const uint16_t numPorts = - Settings::configuration.rtcMaxPort - Settings::configuration.rtcMinPort + 1; - - // Emplace a new vector filled with numPorts false values, meaning that - // all ports are available. - auto pair = PortManager::mapUdpIpPorts.emplace( - std::piecewise_construct, std::make_tuple(ip), std::make_tuple(numPorts, false)); + auto& portRange = it->second; - // pair.first is an iterator to the inserted value. - auto& ports = pair.first->second; - - return ports; - } - - case Transport::TCP: - { - auto it = PortManager::mapTcpIpPorts.find(ip); - - // If the IP is already handled, return its ports vector. - if (it != PortManager::mapTcpIpPorts.end()) - { - auto& ports = it->second; - - return ports; - } - - // Otherwise add an entry in the map and return it. - const uint16_t numPorts = - Settings::configuration.rtcMaxPort - Settings::configuration.rtcMinPort + 1; + return portRange; + } - // Emplace a new vector filled with numPorts false values, meaning that - // all ports are available. - auto pair = PortManager::mapTcpIpPorts.emplace( - std::piecewise_construct, std::make_tuple(ip), std::make_tuple(numPorts, false)); + const uint16_t numPorts = maxPort - minPort + 1; - // pair.first is an iterator to the inserted value. - auto& ports = pair.first->second; + // Emplace a new vector filled with numPorts false values, meaning that + // all ports are available. + auto pair = PortManager::mapPortRanges.emplace( + std::piecewise_construct, std::make_tuple(hash), std::make_tuple(numPorts, minPort)); - return ports; - } - } + // pair.first is an iterator to the inserted value. + auto& portRange = pair.first->second; - return emptyPorts; + return portRange; } - uint8_t PortManager::ConvertSocketFlags( - RTC::Transport::SocketFlags& flags, Transport transport, int family) + uint8_t PortManager::ConvertSocketFlags(RTC::Transport::SocketFlags& flags, Protocol protocol, int family) { MS_TRACE(); @@ -706,16 +755,16 @@ namespace RTC // Ignore ipv6Only in IPv4, otherwise libuv will throw. if (flags.ipv6Only && family == AF_INET6) { - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { bitFlags |= UV_UDP_IPV6ONLY; break; } - case Transport::TCP: + case Protocol::TCP: { bitFlags |= UV_TCP_IPV6ONLY; @@ -725,7 +774,7 @@ namespace RTC } // Ignore udpReusePort in TCP, otherwise libuv will throw. - if (flags.udpReusePort && transport == Transport::UDP) + if (flags.udpReusePort && protocol == Protocol::UDP) { bitFlags |= UV_UDP_REUSEADDR; } diff --git a/worker/src/RTC/TcpServer.cpp b/worker/src/RTC/TcpServer.cpp index 685c0b1118..9ae9b49dfe 100644 --- a/worker/src/RTC/TcpServer.cpp +++ b/worker/src/RTC/TcpServer.cpp @@ -14,10 +14,11 @@ namespace RTC Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, + uint16_t port, RTC::Transport::SocketFlags& flags) : // This may throw. - ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, flags)), listener(listener), - connListener(connListener) + ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, port, flags)), + listener(listener), connListener(connListener), fixedPort(true) { MS_TRACE(); } @@ -26,13 +27,18 @@ namespace RTC Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, - uint16_t port, - RTC::Transport::SocketFlags& flags) + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& portRangeHash) : // This may throw. - ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, port, flags)), - listener(listener), connListener(connListener), fixedPort(true) + ::TcpServerHandle::TcpServerHandle( + RTC::PortManager::BindTcp(ip, minPort, maxPort, flags, portRangeHash)), + listener(listener), connListener(connListener), fixedPort(false) { MS_TRACE(); + + this->portRangeHash = portRangeHash; } TcpServer::~TcpServer() @@ -41,7 +47,7 @@ namespace RTC if (!this->fixedPort) { - RTC::PortManager::UnbindTcp(this->localIp, this->localPort); + RTC::PortManager::Unbind(this->portRangeHash, this->localPort); } } diff --git a/worker/src/RTC/TransportTuple.cpp b/worker/src/RTC/TransportTuple.cpp index 33720bf689..68d14d0bd5 100644 --- a/worker/src/RTC/TransportTuple.cpp +++ b/worker/src/RTC/TransportTuple.cpp @@ -95,4 +95,77 @@ namespace RTC MS_DUMP(""); } + + /* + * Hash for IPv4. + * + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PORT | IP | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IP | |F|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Hash for IPv6. + * + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PORT | IP[0] ^ IP[1] ^ IP[2] ^ IP[3]| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | IP[0] >> 16 |F|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + void TransportTuple::SetHash() + { + MS_TRACE(); + + const struct sockaddr* remoteSockAddr = GetRemoteAddress(); + + switch (remoteSockAddr->sa_family) + { + case AF_INET: + { + const auto* remoteSockAddrIn = reinterpret_cast(remoteSockAddr); + + const uint64_t address = ntohl(remoteSockAddrIn->sin_addr.s_addr); + const uint64_t port = ntohs(remoteSockAddrIn->sin_port); + + this->hash = port << 48; + this->hash |= address << 16; + this->hash |= 0x0000; // AF_INET. + + break; + } + + case AF_INET6: + { + const auto* remoteSockAddrIn6 = reinterpret_cast(remoteSockAddr); + const auto* a = + reinterpret_cast(std::addressof(remoteSockAddrIn6->sin6_addr)); + + const auto address1 = a[0] ^ a[1] ^ a[2] ^ a[3]; + const auto address2 = a[0]; + const uint64_t port = ntohs(remoteSockAddrIn6->sin6_port); + + this->hash = port << 48; + this->hash |= static_cast(address1) << 16; + this->hash |= address2 >> 16 & 0xFFFC; + this->hash |= 0x0002; // AF_INET6. + + break; + } + } + + // Override least significant bit with protocol information: + // - If UDP, start with 0. + // - If TCP, start with 1. + if (this->protocol == Protocol::UDP) + { + this->hash |= 0x0000; + } + else + { + this->hash |= 0x0001; + } + } } // namespace RTC diff --git a/worker/src/RTC/UdpSocket.cpp b/worker/src/RTC/UdpSocket.cpp index c6d4ff5500..5069688baf 100644 --- a/worker/src/RTC/UdpSocket.cpp +++ b/worker/src/RTC/UdpSocket.cpp @@ -10,20 +10,30 @@ namespace RTC { /* Instance methods. */ - UdpSocket::UdpSocket(Listener* listener, std::string& ip, RTC::Transport::SocketFlags& flags) + UdpSocket::UdpSocket( + Listener* listener, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) : // This may throw. - ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip, flags)), listener(listener) + ::UdpSocketHandle::UdpSocketHandle(RTC::PortManager::BindUdp(ip, port, flags)), + listener(listener), fixedPort(true) { MS_TRACE(); } UdpSocket::UdpSocket( - Listener* listener, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) + Listener* listener, + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& portRangeHash) : // This may throw. - ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip, port, flags)), listener(listener), - fixedPort(true) + ::UdpSocketHandle::UdpSocketHandle( + RTC::PortManager::BindUdp(ip, minPort, maxPort, flags, portRangeHash)), + listener(listener), fixedPort(false) { MS_TRACE(); + + this->portRangeHash = portRangeHash; } UdpSocket::~UdpSocket() @@ -32,7 +42,7 @@ namespace RTC if (!this->fixedPort) { - PortManager::UnbindUdp(this->localIp, this->localPort); + RTC::PortManager::Unbind(this->portRangeHash, this->localPort); } } diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 362b43d455..1cd27188b5 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -4,6 +4,7 @@ #include "RTC/WebRtcServer.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Settings.hpp" #include "Utils.hpp" #include // std::pow() @@ -94,13 +95,36 @@ namespace RTC // This may throw. RTC::UdpSocket* udpSocket; - if (listenInfo->port() != 0) + if (listenInfo->portRange()->min() != 0 && listenInfo->portRange()->max() != 0) + { + uint64_t portRangeHash{ 0u }; + + udpSocket = new RTC::UdpSocket( + this, + ip, + listenInfo->portRange()->min(), + listenInfo->portRange()->max(), + flags, + portRangeHash); + } + else if (listenInfo->port() != 0) { udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port(), flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - udpSocket = new RTC::UdpSocket(this, ip, flags); + uint64_t portRangeHash{ 0u }; + + udpSocket = new RTC::UdpSocket( + this, + ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + flags, + portRangeHash); } this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, announcedAddress); @@ -126,13 +150,38 @@ namespace RTC // This may throw. RTC::TcpServer* tcpServer; - if (listenInfo->port() != 0) + if (listenInfo->portRange()->min() != 0 && listenInfo->portRange()->max() != 0) + { + uint64_t portRangeHash{ 0u }; + + tcpServer = new RTC::TcpServer( + this, + this, + ip, + listenInfo->portRange()->min(), + listenInfo->portRange()->max(), + flags, + portRangeHash); + } + else if (listenInfo->port() != 0) { tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port(), flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - tcpServer = new RTC::TcpServer(this, this, ip, flags); + uint64_t portRangeHash{ 0u }; + + tcpServer = new RTC::TcpServer( + this, + this, + ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + flags, + portRangeHash); } this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, announcedAddress); diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index a5deb26fe0..c5d0bc5673 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -4,6 +4,7 @@ #include "RTC/WebRtcTransport.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Settings.hpp" #include "Utils.hpp" #include "FBS/webRtcTransport.h" #include // std::pow() @@ -75,13 +76,36 @@ namespace RTC { RTC::UdpSocket* udpSocket; - if (listenInfo->port() != 0) + if (listenInfo->portRange()->min() != 0 && listenInfo->portRange()->max() != 0) + { + uint64_t portRangeHash{ 0u }; + + udpSocket = new RTC::UdpSocket( + this, + ip, + listenInfo->portRange()->min(), + listenInfo->portRange()->max(), + flags, + portRangeHash); + } + else if (listenInfo->port() != 0) { udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port(), flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - udpSocket = new RTC::UdpSocket(this, ip, flags); + uint64_t portRangeHash{ 0u }; + + udpSocket = new RTC::UdpSocket( + this, + ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + flags, + portRangeHash); } this->udpSockets[udpSocket] = announcedAddress; @@ -117,13 +141,38 @@ namespace RTC { RTC::TcpServer* tcpServer; - if (listenInfo->port() != 0) + if (listenInfo->portRange()->min() != 0 && listenInfo->portRange()->max() != 0) + { + uint64_t portRangeHash{ 0u }; + + tcpServer = new RTC::TcpServer( + this, + this, + ip, + listenInfo->portRange()->min(), + listenInfo->portRange()->max(), + flags, + portRangeHash); + } + else if (listenInfo->port() != 0) { tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port(), flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - tcpServer = new RTC::TcpServer(this, this, ip, flags); + uint64_t portRangeHash{ 0u }; + + tcpServer = new RTC::TcpServer( + this, + this, + ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + flags, + portRangeHash); } this->tcpServers[tcpServer] = announcedAddress; diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 2dd3cb2b6f..5a3e7f4670 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -139,6 +139,7 @@ flatbuffers::Offset Worker::FillBuffer( routerIds.push_back(builder.CreateString(routerId)); } + // Add channelMessageHandlers. auto channelMessageHandlers = this->shared->channelMessageRegistrator->FillBuffer(builder); return FBS::Worker::CreateDumpResponseDirect( From 1d71e4b69e35e3b4c059f0b8270ee0e0993f051b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Apr 2024 16:32:26 +0200 Subject: [PATCH 400/525] 3.14.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3462be0dc..5cec4f7c36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### NEXT +### 3.14.0 - `TransportListenInfo`: Add `portRange` (deprecate worker port range) ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). - Require Node.js >= 18 ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). diff --git a/package-lock.json b/package-lock.json index 4531ca93d3..c3799da215 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.24", + "version": "3.14.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.24", + "version": "3.14.0", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 87fa1f789d..aaf9dd46e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.24", + "version": "3.14.0", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 1a507ecc2da2ce6886a26ead0adf59243519f73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Apr 2024 16:51:38 +0200 Subject: [PATCH 401/525] Node: update tests to use portRange --- node/src/test/test-PipeTransport.ts | 22 ++++- node/src/test/test-PlainTransport.ts | 17 +++- node/src/test/test-WebRtcServer.ts | 71 ++++++++++++++- node/src/test/test-WebRtcTransport.ts | 126 +++++++++++++++++++++----- 4 files changed, 211 insertions(+), 25 deletions(-) diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 3b9052374d..bfa17f9c18 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -453,6 +453,16 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', // @ts-ignore await expect(ctx.router1!.createPipeTransport({})).rejects.toThrow(TypeError); + await expect( + ctx.router1!.createPipeTransport({ + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 4000, max: 3000 }, + }, + }) + ).rejects.toThrow(TypeError); + await expect( ctx.router1!.createPipeTransport({ listenIp: '123' }) ).rejects.toThrow(TypeError); @@ -479,7 +489,11 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', test('router.createPipeTransport() with enableRtx succeeds', async () => { const pipeTransport = await ctx.router1!.createPipeTransport({ - listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 2000, max: 3000 }, + }, enableRtx: true, }); @@ -583,7 +597,11 @@ test('pipeTransport.connect() with valid SRTP parameters succeeds', async () => test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', async () => { const pipeTransport = await ctx.router1!.createPipeTransport({ - listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 2000, max: 3000 }, + }, enableRtx: true, }); diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index 6588fe55cb..c0e1a0afc1 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -60,7 +60,11 @@ afterEach(async () => { test('router.createPlainTransport() succeeds', async () => { const plainTransport = await ctx.router!.createPlainTransport({ - listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 2000, max: 3000 }, + }, }); await expect(ctx.router!.dump()).resolves.toMatchObject({ @@ -77,6 +81,7 @@ test('router.createPlainTransport() succeeds', async () => { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, }, enableSctp: true, appData: { foo: 'bar' }, @@ -171,6 +176,16 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' // @ts-ignore await expect(ctx.router!.createPlainTransport({})).rejects.toThrow(TypeError); + await expect( + ctx.router!.createPlainTransport({ + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 4000, max: 3000 }, + }, + }) + ).rejects.toThrow(TypeError); + await expect( ctx.router!.createPlainTransport({ listenIp: '123' }) ).rejects.toThrow(TypeError); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index e5e2e2b703..4641f7415a 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -91,7 +91,76 @@ test('worker.createWebRtcServer() succeeds', async () => { expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); }, 2000); -test('worker.createWebRtcServer() without specifying port succeeds', async () => { +test('worker.createWebRtcServer() with portRange succeeds', async () => { + const onObserverNewWebRtcServer = jest.fn(); + + ctx.worker!.observer.once('newwebrtcserver', onObserverNewWebRtcServer); + + const port1 = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + const port2 = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + + const webRtcServer = await ctx.worker!.createWebRtcServer({ + listenInfos: [ + { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: port1, max: port1 }, + }, + { + protocol: 'tcp', + ip: '127.0.0.1', + announcedAddress: '1.2.3.4', + portRange: { min: port2, max: port2 }, + }, + ], + appData: { foo: 123 }, + }); + + expect(onObserverNewWebRtcServer).toHaveBeenCalledTimes(1); + expect(onObserverNewWebRtcServer).toHaveBeenCalledWith(webRtcServer); + expect(typeof webRtcServer.id).toBe('string'); + expect(webRtcServer.closed).toBe(false); + expect(webRtcServer.appData).toEqual({ foo: 123 }); + + await expect(ctx.worker!.dump()).resolves.toMatchObject({ + pid: ctx.worker!.pid, + webRtcServerIds: [webRtcServer.id], + routerIds: [], + channelMessageHandlers: { + channelRequestHandlers: [webRtcServer.id], + channelNotificationHandlers: [], + }, + }); + + await expect(webRtcServer.dump()).resolves.toMatchObject({ + id: webRtcServer.id, + udpSockets: [{ ip: '127.0.0.1', port: port1 }], + tcpServers: [{ ip: '127.0.0.1', port: port2 }], + webRtcTransportIds: [], + localIceUsernameFragments: [], + tupleHashes: [], + }); + + // Private API. + expect(ctx.worker!.webRtcServersForTesting.size).toBe(1); + + ctx.worker!.close(); + + expect(webRtcServer.closed).toBe(true); + + // Private API. + expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); +}, 2000); + +test('worker.createWebRtcServer() without specifying port/portRange succeeds', async () => { const onObserverNewWebRtcServer = jest.fn(); ctx.worker!.observer.once('newwebrtcserver', onObserverNewWebRtcServer); diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 109b15499b..c069b54c0c 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -70,12 +70,42 @@ test('router.createWebRtcTransport() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, - { protocol: 'tcp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, - { protocol: 'udp', ip: '0.0.0.0', announcedAddress: 'foo1.bar.org' }, - { protocol: 'tcp', ip: '0.0.0.0', announcedAddress: 'foo2.bar.org' }, - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: undefined }, - { protocol: 'tcp', ip: '127.0.0.1', announcedAddress: undefined }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'tcp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'udp', + ip: '0.0.0.0', + announcedAddress: 'foo1.bar.org', + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'tcp', + ip: '0.0.0.0', + announcedAddress: 'foo2.bar.org', + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: undefined, + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'tcp', + ip: '127.0.0.1', + announcedAddress: undefined, + portRange: { min: 2000, max: 3000 }, + }, ], enableTcp: true, preferUdp: true, @@ -254,6 +284,18 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError TypeError ); + await expect( + ctx.router!.createWebRtcTransport({ + listenInfos: [ + { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 4000, max: 3000 }, + }, + ], + }) + ).rejects.toThrow(TypeError); + await expect( // @ts-ignore ctx.router!.createWebRtcTransport({ listenIps: [123] }) @@ -290,7 +332,9 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError test('router.createWebRtcTransport() with non bindable IP rejects with Error', async () => { await expect( ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '8.8.8.8' }], + listenInfos: [ + { protocol: 'udp', ip: '8.8.8.8', portRange: { min: 2000, max: 3000 } }, + ], }) ).rejects.toThrow(Error); }, 2000); @@ -298,7 +342,12 @@ test('router.createWebRtcTransport() with non bindable IP rejects with Error', a test('webRtcTransport.getStats() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, ], }); @@ -334,7 +383,12 @@ test('webRtcTransport.getStats() succeeds', async () => { test('webRtcTransport.connect() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, ], }); @@ -368,7 +422,12 @@ test('webRtcTransport.connect() succeeds', async () => { test('webRtcTransport.connect() with wrong arguments rejects with TypeError', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, ], }); @@ -428,7 +487,12 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, ], }); @@ -444,7 +508,9 @@ test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => { test('webRtcTransport.setMaxOutgoingBitrate() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); await expect( @@ -459,7 +525,9 @@ test('webRtcTransport.setMaxOutgoingBitrate() succeeds', async () => { test('webRtcTransport.setMinOutgoingBitrate() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); await expect( @@ -474,7 +542,9 @@ test('webRtcTransport.setMinOutgoingBitrate() succeeds', async () => { test('webRtcTransport.setMaxOutgoingBitrate() fails if value is lower than current min limit', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); await expect( @@ -493,7 +563,9 @@ test('webRtcTransport.setMaxOutgoingBitrate() fails if value is lower than curre test('webRtcTransport.setMinOutgoingBitrate() fails if value is higher than current max limit', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); await expect( @@ -512,7 +584,9 @@ test('webRtcTransport.setMinOutgoingBitrate() fails if value is higher than curr test('webRtcTransport.restartIce() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); const previousIceUsernameFragment = @@ -535,7 +609,9 @@ test('webRtcTransport.restartIce() succeeds', async () => { test('transport.enableTraceEvent() succeed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); // @ts-ignore @@ -563,7 +639,9 @@ test('transport.enableTraceEvent() succeed', async () => { test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); // @ts-ignore @@ -584,7 +662,9 @@ test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', test('WebRtcTransport events succeed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); // Private API. @@ -715,7 +795,9 @@ test('WebRtcTransport events succeed', async () => { test('WebRtcTransport methods reject if closed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); const onObserverClose = jest.fn(); @@ -778,7 +860,9 @@ test('WebRtcTransport emits "routerclose" if Router is closed', async () => { test('WebRtcTransport emits "routerclose" if Worker is closed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); const onObserverClose = jest.fn(); From c0e3a62342bb718871ff5ab4efd699257e52f833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Apr 2024 15:16:35 +0200 Subject: [PATCH 402/525] Avoid abseil containers with SeqManager compare functions (#1369) --- .github/workflows/codeql.yaml | 1 + .github/workflows/mediasoup-node.yaml | 4 ++++ .github/workflows/mediasoup-rust.yaml | 6 +++++- .github/workflows/mediasoup-worker-fuzzer.yaml | 4 ++++ .github/workflows/mediasoup-worker-prebuild.yaml | 1 + .github/workflows/mediasoup-worker.yaml | 4 ++++ worker/include/RTC/NackGenerator.hpp | 8 +++----- worker/include/RTC/SenderBandwidthEstimator.hpp | 3 +-- worker/include/RTC/WebRtcServer.hpp | 2 ++ worker/src/RTC/AudioLevelObserver.cpp | 1 + worker/src/RTC/WebRtcServer.cpp | 11 ++++++++++- 11 files changed, 36 insertions(+), 9 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 16712fe8d3..331661b59c 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -42,6 +42,7 @@ jobs: env: MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: 'Release' steps: - name: Checkout repository diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index bf643d7caf..a8436e5e0f 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -29,12 +29,16 @@ jobs: node: 20 - os: windows-2022 node: 20 + build-type: + - Release + - Debug runs-on: ${{ matrix.ci.os }} env: MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: ${{ matrix.build-type }} steps: - name: Checkout diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index c2f449c010..a6605fa8d7 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -49,8 +49,12 @@ jobs: - name: cargo clippy run: cargo clippy --all-targets -- -D warnings + # NOTE: In Windows this will build and test libmediasoupworker in release + # mode twice since build.rs doesn't allow debug mode for Windows. - name: cargo test - run: cargo test --verbose + run: | + cargo test --verbose + cargo test --release --verbose - name: cargo doc run: cargo doc --locked --all --no-deps --lib diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index 6662e144ac..97b2b0cfb5 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -20,6 +20,9 @@ jobs: cc: clang cxx: clang++ arch: arm64 + build-type: + - Release + - Debug runs-on: ${{ matrix.build.os }} @@ -28,6 +31,7 @@ jobs: CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: ${{ matrix.build-type }} steps: - name: Checkout diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index e6616f033d..35cc8466cc 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -51,6 +51,7 @@ jobs: CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: 'Release' steps: - name: Checkout diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 6851658a8f..0b05cd9dc1 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -53,6 +53,9 @@ jobs: # A single Node.js version should be fine for C++. node: - 20 + build-type: + - Release + - Debug runs-on: ${{ matrix.build.os }} @@ -61,6 +64,7 @@ jobs: CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: ${{ matrix.build-type }} steps: - name: Checkout diff --git a/worker/include/RTC/NackGenerator.hpp b/worker/include/RTC/NackGenerator.hpp index 3195267729..f46ab43fe7 100644 --- a/worker/include/RTC/NackGenerator.hpp +++ b/worker/include/RTC/NackGenerator.hpp @@ -5,8 +5,6 @@ #include "RTC/RtpPacket.hpp" #include "RTC/SeqManager.hpp" #include "handles/TimerHandle.hpp" -#include -#include #include #include #include @@ -80,9 +78,9 @@ namespace RTC // Allocated by this. TimerHandle* timer{ nullptr }; // Others. - absl::btree_map::SeqLowerThan> nackList; - absl::btree_set::SeqLowerThan> keyFrameList; - absl::btree_set::SeqLowerThan> recoveredList; + std::map::SeqLowerThan> nackList; + std::set::SeqLowerThan> keyFrameList; + std::set::SeqLowerThan> recoveredList; bool started{ false }; uint16_t lastSeq{ 0u }; // Seq number of last valid packet. uint32_t rtt{ 0u }; // Round trip time (ms). diff --git a/worker/include/RTC/SenderBandwidthEstimator.hpp b/worker/include/RTC/SenderBandwidthEstimator.hpp index 208b188f93..7b715deee9 100644 --- a/worker/include/RTC/SenderBandwidthEstimator.hpp +++ b/worker/include/RTC/SenderBandwidthEstimator.hpp @@ -6,7 +6,6 @@ #include "RTC/RateCalculator.hpp" #include "RTC/SeqManager.hpp" #include "RTC/TrendCalculator.hpp" -#include #include namespace RTC @@ -103,7 +102,7 @@ namespace RTC uint32_t initialAvailableBitrate{ 0u }; uint32_t availableBitrate{ 0u }; uint64_t lastAvailableBitrateEventAtMs{ 0u }; - absl::btree_map::SeqLowerThan> sentInfos; + std::map::SeqLowerThan> sentInfos; float rtt{ 0 }; // Round trip time in ms. CummulativeResult cummulativeResult; CummulativeResult probationCummulativeResult; diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index 96bde6e277..11f3901dfb 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -106,6 +106,8 @@ namespace RTC absl::flat_hash_map mapLocalIceUsernameFragmentWebRtcTransport; // Map of WebRtcTransports indexed by TransportTuple.hash. absl::flat_hash_map mapTupleWebRtcTransport; + // Whether the destructor has been called. + bool closing{ false }; }; } // namespace RTC diff --git a/worker/src/RTC/AudioLevelObserver.cpp b/worker/src/RTC/AudioLevelObserver.cpp index 0b880d88af..ef40fa26e1 100644 --- a/worker/src/RTC/AudioLevelObserver.cpp +++ b/worker/src/RTC/AudioLevelObserver.cpp @@ -5,6 +5,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "RTC/RtpDictionaries.hpp" +#include #include // std::lround() namespace RTC diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 1cd27188b5..274391d922 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -232,6 +232,8 @@ namespace RTC { MS_TRACE(); + this->closing = true; + this->shared->channelMessageRegistrator->UnregisterHandler(this->id); for (auto& item : this->udpSocketOrTcpServers) @@ -497,7 +499,14 @@ namespace RTC this->webRtcTransports.find(webRtcTransport) != this->webRtcTransports.end(), "WebRtcTransport not handled"); - this->webRtcTransports.erase(webRtcTransport); + // NOTE: If WebRtcServer is closing then do not remove the transport from + // the set since it would modify the set while the WebRtcServer destructor + // is iterating it. + // See: https://github.com/versatica/mediasoup/pull/1369#issuecomment-2044672247 + if (!this->closing) + { + this->webRtcTransports.erase(webRtcTransport); + } } inline void WebRtcServer::OnWebRtcTransportLocalIceUsernameFragmentAdded( From 35057305b7574ad641572a64ca62080494d69e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Apr 2024 18:42:26 +0200 Subject: [PATCH 403/525] [Node] Bring transport rtpPacketLossReceived and rtpPacketLossSent stats back (#1371) --- CHANGELOG.md | 4 ++++ node/src/Transport.ts | 37 +++++++++++++++++++++++++++++++----- worker/src/RTC/Transport.cpp | 4 ++-- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cec4f7c36..3fcb84ad71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Node: Bring transport `rtpPacketLossReceived` and `rtpPacketLossSent` stats back ([PR #XXXX](https://github.com/versatica/mediasoup/pull/XXXX)). + ### 3.14.0 - `TransportListenInfo`: Add `portRange` (deprecate worker port range) ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 64299f9ca2..ca330b6c54 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -285,6 +285,10 @@ export type BaseTransportStats = { availableOutgoingBitrate?: number; availableIncomingBitrate?: number; maxIncomingBitrate?: number; + maxOutgoingBitrate?: number; + minOutgoingBitrate?: number; + rtpPacketLossReceived?: number; + rtpPacketLossSent?: number; }; type TransportData = @@ -1475,11 +1479,34 @@ export function parseBaseTransportStats( rtxSendBitrate: Number(binary.rtxSendBitrate()), probationBytesSent: Number(binary.probationBytesSent()), probationSendBitrate: Number(binary.probationSendBitrate()), - availableOutgoingBitrate: Number(binary.availableOutgoingBitrate()), - availableIncomingBitrate: Number(binary.availableIncomingBitrate()), - maxIncomingBitrate: binary.maxIncomingBitrate() - ? Number(binary.maxIncomingBitrate()) - : undefined, + availableOutgoingBitrate: + typeof binary.availableOutgoingBitrate() === 'number' + ? Number(binary.availableOutgoingBitrate()) + : undefined, + availableIncomingBitrate: + typeof binary.availableIncomingBitrate() === 'number' + ? Number(binary.availableIncomingBitrate()) + : undefined, + maxIncomingBitrate: + typeof binary.maxIncomingBitrate() === 'number' + ? Number(binary.maxIncomingBitrate()) + : undefined, + maxOutgoingBitrate: + typeof binary.maxOutgoingBitrate() === 'number' + ? Number(binary.maxOutgoingBitrate()) + : undefined, + minOutgoingBitrate: + typeof binary.minOutgoingBitrate() === 'number' + ? Number(binary.minOutgoingBitrate()) + : undefined, + rtpPacketLossReceived: + typeof binary.rtpPacketLossReceived() === 'number' + ? Number(binary.rtpPacketLossReceived()) + : undefined, + rtpPacketLossSent: + typeof binary.rtpPacketLossSent() === 'number' + ? Number(binary.rtpPacketLossSent()) + : undefined, }; } diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index ea5426970f..89f5800ea3 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -502,10 +502,10 @@ namespace RTC // minOutgoingBitrate. this->minOutgoingBitrate ? flatbuffers::Optional(this->minOutgoingBitrate) : flatbuffers::nullopt, - // packetLossReceived. + // rtpPacketLossReceived. this->tccServer ? flatbuffers::Optional(this->tccServer->GetPacketLoss()) : flatbuffers::nullopt, - // packetLossSent. + // rtpPacketLossSent. this->tccClient ? flatbuffers::Optional(this->tccClient->GetPacketLoss()) : flatbuffers::nullopt); } From 09c1ba5bdc47ce489ded3f7c5e7d3d76191f0a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Apr 2024 18:58:32 +0200 Subject: [PATCH 404/525] 3.14.1 --- CHANGELOG.md | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fcb84ad71..31badafe81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Changelog -### NEXT +### 3.14.1 -- Node: Bring transport `rtpPacketLossReceived` and `rtpPacketLossSent` stats back ([PR #XXXX](https://github.com/versatica/mediasoup/pull/XXXX)). +- Node: Bring transport `rtpPacketLossReceived` and `rtpPacketLossSent` stats back ([PR #1371](https://github.com/versatica/mediasoup/pull/1371)). ### 3.14.0 diff --git a/package-lock.json b/package-lock.json index c3799da215..59f4478ff1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.0", + "version": "3.14.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.0", + "version": "3.14.1", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index aaf9dd46e3..925f1ca850 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.0", + "version": "3.14.1", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 8be8493091a42d54ed6d6b4c0731795894984c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Apr 2024 10:18:27 +0200 Subject: [PATCH 405/525] CI: Remove machines with arch arm64 (#1373) --- .github/workflows/mediasoup-node.yaml | 6 ------ .github/workflows/mediasoup-rust.yaml | 4 ---- .github/workflows/mediasoup-worker-fuzzer.yaml | 4 ---- .github/workflows/mediasoup-worker-prebuild.yaml | 10 ---------- .github/workflows/mediasoup-worker.yaml | 16 ---------------- 5 files changed, 40 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index a8436e5e0f..b035e0c56f 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -17,12 +17,6 @@ jobs: node: 18 - os: ubuntu-22.04 node: 20 - - os: ubuntu-20.04 - node: 18 - arch: arm64 - - os: ubuntu-22.04 - node: 20 - arch: arm64 - os: macos-12 node: 18 - os: macos-14 diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index a6605fa8d7..9b76ffcb22 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -18,10 +18,6 @@ jobs: ci: - os: ubuntu-20.04 - os: ubuntu-22.04 - - os: ubuntu-20.04 - arch: arm64 - - os: ubuntu-22.04 - arch: arm64 - os: macos-12 - os: macos-14 - os: windows-2022 diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index 97b2b0cfb5..60798016db 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -16,10 +16,6 @@ jobs: - os: ubuntu-22.04 cc: clang cxx: clang++ - - os: ubuntu-22.04 - cc: clang - cxx: clang++ - arch: arm64 build-type: - Release - Debug diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 35cc8466cc..762361367b 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -22,16 +22,6 @@ jobs: - os: ubuntu-22.04 cc: gcc cxx: g++ - # Worker prebuild for Linux on arm64. - - os: ubuntu-20.04 - cc: gcc - cxx: g++ - arch: arm64 - # Worker prebuild for Linux on arm64. - - os: ubuntu-22.04 - cc: gcc - cxx: g++ - arch: arm64 - os: macos-12 cc: clang cxx: clang++ diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 0b05cd9dc1..584d4c47e4 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -25,22 +25,6 @@ jobs: - os: ubuntu-22.04 cc: clang cxx: clang++ - - os: ubuntu-20.04 - cc: gcc - cxx: g++ - arch: arm64 - - os: ubuntu-20.04 - cc: clang - cxx: clang++ - arch: arm64 - - os: ubuntu-22.04 - cc: gcc - cxx: g++ - arch: arm64 - - os: ubuntu-22.04 - cc: clang - cxx: clang++ - arch: arm64 - os: macos-12 cc: gcc cxx: g++ From e516ebc2de5aa4f7af4ae05702756f45484daf2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Apr 2024 12:46:46 +0200 Subject: [PATCH 406/525] Node: add enhancedOnce() typed function (#1375) ### Details - Same as [events.once(emmiter, eventName)](https://nodejs.org/api/events.html#eventsonceemitter-name-options) but with TypeScript typed events. - Rename `EnhancedEventEmitter.ts` file to `enhancedEvents.ts` for consistency with the Node `events` module. --- node/src/ActiveSpeakerObserver.ts | 2 +- node/src/AudioLevelObserver.ts | 2 +- node/src/Channel.ts | 2 +- node/src/Consumer.ts | 2 +- node/src/DataConsumer.ts | 2 +- node/src/DataProducer.ts | 2 +- node/src/Producer.ts | 2 +- node/src/Router.ts | 2 +- node/src/RtpObserver.ts | 2 +- node/src/Transport.ts | 2 +- node/src/WebRtcServer.ts | 2 +- node/src/Worker.ts | 2 +- ...ancedEventEmitter.ts => enhancedEvents.ts} | 23 +++++++++++++-- node/src/index.ts | 2 +- node/src/test/test-ActiveSpeakerObserver.ts | 28 +++++++++++-------- node/src/test/test-AudioLevelObserver.ts | 28 +++++++++++-------- node/src/test/test-Consumer.ts | 27 +++++++++--------- node/src/test/test-DataConsumer.ts | 26 +++++++++-------- node/src/test/test-DataProducer.ts | 16 ++++++----- node/src/test/test-DirectTransport.ts | 26 +++++++++-------- node/src/test/test-PipeTransport.ts | 27 +++++++----------- node/src/test/test-PlainTransport.ts | 26 +++++++++-------- node/src/test/test-Producer.ts | 14 +++++----- node/src/test/test-Router.ts | 13 ++++----- node/src/test/test-WebRtcServer.ts | 14 +++++----- node/src/test/test-WebRtcTransport.ts | 26 +++++++++-------- node/src/test/test-Worker.ts | 24 ++++++++-------- node/src/test/test-multiopus.ts | 6 ++-- node/src/test/test-node-sctp.ts | 8 +++--- 29 files changed, 199 insertions(+), 159 deletions(-) rename node/src/{EnhancedEventEmitter.ts => enhancedEvents.ts} (81%) diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index 4cdd1d675e..88229731dc 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { RtpObserver, RtpObserverEvents, diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index b6a725ae39..f24e5d6b16 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { RtpObserver, RtpObserverEvents, diff --git a/node/src/Channel.ts b/node/src/Channel.ts index d0b9664707..a2fa6b3a6c 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -3,7 +3,7 @@ import { Duplex } from 'node:stream'; import { info, warn } from 'node:console'; import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { InvalidStateError } from './errors'; import { Body as RequestBody, Method, Request } from './fbs/request'; import { Response } from './fbs/response'; diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 6b70025d18..8ada889603 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { ProducerStat } from './Producer'; diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 202b5d32f4..d0ff2ace7c 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 2763e4fbfa..af7ef5c716 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { diff --git a/node/src/Producer.ts b/node/src/Producer.ts index a36f7c5a75..afadbc8255 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { MediaKind, RtpParameters, parseRtpParameters } from './RtpParameters'; diff --git a/node/src/Router.ts b/node/src/Router.ts index e0d61f6f91..c604768053 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; import { InvalidStateError } from './errors'; import { Channel } from './Channel'; diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 705488f0d4..1756880755 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { RouterInternal } from './Router'; import { Producer } from './Producer'; diff --git a/node/src/Transport.ts b/node/src/Transport.ts index ca330b6c54..30812e6dfa 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -1,6 +1,6 @@ import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; import { Channel } from './Channel'; import { RouterInternal } from './Router'; diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index c13f83c35d..a820bfda3d 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportListenInfo } from './Transport'; import { WebRtcTransport } from './WebRtcTransport'; diff --git a/node/src/Worker.ts b/node/src/Worker.ts index cce310e810..b69d2c9c29 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -3,7 +3,7 @@ import * as path from 'node:path'; import { spawn, ChildProcess } from 'node:child_process'; import { version } from './'; import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; import { Channel } from './Channel'; import { Router, RouterOptions } from './Router'; diff --git a/node/src/EnhancedEventEmitter.ts b/node/src/enhancedEvents.ts similarity index 81% rename from node/src/EnhancedEventEmitter.ts rename to node/src/enhancedEvents.ts index f5d1f688a3..a5458d3a08 100644 --- a/node/src/EnhancedEventEmitter.ts +++ b/node/src/enhancedEvents.ts @@ -1,7 +1,7 @@ -import { EventEmitter } from 'node:events'; +import { EventEmitter, once } from 'node:events'; import { Logger } from './Logger'; -const logger = new Logger('EnhancedEventEmitter'); +const enhancedEventEmitterLogger = new Logger('EnhancedEventEmitter'); type Events = Record; @@ -24,7 +24,7 @@ export class EnhancedEventEmitter< try { return super.emit(eventName, ...args); } catch (error) { - logger.error( + enhancedEventEmitterLogger.error( 'safeEmit() | event listener threw an error [eventName:%s]:%o', eventName, error @@ -121,3 +121,20 @@ export class EnhancedEventEmitter< return super.rawListeners(eventName); } } + +/** + * TypeScript version of events.once(): + * https://nodejs.org/api/events.html#eventsonceemitter-name-options + * + * Usage example: + * ```ts + * await enhancedOnce(videoConsumer, 'producerpause'); + * ```` + */ +export async function enhancedOnce( + emmiter: EnhancedEventEmitter, + eventName: keyof E & string, + options?: any +): Promise { + return once(emmiter, eventName, options); +} diff --git a/node/src/index.ts b/node/src/index.ts index b2efb864b2..28c41f361d 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { workerBin, Worker, WorkerSettings } from './Worker'; import * as utils from './utils'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index b4f2689fd0..f957a727c2 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, ActiveSpeakerObserverEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -31,9 +33,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -105,10 +105,13 @@ test('activeSpeakerObserver.close() succeeds', async () => { test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () => { const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise(resolve => { - activeSpeakerObserver.on('routerclose', resolve); - ctx.router!.close(); - }); + const promise = enhancedOnce( + activeSpeakerObserver, + 'routerclose' + ); + + ctx.router!.close(); + await promise; expect(activeSpeakerObserver.closed).toBe(true); }, 2000); @@ -116,10 +119,13 @@ test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () = test('ActiveSpeakerObserver emits "routerclose" if Worker is closed', async () => { const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise(resolve => { - activeSpeakerObserver.on('routerclose', resolve); - ctx.worker!.close(); - }); + const promise = enhancedOnce( + activeSpeakerObserver, + 'routerclose' + ); + + ctx.worker!.close(); + await promise; expect(activeSpeakerObserver.closed).toBe(true); }, 2000); diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index 7d4fe82592..f6d6f61723 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, AudioLevelObserverEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -31,9 +33,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -114,10 +114,13 @@ test('audioLevelObserver.close() succeeds', async () => { test('AudioLevelObserver emits "routerclose" if Router is closed', async () => { const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise(resolve => { - audioLevelObserver.on('routerclose', resolve); - ctx.router!.close(); - }); + const promise = enhancedOnce( + audioLevelObserver, + 'routerclose' + ); + + ctx.router!.close(); + await promise; expect(audioLevelObserver.closed).toBe(true); }, 2000); @@ -125,10 +128,13 @@ test('AudioLevelObserver emits "routerclose" if Router is closed', async () => { test('AudioLevelObserver emits "routerclose" if Worker is closed', async () => { const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise(resolve => { - audioLevelObserver.on('routerclose', resolve); - ctx.worker!.close(); - }); + const promise = enhancedOnce( + audioLevelObserver, + 'routerclose' + ); + + ctx.worker!.close(); + await promise; expect(audioLevelObserver.closed).toBe(true); }, 2000); diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index 0d3a4a056e..436145fbc2 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -1,6 +1,7 @@ -import { once } from 'node:events'; import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, ConsumerEvents } from '../types'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; import { @@ -248,9 +249,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -1025,7 +1024,7 @@ test('Consumer emits "producerpause" and "producerresume"', async () => { }); await Promise.all([ - once(audioConsumer, 'producerpause'), + enhancedOnce(audioConsumer, 'producerpause'), // Let's await for pause() to resolve to avoid aborted channel requests // due to worker closure. @@ -1036,7 +1035,7 @@ test('Consumer emits "producerpause" and "producerresume"', async () => { expect(audioConsumer.producerPaused).toBe(true); await Promise.all([ - once(audioConsumer, 'producerresume'), + enhancedOnce(audioConsumer, 'producerresume'), // Let's await for resume() to resolve to avoid aborted channel requests // due to worker closure. @@ -1162,10 +1161,10 @@ test('Consumer emits "producerclose" if Producer is closed', async () => { audioConsumer.observer.once('close', onObserverClose); - await new Promise(resolve => { - audioConsumer.on('producerclose', resolve); - ctx.audioProducer!.close(); - }); + const promise = enhancedOnce(audioConsumer, 'producerclose'); + + ctx.audioProducer!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(audioConsumer.closed).toBe(true); @@ -1181,10 +1180,10 @@ test('Consumer emits "transportclose" if Transport is closed', async () => { videoConsumer.observer.once('close', onObserverClose); - await new Promise(resolve => { - videoConsumer.on('transportclose', resolve); - ctx.webRtcTransport2!.close(); - }); + const promise = enhancedOnce(videoConsumer, 'transportclose'); + + ctx.webRtcTransport2!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(videoConsumer.closed).toBe(true); diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index 163f4d4e19..e51a718095 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, DataConsumerEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -44,9 +46,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -374,11 +374,13 @@ test('DataConsumer emits "dataproducerclose" if DataProducer is closed', async ( dataConsumer.observer.once('close', onObserverClose); - await new Promise(resolve => { - dataConsumer.on('dataproducerclose', resolve); + const promise = enhancedOnce( + dataConsumer, + 'dataproducerclose' + ); - ctx.dataProducer!.close(); - }); + ctx.dataProducer!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataConsumer.closed).toBe(true); @@ -392,11 +394,13 @@ test('DataConsumer emits "transportclose" if Transport is closed', async () => { dataConsumer.observer.once('close', onObserverClose); - await new Promise(resolve => { - dataConsumer.on('transportclose', resolve); + const promise = enhancedOnce( + dataConsumer, + 'transportclose' + ); - ctx.webRtcTransport2!.close(); - }); + ctx.webRtcTransport2!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataConsumer.closed).toBe(true); diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index c5dddaacba..ad1457caea 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, DataProducerEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -48,9 +50,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -353,11 +353,13 @@ test('DataProducer emits "transportclose" if Transport is closed', async () => { dataProducer2.observer.once('close', onObserverClose); - await new Promise(resolve => { - dataProducer2.on('transportclose', resolve); + const promise = enhancedOnce( + dataProducer2, + 'transportclose' + ); - ctx.webRtcTransport2!.close(); - }); + ctx.webRtcTransport2!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataProducer2.closed).toBe(true); diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index ac2f6ff8e8..3b7689acc1 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, DirectTransportEvents } from '../types'; type TestContext = { worker?: mediasoup.types.Worker; @@ -16,9 +18,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -397,11 +397,13 @@ test('DirectTransport emits "routerclose" if Router is closed', async () => { directTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - directTransport.on('routerclose', resolve); + const promise = enhancedOnce( + directTransport, + 'routerclose' + ); - ctx.router!.close(); - }); + ctx.router!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(directTransport.closed).toBe(true); @@ -413,11 +415,13 @@ test('DirectTransport emits "routerclose" if Worker is closed', async () => { directTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - directTransport.on('routerclose', resolve); + const promise = enhancedOnce( + directTransport, + 'routerclose' + ); - ctx.worker!.close(); - }); + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(directTransport.closed).toBe(true); diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index bfa17f9c18..0ded5cab8a 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -1,5 +1,7 @@ import { pickPort } from 'pick-port'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, ConsumerEvents, DataConsumerEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -201,15 +203,11 @@ afterEach(async () => { ctx.worker2?.close(); if (ctx.worker1?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker1?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker1, 'subprocessclose'); } if (ctx.worker2?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker2?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker2, 'subprocessclose'); } }); @@ -827,8 +825,9 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', // NOTE: Let's use a Promise since otherwise there may be race conditions // between events and await lines below. - const promise1 = new Promise(resolve => - videoConsumer.once('producerresume', resolve) + const promise1 = enhancedOnce( + videoConsumer, + 'producerresume' ); await ctx.videoProducer!.resume(); @@ -837,9 +836,7 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', expect(videoConsumer.producerPaused).toBe(false); expect(videoConsumer.paused).toBe(false); - const promise2 = new Promise(resolve => - videoConsumer.once('producerpause', resolve) - ); + const promise2 = enhancedOnce(videoConsumer, 'producerpause'); await ctx.videoProducer!.pause(); await promise2; @@ -864,9 +861,7 @@ test('producer.close() is transmitted to pipe Consumer', async () => { expect(ctx.videoProducer!.closed).toBe(true); if (!videoConsumer.closed) { - await new Promise(resolve => - videoConsumer.once('producerclose', resolve) - ); + await enhancedOnce(videoConsumer, 'producerclose'); } expect(videoConsumer.closed).toBe(true); @@ -969,9 +964,7 @@ test('dataProducer.close() is transmitted to pipe DataConsumer', async () => { expect(ctx.dataProducer!.closed).toBe(true); if (!dataConsumer.closed) { - await new Promise(resolve => - dataConsumer.once('dataproducerclose', resolve) - ); + await enhancedOnce(dataConsumer, 'dataproducerclose'); } expect(dataConsumer.closed).toBe(true); diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index c0e1a0afc1..31508bbddf 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -1,6 +1,8 @@ import * as os from 'node:os'; import { pickPort } from 'pick-port'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, PlainTransportEvents } from '../types'; import * as utils from '../utils'; const IS_WINDOWS = os.platform() === 'win32'; @@ -52,9 +54,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -539,11 +539,13 @@ test('PlainTransport emits "routerclose" if Router is closed', async () => { plainTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - plainTransport.on('routerclose', resolve); + const promise = enhancedOnce( + plainTransport, + 'routerclose' + ); - ctx.router!.close(); - }); + ctx.router!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(plainTransport.closed).toBe(true); @@ -558,11 +560,13 @@ test('PlainTransport emits "routerclose" if Worker is closed', async () => { plainTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - plainTransport.on('routerclose', resolve); + const promise = enhancedOnce( + plainTransport, + 'routerclose' + ); - ctx.worker!.close(); - }); + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(plainTransport.closed).toBe(true); diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index d6fe900cf4..fbf2cef5c1 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -1,5 +1,7 @@ import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, ProducerEvents } from '../types'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; import { @@ -148,9 +150,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -823,10 +823,10 @@ test('Producer emits "transportclose" if Transport is closed', async () => { videoProducer.observer.once('close', onObserverClose); - await new Promise(resolve => { - videoProducer.on('transportclose', resolve); - ctx.webRtcTransport2!.close(); - }); + const promise = enhancedOnce(videoProducer, 'transportclose'); + + ctx.webRtcTransport2!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(videoProducer.closed).toBe(true); diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index d904883509..50602aec32 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, RouterEvents } from '../types'; import { InvalidStateError } from '../errors'; import * as utils from '../utils'; @@ -46,9 +48,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -148,11 +148,10 @@ test('Router emits "workerclose" if Worker is closed', async () => { router.observer.once('close', onObserverClose); - await new Promise(resolve => { - router.on('workerclose', resolve); + const promise = enhancedOnce(router, 'workerclose'); - ctx.worker!.close(); - }); + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(router.closed).toBe(true); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index 4641f7415a..8297941723 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -1,5 +1,7 @@ import { pickPort } from 'pick-port'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, WebRtcServerEvents } from '../types'; import { InvalidStateError } from '../errors'; type TestContext = { @@ -16,9 +18,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -359,10 +359,10 @@ test('WebRtcServer emits "workerclose" if Worker is closed', async () => { webRtcServer.observer.once('close', onObserverClose); - await new Promise(resolve => { - webRtcServer.on('workerclose', resolve); - ctx.worker!.close(); - }); + const promise = enhancedOnce(webRtcServer, 'workerclose'); + + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(webRtcServer.closed).toBe(true); diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index c069b54c0c..601073d209 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -1,6 +1,8 @@ import { pickPort } from 'pick-port'; import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, WebRtcTransportEvents } from '../types'; import * as utils from '../utils'; import { serializeProtocol, TransportTuple } from '../Transport'; import { @@ -57,9 +59,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -844,11 +844,13 @@ test('WebRtcTransport emits "routerclose" if Router is closed', async () => { webRtcTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - webRtcTransport.on('routerclose', resolve); + const promise = enhancedOnce( + webRtcTransport, + 'routerclose' + ); - ctx.router!.close(); - }); + ctx.router!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(webRtcTransport.closed).toBe(true); @@ -869,11 +871,13 @@ test('WebRtcTransport emits "routerclose" if Worker is closed', async () => { webRtcTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - webRtcTransport.on('routerclose', resolve); + const promise = enhancedOnce( + webRtcTransport, + 'routerclose' + ); - ctx.worker!.close(); - }); + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(webRtcTransport.closed).toBe(true); diff --git a/node/src/test/test-Worker.ts b/node/src/test/test-Worker.ts index a29fa5e457..6f1b28dedc 100644 --- a/node/src/test/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -2,6 +2,8 @@ import * as os from 'node:os'; import * as process from 'node:process'; import * as path from 'node:path'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents } from '../types'; import { InvalidStateError } from '../errors'; test('Worker.workerBin matches mediasoup-worker absolute path', () => { @@ -48,7 +50,7 @@ test('createWorker() succeeds', async () => { worker1.close(); - await new Promise(resolve => worker1.on('subprocessclose', resolve)); + await enhancedOnce(worker1, 'subprocessclose'); expect(worker1.closed).toBe(true); expect(worker1.died).toBe(false); @@ -72,7 +74,7 @@ test('createWorker() succeeds', async () => { worker2.close(); - await new Promise(resolve => worker2.on('subprocessclose', resolve)); + await enhancedOnce(worker2, 'subprocessclose'); expect(worker2.closed).toBe(true); expect(worker2.died).toBe(false); @@ -116,7 +118,7 @@ test('worker.updateSettings() succeeds', async () => { worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); }, 2000); test('worker.updateSettings() with wrong settings rejects with TypeError', async () => { @@ -129,7 +131,7 @@ test('worker.updateSettings() with wrong settings rejects with TypeError', async worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); }, 2000); test('worker.updateSettings() rejects with InvalidStateError if closed', async () => { @@ -137,7 +139,7 @@ test('worker.updateSettings() rejects with InvalidStateError if closed', async ( worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); await expect(worker.updateSettings({ logLevel: 'error' })).rejects.toThrow( InvalidStateError @@ -165,7 +167,7 @@ test('worker.dump() rejects with InvalidStateError if closed', async () => { worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); await expect(worker.dump()).rejects.toThrow(InvalidStateError); }, 2000); @@ -177,7 +179,7 @@ test('worker.getResourceUsage() succeeds', async () => { worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); }, 2000); test('worker.close() succeeds', async () => { @@ -187,7 +189,7 @@ test('worker.close() succeeds', async () => { worker.observer.once('close', onObserverClose); worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker.closed).toBe(true); @@ -224,7 +226,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { }); if (!worker1.subprocessClosed) { - await new Promise(resolve => worker1.on('subprocessclose', resolve)); + await enhancedOnce(worker1, 'subprocessclose'); } expect(onDied).toHaveBeenCalledTimes(1); @@ -258,7 +260,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { }); if (!worker2.subprocessClosed) { - await new Promise(resolve => worker2.on('subprocessclose', resolve)); + await enhancedOnce(worker2, 'subprocessclose'); } expect(onDied).toHaveBeenCalledTimes(1); @@ -292,7 +294,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { }); if (!worker3.subprocessClosed) { - await new Promise(resolve => worker3.on('subprocessclose', resolve)); + await enhancedOnce(worker3, 'subprocessclose'); } expect(onDied).toHaveBeenCalledTimes(1); diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index 2b419271bf..d6542fb391 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents } from '../types'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; @@ -109,9 +111,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index f5e402f082..46b2f93036 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -2,6 +2,8 @@ import * as dgram from 'node:dgram'; // @ts-ignore import * as sctp from 'sctp'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents } from '../types'; type TestContext = { worker?: mediasoup.types.Worker; @@ -66,7 +68,7 @@ beforeEach(async () => { // Wait for the SCTP association to be open. await Promise.race([ - new Promise(resolve => ctx.sctpSocket.on('connect', resolve)), + enhancedOnce(ctx.sctpSocket, 'connect'), new Promise((resolve, reject) => setTimeout(() => reject(new Error('SCTP connection timeout')), 3000) ), @@ -100,9 +102,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } // NOTE: For some reason we have to wait a bit for the SCTP stuff to release From b1b5ad4a17f24d7fe17aed45f493c3ce714f9dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 15 Apr 2024 10:59:48 +0200 Subject: [PATCH 407/525] Update Node deps --- npm-scripts.mjs | 2 +- package-lock.json | 1501 ++++++++++++++++++++++++++++++++------------- package.json | 10 +- 3 files changed, 1073 insertions(+), 440 deletions(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 7cdffa32e4..280f68c270 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -4,7 +4,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; import { execSync } from 'node:child_process'; import fetch from 'node-fetch'; -import tar from 'tar'; +import * as tar from 'tar'; import * as ini from 'ini'; const PKG = JSON.parse( diff --git a/package-lock.json b/package-lock.json index 59f4478ff1..723424671e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,15 +17,15 @@ "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.2.1" + "tar": "^7.0.1" }, "devDependencies": { "@octokit/rest": "^20.1.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.5", - "@typescript-eslint/eslint-plugin": "^7.5.0", - "@typescript-eslint/parser": "^7.5.0", + "@types/node": "^20.12.7", + "@typescript-eslint/eslint-plugin": "^7.6.0", + "@typescript-eslint/parser": "^7.6.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.2.0", @@ -37,7 +37,7 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.4" + "typescript": "^5.4.5" }, "engines": { "node": ">=18" @@ -738,9 +738,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -811,6 +811,114 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.0.tgz", + "integrity": "sha512-S00nN1Qt3z3dSP6Db45fj/mksrAq5XWNIJ/SWXGP8XPT2jrzEuYRCSEx08JpJwBcG2F1xgiOtBMGDU0AZHmxew==", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/fs-minipass/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1480,6 +1588,15 @@ "@octokit/openapi-types": "^21.0.0" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@pkgr/core": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", @@ -1620,9 +1737,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/ms": { @@ -1631,18 +1748,18 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.12.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz", - "integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/stack-utils": { @@ -1667,22 +1784,22 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", - "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz", + "integrity": "sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/type-utils": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/type-utils": "7.6.0", + "@typescript-eslint/utils": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1702,14 +1819,27 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -1718,16 +1848,34 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", - "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1745,11 +1893,15 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" + }, "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -1758,47 +1910,33 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, "engines": { "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", - "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "semver": "^7.5.4" + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1807,18 +1945,20 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^8.56.0" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1828,7 +1968,7 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -1837,10 +1977,10 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -1852,42 +1992,33 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/parser": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", - "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", - "debug": "^4.3.4" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz", + "integrity": "sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" + "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/utils": "7.6.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1895,12 +2026,20 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1910,20 +2049,20 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1938,14 +2077,14 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1955,7 +2094,7 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -1964,10 +2103,10 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -1979,23 +2118,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", @@ -2061,6 +2183,130 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@typescript-eslint/utils": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.6.0.tgz", + "integrity": "sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.15", + "@types/semver": "^7.5.8", + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/typescript-estree": "7.6.0", + "semver": "^7.6.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/visitor-keys": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", @@ -2152,7 +2398,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2161,7 +2406,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -2294,8 +2538,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/before-after-hook": { "version": "2.2.3", @@ -2476,11 +2719,11 @@ } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/ci-info": { @@ -2532,7 +2775,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -2543,8 +2785,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/concat-map": { "version": "0.0.1", @@ -2583,7 +2824,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2761,6 +3001,11 @@ "node": ">=6.0.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -2782,8 +3027,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/error-ex": { "version": "1.3.2", @@ -3284,37 +3528,41 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dependencies": { - "fetch-blob": "^3.1.2" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=12.20.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "engines": { - "node": ">= 8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "dependencies": { - "yallist": "^4.0.0" + "fetch-blob": "^3.1.2" }, "engines": { - "node": ">=8" + "node": ">=12.20.0" } }, "node_modules/fs.realpath": { @@ -3546,9 +3794,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -3674,7 +3922,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -3766,8 +4013,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -3865,6 +4111,23 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -4692,37 +4955,97 @@ } }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^7.0.4", + "rimraf": "^5.0.5" }, "engines": { - "node": ">= 8" + "node": ">= 18" + } + }, + "node_modules/minizlib/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/minizlib/node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minizlib/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib/node_modules/rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", "dependencies": { - "yallist": "^4.0.0" + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "bin": { - "mkdirp": "bin/cmd.js" + "mkdirp": "dist/cjs/src/bin.js" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/ms": { @@ -4976,7 +5299,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -4987,6 +5309,29 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -5434,9 +5779,9 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -5452,7 +5797,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -5464,7 +5808,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -5562,7 +5905,20 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5576,7 +5932,18 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -5677,19 +6044,27 @@ "dev": true }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.0.1.tgz", + "integrity": "sha512-IjMhdQMZFpKsHEQT3woZVxBtCQY+0wk3CVxdRkGXEgyGa0dNS/ehPvOMr2nmfC7x5Zj2N+l6yZUpmICjLGS35w==", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "engines": { + "node": ">=18" } }, "node_modules/temp-dir": { @@ -5808,9 +6183,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { "node": ">=16" @@ -5896,9 +6271,9 @@ } }, "node_modules/typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -6017,22 +6392,38 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi": { + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -6076,7 +6467,8 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/yargs": { "version": "17.7.2", @@ -6647,9 +7039,9 @@ } }, "@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true }, "@eslint/eslintrc": { @@ -6698,6 +7090,79 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@isaacs/fs-minipass": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.0.tgz", + "integrity": "sha512-S00nN1Qt3z3dSP6Db45fj/mksrAq5XWNIJ/SWXGP8XPT2jrzEuYRCSEx08JpJwBcG2F1xgiOtBMGDU0AZHmxew==", + "requires": { + "minipass": "^7.0.4" + }, + "dependencies": { + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -7231,6 +7696,12 @@ "@octokit/openapi-types": "^21.0.0" } }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, "@pkgr/core": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", @@ -7365,9 +7836,9 @@ } }, "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "@types/ms": { @@ -7376,18 +7847,18 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.12.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz", - "integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dev": true, "requires": { "undici-types": "~5.26.4" } }, "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "@types/stack-utils": { @@ -7412,91 +7883,105 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", - "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz", + "integrity": "sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==", "dev": true, "requires": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/type-utils": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/type-utils": "7.6.0", + "@typescript-eslint/utils": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" } }, - "@typescript-eslint/type-utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", - "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "dev": true + }, + "@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" } }, "@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", - "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "semver": "^7.5.4" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" } }, "brace-expansion": { @@ -7509,9 +7994,9 @@ } }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -7519,59 +8004,58 @@ } } }, - "@typescript-eslint/parser": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", - "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", + "@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", - "debug": "^4.3.4" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz", + "integrity": "sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/utils": "7.6.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" - } - }, "@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" } }, "brace-expansion": { @@ -7584,9 +8068,9 @@ } }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -7594,16 +8078,6 @@ } } }, - "@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - } - }, "@typescript-eslint/types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", @@ -7646,6 +8120,83 @@ } } }, + "@typescript-eslint/utils": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.6.0.tgz", + "integrity": "sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.15", + "@types/semver": "^7.5.8", + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/typescript-estree": "7.6.0", + "semver": "^7.6.0" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" + } + }, + "@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "@typescript-eslint/visitor-keys": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", @@ -7707,14 +8258,12 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -7814,8 +8363,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "before-after-hook": { "version": "2.2.3", @@ -7939,9 +8487,9 @@ "dev": true }, "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==" }, "ci-info": { "version": "3.6.1", @@ -7982,7 +8530,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -7990,8 +8537,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "concat-map": { "version": "0.0.1", @@ -8024,7 +8570,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -8138,6 +8683,11 @@ "esutils": "^2.0.2" } }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -8153,8 +8703,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "error-ex": { "version": "1.3.2", @@ -8501,6 +9050,22 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + } + } + }, "formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -8509,24 +9074,6 @@ "fetch-blob": "^3.1.2" } }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -8677,9 +9224,9 @@ "dev": true }, "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true }, "import-fresh": { @@ -8765,8 +9312,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-generator-fn": { "version": "2.1.0", @@ -8822,8 +9368,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -8901,6 +9446,15 @@ "istanbul-lib-report": "^3.0.0" } }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -9530,28 +10084,61 @@ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" }, "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^7.0.4", + "rimraf": "^5.0.5" }, "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + } + }, + "minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" + }, + "rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", "requires": { - "yallist": "^4.0.0" + "glob": "^10.3.7" } } } }, "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==" }, "ms": { "version": "2.1.2", @@ -9723,8 +10310,7 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", @@ -9732,6 +10318,22 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-scurry": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==" + } + } + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -10013,9 +10615,9 @@ } }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -10025,7 +10627,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -10033,8 +10634,7 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "signal-exit": { "version": "3.0.7", @@ -10116,7 +10716,16 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10127,7 +10736,14 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { "ansi-regex": "^5.0.1" } @@ -10190,16 +10806,23 @@ } }, "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.0.1.tgz", + "integrity": "sha512-IjMhdQMZFpKsHEQT3woZVxBtCQY+0wk3CVxdRkGXEgyGa0dNS/ehPvOMr2nmfC7x5Zj2N+l6yZUpmICjLGS35w==", "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "dependencies": { + "yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==" + } } }, "temp-dir": { @@ -10283,9 +10906,9 @@ } }, "ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "requires": {} }, @@ -10327,9 +10950,9 @@ "dev": true }, "typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true }, "undici-types": { @@ -10415,7 +11038,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -10431,6 +11053,16 @@ "strip-ansi": "^6.0.0" } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -10456,7 +11088,8 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "yargs": { "version": "17.7.2", diff --git a/package.json b/package.json index 925f1ca850..395182b1ed 100644 --- a/package.json +++ b/package.json @@ -106,15 +106,15 @@ "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.2.1" + "tar": "^7.0.1" }, "devDependencies": { "@octokit/rest": "^20.1.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.5", - "@typescript-eslint/eslint-plugin": "^7.5.0", - "@typescript-eslint/parser": "^7.5.0", + "@types/node": "^20.12.7", + "@typescript-eslint/eslint-plugin": "^7.6.0", + "@typescript-eslint/parser": "^7.6.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.2.0", @@ -126,6 +126,6 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.4" + "typescript": "^5.4.5" } } From 80960abfb7f9915a79dd6c9562aa0e5f3e179894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 15 Apr 2024 14:46:32 +0200 Subject: [PATCH 408/525] Update worker subprojects (#1376) ### Details - Update `openssl` from 3.0.8-2 to 3.0.8-3 - Update `abseil-cpp` from 20230802.0-3 to 20230802.1-2 - Update `Catch2` from 3.4.0-1 to 3.5.3-1 - Update `usrsctp` from commit ebb18adac6501bad4501b1f6dccb67a1c85cc299 to latest commit d45b53f5dfa79533f5c5e7aefa5d7570405afb39, diff: https://github.com/sctplab/usrsctp/compare/ebb18adac6501bad4501b1f6dccb67a1c85cc299...master --- worker/subprojects/abseil-cpp.wrap | 24 +++++++++++++++--------- worker/subprojects/catch2.wrap | 12 ++++++------ worker/subprojects/openssl.wrap | 10 +++++----- worker/subprojects/usrsctp.wrap | 8 ++++---- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/worker/subprojects/abseil-cpp.wrap b/worker/subprojects/abseil-cpp.wrap index 61e2e4a4f6..4e62885650 100644 --- a/worker/subprojects/abseil-cpp.wrap +++ b/worker/subprojects/abseil-cpp.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = abseil-cpp-20230802.0 -source_url = https://github.com/abseil/abseil-cpp/archive/20230802.0.tar.gz -source_filename = abseil-cpp-20230802.0.tar.gz -source_hash = 59d2976af9d6ecf001a81a35749a6e551a335b949d34918cfade07737b9d93c5 -patch_filename = abseil-cpp_20230802.0-3_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20230802.0-3/get_patch -patch_hash = 1bcd502774c0cd7ad2f3b310bb6bffaa440a290e7300d7df79557b6be20b5daf -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20230802.0-3/abseil-cpp-20230802.0.tar.gz -wrapdb_version = 20230802.0-3 +directory = abseil-cpp-20230802.1 +source_url = https://github.com/abseil/abseil-cpp/archive/20230802.1.tar.gz +source_filename = abseil-cpp-20230802.1.tar.gz +source_hash = 987ce98f02eefbaf930d6e38ab16aa05737234d7afbab2d5c4ea7adbe50c28ed +patch_filename = abseil-cpp_20230802.1-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20230802.1-2/get_patch +patch_hash = f6ceb55ca4b0995d826cbdefc0a37e0f8b6202d3e7ecb3436298f54d3a23942b +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20230802.1-2/abseil-cpp-20230802.1.tar.gz +wrapdb_version = 20230802.1-2 [provide] absl_base = absl_base_dep @@ -41,8 +41,10 @@ absl_cordz_handle = absl_strings_dep absl_cordz_info = absl_strings_dep absl_cordz_sample_token = absl_strings_dep absl_core_headers = absl_base_dep +absl_crc32c = absl_crc_dep absl_debugging_internal = absl_debugging_dep absl_demangle_internal = absl_debugging_dep +absl_die_if_null = absl_log_dep absl_examine_stack = absl_debugging_dep absl_exponential_biased = absl_profiling_dep absl_failure_signal_handler = absl_debugging_dep @@ -65,6 +67,9 @@ absl_hashtablez_sampler = absl_container_dep absl_inlined_vector = absl_container_dep absl_int128 = absl_numeric_dep absl_leak_check = absl_debugging_dep +absl_log_initialize = absl_log_dep +absl_log_internal_check_op = absl_log_dep +absl_log_internal_message = absl_log_dep absl_log_severity = absl_base_dep absl_low_level_hash = absl_hash_dep absl_memory = absl_base_dep @@ -93,6 +98,7 @@ absl_statusor = absl_status_dep absl_str_format = absl_strings_dep absl_str_format_internal = absl_strings_dep absl_strerror = absl_base_dep +absl_string_view = absl_strings_dep absl_strings_internal = absl_strings_dep absl_symbolize = absl_debugging_dep absl_throw_delegate = absl_base_dep diff --git a/worker/subprojects/catch2.wrap b/worker/subprojects/catch2.wrap index 691d39c858..9566401a2d 100644 --- a/worker/subprojects/catch2.wrap +++ b/worker/subprojects/catch2.wrap @@ -1,10 +1,10 @@ [wrap-file] -directory = Catch2-3.4.0 -source_url = https://github.com/catchorg/Catch2/archive/v3.4.0.tar.gz -source_filename = Catch2-3.4.0.tar.gz -source_hash = 122928b814b75717316c71af69bd2b43387643ba076a6ec16e7882bfb2dfacbb -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.4.0-1/Catch2-3.4.0.tar.gz -wrapdb_version = 3.4.0-1 +directory = Catch2-3.5.3 +source_url = https://github.com/catchorg/Catch2/archive/v3.5.3.tar.gz +source_filename = Catch2-3.5.3.tar.gz +source_hash = 8d723b0535c94860ef8cf6231580fa47d67a3416757ecb10639e40d748ab6c71 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.5.3-1/Catch2-3.5.3.tar.gz +wrapdb_version = 3.5.3-1 [provide] catch2 = catch2_dep diff --git a/worker/subprojects/openssl.wrap b/worker/subprojects/openssl.wrap index b69462f53e..873d55106e 100644 --- a/worker/subprojects/openssl.wrap +++ b/worker/subprojects/openssl.wrap @@ -3,11 +3,11 @@ directory = openssl-3.0.8 source_url = https://www.openssl.org/source/openssl-3.0.8.tar.gz source_filename = openssl-3.0.8.tar.gz source_hash = 6c13d2bf38fdf31eac3ce2a347073673f5d63263398f1f69d0df4a41253e4b3e -patch_filename = openssl_3.0.8-2_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.8-2/get_patch -patch_hash = e84b5fe469e681e3318184157a0c7c43d4cbacd078bb88f506e31569f8f75072 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openssl_3.0.8-2/openssl-3.0.8.tar.gz -wrapdb_version = 3.0.8-2 +patch_filename = openssl_3.0.8-3_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.8-3/get_patch +patch_hash = 300da189e106942347d61a4a4295aa2edbcf06184f8d13b4cee0bed9fb936963 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openssl_3.0.8-3/openssl-3.0.8.tar.gz +wrapdb_version = 3.0.8-3 [provide] libcrypto = libcrypto_dep diff --git a/worker/subprojects/usrsctp.wrap b/worker/subprojects/usrsctp.wrap index 3cd7061b98..469f66291b 100644 --- a/worker/subprojects/usrsctp.wrap +++ b/worker/subprojects/usrsctp.wrap @@ -1,8 +1,8 @@ [wrap-file] -directory = usrsctp-ebb18adac6501bad4501b1f6dccb67a1c85cc299 -source_url = https://github.com/sctplab/usrsctp/archive/ebb18adac6501bad4501b1f6dccb67a1c85cc299.zip -source_filename = ebb18adac6501bad4501b1f6dccb67a1c85cc299.zip -source_hash = e77a855ce395b877e9f2aa7ebe070dfaf5cb11cfecdeb424cc876fc0d98e5d11 +directory = usrsctp-d45b53f5dfa79533f5c5e7aefa5d7570405afb39 +source_url = https://github.com/sctplab/usrsctp/archive/d45b53f5dfa79533f5c5e7aefa5d7570405afb39.zip +source_filename = d45b53f5dfa79533f5c5e7aefa5d7570405afb39.zip +source_hash = da5f9adafc48fb5451f8355fee06508db52a3fca11138852c73ecb844f3b8647 [provide] usrsctp = usrsctp_dep From d534be0cf3a90a7199435deb601dba73401bd767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 15 Apr 2024 14:47:32 +0200 Subject: [PATCH 409/525] Update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31badafe81..d1a851dc1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Update worker subprojects ([PR #1376](https://github.com/versatica/mediasoup/pull/1376)). + ### 3.14.1 - Node: Bring transport `rtpPacketLossReceived` and `rtpPacketLossSent` stats back ([PR #1371](https://github.com/versatica/mediasoup/pull/1371)). From d6373d540751c06b7fb96f0e7e26ad56f50f25bd Mon Sep 17 00:00:00 2001 From: satoren Date: Tue, 16 Apr 2024 21:12:26 +0900 Subject: [PATCH 410/525] Rust: fix panic with normal errors (#1377) --- rust/src/router/consumer.rs | 4 ++-- rust/src/router/producer.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/src/router/consumer.rs b/rust/src/router/consumer.rs index 3914d40b2d..8d58811aea 100644 --- a/rust/src/router/consumer.rs +++ b/rust/src/router/consumer.rs @@ -1020,9 +1020,9 @@ impl Consumer { .inner .channel .request(self.id(), ConsumerGetStatsRequest {}) - .await; + .await?; - if let Ok(response::Body::ConsumerGetStatsResponse(data)) = response { + if let response::Body::ConsumerGetStatsResponse(data) = response { match data.stats.len() { 0 => panic!("Empty stats response from worker"), 1 => { diff --git a/rust/src/router/producer.rs b/rust/src/router/producer.rs index 8b1a952e37..ec60283239 100644 --- a/rust/src/router/producer.rs +++ b/rust/src/router/producer.rs @@ -899,9 +899,9 @@ impl Producer { .inner() .channel .request(self.id(), ProducerGetStatsRequest {}) - .await; + .await?; - if let Ok(response::Body::ProducerGetStatsResponse(data)) = response { + if let response::Body::ProducerGetStatsResponse(data) = response { Ok(data.stats.iter().map(ProducerStat::from_fbs).collect()) } else { panic!("Wrong message from worker"); From 2854761ff1dc984d1d3f31cbf216319c085b2e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 22 Apr 2024 12:25:32 +0200 Subject: [PATCH 411/525] CHANGELOG: Add a note about the behavior change due to flags.ipv6Only --- CHANGELOG.md | 1 + node/src/Transport.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1a851dc1f..3b67364665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ - Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). - `TransportListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). + - Note that `flags.ipv6Only` is `false` by default. - `TransportListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). - Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). - Add RTCP Sender Report trace event ([PR #1267](https://github.com/versatica/mediasoup/pull/1267) by @GithubUser8080). diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 30812e6dfa..f748b9e9c1 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -152,11 +152,11 @@ export type TransportPortRange = { */ export type TransportSocketFlags = { /** - * Disable dual-stack support so only IPv6 is used (only if ip is IPv6). + * Disable dual-stack support so only IPv6 is used (only if |ip| is IPv6). */ ipv6Only?: boolean; /** - * Make different transports bind to the same ip and port (only for UDP). + * Make different transports bind to the same IP and port (only for UDP). * Useful for multicast scenarios with plain transport. Use with caution. */ udpReusePort?: boolean; From 3c012fe643474587fce03edae69a52ab0d0bfa32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 22 Apr 2024 20:31:22 +0200 Subject: [PATCH 412/525] fix typo in fuzzer script --- worker/scripts/run-fuzzer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/scripts/run-fuzzer.sh b/worker/scripts/run-fuzzer.sh index bc9c5321b6..ffe0d8ac87 100755 --- a/worker/scripts/run-fuzzer.sh +++ b/worker/scripts/run-fuzzer.sh @@ -10,7 +10,7 @@ if [ "${current_dir_name}" != "worker" ] ; then fi if [ "$#" -eq 0 ] ; then - echo "run-fuzzer.sh [ERROR] duration (in seconds) must be fiven as argument" >&2 + echo "run-fuzzer.sh [ERROR] duration (in seconds) must be given as argument" >&2 exit 1 fi From 3d5fd7614607ce6e6314992535e04230983f2a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 22 Apr 2024 20:42:34 +0200 Subject: [PATCH 413/525] RtpPacket: Make (almost) all methods remove payload padding if present (#1380) --- worker/src/RTC/RtpPacket.cpp | 52 ++++++++++++++++++++------- worker/test/src/RTC/TestRtpPacket.cpp | 32 ++++++++++++----- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index c38f1eefd4..8bf92ed232 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -96,6 +96,7 @@ namespace RTC } payloadPadding = data[len - 1]; + if (payloadPadding == 0) { MS_WARN_TAG(rtp, "padding byte cannot be 0, packet discarded"); @@ -112,6 +113,7 @@ namespace RTC return nullptr; } + payloadLength -= size_t{ payloadPadding }; } @@ -650,20 +652,25 @@ namespace RTC } } + /** + * NOTE: This method automatically removes payload padding if present. + */ void RtpPacket::SetPayloadLength(size_t length) { MS_TRACE(); - // Pad desired length to 4 bytes. - length = static_cast(Utils::Byte::PadTo4Bytes(static_cast(length))); - this->size -= this->payloadLength; - this->size -= size_t{ this->payloadPadding }; - this->payloadLength = length; - this->payloadPadding = 0u; - this->size += length; + this->payloadLength = length; + this->size += this->payloadLength; + + // Remove padding if present. + if (this->payloadPadding != 0u) + { + SetPayloadPaddingFlag(false); - SetPayloadPaddingFlag(false); + this->size -= size_t{ this->payloadPadding }; + this->payloadPadding = 0u; + } } RtpPacket* RtpPacket::Clone() const @@ -749,8 +756,12 @@ namespace RTC return packet; } - // NOTE: The caller must ensure that the buffer/memmory of the packet has - // space enough for adding 2 extra bytes. + /** + * NOTE: The caller must ensure that the buffer/memmory of the packet has + * space enough for adding 2 extra bytes. + * + * NOTE: This method automatically removes payload padding if present. + */ void RtpPacket::RtxEncode(uint8_t payloadType, uint32_t ssrc, uint16_t seq) { MS_TRACE(); @@ -784,6 +795,9 @@ namespace RTC } } + /** + * NOTE: This method automatically removes payload padding if present. + */ bool RtpPacket::RtxDecode(uint8_t payloadType, uint32_t ssrc) { MS_TRACE(); @@ -849,6 +863,11 @@ namespace RTC this->payloadDescriptorHandler->Restore(this->payload); } + /** + * Shifts the payload given offset (to right or to left). + * + * NOTE: This method automatically removes payload padding if present. + */ void RtpPacket::ShiftPayload(size_t payloadOffset, size_t shift, bool expand) { MS_TRACE(); @@ -870,7 +889,7 @@ namespace RTC if (expand) { - shiftedLen = this->payloadLength + size_t{ this->payloadPadding } - payloadOffset; + shiftedLen = this->payloadLength - payloadOffset; std::memmove(payloadOffsetPtr + shift, payloadOffsetPtr, shiftedLen); @@ -879,13 +898,22 @@ namespace RTC } else { - shiftedLen = this->payloadLength + size_t{ this->payloadPadding } - payloadOffset - shift; + shiftedLen = this->payloadLength - payloadOffset - shift; std::memmove(payloadOffsetPtr, payloadOffsetPtr + shift, shiftedLen); this->payloadLength -= shift; this->size -= shift; } + + // Remove padding if present. + if (this->payloadPadding != 0u) + { + SetPayloadPaddingFlag(false); + + this->size -= size_t{ this->payloadPadding }; + this->payloadPadding = 0u; + } } void RtpPacket::ParseExtensions() diff --git a/worker/test/src/RTC/TestRtpPacket.cpp b/worker/test/src/RTC/TestRtpPacket.cpp index ade9004564..699cd14bbd 100644 --- a/worker/test/src/RTC/TestRtpPacket.cpp +++ b/worker/test/src/RTC/TestRtpPacket.cpp @@ -435,6 +435,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 8); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetSize() == 40); auto* payload = packet->GetPayload(); @@ -448,11 +449,12 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(payload[6] == 0x06); REQUIRE(payload[7] == 0x07); + // NOTE: This will remove padding. packet->ShiftPayload(0, 2, true); REQUIRE(packet->GetPayloadLength() == 10); - REQUIRE(packet->GetPayloadPadding() == 4); - REQUIRE(packet->GetSize() == 42); + REQUIRE(packet->GetPayloadPadding() == 0); + REQUIRE(packet->GetSize() == 38); REQUIRE(payload[2] == 0x00); REQUIRE(payload[3] == 0x01); REQUIRE(payload[4] == 0x02); @@ -465,8 +467,8 @@ SCENARIO("parse RTP packets", "[parser][rtp]") packet->ShiftPayload(0, 2, false); REQUIRE(packet->GetPayloadLength() == 8); - REQUIRE(packet->GetPayloadPadding() == 4); - REQUIRE(packet->GetSize() == 40); + REQUIRE(packet->GetPayloadPadding() == 0); + REQUIRE(packet->GetSize() == 36); REQUIRE(payload[0] == 0x00); REQUIRE(payload[1] == 0x01); REQUIRE(payload[2] == 0x02); @@ -476,18 +478,18 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(payload[6] == 0x06); REQUIRE(payload[7] == 0x07); - // NOTE: This will require padding to 4 bytes. + // NOTE: This will remove padding. packet->SetPayloadLength(14); - REQUIRE(packet->GetPayloadLength() == 16); + REQUIRE(packet->GetPayloadLength() == 14); REQUIRE(packet->GetPayloadPadding() == 0); - REQUIRE(packet->GetSize() == 44); + REQUIRE(packet->GetSize() == 42); packet->ShiftPayload(4, 4, true); - REQUIRE(packet->GetPayloadLength() == 20); + REQUIRE(packet->GetPayloadLength() == 18); REQUIRE(packet->GetPayloadPadding() == 0); - REQUIRE(packet->GetSize() == 48); + REQUIRE(packet->GetSize() == 46); REQUIRE(payload[0] == 0x00); REQUIRE(payload[1] == 0x01); REQUIRE(payload[2] == 0x02); @@ -545,6 +547,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); @@ -560,6 +563,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); @@ -612,6 +616,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); REQUIRE(packet->GetExtension(0, extenLen) == nullptr); @@ -647,6 +652,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); REQUIRE(packet->GetExtension(1, extenLen) == nullptr); @@ -689,6 +695,10 @@ SCENARIO("parse RTP packets", "[parser][rtp]") 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; // clang-format on @@ -710,6 +720,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); @@ -725,6 +736,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == true); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); @@ -763,6 +775,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == true); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); REQUIRE(packet->GetExtension(0, extenLen) == nullptr); @@ -806,6 +819,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == true); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); REQUIRE(packet->GetExtension(1, extenLen) == nullptr); From f0a0a5b3b7379290261d433f6e3a6ee7cbd87648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 22 Apr 2024 20:48:46 +0200 Subject: [PATCH 414/525] update NPM deps --- package-lock.json | 350 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 178 insertions(+), 178 deletions(-) diff --git a/package-lock.json b/package-lock.json index 723424671e..f914ae513b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,14 +24,14 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.7", - "@typescript-eslint/eslint-plugin": "^7.6.0", - "@typescript-eslint/parser": "^7.6.0", + "@typescript-eslint/eslint-plugin": "^7.7.1", + "@typescript-eslint/parser": "^7.7.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.2.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^12.0.1", + "marked": "^12.0.2", "open-cli": "^8.0.0", "pick-port": "^2.0.1", "prettier": "^3.2.5", @@ -1784,16 +1784,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz", - "integrity": "sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz", + "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/type-utils": "7.6.0", - "@typescript-eslint/utils": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/type-utils": "7.7.1", + "@typescript-eslint/utils": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.3.1", @@ -1819,13 +1819,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1836,9 +1836,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1849,12 +1849,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -1866,15 +1866,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", - "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz", + "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/typescript-estree": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4" }, "engines": { @@ -1894,13 +1894,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1911,9 +1911,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1924,13 +1924,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1952,12 +1952,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2010,13 +2010,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz", - "integrity": "sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz", + "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.6.0", - "@typescript-eslint/utils": "7.6.0", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/utils": "7.7.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2037,9 +2037,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2050,13 +2050,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2078,12 +2078,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2184,17 +2184,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.6.0.tgz", - "integrity": "sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz", + "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.15", "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", "semver": "^7.6.0" }, "engines": { @@ -2209,13 +2209,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2226,9 +2226,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2239,13 +2239,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2267,12 +2267,12 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -4874,9 +4874,9 @@ } }, "node_modules/marked": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.1.tgz", - "integrity": "sha512-Y1/V2yafOcOdWQCX0XpAKXzDakPOpn6U0YLxTJs3cww6VxOzZV1BTOOYWLvH3gX38cq+iLwljHHTnMtlDfg01Q==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -7883,16 +7883,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz", - "integrity": "sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz", + "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/type-utils": "7.6.0", - "@typescript-eslint/utils": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/type-utils": "7.7.1", + "@typescript-eslint/utils": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.3.1", @@ -7902,70 +7902,70 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" } }, "@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true }, "@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" } } } }, "@typescript-eslint/parser": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", - "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz", + "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/typescript-estree": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" } }, "@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7975,12 +7975,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" } }, @@ -8015,31 +8015,31 @@ } }, "@typescript-eslint/type-utils": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz", - "integrity": "sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz", + "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.6.0", - "@typescript-eslint/utils": "7.6.0", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/utils": "7.7.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "dependencies": { "@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8049,12 +8049,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" } }, @@ -8121,44 +8121,44 @@ } }, "@typescript-eslint/utils": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.6.0.tgz", - "integrity": "sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz", + "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.15", "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", "semver": "^7.6.0" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" } }, "@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8168,12 +8168,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" } }, @@ -10030,9 +10030,9 @@ } }, "marked": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.1.tgz", - "integrity": "sha512-Y1/V2yafOcOdWQCX0XpAKXzDakPOpn6U0YLxTJs3cww6VxOzZV1BTOOYWLvH3gX38cq+iLwljHHTnMtlDfg01Q==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", "dev": true }, "meow": { diff --git a/package.json b/package.json index 395182b1ed..b33e8412c7 100644 --- a/package.json +++ b/package.json @@ -113,14 +113,14 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.7", - "@typescript-eslint/eslint-plugin": "^7.6.0", - "@typescript-eslint/parser": "^7.6.0", + "@typescript-eslint/eslint-plugin": "^7.7.1", + "@typescript-eslint/parser": "^7.7.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.2.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^12.0.1", + "marked": "^12.0.2", "open-cli": "^8.0.0", "pick-port": "^2.0.1", "prettier": "^3.2.5", From d4204c6e80132789b8b1b4828bd8679688dd6653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 23 Apr 2024 18:35:03 +0200 Subject: [PATCH 415/525] OPUS: Fix DTX detection (#1357) --- CHANGELOG.md | 1 + worker/include/RTC/Codecs/Opus.hpp | 3 ++ worker/src/RTC/Codecs/H264.cpp | 2 + worker/src/RTC/Codecs/H264_SVC.cpp | 17 +++++-- worker/src/RTC/Codecs/Opus.cpp | 73 ++++++++++++++++++++++++++++-- worker/src/RTC/Codecs/VP8.cpp | 14 ++++++ worker/src/RTC/Codecs/VP9.cpp | 10 ++++ 7 files changed, 113 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b67364665..022325c673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT - Update worker subprojects ([PR #1376](https://github.com/versatica/mediasoup/pull/1376)). +- OPUS: Fix DTX detection #1357 ([PR #1357](https://github.com/versatica/mediasoup/pull/1357)). ### 3.14.1 diff --git a/worker/include/RTC/Codecs/Opus.hpp b/worker/include/RTC/Codecs/Opus.hpp index a703e224de..ac889e149c 100644 --- a/worker/include/RTC/Codecs/Opus.hpp +++ b/worker/include/RTC/Codecs/Opus.hpp @@ -20,6 +20,9 @@ namespace RTC void Dump() const override; + // Mandatory fields. + uint8_t stereo : 1; + uint8_t code : 2; // Parsed values. bool isDtx{ false }; }; diff --git a/worker/src/RTC/Codecs/H264.cpp b/worker/src/RTC/Codecs/H264.cpp index 63bff4dcab..b2dd988e65 100644 --- a/worker/src/RTC/Codecs/H264.cpp +++ b/worker/src/RTC/Codecs/H264.cpp @@ -18,6 +18,8 @@ namespace RTC if (len < 2) { + MS_WARN_DEV("ignoring payload with length < 2"); + return nullptr; } diff --git a/worker/src/RTC/Codecs/H264_SVC.cpp b/worker/src/RTC/Codecs/H264_SVC.cpp index 05e43ec318..9214094ffb 100644 --- a/worker/src/RTC/Codecs/H264_SVC.cpp +++ b/worker/src/RTC/Codecs/H264_SVC.cpp @@ -17,6 +17,8 @@ namespace RTC if (len < 2) { + MS_WARN_DEV("ignoring payload with length < 2"); + return nullptr; } @@ -54,12 +56,13 @@ namespace RTC } } - // NOTE: Unfortunately libwebrtc produces wrong Frame-Marking (without i=1 in - // keyframes) when it uses H264 hardware encoder (at least in Mac): + // NOTE: Unfortunately libwebrtc produces wrong Frame-Marking (without i=1 + // in keyframes) when it uses H264 hardware encoder (at least in Mac): // https://bugs.chromium.org/p/webrtc/issues/detail?id=10746 // - // As a temporal workaround, always do payload parsing to detect keyframes if - // there is no frame-marking or if there is but keyframe was not detected above. + // As a temporal workaround, always do payload parsing to detect keyframes + // if there is no frame-marking or if there is but keyframe was not + // detected above. if (!frameMarking || !payloadDescriptor->isKeyFrame) { const uint8_t nal = *data & 0x1F; @@ -79,6 +82,8 @@ namespace RTC if (payloadDescriptor == nullptr) { + MS_WARN_DEV("ignoring invalid payload (1)"); + return nullptr; } @@ -106,6 +111,8 @@ namespace RTC if (payloadDescriptor == nullptr) { + MS_WARN_DEV("ignoring invalid payload (2)"); + return nullptr; } @@ -142,6 +149,8 @@ namespace RTC if (payloadDescriptor == nullptr) { + MS_WARN_DEV("ignoring invalid payload (3)"); + return nullptr; } diff --git a/worker/src/RTC/Codecs/Opus.cpp b/worker/src/RTC/Codecs/Opus.cpp index 4ff265ec1b..0fa4dff95e 100644 --- a/worker/src/RTC/Codecs/Opus.cpp +++ b/worker/src/RTC/Codecs/Opus.cpp @@ -14,12 +14,72 @@ namespace RTC { MS_TRACE(); + if (len < 1) + { + MS_WARN_DEV("ignoring empty payload"); + + return nullptr; + } + std::unique_ptr payloadDescriptor(new PayloadDescriptor()); - // libopus generates a single byte payload (TOC, no frames) to generate DTX. - if (len == 1) + uint8_t byte = data[0]; + + payloadDescriptor->stereo = (byte >> 2) & 0x01; + payloadDescriptor->code = byte & 0x03; + + switch (payloadDescriptor->code) { - payloadDescriptor->isDtx = true; + case 0: + case 1: + { + // In code 0 and 1 packets, DTX is determined by total length = 1 (TOC + // byte only). + if (len == 1) + { + payloadDescriptor->isDtx = true; + } + + break; + } + + case 2: + { + // As per spec, a 1-byte code 2 packet is always invalid. + if (len == 1) + { + MS_WARN_DEV("ignoring invalid payload (1)"); + + return nullptr; + } + + // In code 2 packets, DTX is determined by total length = 2 (TOC byte + // only). Per spec, the only valid 2-byte code 2 packet is one where + // the length of both frames is zero. + if (len == 2) + { + payloadDescriptor->isDtx = true; + } + + break; + } + + case 3: + { + // As per spec, a 1-byte code 3 packet is always invalid. + if (len == 1) + { + MS_WARN_DEV("ignoring invalid payload (2)"); + + return nullptr; + } + + // A code 3 packet can never be DTX. + + break; + } + + default:; } return payloadDescriptor.release(); @@ -34,6 +94,11 @@ namespace RTC PayloadDescriptor* payloadDescriptor = Opus::Parse(data, len); + if (!payloadDescriptor) + { + return; + } + auto* payloadDescriptorHandler = new PayloadDescriptorHandler(payloadDescriptor); packet->SetPayloadDescriptorHandler(payloadDescriptorHandler); @@ -46,6 +111,8 @@ namespace RTC MS_TRACE(); MS_DUMP(""); + MS_DUMP(" stereo: %" PRIu8, this->stereo); + MS_DUMP(" code: %" PRIu8, this->code); MS_DUMP(" isDtx: %s", this->isDtx ? "true" : "false"); MS_DUMP(""); } diff --git a/worker/src/RTC/Codecs/VP8.cpp b/worker/src/RTC/Codecs/VP8.cpp index 0c336ce1b3..4dd9bc5127 100644 --- a/worker/src/RTC/Codecs/VP8.cpp +++ b/worker/src/RTC/Codecs/VP8.cpp @@ -21,6 +21,8 @@ namespace RTC if (len < 1) { + MS_WARN_DEV("ignoring empty payload"); + return nullptr; } @@ -36,12 +38,16 @@ namespace RTC if (!payloadDescriptor->extended) { + MS_WARN_DEV("ignoring invalid payload (1)"); + return nullptr; } else { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (2)"); + return nullptr; } @@ -57,6 +63,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (3)"); + return nullptr; } @@ -66,6 +74,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (4)"); + return nullptr; } @@ -86,6 +96,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (5)"); + return nullptr; } @@ -97,6 +109,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (6)"); + return nullptr; } diff --git a/worker/src/RTC/Codecs/VP9.cpp b/worker/src/RTC/Codecs/VP9.cpp index 646ca8d72a..dea55d37c3 100644 --- a/worker/src/RTC/Codecs/VP9.cpp +++ b/worker/src/RTC/Codecs/VP9.cpp @@ -20,6 +20,8 @@ namespace RTC if (len < 1) { + MS_WARN_DEV("ignoring empty payload"); + return nullptr; } @@ -40,6 +42,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (1)"); + return nullptr; } @@ -49,6 +53,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (2)"); + return nullptr; } @@ -69,6 +75,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (3)"); + return nullptr; } @@ -83,6 +91,8 @@ namespace RTC if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (4)"); + return nullptr; } From c7e05eff0e870182c8f97252fb957ce55a1e428c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 28 Apr 2024 13:21:13 +0200 Subject: [PATCH 416/525] Worker: Fix sending callback leaks (#1383) --- CHANGELOG.md | 21 +++++++++++---------- worker/src/RTC/DataConsumer.cpp | 24 ++++++++++++++++++++++++ worker/src/RTC/DirectTransport.cpp | 18 +++++++++++++----- 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 022325c673..28b2a97ae3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ### NEXT - Update worker subprojects ([PR #1376](https://github.com/versatica/mediasoup/pull/1376)). -- OPUS: Fix DTX detection #1357 ([PR #1357](https://github.com/versatica/mediasoup/pull/1357)). +- OPUS: Fix DTX detection ([PR #1357](https://github.com/versatica/mediasoup/pull/1357)). +- Worker: Fix sending callback leaks ([PR #1383](https://github.com/versatica/mediasoup/pull/1383), credits to @Lynnworld). ### 3.14.1 @@ -72,13 +73,13 @@ ### 3.13.13 -- worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). +- Worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). - liburing: Enable zero copy ([PR #1273](https://github.com/versatica/mediasoup/pull/1273)). - Fix build on musl based systems (such as Alpine Linux) ([PR #1279](https://github.com/versatica/mediasoup/pull/1279)). ### 3.13.12 -- worker: Disable `RtcLogger` usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). +- Worker: Disable `RtcLogger` usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). - npm installation: Don't require Python if valid worker prebuilt binary is fetched ([PR #1265](https://github.com/versatica/mediasoup/pull/1265)). - Update h264-profile-level-id NPM dependency to 1.1.0. @@ -144,7 +145,7 @@ - Add optional `rtcpListenInfo` in `PlainTransportOptions` ([PR #1099](https://github.com/versatica/mediasoup/pull/1099)). - Add pause/resume API in `DataProducer` and `DataConsumer` ([PR #1104](https://github.com/versatica/mediasoup/pull/1104)). - DataChannel subchannels feature ([PR #1152](https://github.com/versatica/mediasoup/pull/1152)). -- `Worker`: Make DTLS fragment stay within MTU size range ([PR #1156](https://github.com/versatica/mediasoup/pull/1156), based on [PR #1143](https://github.com/versatica/mediasoup/pull/1143) by @vpnts-se). +- Worker: Make DTLS fragment stay within MTU size range ([PR #1156](https://github.com/versatica/mediasoup/pull/1156), based on [PR #1143](https://github.com/versatica/mediasoup/pull/1143) by @vpnts-se). ### 3.12.16 @@ -189,7 +190,7 @@ ### 3.12.6 -- `Worker`: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). +- Worker: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). - `RtpStreamRecv`: Fix jitter calculation ([PR #1117](https://github.com/versatica/mediasoup/pull/1117), thanks to @penguinol). - Revert "Node: make types.ts only export types rather than the entire class/code" ([PR #1109](https://github.com/versatica/mediasoup/pull/1109)) because it requires `typescript` >= 5 in the apps that import mediasoup and we don't want to be that strict yet. @@ -219,11 +220,11 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.11.26 -- `Worker`: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to @o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). +- Worker: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to @o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). ### 3.11.25 -- `Worker`: Require C++17, Meson >= 1.1.0 and update subprojects ([PR #1081](https://github.com/versatica/mediasoup/pull/1081)). +- Worker: Require C++17, Meson >= 1.1.0 and update subprojects ([PR #1081](https://github.com/versatica/mediasoup/pull/1081)). ### 3.11.24 @@ -323,7 +324,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi - Node: Migrate tests to TypeScript ([PR #958](https://github.com/versatica/mediasoup/pull/958)). - Node: Remove compiled JavaScript from repository and compile TypeScript code on NPM `prepare` script on demand when installed via git ([PR #954](https://github.com/versatica/mediasoup/pull/954)). -- `Worker`: Add `RTC::Shared` singleton for RTC entities ([PR #953](https://github.com/versatica/mediasoup/pull/953)). +- Worker: Add `RTC::Shared` singleton for RTC entities ([PR #953](https://github.com/versatica/mediasoup/pull/953)). - Update OpenSSL to 3.0.7. ### 3.11.3 @@ -499,7 +500,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.9.4 -- `Worker`: Fix bad printing of error messages from Worker ([PR #750](https://github.com/versatica/mediasoup/pull/750) by @j1elo). +- Worker: Fix bad printing of error messages from Worker ([PR #750](https://github.com/versatica/mediasoup/pull/750) by @j1elo). ### 3.9.3 @@ -517,7 +518,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.9.1 - NixOS friendly build process ([PR #683](https://github.com/versatica/mediasoup/pull/683)). -- `Worker`: Emit "died" event before observer "close" ([PR #684](https://github.com/versatica/mediasoup/pull/684)). +- Worker: Emit "died" event before observer "close" ([PR #684](https://github.com/versatica/mediasoup/pull/684)). - Transport: Hide debug message for RTX RTCP-RR packets ([PR #688](https://github.com/versatica/mediasoup/pull/688)). - Update `libuv` to 1.42.0. - Improve Windows support ([PR #692](https://github.com/versatica/mediasoup/pull/692)). diff --git a/worker/src/RTC/DataConsumer.cpp b/worker/src/RTC/DataConsumer.cpp index 1aaf97df12..c9034cdf0f 100644 --- a/worker/src/RTC/DataConsumer.cpp +++ b/worker/src/RTC/DataConsumer.cpp @@ -527,6 +527,12 @@ namespace RTC if (!IsActive()) { + if (cb) + { + (*cb)(false, false); + delete cb; + } + return; } @@ -536,6 +542,12 @@ namespace RTC requiredSubchannel.has_value() && this->subchannels.find(requiredSubchannel.value()) == this->subchannels.end()) { + if (cb) + { + (*cb)(false, false); + delete cb; + } + return; } @@ -557,6 +569,12 @@ namespace RTC if (!subchannelMatched) { + if (cb) + { + (*cb)(false, false); + delete cb; + } + return; } } @@ -569,6 +587,12 @@ namespace RTC len, this->maxMessageSize); + if (cb) + { + (*cb)(false, false); + delete cb; + } + return; } diff --git a/worker/src/RTC/DirectTransport.cpp b/worker/src/RTC/DirectTransport.cpp index 435c4b406b..f3af041e0f 100644 --- a/worker/src/RTC/DirectTransport.cpp +++ b/worker/src/RTC/DirectTransport.cpp @@ -146,6 +146,12 @@ namespace RTC { MS_WARN_TAG(rtp, "cannot send RTP packet not associated to a Consumer"); + if (cb) + { + (*cb)(false); + delete cb; + } + return; } @@ -212,11 +218,7 @@ namespace RTC } void DirectTransport::SendMessage( - RTC::DataConsumer* dataConsumer, - const uint8_t* msg, - size_t len, - uint32_t ppid, - onQueuedCallback* /*cb*/) + RTC::DataConsumer* dataConsumer, const uint8_t* msg, size_t len, uint32_t ppid, onQueuedCallback* cb) { MS_TRACE(); @@ -232,6 +234,12 @@ namespace RTC FBS::Notification::Body::DataConsumer_MessageNotification, notification); + if (cb) + { + (*cb)(true, false); + delete cb; + } + // Increase send transmission. RTC::Transport::DataSent(len); } From d3f1402f79755d07fdcd46e01144da843ae128be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 28 Apr 2024 13:24:37 +0200 Subject: [PATCH 417/525] 3.14.2 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28b2a97ae3..ef5a7f78de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### NEXT +### 3.14.2 - Update worker subprojects ([PR #1376](https://github.com/versatica/mediasoup/pull/1376)). - OPUS: Fix DTX detection ([PR #1357](https://github.com/versatica/mediasoup/pull/1357)). diff --git a/package-lock.json b/package-lock.json index f914ae513b..93c17522b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.1", + "version": "3.14.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.1", + "version": "3.14.2", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index b33e8412c7..b371d96fe1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.1", + "version": "3.14.2", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From ecb507e533d0c32cb1e2eb30f3306cdcb862f56f Mon Sep 17 00:00:00 2001 From: Liu <34062520+liuzhenyilang@users.noreply.github.com> Date: Tue, 30 Apr 2024 16:57:25 +0800 Subject: [PATCH 418/525] Fix: call parent method explicitly (#1384) --- worker/src/RTC/RtpStreamRecv.cpp | 3 ++- worker/src/RTC/RtpStreamSend.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index ba9e50c6d8..70917e04ff 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -843,7 +843,8 @@ namespace RTC score); #endif - RtpStream::UpdateScore(score); + // Call the parent method for update score. + RTC::RtpStream::UpdateScore(score); } void RtpStreamRecv::UserOnSequenceNumberReset() diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index 79875ce9c3..c0c6f6ce2a 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -637,7 +637,8 @@ namespace RTC score); #endif - RtpStream::UpdateScore(score); + // Call the parent method for update score. + RTC::RtpStream::UpdateScore(score); } void RtpStreamSend::UserOnSequenceNumberReset() From 0311073804f3e6e9cc54e9be97014b319b563f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 30 Apr 2024 14:43:35 +0200 Subject: [PATCH 419/525] Stop using C++ auto to assign results of arithmetic operations (#1386) --- CHANGELOG.md | 4 ++++ worker/src/RTC/RTCP/FeedbackRtpTransport.cpp | 4 +++- worker/src/RTC/RtpRetransmissionBuffer.cpp | 19 +++++++++---------- worker/src/RTC/RtxStream.cpp | 2 +- .../RTC/TransportCongestionControlServer.cpp | 4 ++-- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef5a7f78de..49203439be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Worker: Fix possible value overflow in `FeedbackRtpTransport.cpp` ([PR #1386](https://github.com/versatica/mediasoup/pull/1386), credits to @Lynnworld). + ### 3.14.2 - Update worker subprojects ([PR #1376](https://github.com/versatica/mediasoup/pull/1376)). diff --git a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp index 7463403991..cf85d1153b 100644 --- a/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +++ b/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp @@ -310,7 +310,9 @@ namespace RTC // Check if there are too many missing packets. { - auto missingPackets = sequenceNumber - (this->latestSequenceNumber + 1); + // NOTE: We CANNOT use auto here, we must use uint16_t. Otherwise this is a bug. + // https://github.com/versatica/mediasoup/issues/1385#issuecomment-2084982087 + const uint16_t missingPackets = sequenceNumber - (this->latestSequenceNumber + 1); if (missingPackets > FeedbackRtpTransportPacket::maxMissingPackets) { diff --git a/worker/src/RTC/RtpRetransmissionBuffer.cpp b/worker/src/RTC/RtpRetransmissionBuffer.cpp index 284d5e3c51..7b846bd672 100644 --- a/worker/src/RTC/RtpRetransmissionBuffer.cpp +++ b/worker/src/RTC/RtpRetransmissionBuffer.cpp @@ -72,9 +72,9 @@ namespace RTC return nullptr; } - const auto idx = static_cast(seq - oldestItem->sequenceNumber); + const uint16_t idx = seq - oldestItem->sequenceNumber; - if (idx > static_cast(this->buffer.size() - 1)) + if (static_cast(idx) > this->buffer.size() - 1) { return nullptr; } @@ -198,14 +198,13 @@ namespace RTC // Calculate how many blank slots it would be necessary to add when // pushing new item to the back of the buffer. - auto numBlankSlots = static_cast(seq - newestItem->sequenceNumber - 1); + uint16_t numBlankSlots = seq - newestItem->sequenceNumber - 1; // We may have to remove oldest items not to exceed the maximum size of // the buffer. if (this->buffer.size() + numBlankSlots + 1 > this->maxItems) { - const auto numItemsToRemove = - static_cast(this->buffer.size() + numBlankSlots + 1 - this->maxItems); + const uint16_t numItemsToRemove = this->buffer.size() + numBlankSlots + 1 - this->maxItems; // If num of items to be removed exceed buffer size minus one (needed to // allocate current packet) then we must clear the entire buffer. @@ -286,7 +285,7 @@ namespace RTC // Calculate how many blank slots it would be necessary to add when // pushing new item to the fton of the buffer. - const auto numBlankSlots = static_cast(oldestItem->sequenceNumber - seq - 1); + const uint16_t numBlankSlots = oldestItem->sequenceNumber - seq - 1; // If adding this packet (and needed blank slots) to the front makes the // buffer exceed its max size, discard this packet. @@ -339,11 +338,11 @@ namespace RTC } // idx is the intended position of the received packet in the buffer. - const auto idx = static_cast(seq - oldestItem->sequenceNumber); + const uint16_t idx = seq - oldestItem->sequenceNumber; // Validate that packet timestamp is equal or higher than the timestamp of // the immediate older packet (if any). - for (auto idx2 = static_cast(idx - 1); idx2 >= 0; --idx2) + for (int32_t idx2 = idx - 1; idx2 >= 0; --idx2) { const auto* olderItem = this->buffer.at(idx2); @@ -374,7 +373,7 @@ namespace RTC // Validate that packet timestamp is equal or less than the timestamp of // the immediate newer packet (if any). - for (auto idx2 = static_cast(idx + 1); idx2 < this->buffer.size(); ++idx2) + for (size_t idx2 = idx + 1; idx2 < this->buffer.size(); ++idx2) { const auto* newerItem = this->buffer.at(idx2); @@ -535,7 +534,7 @@ namespace RTC numItems, this->buffer.size()); - const auto intendedBufferSize = this->buffer.size() - numItems; + const size_t intendedBufferSize = this->buffer.size() - numItems; while (this->buffer.size() > intendedBufferSize) { diff --git a/worker/src/RTC/RtxStream.cpp b/worker/src/RTC/RtxStream.cpp index 008aa65b6b..59f1e3a5b3 100644 --- a/worker/src/RTC/RtxStream.cpp +++ b/worker/src/RTC/RtxStream.cpp @@ -137,7 +137,7 @@ namespace RTC if (this->lastSrReceived != 0) { // Get delay in milliseconds. - auto delayMs = static_cast(DepLibUV::GetTimeMs() - this->lastSrReceived); + const uint32_t delayMs = DepLibUV::GetTimeMs() - this->lastSrReceived; // Express delay in units of 1/65536 seconds. uint32_t dlsr = (delayMs / 1000) << 16; diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index c5d21de37a..5beba32038 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -338,8 +338,8 @@ namespace RTC // the condition is met. if (nowMs >= PacketArrivalTimestampWindow) { - auto expiryTimestamp = nowMs - PacketArrivalTimestampWindow; - auto it = this->mapPacketArrivalTimes.begin(); + uint64_t expiryTimestamp = nowMs - PacketArrivalTimestampWindow; + auto it = this->mapPacketArrivalTimes.begin(); while (it != this->mapPacketArrivalTimes.end() && it->first != this->transportCcFeedbackWideSeqNumStart && From 6de10e2e8b1eb21ca79ffd1fad9a218a8a8d0c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 30 Apr 2024 14:47:07 +0200 Subject: [PATCH 420/525] Update deps --- package-lock.json | 350 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 178 insertions(+), 178 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93c17522b1..38c0602b2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,11 +24,11 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.7", - "@typescript-eslint/eslint-plugin": "^7.7.1", - "@typescript-eslint/parser": "^7.7.1", + "@typescript-eslint/eslint-plugin": "^7.8.0", + "@typescript-eslint/parser": "^7.8.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.2.0", + "eslint-plugin-jest": "^28.3.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.2", @@ -1784,16 +1784,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz", - "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", + "integrity": "sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.7.1", - "@typescript-eslint/type-utils": "7.7.1", - "@typescript-eslint/utils": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/scope-manager": "7.8.0", + "@typescript-eslint/type-utils": "7.8.0", + "@typescript-eslint/utils": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.3.1", @@ -1819,13 +1819,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", - "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", + "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1" + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1836,9 +1836,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", - "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", + "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1849,12 +1849,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", - "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", + "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/types": "7.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -1866,15 +1866,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz", - "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.8.0.tgz", + "integrity": "sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.7.1", - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/typescript-estree": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/scope-manager": "7.8.0", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/typescript-estree": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4" }, "engines": { @@ -1894,13 +1894,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", - "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", + "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1" + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1911,9 +1911,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", - "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", + "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1924,13 +1924,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", - "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", + "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1952,12 +1952,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", - "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", + "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/types": "7.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2010,13 +2010,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz", - "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", + "integrity": "sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.7.1", - "@typescript-eslint/utils": "7.7.1", + "@typescript-eslint/typescript-estree": "7.8.0", + "@typescript-eslint/utils": "7.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2037,9 +2037,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", - "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", + "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2050,13 +2050,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", - "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", + "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2078,12 +2078,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", - "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", + "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/types": "7.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2184,17 +2184,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz", - "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", + "integrity": "sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.15", "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.7.1", - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/scope-manager": "7.8.0", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/typescript-estree": "7.8.0", "semver": "^7.6.0" }, "engines": { @@ -2209,13 +2209,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", - "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", + "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1" + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2226,9 +2226,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", - "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", + "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2239,13 +2239,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", - "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", + "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2267,12 +2267,12 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", - "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", + "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/types": "7.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3127,9 +3127,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz", - "integrity": "sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g==", + "version": "28.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.3.0.tgz", + "integrity": "sha512-5LjCSSno8E+IUCOX4hJiIb/upPIgpkaDEcaN/40gOcw26t/5UTLHFc4JdxKjOOvGTh0XdCu+fNr0fpOVNvcxMA==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^6.0.0" @@ -7883,16 +7883,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz", - "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", + "integrity": "sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.7.1", - "@typescript-eslint/type-utils": "7.7.1", - "@typescript-eslint/utils": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/scope-manager": "7.8.0", + "@typescript-eslint/type-utils": "7.8.0", + "@typescript-eslint/utils": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.3.1", @@ -7902,70 +7902,70 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", - "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", + "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1" + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0" } }, "@typescript-eslint/types": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", - "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", + "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", "dev": true }, "@typescript-eslint/visitor-keys": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", - "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", + "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/types": "7.8.0", "eslint-visitor-keys": "^3.4.3" } } } }, "@typescript-eslint/parser": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz", - "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.8.0.tgz", + "integrity": "sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.7.1", - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/typescript-estree": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/scope-manager": "7.8.0", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/typescript-estree": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", - "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", + "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1" + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0" } }, "@typescript-eslint/types": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", - "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", + "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", - "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", + "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7975,12 +7975,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", - "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", + "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/types": "7.8.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -8015,31 +8015,31 @@ } }, "@typescript-eslint/type-utils": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz", - "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", + "integrity": "sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.7.1", - "@typescript-eslint/utils": "7.7.1", + "@typescript-eslint/typescript-estree": "7.8.0", + "@typescript-eslint/utils": "7.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "dependencies": { "@typescript-eslint/types": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", - "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", + "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", - "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", + "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8049,12 +8049,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", - "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", + "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/types": "7.8.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -8121,44 +8121,44 @@ } }, "@typescript-eslint/utils": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz", - "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", + "integrity": "sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.15", "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.7.1", - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/scope-manager": "7.8.0", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/typescript-estree": "7.8.0", "semver": "^7.6.0" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", - "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", + "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1" + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0" } }, "@typescript-eslint/types": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", - "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", + "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", - "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", + "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8168,12 +8168,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", - "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", + "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/types": "7.8.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -8780,9 +8780,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "28.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz", - "integrity": "sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g==", + "version": "28.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.3.0.tgz", + "integrity": "sha512-5LjCSSno8E+IUCOX4hJiIb/upPIgpkaDEcaN/40gOcw26t/5UTLHFc4JdxKjOOvGTh0XdCu+fNr0fpOVNvcxMA==", "dev": true, "requires": { "@typescript-eslint/utils": "^6.0.0" diff --git a/package.json b/package.json index b371d96fe1..555f1ea632 100644 --- a/package.json +++ b/package.json @@ -113,11 +113,11 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.7", - "@typescript-eslint/eslint-plugin": "^7.7.1", - "@typescript-eslint/parser": "^7.7.1", + "@typescript-eslint/eslint-plugin": "^7.8.0", + "@typescript-eslint/parser": "^7.8.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.2.0", + "eslint-plugin-jest": "^28.3.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.2", From 1cac1ab92f846507e2996733460b4306ab381d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 30 Apr 2024 14:52:39 +0200 Subject: [PATCH 421/525] 3.14.3 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49203439be..9912c3921c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### NEXT +### 3.14.3 - Worker: Fix possible value overflow in `FeedbackRtpTransport.cpp` ([PR #1386](https://github.com/versatica/mediasoup/pull/1386), credits to @Lynnworld). diff --git a/package-lock.json b/package-lock.json index 38c0602b2f..fadd34ff9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.2", + "version": "3.14.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.2", + "version": "3.14.3", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 555f1ea632..04ab196066 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.2", + "version": "3.14.3", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 06ae37335c530859f17a959821d5c9e9806414dd Mon Sep 17 00:00:00 2001 From: Lynnworld Date: Thu, 2 May 2024 22:25:14 +0900 Subject: [PATCH 422/525] fix RtcpFeedback Parameter empty (#1387) --- worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp index 6f132a8dc5..0c9b367eb0 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp @@ -13,7 +13,10 @@ namespace RTC MS_TRACE(); this->type = data->type()->str(); - this->parameter = data->parameter()->str(); + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtcpFeedback::VT_PARAMETER)) + { + this->parameter = data->parameter()->str(); + } } flatbuffers::Offset RtcpFeedback::FillBuffer( From 98cf79eb29e6a3f574cf0b56deb44d76a3f1c5cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Thu, 2 May 2024 15:36:27 +0200 Subject: [PATCH 423/525] 3.14.4 --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9912c3921c..fbf4306492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### 3.14.4 + +- Worker: Fix crash. RtcpFeedback parameter is optional ([PR #1387](https://github.com/versatica/mediasoup/pull/1387), credits to @Lynnworld). + ### 3.14.3 - Worker: Fix possible value overflow in `FeedbackRtpTransport.cpp` ([PR #1386](https://github.com/versatica/mediasoup/pull/1386), credits to @Lynnworld). diff --git a/package-lock.json b/package-lock.json index fadd34ff9f..40051d0ea3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.3", + "version": "3.14.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.3", + "version": "3.14.4", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 04ab196066..17cc7ef3e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.3", + "version": "3.14.4", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", diff --git a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp index 0c9b367eb0..b95bb46e36 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp @@ -12,7 +12,7 @@ namespace RTC { MS_TRACE(); - this->type = data->type()->str(); + this->type = data->type()->str(); if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtcpFeedback::VT_PARAMETER)) { this->parameter = data->parameter()->str(); From 34336429ba5d4d2fe8d2a6bffb9d16e083183bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 3 May 2024 12:26:16 +0200 Subject: [PATCH 424/525] Worker: Fix memory leak when using WebRtcServer with TCP enabled (#1389) --- CHANGELOG.md | 6 +- worker/include/RTC/IceServer.hpp | 1 + worker/include/RTC/TransportTuple.hpp | 24 +---- worker/include/handles/SignalHandle.hpp | 4 +- .../include/handles/TcpConnectionHandle.hpp | 3 +- worker/include/handles/TcpServerHandle.hpp | 2 +- worker/include/handles/TimerHandle.hpp | 4 +- worker/include/handles/UdpSocketHandle.hpp | 2 +- worker/src/Channel/ChannelSocket.cpp | 2 +- worker/src/RTC/IceServer.cpp | 9 ++ worker/src/RTC/TransportTuple.cpp | 16 ++++ worker/src/RTC/WebRtcTransport.cpp | 4 +- worker/src/handles/SignalHandle.cpp | 38 ++++---- worker/src/handles/TcpConnectionHandle.cpp | 94 +++++++++++-------- worker/src/handles/TcpServerHandle.cpp | 50 +++++----- worker/src/handles/TimerHandle.cpp | 30 +++--- worker/src/handles/UdpSocketHandle.cpp | 52 +++++----- worker/src/handles/UnixStreamSocketHandle.cpp | 6 +- 18 files changed, 188 insertions(+), 159 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbf4306492..2f38e77021 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,12 @@ # Changelog +### NEXT + +- Worker: Fix memory leak when using `WebRtcServer` with TCP enabled ([PR #1389](https://github.com/versatica/mediasoup/pull/1389)). + ### 3.14.4 -- Worker: Fix crash. RtcpFeedback parameter is optional ([PR #1387](https://github.com/versatica/mediasoup/pull/1387), credits to @Lynnworld). +- Worker: Fix crash. `RtcpFeedback` parameter is optional ([PR #1387](https://github.com/versatica/mediasoup/pull/1387), credits to @Lynnworld). ### 3.14.3 diff --git a/worker/include/RTC/IceServer.hpp b/worker/include/RTC/IceServer.hpp index 72d7710363..fb80ad8966 100644 --- a/worker/include/RTC/IceServer.hpp +++ b/worker/include/RTC/IceServer.hpp @@ -131,6 +131,7 @@ namespace RTC std::string password; uint16_t consentTimeoutMs{ 30000u }; // Others. + bool destroying{ false }; std::string oldUsernameFragment; std::string oldPassword; IceState state{ IceState::NEW }; diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 8df96d10ce..8b01dbc476 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -51,29 +51,7 @@ namespace RTC } public: - void Close() - { - if (this->protocol == Protocol::UDP) - { - this->udpSocket->Close(); - } - else - { - this->tcpConnection->Close(); - } - } - - bool IsClosed() - { - if (this->protocol == Protocol::UDP) - { - return this->udpSocket->IsClosed(); - } - else - { - return this->tcpConnection->IsClosed(); - } - } + void CloseTcpConnection(); flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; diff --git a/worker/include/handles/SignalHandle.hpp b/worker/include/handles/SignalHandle.hpp index ff32054389..462b0e7902 100644 --- a/worker/include/handles/SignalHandle.hpp +++ b/worker/include/handles/SignalHandle.hpp @@ -22,9 +22,11 @@ class SignalHandle ~SignalHandle(); public: - void Close(); void AddSignal(int signum, const std::string& name); +private: + void InternalClose(); + /* Callbacks fired by UV events. */ public: void OnUvSignal(int signum); diff --git a/worker/include/handles/TcpConnectionHandle.hpp b/worker/include/handles/TcpConnectionHandle.hpp index 76c92e3512..ad9cc12807 100644 --- a/worker/include/handles/TcpConnectionHandle.hpp +++ b/worker/include/handles/TcpConnectionHandle.hpp @@ -49,7 +49,7 @@ class TcpConnectionHandle virtual ~TcpConnectionHandle(); public: - void Close(); + void TriggerClose(); bool IsClosed() const { return this->closed; @@ -110,6 +110,7 @@ class TcpConnectionHandle } private: + void InternalClose(); bool SetPeerAddress(); /* Callbacks fired by UV events. */ diff --git a/worker/include/handles/TcpServerHandle.hpp b/worker/include/handles/TcpServerHandle.hpp index e82c92a9a5..f2ac9a0fc7 100644 --- a/worker/include/handles/TcpServerHandle.hpp +++ b/worker/include/handles/TcpServerHandle.hpp @@ -17,7 +17,6 @@ class TcpServerHandle : public TcpConnectionHandle::Listener ~TcpServerHandle() override; public: - void Close(); void Dump() const; const struct sockaddr* GetLocalAddress() const { @@ -48,6 +47,7 @@ class TcpServerHandle : public TcpConnectionHandle::Listener void AcceptTcpConnection(TcpConnectionHandle* connection); private: + void InternalClose(); bool SetLocalAddress(); /* Pure virtual methods that must be implemented by the subclass. */ diff --git a/worker/include/handles/TimerHandle.hpp b/worker/include/handles/TimerHandle.hpp index 09ea83b5a8..7948ec608f 100644 --- a/worker/include/handles/TimerHandle.hpp +++ b/worker/include/handles/TimerHandle.hpp @@ -23,7 +23,6 @@ class TimerHandle ~TimerHandle(); public: - void Close(); void Start(uint64_t timeout, uint64_t repeat = 0); void Stop(); void Reset(); @@ -41,6 +40,9 @@ class TimerHandle return uv_is_active(reinterpret_cast(this->uvHandle)) != 0; } +private: + void InternalClose(); + /* Callbacks fired by UV events. */ public: void OnUvTimer(); diff --git a/worker/include/handles/UdpSocketHandle.hpp b/worker/include/handles/UdpSocketHandle.hpp index 084690e76e..307503b459 100644 --- a/worker/include/handles/UdpSocketHandle.hpp +++ b/worker/include/handles/UdpSocketHandle.hpp @@ -42,7 +42,6 @@ class UdpSocketHandle virtual ~UdpSocketHandle(); public: - void Close(); bool IsClosed() const { return this->closed; @@ -80,6 +79,7 @@ class UdpSocketHandle void SetRecvBufferSize(uint32_t size); private: + void InternalClose(); bool SetLocalAddress(); /* Callbacks fired by UV events. */ diff --git a/worker/src/Channel/ChannelSocket.cpp b/worker/src/Channel/ChannelSocket.cpp index 058d7b21b4..cb99e8472b 100644 --- a/worker/src/Channel/ChannelSocket.cpp +++ b/worker/src/Channel/ChannelSocket.cpp @@ -247,7 +247,7 @@ namespace Channel return free != nullptr; } - inline void ChannelSocket::SendImpl(const uint8_t* payload, uint32_t payloadLen) + void ChannelSocket::SendImpl(const uint8_t* payload, uint32_t payloadLen) { MS_TRACE_STD(); diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index f2ddc8e224..48fae78030 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -112,6 +112,8 @@ namespace RTC { MS_TRACE(); + this->destroying = true; + // Here we must notify the listener about the removal of current // usernameFragments (and also the old one if any) and all tuples. @@ -223,6 +225,13 @@ namespace RTC { MS_TRACE(); + // While IceServer is being destroyed, it may call listener methods that may + // end calling RemoveTuple(). We must ignore it to avoid double-free issues. + if (this->destroying) + { + return; + } + RTC::TransportTuple* removedTuple{ nullptr }; // Find the removed tuple. diff --git a/worker/src/RTC/TransportTuple.cpp b/worker/src/RTC/TransportTuple.cpp index 68d14d0bd5..8e59399640 100644 --- a/worker/src/RTC/TransportTuple.cpp +++ b/worker/src/RTC/TransportTuple.cpp @@ -11,6 +11,8 @@ namespace RTC TransportTuple::Protocol TransportTuple::ProtocolFromFbs(FBS::Transport::Protocol protocol) { + MS_TRACE(); + switch (protocol) { case FBS::Transport::Protocol::UDP: @@ -23,6 +25,8 @@ namespace RTC FBS::Transport::Protocol TransportTuple::ProtocolToFbs(TransportTuple::Protocol protocol) { + MS_TRACE(); + switch (protocol) { case TransportTuple::Protocol::UDP: @@ -35,6 +39,18 @@ namespace RTC /* Instance methods. */ + void TransportTuple::CloseTcpConnection() + { + MS_TRACE(); + + if (this->protocol == Protocol::UDP) + { + MS_ABORT("cannot delete a UDP socket"); + } + + this->tcpConnection->TriggerClose(); + } + flatbuffers::Offset TransportTuple::FillBuffer( flatbuffers::FlatBufferBuilder& builder) const { diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index c5d0bc5673..c25ccc8430 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -1180,9 +1180,9 @@ namespace RTC } // If this is a TCP tuple, close its underlaying TCP connection. - if (tuple->GetProtocol() == RTC::TransportTuple::Protocol::TCP && !tuple->IsClosed()) + if (tuple->GetProtocol() == RTC::TransportTuple::Protocol::TCP) { - tuple->Close(); + tuple->CloseTcpConnection(); } } diff --git a/worker/src/handles/SignalHandle.cpp b/worker/src/handles/SignalHandle.cpp index 0ceabc0b33..9dd8fb3cf7 100644 --- a/worker/src/handles/SignalHandle.cpp +++ b/worker/src/handles/SignalHandle.cpp @@ -31,24 +31,7 @@ SignalHandle::~SignalHandle() if (!this->closed) { - Close(); - } -} - -void SignalHandle::Close() -{ - MS_TRACE(); - - if (this->closed) - { - return; - } - - this->closed = true; - - for (auto* uvHandle : this->uvHandles) - { - uv_close(reinterpret_cast(uvHandle), static_cast(onCloseSignal)); + InternalClose(); } } @@ -86,7 +69,24 @@ void SignalHandle::AddSignal(int signum, const std::string& name) this->uvHandles.push_back(uvHandle); } -inline void SignalHandle::OnUvSignal(int signum) +void SignalHandle::InternalClose() +{ + MS_TRACE(); + + if (this->closed) + { + return; + } + + this->closed = true; + + for (auto* uvHandle : this->uvHandles) + { + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseSignal)); + } +} + +void SignalHandle::OnUvSignal(int signum) { MS_TRACE(); diff --git a/worker/src/handles/TcpConnectionHandle.cpp b/worker/src/handles/TcpConnectionHandle.cpp index 56d9e10004..5a7c39ba30 100644 --- a/worker/src/handles/TcpConnectionHandle.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -90,13 +90,13 @@ TcpConnectionHandle::~TcpConnectionHandle() if (!this->closed) { - Close(); + InternalClose(); } delete[] this->buffer; } -void TcpConnectionHandle::Close() +void TcpConnectionHandle::TriggerClose() { MS_TRACE(); @@ -105,41 +105,9 @@ void TcpConnectionHandle::Close() return; } - int err; - - this->closed = true; - - // Tell the UV handle that the TcpConnectionHandle has been closed. - this->uvHandle->data = nullptr; - - // Don't read more. - err = uv_read_stop(reinterpret_cast(this->uvHandle)); - - if (err != 0) - { - MS_ABORT("uv_read_stop() failed: %s", uv_strerror(err)); - } - - // If there is no error and the peer didn't close its connection side then close gracefully. - if (!this->hasError && !this->isClosedByPeer) - { - // Use uv_shutdown() so pending data to be written will be sent to the peer - // before closing. - auto* req = new uv_shutdown_t; - req->data = static_cast(this); - err = uv_shutdown( - req, reinterpret_cast(this->uvHandle), static_cast(onShutdown)); + InternalClose(); - if (err != 0) - { - MS_ABORT("uv_shutdown() failed: %s", uv_strerror(err)); - } - } - // Otherwise directly close the socket. - else - { - uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTcp)); - } + this->listener->OnTcpConnectionClosed(this); } void TcpConnectionHandle::Dump() const @@ -366,11 +334,57 @@ void TcpConnectionHandle::ErrorReceiving() { MS_TRACE(); - Close(); + InternalClose(); this->listener->OnTcpConnectionClosed(this); } +void TcpConnectionHandle::InternalClose() +{ + MS_TRACE(); + + if (this->closed) + { + return; + } + + int err; + + this->closed = true; + + // Tell the UV handle that the TcpConnectionHandle has been closed. + this->uvHandle->data = nullptr; + + // Don't read more. + err = uv_read_stop(reinterpret_cast(this->uvHandle)); + + if (err != 0) + { + MS_ABORT("uv_read_stop() failed: %s", uv_strerror(err)); + } + + // If there is no error and the peer didn't close its connection side then close gracefully. + if (!this->hasError && !this->isClosedByPeer) + { + // Use uv_shutdown() so pending data to be written will be sent to the peer + // before closing. + auto* req = new uv_shutdown_t; + req->data = static_cast(this); + err = uv_shutdown( + req, reinterpret_cast(this->uvHandle), static_cast(onShutdown)); + + if (err != 0) + { + MS_ABORT("uv_shutdown() failed: %s", uv_strerror(err)); + } + } + // Otherwise directly close the socket. + else + { + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTcp)); + } +} + bool TcpConnectionHandle::SetPeerAddress() { MS_TRACE(); @@ -450,7 +464,7 @@ inline void TcpConnectionHandle::OnUvRead(ssize_t nread, const uv_buf_t* /*buf*/ this->isClosedByPeer = true; // Close server side of the connection. - Close(); + InternalClose(); // Notify the listener. this->listener->OnTcpConnectionClosed(this); @@ -463,7 +477,7 @@ inline void TcpConnectionHandle::OnUvRead(ssize_t nread, const uv_buf_t* /*buf*/ this->hasError = true; // Close server side of the connection. - Close(); + InternalClose(); // Notify the listener. this->listener->OnTcpConnectionClosed(this); @@ -497,7 +511,7 @@ inline void TcpConnectionHandle::OnUvWrite(int status, TcpConnectionHandle::onSe (*cb)(false); } - Close(); + InternalClose(); this->listener->OnTcpConnectionClosed(this); } diff --git a/worker/src/handles/TcpServerHandle.cpp b/worker/src/handles/TcpServerHandle.cpp index c6cf895110..def778a577 100644 --- a/worker/src/handles/TcpServerHandle.cpp +++ b/worker/src/handles/TcpServerHandle.cpp @@ -65,34 +65,10 @@ TcpServerHandle::~TcpServerHandle() if (!this->closed) { - Close(); + InternalClose(); } } -void TcpServerHandle::Close() -{ - MS_TRACE(); - - if (this->closed) - { - return; - } - - this->closed = true; - - // Tell the UV handle that the TcpServerHandle has been closed. - this->uvHandle->data = nullptr; - - MS_DEBUG_DEV("closing %zu active connections", this->connections.size()); - - for (auto* connection : this->connections) - { - delete connection; - } - - uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTcp)); -} - void TcpServerHandle::Dump() const { MS_DUMP(""); @@ -219,6 +195,30 @@ void TcpServerHandle::AcceptTcpConnection(TcpConnectionHandle* connection) this->connections.insert(connection); } +void TcpServerHandle::InternalClose() +{ + MS_TRACE(); + + if (this->closed) + { + return; + } + + this->closed = true; + + // Tell the UV handle that the TcpServerHandle has been closed. + this->uvHandle->data = nullptr; + + MS_DEBUG_DEV("closing %zu active connections", this->connections.size()); + + for (auto* connection : this->connections) + { + delete connection; + } + + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTcp)); +} + bool TcpServerHandle::SetLocalAddress() { MS_TRACE(); diff --git a/worker/src/handles/TimerHandle.cpp b/worker/src/handles/TimerHandle.cpp index e40ae8efb1..a5e4c1afd9 100644 --- a/worker/src/handles/TimerHandle.cpp +++ b/worker/src/handles/TimerHandle.cpp @@ -43,24 +43,10 @@ TimerHandle::~TimerHandle() if (!this->closed) { - Close(); + InternalClose(); } } -void TimerHandle::Close() -{ - MS_TRACE(); - - if (this->closed) - { - return; - } - - this->closed = true; - - uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTimer)); -} - void TimerHandle::Start(uint64_t timeout, uint64_t repeat) { MS_TRACE(); @@ -154,6 +140,20 @@ void TimerHandle::Restart() } } +void TimerHandle::InternalClose() +{ + MS_TRACE(); + + if (this->closed) + { + return; + } + + this->closed = true; + + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseTimer)); +} + inline void TimerHandle::OnUvTimer() { MS_TRACE(); diff --git a/worker/src/handles/UdpSocketHandle.cpp b/worker/src/handles/UdpSocketHandle.cpp index 416dac18cf..2cb42e40c5 100644 --- a/worker/src/handles/UdpSocketHandle.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -103,35 +103,10 @@ UdpSocketHandle::~UdpSocketHandle() if (!this->closed) { - Close(); + InternalClose(); } } -void UdpSocketHandle::Close() -{ - MS_TRACE(); - - if (this->closed) - { - return; - } - - this->closed = true; - - // Tell the UV handle that the UdpSocketHandle has been closed. - this->uvHandle->data = nullptr; - - // Don't read more. - const int err = uv_udp_recv_stop(this->uvHandle); - - if (err != 0) - { - MS_ABORT("uv_udp_recv_stop() failed: %s", uv_strerror(err)); - } - - uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseUdp)); -} - void UdpSocketHandle::Dump() const { MS_DUMP(""); @@ -338,6 +313,31 @@ void UdpSocketHandle::SetRecvBufferSize(uint32_t size) } } +void UdpSocketHandle::InternalClose() +{ + MS_TRACE(); + + if (this->closed) + { + return; + } + + this->closed = true; + + // Tell the UV handle that the UdpSocketHandle has been closed. + this->uvHandle->data = nullptr; + + // Don't read more. + const int err = uv_udp_recv_stop(this->uvHandle); + + if (err != 0) + { + MS_ABORT("uv_udp_recv_stop() failed: %s", uv_strerror(err)); + } + + uv_close(reinterpret_cast(this->uvHandle), static_cast(onCloseUdp)); +} + bool UdpSocketHandle::SetLocalAddress() { MS_TRACE(); diff --git a/worker/src/handles/UnixStreamSocketHandle.cpp b/worker/src/handles/UnixStreamSocketHandle.cpp index bf024d1d8e..1696cb3736 100644 --- a/worker/src/handles/UnixStreamSocketHandle.cpp +++ b/worker/src/handles/UnixStreamSocketHandle.cpp @@ -126,14 +126,16 @@ UnixStreamSocketHandle::~UnixStreamSocketHandle() { MS_TRACE_STD(); - delete[] this->buffer; - if (!this->closed) { Close(); } + + delete[] this->buffer; } +// NOTE: In UnixStreamSocketHandle we need a poublic Close() method and cannot +// just rely on the destructor plus a private InternalClose() method. void UnixStreamSocketHandle::Close() { MS_TRACE_STD(); From d33cb8873dff75aca4432ffeabed253fe0ca4e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 3 May 2024 13:22:32 +0200 Subject: [PATCH 425/525] Fix Worker crash when closing WebRtcServer with active WebRtcTransports (#1390) * Fix Worker crash when closing WebRtcServer with active WebRtcTransports Fixes #1388 ### Details - `WebRtcServer` destructor must first close its `WebRtcTransports` and then the UDP sockets and TCP servers (so also its TCP connections). Otherwise those `WebRtcTransports` will try to send DTLS Close Alert on an already closed/freed `UdpSocketHandle` or `TcpConnectionHandle`. ### Steps to verify 1. Have `WebRtcServer` running and a client connected. 2. In server side call `webRtcServer.close()`. 3. It should not crash anymore. * Update CHANGELOG --- CHANGELOG.md | 1 + worker/src/RTC/WebRtcServer.cpp | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f38e77021..8d335b3c08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT - Worker: Fix memory leak when using `WebRtcServer` with TCP enabled ([PR #1389](https://github.com/versatica/mediasoup/pull/1389)). +- Worker: Fix crash when closing `WebRtcServer` with active `WebRtcTransports` ([PR #1390](https://github.com/versatica/mediasoup/pull/1390)). ### 3.14.4 diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 274391d922..c088564546 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -236,6 +236,15 @@ namespace RTC this->shared->channelMessageRegistrator->UnregisterHandler(this->id); + // NOTE: We need to close WebRtcTransports first since they may need to + // send DTLS Close Alert so UDP sockets and TCP connections must remain + // open. + for (auto* webRtcTransport : this->webRtcTransports) + { + webRtcTransport->ListenServerClosed(); + } + this->webRtcTransports.clear(); + for (auto& item : this->udpSocketOrTcpServers) { delete item.udpSocket; @@ -245,12 +254,6 @@ namespace RTC item.tcpServer = nullptr; } this->udpSocketOrTcpServers.clear(); - - for (auto* webRtcTransport : this->webRtcTransports) - { - webRtcTransport->ListenServerClosed(); - } - this->webRtcTransports.clear(); } flatbuffers::Offset WebRtcServer::FillBuffer( From 2cae8ec709bdecfa9bfa1ec04dbf5e1fae16856e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Fri, 3 May 2024 13:26:02 +0200 Subject: [PATCH 426/525] 3.14.5 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d335b3c08..a36546fe7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### NEXT +### 3.14.5 - Worker: Fix memory leak when using `WebRtcServer` with TCP enabled ([PR #1389](https://github.com/versatica/mediasoup/pull/1389)). - Worker: Fix crash when closing `WebRtcServer` with active `WebRtcTransports` ([PR #1390](https://github.com/versatica/mediasoup/pull/1390)). diff --git a/package-lock.json b/package-lock.json index 40051d0ea3..6a7f57af7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.4", + "version": "3.14.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.4", + "version": "3.14.5", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 17cc7ef3e8..8a09dbbbc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.4", + "version": "3.14.5", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From ea40829a7e7744d619e2befc19260517370d341d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s-Combarro?= Date: Tue, 7 May 2024 11:10:54 +0200 Subject: [PATCH 427/525] Fix typo in test-PipeTransport.ts (#1391) --- node/src/test/test-PipeTransport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 0ded5cab8a..74809b320b 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -1011,7 +1011,7 @@ test('router.pipeToRouter() called twice generates a single PipeTransport pair', expect(dump2.transportIds.length).toBe(1); }, 2000); -test('router.pipeToRouter() called in two Routers passing one to each other as argument generates a single a single PipeTransport pair', async () => { +test('router.pipeToRouter() called in two Routers passing one to each other as argument generates a single PipeTransport pair', async () => { const routerA = await ctx.worker1!.createRouter({ mediaCodecs: ctx.mediaCodecs, }); From fab4891c0124f1b43e42eee134db7ff186d70400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 9 May 2024 17:20:35 +0200 Subject: [PATCH 428/525] Worker: Fix possible double free when ICE consent check fails (#1393) --- CHANGELOG.md | 4 ++++ worker/include/RTC/IceServer.hpp | 2 +- worker/src/RTC/IceServer.cpp | 21 ++++++++++++++++----- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a36546fe7d..f2100d3eee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Worker: Fix possible double free when ICE consent check fails ([PR #1393](https://github.com/versatica/mediasoup/pull/1393)). + ### 3.14.5 - Worker: Fix memory leak when using `WebRtcServer` with TCP enabled ([PR #1389](https://github.com/versatica/mediasoup/pull/1389)). diff --git a/worker/include/RTC/IceServer.hpp b/worker/include/RTC/IceServer.hpp index fb80ad8966..6c1be537bd 100644 --- a/worker/include/RTC/IceServer.hpp +++ b/worker/include/RTC/IceServer.hpp @@ -131,7 +131,6 @@ namespace RTC std::string password; uint16_t consentTimeoutMs{ 30000u }; // Others. - bool destroying{ false }; std::string oldUsernameFragment; std::string oldPassword; IceState state{ IceState::NEW }; @@ -140,6 +139,7 @@ namespace RTC RTC::TransportTuple* selectedTuple{ nullptr }; TimerHandle* consentCheckTimer{ nullptr }; uint64_t lastConsentRequestReceivedAtMs{ 0u }; + bool isRemovingTuples{ false }; }; } // namespace RTC diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index 48fae78030..f4754fb0a8 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -112,8 +112,6 @@ namespace RTC { MS_TRACE(); - this->destroying = true; - // Here we must notify the listener about the removal of current // usernameFragments (and also the old one if any) and all tuples. @@ -125,6 +123,8 @@ namespace RTC } // Clear all tuples. + this->isRemovingTuples = true; + for (const auto& it : this->tuples) { auto* storedTuple = const_cast(std::addressof(it)); @@ -133,6 +133,8 @@ namespace RTC this->listener->OnIceServerTupleRemoved(this, storedTuple); } + this->isRemovingTuples = false; + // Clear all tuples. // NOTE: Do it after notifying the listener since the listener may need to // use/read the tuple being removed so we cannot free it yet. @@ -225,9 +227,10 @@ namespace RTC { MS_TRACE(); - // While IceServer is being destroyed, it may call listener methods that may - // end calling RemoveTuple(). We must ignore it to avoid double-free issues. - if (this->destroying) + // If IceServer is removing a tuple or all tuples (for instance in the + // destructor), the OnIceServerTupleRemoved() callback may end triggering + // new calls to RemoveTuple(). We must ignore it to avoid double-free issues. + if (this->isRemovingTuples) { return; } @@ -256,7 +259,9 @@ namespace RTC } // Notify the listener. + this->isRemovingTuples = true; this->listener->OnIceServerTupleRemoved(this, removedTuple); + this->isRemovingTuples = false; // Remove it from the list of tuples. // NOTE: Do it after notifying the listener since the listener may need to @@ -810,7 +815,9 @@ namespace RTC MS_ASSERT(removedTuple, "couldn't find any tuple to be removed"); // Notify the listener. + this->isRemovingTuples = true; this->listener->OnIceServerTupleRemoved(this, removedTuple); + this->isRemovingTuples = false; // Remove it from the list of tuples. // NOTE: Do it after notifying the listener since the listener may need to @@ -927,6 +934,8 @@ namespace RTC this->remoteNomination = 0u; // Clear all tuples. + this->isRemovingTuples = true; + for (const auto& it : this->tuples) { auto* storedTuple = const_cast(std::addressof(it)); @@ -935,6 +944,8 @@ namespace RTC this->listener->OnIceServerTupleRemoved(this, storedTuple); } + this->isRemovingTuples = false; + // Clear all tuples. // NOTE: Do it after notifying the listener since the listener may need to // use/read the tuple being removed so we cannot free it yet. From 5fed7caab2fc6ab7cd17c4d317967c9f00a9be33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 9 May 2024 17:22:32 +0200 Subject: [PATCH 429/525] Update NPM deps --- package-lock.json | 443 ++++++++-------------------------------------- package.json | 8 +- 2 files changed, 78 insertions(+), 373 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6a7f57af7d..223ded6784 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,18 +17,18 @@ "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^7.0.1" + "tar": "^7.1.0" }, "devDependencies": { - "@octokit/rest": "^20.1.0", + "@octokit/rest": "^20.1.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@typescript-eslint/eslint-plugin": "^7.8.0", "@typescript-eslint/parser": "^7.8.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.3.0", + "eslint-plugin-jest": "^28.5.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.2", @@ -911,14 +911,6 @@ "node": ">=18.0.0" } }, - "node_modules/@isaacs/fs-minipass/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1458,18 +1450,18 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-21.2.0.tgz", - "integrity": "sha512-xx+Xd6I7rYvul/hgUDqv6TeGX0IOGnhSg9IOeYgd/uI7IAqUy6DE2B6Ipv2M4mWoxaMcWjIzgTIcv8pMO3F3vw==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", - "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.1.tgz", + "integrity": "sha512-ryqobs26cLtM1kQxqeZui4v8FeznirUsksiA+RYemMPJ7Micju0WSkv50dBksTuZks9O5cg4wp+t8fZ/cLY56g==", "dev": true, "dependencies": { - "@octokit/types": "^12.6.0" + "@octokit/types": "^13.5.0" }, "engines": { "node": ">= 18" @@ -1478,21 +1470,6 @@ "@octokit/core": "5" } }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", - "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", - "dev": true - }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", - "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^20.0.0" - } - }, "node_modules/@octokit/plugin-request-log": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", @@ -1506,33 +1483,18 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", - "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.2.tgz", + "integrity": "sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA==", "dev": true, "dependencies": { - "@octokit/types": "^12.6.0" + "@octokit/types": "^13.5.0" }, "engines": { "node": ">= 18" }, "peerDependencies": { - "@octokit/core": "5" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", - "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", - "dev": true - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", - "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^20.0.0" + "@octokit/core": "^5" } }, "node_modules/@octokit/request": { @@ -1565,27 +1527,27 @@ } }, "node_modules/@octokit/rest": { - "version": "20.1.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.0.tgz", - "integrity": "sha512-STVO3itHQLrp80lvcYB2UIKoeil5Ctsgd2s1AM+du3HqZIR35ZH7WE9HLwUOLXH0myA0y3AGNPo8gZtcgIbw0g==", + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.1.tgz", + "integrity": "sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw==", "dev": true, "dependencies": { "@octokit/core": "^5.0.2", - "@octokit/plugin-paginate-rest": "^9.1.5", + "@octokit/plugin-paginate-rest": "11.3.1", "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.2.0" + "@octokit/plugin-rest-endpoint-methods": "13.2.2" }, "engines": { "node": ">= 18" } }, "node_modules/@octokit/types": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.1.0.tgz", - "integrity": "sha512-nBwAFOYqVUUJ2AZFK4ZzESQptaAVqdTDKk8gE0Xr0o99WuPDSrhUC38x0F40xD9OUxXhOOuZKWNNVVLPSHQDvQ==", + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", + "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^21.0.0" + "@octokit/openapi-types": "^22.2.0" } }, "node_modules/@pkgjs/parseargs": { @@ -1748,9 +1710,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "version": "20.12.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", + "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1992,23 +1954,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/type-utils": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", @@ -2118,71 +2063,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@typescript-eslint/utils": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", @@ -2307,23 +2187,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -3127,12 +2990,12 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.3.0.tgz", - "integrity": "sha512-5LjCSSno8E+IUCOX4hJiIb/upPIgpkaDEcaN/40gOcw26t/5UTLHFc4JdxKjOOvGTh0XdCu+fNr0fpOVNvcxMA==", + "version": "28.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz", + "integrity": "sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^6.0.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" }, "engines": { "node": "^16.10.0 || ^18.12.0 || >=20.0.0" @@ -3151,31 +3014,6 @@ } } }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, "node_modules/eslint-plugin-prettier": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", @@ -4947,11 +4785,11 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minizlib": { @@ -5009,14 +4847,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minizlib/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/minizlib/node_modules/rimraf": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", @@ -6044,13 +5874,13 @@ "dev": true }, "node_modules/tar": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.0.1.tgz", - "integrity": "sha512-IjMhdQMZFpKsHEQT3woZVxBtCQY+0wk3CVxdRkGXEgyGa0dNS/ehPvOMr2nmfC7x5Zj2N+l6yZUpmICjLGS35w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.1.0.tgz", + "integrity": "sha512-ENhg4W6BmjYxl8GTaE7/h99f0aXiSWv4kikRZ9n2/JRxypZniE84ILZqimAhxxX7Zb8Px6pFdheW3EeHfhnXQQ==", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", - "minipass": "^5.0.0", + "minipass": "^7.1.0", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" @@ -7154,13 +6984,6 @@ "integrity": "sha512-S00nN1Qt3z3dSP6Db45fj/mksrAq5XWNIJ/SWXGP8XPT2jrzEuYRCSEx08JpJwBcG2F1xgiOtBMGDU0AZHmxew==", "requires": { "minipass": "^7.0.4" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - } } }, "@istanbuljs/load-nyc-config": { @@ -7588,35 +7411,18 @@ } }, "@octokit/openapi-types": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-21.2.0.tgz", - "integrity": "sha512-xx+Xd6I7rYvul/hgUDqv6TeGX0IOGnhSg9IOeYgd/uI7IAqUy6DE2B6Ipv2M4mWoxaMcWjIzgTIcv8pMO3F3vw==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", "dev": true }, "@octokit/plugin-paginate-rest": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", - "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.1.tgz", + "integrity": "sha512-ryqobs26cLtM1kQxqeZui4v8FeznirUsksiA+RYemMPJ7Micju0WSkv50dBksTuZks9O5cg4wp+t8fZ/cLY56g==", "dev": true, "requires": { - "@octokit/types": "^12.6.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", - "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", - "dev": true - }, - "@octokit/types": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", - "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^20.0.0" - } - } + "@octokit/types": "^13.5.0" } }, "@octokit/plugin-request-log": { @@ -7627,29 +7433,12 @@ "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", - "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.2.tgz", + "integrity": "sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA==", "dev": true, "requires": { - "@octokit/types": "^12.6.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", - "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", - "dev": true - }, - "@octokit/types": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", - "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^20.0.0" - } - } + "@octokit/types": "^13.5.0" } }, "@octokit/request": { @@ -7676,24 +7465,24 @@ } }, "@octokit/rest": { - "version": "20.1.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.0.tgz", - "integrity": "sha512-STVO3itHQLrp80lvcYB2UIKoeil5Ctsgd2s1AM+du3HqZIR35ZH7WE9HLwUOLXH0myA0y3AGNPo8gZtcgIbw0g==", + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.1.tgz", + "integrity": "sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw==", "dev": true, "requires": { "@octokit/core": "^5.0.2", - "@octokit/plugin-paginate-rest": "^9.1.5", + "@octokit/plugin-paginate-rest": "11.3.1", "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.2.0" + "@octokit/plugin-rest-endpoint-methods": "13.2.2" } }, "@octokit/types": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.1.0.tgz", - "integrity": "sha512-nBwAFOYqVUUJ2AZFK4ZzESQptaAVqdTDKk8gE0Xr0o99WuPDSrhUC38x0F40xD9OUxXhOOuZKWNNVVLPSHQDvQ==", + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", + "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==", "dev": true, "requires": { - "@octokit/openapi-types": "^21.0.0" + "@octokit/openapi-types": "^22.2.0" } }, "@pkgjs/parseargs": { @@ -7847,9 +7636,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "version": "20.12.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", + "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -8004,16 +7793,6 @@ } } }, - "@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - } - }, "@typescript-eslint/type-utils": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", @@ -8078,48 +7857,6 @@ } } }, - "@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, "@typescript-eslint/utils": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", @@ -8197,16 +7934,6 @@ } } }, - "@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" - } - }, "@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -8780,29 +8507,12 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "28.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.3.0.tgz", - "integrity": "sha512-5LjCSSno8E+IUCOX4hJiIb/upPIgpkaDEcaN/40gOcw26t/5UTLHFc4JdxKjOOvGTh0XdCu+fNr0fpOVNvcxMA==", + "version": "28.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz", + "integrity": "sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==", "dev": true, "requires": { - "@typescript-eslint/utils": "^6.0.0" - }, - "dependencies": { - "@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" - } - } + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" } }, "eslint-plugin-prettier": { @@ -10079,9 +9789,9 @@ } }, "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==" }, "minizlib": { "version": "3.0.1", @@ -10120,11 +9830,6 @@ "brace-expansion": "^2.0.1" } }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - }, "rimraf": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", @@ -10806,13 +10511,13 @@ } }, "tar": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.0.1.tgz", - "integrity": "sha512-IjMhdQMZFpKsHEQT3woZVxBtCQY+0wk3CVxdRkGXEgyGa0dNS/ehPvOMr2nmfC7x5Zj2N+l6yZUpmICjLGS35w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.1.0.tgz", + "integrity": "sha512-ENhg4W6BmjYxl8GTaE7/h99f0aXiSWv4kikRZ9n2/JRxypZniE84ILZqimAhxxX7Zb8Px6pFdheW3EeHfhnXQQ==", "requires": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", - "minipass": "^5.0.0", + "minipass": "^7.1.0", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" diff --git a/package.json b/package.json index 8a09dbbbc2..027df80062 100644 --- a/package.json +++ b/package.json @@ -106,18 +106,18 @@ "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^7.0.1" + "tar": "^7.1.0" }, "devDependencies": { - "@octokit/rest": "^20.1.0", + "@octokit/rest": "^20.1.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@typescript-eslint/eslint-plugin": "^7.8.0", "@typescript-eslint/parser": "^7.8.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.3.0", + "eslint-plugin-jest": "^28.5.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.2", From c042ee7f08ca94ac903f8140f66febb720ef9f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 9 May 2024 17:24:26 +0200 Subject: [PATCH 430/525] 3.14.6 --- CHANGELOG.md | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2100d3eee..431ae87c84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Changelog -### NEXT +### 3.14.6 -- Worker: Fix possible double free when ICE consent check fails ([PR #1393](https://github.com/versatica/mediasoup/pull/1393)). +- Worker: Fix potential double free when ICE consent check fails ([PR #1393](https://github.com/versatica/mediasoup/pull/1393)). ### 3.14.5 diff --git a/package-lock.json b/package-lock.json index 223ded6784..aad83f706d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.5", + "version": "3.14.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.5", + "version": "3.14.6", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 027df80062..0eb048158f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.5", + "version": "3.14.6", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From f1973891e792eab40ebda54deed163d04aa1ead4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 9 May 2024 18:32:20 +0200 Subject: [PATCH 431/525] cosmetic --- .eslintignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.eslintignore b/.eslintignore index cab871b0c9..77bb6c4691 100644 --- a/.eslintignore +++ b/.eslintignore @@ -18,4 +18,3 @@ /worker/test /worker/out /NO_GIT - From 371df0e9fa7134ebd82aff4eb2881106cee9f96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 10 May 2024 10:44:44 +0200 Subject: [PATCH 432/525] Get rid of .eslintignore and .prettierignore (#1395) Instead of ignoring complex paths, be explicit in what ESLint and Prettier must check. --- .eslintignore | 20 -------------------- .prettierignore | 20 -------------------- npm-scripts.mjs | 32 ++++++++++++++++++++++++++++---- 3 files changed, 28 insertions(+), 44 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .prettierignore diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 77bb6c4691..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,20 +0,0 @@ -# NOTE: This file and .prettierignore must contain same paths. - -/.cache -/art -/coverage -/node/lib -/node/src/fbs -/rust -/target -/worker/deps -/worker/fbs -/worker/fuzzer -/worker/include -/worker/prebuild -/worker/pip_invoke -/worker/src -/worker/subprojects -/worker/test -/worker/out -/NO_GIT diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 1a5b7522c6..0000000000 --- a/.prettierignore +++ /dev/null @@ -1,20 +0,0 @@ -# NOTE: This file and .eslintignore must contain same paths. - -/.cache -/art -/coverage -/node/lib -/node/src/fbs -/rust -/target -/worker/deps -/worker/fbs -/worker/fuzzer -/worker/include -/worker/prebuild -/worker/pip_invoke -/worker/src -/worker/subprojects -/worker/test -/worker/out -/NO_GIT diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 280f68c270..a849f65a23 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -25,6 +25,28 @@ const WORKER_PREBUILD_TAR_PATH = `${WORKER_PREBUILD_DIR}/${WORKER_PREBUILD_TAR}` const GH_OWNER = 'versatica'; const GH_REPO = 'mediasoup'; +// Paths for ESLint to check. Converted to string for convenience. +const ESLINT_PATHS = ['node/src', 'npm-scripts.mjs', 'worker/scripts'].join( + ' ' +); +// Paths for ESLint to ignore. Converted to string argument for convenience. +const ESLINT_IGNORE_PATTERN_ARGS = ['node/src/fbs'] + .map(entry => `--ignore-pattern ${entry}`) + .join(' '); +// Paths for Prettier to check/write. Converted to string for convenience. +// NOTE: Prettier ignores paths in .gitignore so we don't need to care about +// node/src/fbs. +const PRETTIER_PATHS = [ + 'CHANGELOG.md', + 'CONTRIBUTING.md', + 'README.md', + 'doc', + 'node/src', + 'npm-scripts.mjs', + 'package.json', + 'worker/scripts', +].join(' '); + const task = process.argv[2]; const args = process.argv.slice(3).join(' '); @@ -331,13 +353,15 @@ function cleanWorkerArtifacts() { function lintNode() { logInfo('lintNode()'); - executeCmd('prettier . --check'); - // Ensure there are no rules that are unnecessary or conflict with Prettier // rules. executeCmd('eslint-config-prettier .eslintrc.js'); - executeCmd('eslint -c .eslintrc.js --max-warnings 0 .'); + executeCmd( + `eslint -c .eslintrc.js --ext=ts,js,mjs --max-warnings 0 ${ESLINT_IGNORE_PATTERN_ARGS} ${ESLINT_PATHS}` + ); + + executeCmd(`prettier --check ${PRETTIER_PATHS}`); } function lintWorker() { @@ -351,7 +375,7 @@ function lintWorker() { function formatNode() { logInfo('formatNode()'); - executeCmd('prettier . --write'); + executeCmd(`prettier --write ${PRETTIER_PATHS}`); } function flatcNode() { From c6aa049d80d36ad505617b28b38b1ab6c41bc917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 10 May 2024 10:58:46 +0200 Subject: [PATCH 433/525] mediasoup-rust 0.17.0 --- rust/CHANGELOG.md | 178 +++++++++++++++++++++++++--------------------- rust/Cargo.toml | 4 +- worker/Cargo.toml | 2 +- 3 files changed, 99 insertions(+), 85 deletions(-) diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index 8152c3efb5..71e2a340fa 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,155 +1,169 @@ # Changelog +# 0.17.0 + +- Updates from mediasoup TypeScript `3.13.18..=3.14.6`. +- General mediasoup changes: + - Worker: Fix crash when closing `WebRtcServer` with active `WebRtcTransports` (PR #1390). + - `Worker: Fix memory leak when using `WebRtcServer` with TCP enabled (PR #1389). + - OPUS: Fix DTX detection (PR #1357). + - `TransportListenInfo`: Add `portRange` (deprecate worker port range) (PR #1365). + - Update worker FlatBuffers to 24.3.6-1 (fix cannot set temporal layer 0) (PR #1348). + - Fix DTLS packets do not honor configured DTLS MTU (attempt 3) (PR #1345). + - Add server side ICE consent checks to detect silent WebRTC disconnections (PR #1332). + - `TransportListenInfo`: "announced ip" can also be a hostname (PR #1322). + - `TransportListenInfo`: Rename "announced ip" to "announced address" (PR #1324). + # 0.16.0 -* Updates from mediasoup TypeScript `3.13.13..=3.13.17`. -* General mediasoup changes: - * `TransportListenInfo.announced_ip` can also be a hostname (PR #1322). - * `TransportListenInfo.announced_ip` is now `announced_address`, `IceCandidate.ip` is now `IceCandidate.address` and `TransportTuple.local_ip` is not `TransportTuple.local_address` (PR #1324). +- Updates from mediasoup TypeScript `3.13.13..=3.13.17`. +- General mediasoup changes: + - `TransportListenInfo.announced_ip` can also be a hostname (PR #1322). + - `TransportListenInfo.announced_ip` is now `announced_address`, `IceCandidate.ip` is now `IceCandidate.address` and `TransportTuple.local_ip` is not `TransportTuple.local_address` (PR #1324). # 0.15.0 -* Expose DataChannel string message as binary (PR #1289). +- Expose DataChannel string message as binary (PR #1289). # 0.14.0 -* Updates from mediasoup TypeScript `3.13.8..=3.13.12`. -* Update h264-profile-level-id dependency to 0.2.0. -* Fix docs build (PR #1271). -* Rename `data_consumer::on_producer_resume` to `data_consumer::on_data_producer_resume` (PR #1271). +- Updates from mediasoup TypeScript `3.13.8..=3.13.12`. +- Update h264-profile-level-id dependency to 0.2.0. +- Fix docs build (PR #1271). +- Rename `data_consumer::on_producer_resume` to `data_consumer::on_data_producer_resume` (PR #1271). # 0.13.0 -* Updates from mediasoup TypeScript `3.13.0..=3.13.7`. -* General mediasoup changes: - * Switch from JSON based messages to `flatbuffers` (PR #1064). - * Enable `liburing` usage for Linux (kernel versions >= 6) (PR #1218). - * Add pause/resume API in `DataProducer` and `DataConsumer` (PR #1104). - * DataChannel subchannels feature (PR #1152). - * `Worker`: Make DTLS fragment stay within MTU size range (PR #1156). - * Replace make + Makefile with Python Invoke library + tasks.py (also fix installation under path with whitespaces) (PR #1239). +- Updates from mediasoup TypeScript `3.13.0..=3.13.7`. +- General mediasoup changes: + - Switch from JSON based messages to `flatbuffers` (PR #1064). + - Enable `liburing` usage for Linux (kernel versions >= 6) (PR #1218). + - Add pause/resume API in `DataProducer` and `DataConsumer` (PR #1104). + - DataChannel subchannels feature (PR #1152). + - `Worker`: Make DTLS fragment stay within MTU size range (PR #1156). + - Replace make + Makefile with Python Invoke library + tasks.py (also fix installation under path with whitespaces) (PR #1239). # 0.12.0 -* Updates from mediasoup TypeScript `3.11.9..=3.12.16`. +- Updates from mediasoup TypeScript `3.11.9..=3.12.16`. # 0.11.4 -* Fix consuming data producer from direct transport by data consumer on non-direct transport. +- Fix consuming data producer from direct transport by data consumer on non-direct transport. # 0.11.3 -* Updates from mediasoup TypeScript `3.11.3..=3.11.8`. +- Updates from mediasoup TypeScript `3.11.3..=3.11.8`. # 0.11.2 -* Updates from mediasoup TypeScript `3.10.11..=3.11.2`. +- Updates from mediasoup TypeScript `3.10.11..=3.11.2`. # 0.11.1 -* Updates from mediasoup TypeScript `3.10.7..=3.10.10`. +- Updates from mediasoup TypeScript `3.10.7..=3.10.10`. # 0.11.0 -* Updates from mediasoup TypeScript `3.10.2..=3.10.6`. +- Updates from mediasoup TypeScript `3.10.2..=3.10.6`. # 0.10.0 -* Updates from mediasoup TypeScript `3.9.10..=3.10.1`. -* `WebRtcServer`: A new class that brings to `WebRtcTransports` the ability to listen on a single UDP/TCP port (PR #834, PR #845). -* Minor API breaking changes. +- Updates from mediasoup TypeScript `3.9.10..=3.10.1`. +- `WebRtcServer`: A new class that brings to `WebRtcTransports` the ability to listen on a single UDP/TCP port (PR #834, PR #845). +- Minor API breaking changes. # 0.9.3 -* Fix a segfaults in tests and under multithreaded executor. -* Fix another racy deadlock situation. -* Expose hierarchical dependencies of ownership of Rust data structures, now it is possible to call `consumer.transport().router().worker().worker_manager()`. -* General mediasoup changes: - * ICE renomination support (PR #756). - * Update `libuv` to 1.43.0. - * TCC client optimizations for faster and more stable BWE (PR #712 by @ggarber). - * Added support for RTP abs-capture-time header (PR #761 by @oto313). - * Fix VP9 kSVC forwarding logic to not forward lower unneded layers (PR #778 by @ggarber). - * Fix update bandwidth estimation configuration and available bitrate when updating max outgoing bitrate (PR #779 by @ggarber). - * Optimize RTP header extension handling (PR #786). - * `RateCalculator`: Reset optimization (PR #785). - * Fix frozen video due to double call to `Consumer::UserOnTransportDisconnected()` (PR #788, thanks to @ggarber for exposing this issue in PR #787). +- Fix a segfaults in tests and under multithreaded executor. +- Fix another racy deadlock situation. +- Expose hierarchical dependencies of ownership of Rust data structures, now it is possible to call `consumer.transport().router().worker().worker_manager()`. +- General mediasoup changes: + - ICE renomination support (PR #756). + - Update `libuv` to 1.43.0. + - TCC client optimizations for faster and more stable BWE (PR #712 by @ggarber). + - Added support for RTP abs-capture-time header (PR #761 by @oto313). + - Fix VP9 kSVC forwarding logic to not forward lower unneded layers (PR #778 by @ggarber). + - Fix update bandwidth estimation configuration and available bitrate when updating max outgoing bitrate (PR #779 by @ggarber). + - Optimize RTP header extension handling (PR #786). + - `RateCalculator`: Reset optimization (PR #785). + - Fix frozen video due to double call to `Consumer::UserOnTransportDisconnected()` (PR #788, thanks to @ggarber for exposing this issue in PR #787). # 0.9.2 -* Update `lru` dependency to fix security vulnerability +- Update `lru` dependency to fix security vulnerability # 0.9.1 -* Fix cleanup of build artifacts. -* Make `Transport` implement `Send`. -* Another fix to rare deadlock. -* Improved Windows support (doesn't require MSVS activation). +- Fix cleanup of build artifacts. +- Make `Transport` implement `Send`. +- Another fix to rare deadlock. +- Improved Windows support (doesn't require MSVS activation). # 0.9.0 -* Fix for receiving data over payload channel. -* Support thread initializer function for worker threads, can be used for pinning worker threads to CPU cores. -* Significant worker communication optimizations (especially latency). -* Switch from file descriptors to function calls when communicating with worker. -* Various optimizations that caused minor breaking changes to public API. -* Requests no longer have internal timeout, but they can now be cancelled, add your own timeouts on top if needed. -* Windows support. -* General mediasoup changes: - * Replaces GYP build system with fully-functional Meson build system (PR #622). - * `Consumer`: Modification of bitrate allocation algorithm (PR #708). - * Single H264/H265 codec configuration in `supportedRtpCapabilities` (PR #718). +- Fix for receiving data over payload channel. +- Support thread initializer function for worker threads, can be used for pinning worker threads to CPU cores. +- Significant worker communication optimizations (especially latency). +- Switch from file descriptors to function calls when communicating with worker. +- Various optimizations that caused minor breaking changes to public API. +- Requests no longer have internal timeout, but they can now be cancelled, add your own timeouts on top if needed. +- Windows support. +- General mediasoup changes: + - Replaces GYP build system with fully-functional Meson build system (PR #622). + - `Consumer`: Modification of bitrate allocation algorithm (PR #708). + - Single H264/H265 codec configuration in `supportedRtpCapabilities` (PR #718). # 0.8.5 -* Fix types for `round_trip_time` and `bitrate_by_layer` fields `ProducerStat` and `ConsumerStat`. -* Accumulation of worker fixes. +- Fix types for `round_trip_time` and `bitrate_by_layer` fields `ProducerStat` and `ConsumerStat`. +- Accumulation of worker fixes. # 0.8.4 -* Add Active Speaker Observer to prelude. -* Fix consumers preventing producers from being closed (regression introduced in 0.8.3). +- Add Active Speaker Observer to prelude. +- Fix consumers preventing producers from being closed (regression introduced in 0.8.3). # 0.8.3 -* prelude module containing traits and structs that should be sufficient for most basic mediasoup-based apps. -* Dominant Speaker Event (PR #603 by @SteveMcFarlin). +- prelude module containing traits and structs that should be sufficient for most basic mediasoup-based apps. +- Dominant Speaker Event (PR #603 by @SteveMcFarlin). ### 0.8.2 -* Support for optional fixed port on transports. +- Support for optional fixed port on transports. ### 0.8.1 -* Add convenience methods for getting information from `TransportTuple` enum, especially local IP/port. -* Add `mid` option in `ConsumerOptions` to provide way to override MID -* Add convenience method `ConsumerStats::consumer_stat()`. +- Add convenience methods for getting information from `TransportTuple` enum, especially local IP/port. +- Add `mid` option in `ConsumerOptions` to provide way to override MID +- Add convenience method `ConsumerStats::consumer_stat()`. ### 0.8.0 -* `NonClosingProducer` removed (use `PipedProducer` instead, they were identical). -* `RtpHeaderExtensionUri::as_str()` now takes `self` instead of `&self`. -* `kind` field of `RtpHeaderExtension` is no longer optional. -* Refactor `ScalabilityMode` from being a string to enum, make sure layers are not zero on type system level. -* Concrete types for info field of tracing events. +- `NonClosingProducer` removed (use `PipedProducer` instead, they were identical). +- `RtpHeaderExtensionUri::as_str()` now takes `self` instead of `&self`. +- `kind` field of `RtpHeaderExtension` is no longer optional. +- Refactor `ScalabilityMode` from being a string to enum, make sure layers are not zero on type system level. +- Concrete types for info field of tracing events. ### 0.7.2 -* Thread and memory safety fixes in mediasoup-sys. -* macOS support. -* `NonClosingProducer` renamed into `PipedProducer` with better docs. -* Internal restructuring of modules for better compatibility with IDEs. -* Feature level updated to mediasoup `3.7.6`. +- Thread and memory safety fixes in mediasoup-sys. +- macOS support. +- `NonClosingProducer` renamed into `PipedProducer` with better docs. +- Internal restructuring of modules for better compatibility with IDEs. +- Feature level updated to mediasoup `3.7.6`. ### 0.7.0 -* Switch from running C++ worker processes to worker threads using mediasoup-sys that wraps mediasoup-worker into library. -* Simplify `WorkerManager::new()` and `WorkerManager::with_executor()` API as the result of above. -* Support `rtxPacketsDiscarded` in `Producer` stats. -* Enable Rust 2018 idioms warnings. -* Make sure all public types have `Debug` implementation on them. -* Enforce docs on public types and add missing documentation. -* Remove `RtpCodecParametersParameters::new()` (`RtpCodecParametersParameters::default()` does the same thing). +- Switch from running C++ worker processes to worker threads using mediasoup-sys that wraps mediasoup-worker into library. +- Simplify `WorkerManager::new()` and `WorkerManager::with_executor()` API as the result of above. +- Support `rtxPacketsDiscarded` in `Producer` stats. +- Enable Rust 2018 idioms warnings. +- Make sure all public types have `Debug` implementation on them. +- Enforce docs on public types and add missing documentation. +- Remove `RtpCodecParametersParameters::new()` (`RtpCodecParametersParameters::default()` does the same thing). ### 0.6.0 diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 5003af1220..98aadbd2bd 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup" -version = "0.16.0" +version = "0.17.0" description = "Cutting Edge WebRTC Video Conferencing in Rust" categories = ["api-bindings", "multimedia", "network-programming"] authors = ["Nazar Mokrynskyi "] @@ -46,7 +46,7 @@ version = "0.8.1" [dependencies.mediasoup-sys] path = "../worker" -version = "0.8.0" +version = "0.9.0" [dependencies.parking_lot] version = "0.12.1" diff --git a/worker/Cargo.toml b/worker/Cargo.toml index bad31281f0..9ec9be69c6 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup-sys" -version = "0.8.0" +version = "0.9.0" description = "FFI bindings to C++ libmediasoup-worker" authors = ["Nazar Mokrynskyi "] edition = "2021" From 7db7e36685784ad25d3b69c07a45daccffed99cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 10 May 2024 12:25:12 +0200 Subject: [PATCH 434/525] Make invoke clean-all task delete worker/include/FBS (#1397) - `worker/fbs/meson.build` produces FlatBuffers C++ include files in `worker/include/FBS` folder. - Despite such a folder is gitignored, `cargo publish` complains if that folder and its files exist. - So make `invoke clean-all` also delete `worker/include/FBS`. - Bonus track: Use `shutil.rmtree(path, ignore_errors=True)` instead of wrapping it with `try/except` everywhere. --- worker/tasks.py | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/worker/tasks.py b/worker/tasks.py index 728e7cf962..d24ad3ed70 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -170,10 +170,7 @@ def clean(ctx): # pylint: disable=unused-argument """ Clean the installation directory """ - try: - shutil.rmtree(MEDIASOUP_INSTALL_DIR); - except: - pass; + shutil.rmtree(MEDIASOUP_INSTALL_DIR, ignore_errors=True); @task @@ -181,10 +178,7 @@ def clean_build(ctx): # pylint: disable=unused-argument """ Clean the build directory """ - try: - shutil.rmtree(BUILD_DIR); - except: - pass; + shutil.rmtree(BUILD_DIR, ignore_errors=True); @task @@ -192,15 +186,8 @@ def clean_pip(ctx): # pylint: disable=unused-argument """ Clean the local pip setup """ - try: - shutil.rmtree(PIP_MESON_NINJA_DIR); - except: - pass; - - try: - shutil.rmtree(PIP_PYLINT_DIR); - except: - pass; + shutil.rmtree(PIP_MESON_NINJA_DIR, ignore_errors=True); + shutil.rmtree(PIP_PYLINT_DIR, ignore_errors=True); @task(pre=[meson_ninja]) @@ -233,10 +220,8 @@ def clean_all(ctx): except: pass; - try: - shutil.rmtree(MEDIASOUP_OUT_DIR); - except: - pass; + shutil.rmtree(MEDIASOUP_OUT_DIR, ignore_errors=True); + shutil.rmtree('include/FBS', ignore_errors=True); @task(pre=[meson_ninja]) From dfca39b363a3eb138ec4c72511ff0f1e9faff234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 13 May 2024 14:02:27 +0200 Subject: [PATCH 435/525] ESLint: include node/tsconfig.json --- npm-scripts.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index a849f65a23..2bb7081e84 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -42,6 +42,7 @@ const PRETTIER_PATHS = [ 'README.md', 'doc', 'node/src', + 'node/tsconfig.json', 'npm-scripts.mjs', 'package.json', 'worker/scripts', From 7207df7f28af5ba002b7e62d6811bf8abfa63da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 May 2024 10:29:34 +0200 Subject: [PATCH 436/525] Update Node dev deps --- package-lock.json | 664 +++++++++------------------------------------- package.json | 6 +- 2 files changed, 133 insertions(+), 537 deletions(-) diff --git a/package-lock.json b/package-lock.json index aad83f706d..a84c9e2fc8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,9 +23,9 @@ "@octokit/rest": "^20.1.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.11", - "@typescript-eslint/eslint-plugin": "^7.8.0", - "@typescript-eslint/parser": "^7.8.0", + "@types/node": "^20.12.12", + "@typescript-eslint/eslint-plugin": "^7.9.0", + "@typescript-eslint/parser": "^7.9.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.5.0", @@ -1698,32 +1698,20 @@ "pretty-format": "^29.0.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.12.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", - "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -1746,21 +1734,19 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", - "integrity": "sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz", + "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/type-utils": "7.8.0", - "@typescript-eslint/utils": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/type-utils": "7.9.0", + "@typescript-eslint/utils": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { @@ -1780,63 +1766,16 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", - "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.8.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.8.0.tgz", - "integrity": "sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", + "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "debug": "^4.3.4" }, "engines": { @@ -1855,14 +1794,14 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", - "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", + "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0" + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1872,96 +1811,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", - "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.8.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", - "integrity": "sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz", + "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/utils": "7.8.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/utils": "7.9.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1981,10 +1838,10 @@ } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", + "node_modules/@typescript-eslint/types": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", + "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1994,14 +1851,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", - "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", + "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2022,24 +1879,7 @@ } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.8.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -2048,7 +1888,7 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", @@ -2064,18 +1904,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", - "integrity": "sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz", + "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.15", - "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "semver": "^7.6.0" + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2088,71 +1925,13 @@ "eslint": "^8.56.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", - "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", - "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", + "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/types": "7.9.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2163,30 +1942,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -3205,9 +2960,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -7624,32 +7379,20 @@ "pretty-format": "^29.0.0" } }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, "@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.12.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", - "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", "dev": true, "requires": { "undici-types": "~5.26.4" } }, - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -7672,171 +7415,79 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", - "integrity": "sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz", + "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/type-utils": "7.8.0", - "@typescript-eslint/utils": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/type-utils": "7.9.0", + "@typescript-eslint/utils": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.6.0", "ts-api-utils": "^1.3.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", - "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0" - } - }, - "@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", - "dev": true - }, - "@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "eslint-visitor-keys": "^3.4.3" - } - } } }, "@typescript-eslint/parser": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.8.0.tgz", - "integrity": "sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", + "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "debug": "^4.3.4" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", - "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0" - } - }, - "@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", - "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "eslint-visitor-keys": "^3.4.3" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } + } + }, + "@typescript-eslint/scope-manager": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", + "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0" } }, "@typescript-eslint/type-utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", - "integrity": "sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz", + "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/utils": "7.8.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/utils": "7.9.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/types": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", + "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", + "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "dependencies": { - "@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", - "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "eslint-visitor-keys": "^3.4.3" - } - }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -7858,80 +7509,25 @@ } }, "@typescript-eslint/utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", - "integrity": "sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz", + "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.15", - "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "semver": "^7.6.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", - "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0" - } - }, - "@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", - "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.8.0", - "eslint-visitor-keys": "^3.4.3" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", + "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.9.0", + "eslint-visitor-keys": "^3.4.3" } }, "@ungap/structured-clone": { @@ -8637,9 +8233,9 @@ "dev": true }, "fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", diff --git a/package.json b/package.json index 0eb048158f..80d73d6af2 100644 --- a/package.json +++ b/package.json @@ -112,9 +112,9 @@ "@octokit/rest": "^20.1.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.11", - "@typescript-eslint/eslint-plugin": "^7.8.0", - "@typescript-eslint/parser": "^7.8.0", + "@types/node": "^20.12.12", + "@typescript-eslint/eslint-plugin": "^7.9.0", + "@typescript-eslint/parser": "^7.9.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.5.0", From 84a39ffe35432a32fee5ab041c7332befc9e5e93 Mon Sep 17 00:00:00 2001 From: Yury Yarashevich Date: Fri, 17 May 2024 18:00:30 +0200 Subject: [PATCH 437/525] Fix rtcp_feedback for audio not written into flat buffers (#1401) --- rust/src/rtp_parameters.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/rust/src/rtp_parameters.rs b/rust/src/rtp_parameters.rs index cefe8d8c1c..2eec79a101 100644 --- a/rust/src/rtp_parameters.rs +++ b/rust/src/rtp_parameters.rs @@ -943,21 +943,19 @@ impl RtpParameters { }) .collect(), ), - rtcp_feedback: match &codec { - RtpCodecParameters::Audio { .. } => None, - RtpCodecParameters::Video { rtcp_feedback, .. } => Some( - rtcp_feedback - .iter() - .map(|rtcp_feedback| { - let (r#type, parameter) = rtcp_feedback.as_type_parameter(); - rtp_parameters::RtcpFeedback { - type_: r#type.to_string(), - parameter: Some(parameter.to_string()), - } - }) - .collect(), - ), - }, + rtcp_feedback: Some( + codec + .rtcp_feedback() + .iter() + .map(|rtcp_feedback| { + let (r#type, parameter) = rtcp_feedback.as_type_parameter(); + rtp_parameters::RtcpFeedback { + type_: r#type.to_string(), + parameter: Some(parameter.to_string()), + } + }) + .collect(), + ), }) .collect(), header_extensions: self @@ -1118,6 +1116,11 @@ impl RtpCodecParameters { parameters } + pub(crate) fn rtcp_feedback(&self) -> &[RtcpFeedback] { + let (Self::Audio { rtcp_feedback, .. } | Self::Video { rtcp_feedback, .. }) = self; + rtcp_feedback + } + pub(crate) fn rtcp_feedback_mut(&mut self) -> &mut Vec { let (Self::Audio { rtcp_feedback, .. } | Self::Video { rtcp_feedback, .. }) = self; rtcp_feedback From 26ee0df7df8468e825195fb41b61abc083400697 Mon Sep 17 00:00:00 2001 From: Junlong Zou Date: Mon, 20 May 2024 01:56:14 +0800 Subject: [PATCH 438/525] fix increase layer when current layer has not receive SR (#1098) --- worker/src/RTC/SimulcastConsumer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index 6151a1c0b8..c0633ca636 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -366,11 +366,11 @@ namespace RTC MS_DEBUG_TAG(simulcast, "first SenderReport [ssrc:%" PRIu32 "]", rtpStream->GetSsrc()); - // If our current selected RTP stream does not yet have SR, do nothing since - // we know we won't be able to switch. - auto* producerCurrentRtpStream = GetProducerCurrentRtpStream(); + // If our RTP timestamp reference stream does not yet have SR, do nothing + // since we know we won't be able to switch. + auto* producerTsReferenceRtpStream = GetProducerTsReferenceRtpStream(); - if (!producerCurrentRtpStream || !producerCurrentRtpStream->GetSenderReportNtpMs()) + if (!producerTsReferenceRtpStream || !producerTsReferenceRtpStream->GetSenderReportNtpMs()) { return; } From 536ac74b1bdecbbc51509edf69c8eaff8dd945c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 19 May 2024 19:57:47 +0200 Subject: [PATCH 439/525] Update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 431ae87c84..3dda6f6800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- `SimulcastConsumer`: Fix increase layer when current layer has not receive SR ([PR #1098](https://github.com/versatica/mediasoup/pull/1098) by @penguinol). + ### 3.14.6 - Worker: Fix potential double free when ICE consent check fails ([PR #1393](https://github.com/versatica/mediasoup/pull/1393)). From a792a13f45fa0d21cf9336bc87ef80dd59fb8f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 May 2024 10:48:21 +0200 Subject: [PATCH 440/525] Ignore RTP packets with empty payload (#1403) --- CHANGELOG.md | 1 + worker/include/RTC/RtcLogger.hpp | 1 + worker/src/RTC/PipeConsumer.cpp | 12 ++++++++++++ worker/src/RTC/RtcLogger.cpp | 1 + worker/src/RTC/RtpStreamRecv.cpp | 14 ++++++++++++++ worker/src/RTC/SimpleConsumer.cpp | 12 ++++++++++++ worker/src/RTC/SimulcastConsumer.cpp | 12 ++++++++++++ worker/src/RTC/SvcConsumer.cpp | 12 ++++++++++++ 8 files changed, 65 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dda6f6800..ae24b981d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT - `SimulcastConsumer`: Fix increase layer when current layer has not receive SR ([PR #1098](https://github.com/versatica/mediasoup/pull/1098) by @penguinol). +- Ignore RTP packets with empty payload ([PR #1403](https://github.com/versatica/mediasoup/pull/1403), credits to @ggarber). ### 3.14.6 diff --git a/worker/include/RTC/RtcLogger.hpp b/worker/include/RTC/RtcLogger.hpp index a241d407c2..334e9df552 100644 --- a/worker/include/RTC/RtcLogger.hpp +++ b/worker/include/RTC/RtcLogger.hpp @@ -21,6 +21,7 @@ namespace RTC INVALID_TARGET_LAYER, UNSUPPORTED_PAYLOAD_TYPE, NOT_A_KEYFRAME, + EMPTY_PAYLOAD, SPATIAL_LAYER_MISMATCH, TOO_HIGH_TIMESTAMP_EXTRA_NEEDED, PACKET_PREVIOUS_TO_SPATIAL_LAYER_SWITCH, diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index 2312ed87c9..35a0c3d1a9 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -250,6 +250,18 @@ namespace RTC auto& syncRequired = this->mapRtpStreamSyncRequired.at(rtpStream); auto& rtpSeqManager = this->mapRtpStreamRtpSeqManager.at(rtpStream); + // Packets with only padding are not forwarded. + if (packet->GetPayloadLength() == 0) + { + rtpSeqManager.Drop(packet->GetSequenceNumber()); + +#ifdef MS_RTC_LOGGER_RTP + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); +#endif + + return; + } + // If we need to sync, support key frames and this is not a key frame, ignore // the packet. if (syncRequired && this->keyFrameSupported && !packet->IsKeyFrame()) diff --git a/worker/src/RTC/RtcLogger.cpp b/worker/src/RTC/RtcLogger.cpp index 2b7a72b093..4237dcd90f 100644 --- a/worker/src/RTC/RtcLogger.cpp +++ b/worker/src/RTC/RtcLogger.cpp @@ -18,6 +18,7 @@ namespace RTC { RtpPacket::DropReason::INVALID_TARGET_LAYER, "InvalidTargetLayer" }, { RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE, "UnsupportedPayloadType" }, { RtpPacket::DropReason::NOT_A_KEYFRAME, "NotAKeyframe" }, + { RtpPacket::DropReason::EMPTY_PAYLOAD, "EmptyPayload" }, { RtpPacket::DropReason::SPATIAL_LAYER_MISMATCH, "SpatialLayerMismatch" }, { RtpPacket::DropReason::TOO_HIGH_TIMESTAMP_EXTRA_NEEDED, "TooHighTimestampExtraNeeded" }, { RtpPacket::DropReason::PACKET_PREVIOUS_TO_SPATIAL_LAYER_SWITCH, "PacketPreviousToSpatialLayerSwitch" }, diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index 70917e04ff..439f186908 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -303,6 +303,13 @@ namespace RTC // Calculate Jitter. CalculateJitter(packet->GetTimestamp()); + // Padding only packet, do not consider it for counter increase nor + // stream activation. + if (packet->GetPayloadLength() == 0) + { + return true; + } + // Increase transmission counter. this->transmissionCounter.Update(packet); @@ -413,6 +420,13 @@ namespace RTC // NACKed packet. if (this->nackGenerator->ReceivePacket(packet, /*isRecovered*/ true)) { + // Padding only packet, do not consider it for counter increase nor + // stream activation. + if (packet->GetPayloadLength() == 0) + { + return true; + } + // Mark the packet as repaired. RTC::RtpStream::PacketRepaired(packet); diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index 9523ce3f71..ce7fa9283c 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -314,6 +314,18 @@ namespace RTC return; } + // Packets with only padding are not forwarded. + if (packet->GetPayloadLength() == 0) + { + this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + +#ifdef MS_RTC_LOGGER_RTP + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); +#endif + + return; + } + auto payloadType = packet->GetPayloadType(); // NOTE: This may happen if this Consumer supports just some codecs of those diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index c0633ca636..d55ba6af58 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -724,6 +724,18 @@ namespace RTC return; } + // Packets with only padding are not forwarded. + if (packet->GetPayloadLength() == 0) + { + this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + +#ifdef MS_RTC_LOGGER_RTP + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); +#endif + + return; + } + if (this->targetTemporalLayer == -1) { #ifdef MS_RTC_LOGGER_RTP diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index 24ddf2418c..bc0ce1417b 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -639,6 +639,18 @@ namespace RTC return; } + // Packets with only padding are not forwarded. + if (packet->GetPayloadLength() == 0) + { + this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + +#ifdef MS_RTC_LOGGER_RTP + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); +#endif + + return; + } + // clang-format off if ( this->encodingContext->GetTargetSpatialLayer() == -1 || From 18e36978c6ee8f8e161a90804322ff63c3fbe883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 May 2024 13:53:30 +0200 Subject: [PATCH 441/525] Update NPM dev deps --- package-lock.json | 192 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 101 insertions(+), 97 deletions(-) diff --git a/package-lock.json b/package-lock.json index a84c9e2fc8..1240d45e6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,8 +24,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.12", - "@typescript-eslint/eslint-plugin": "^7.9.0", - "@typescript-eslint/parser": "^7.9.0", + "@typescript-eslint/eslint-plugin": "^7.10.0", + "@typescript-eslint/parser": "^7.10.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.5.0", @@ -36,7 +36,7 @@ "pick-port": "^2.0.1", "prettier": "^3.2.5", "sctp": "^1.0.0", - "ts-jest": "^29.1.2", + "ts-jest": "^29.1.3", "typescript": "^5.4.5" }, "engines": { @@ -1734,16 +1734,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz", - "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz", + "integrity": "sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/type-utils": "7.9.0", - "@typescript-eslint/utils": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", + "@typescript-eslint/scope-manager": "7.10.0", + "@typescript-eslint/type-utils": "7.10.0", + "@typescript-eslint/utils": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1767,15 +1767,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", - "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.10.0.tgz", + "integrity": "sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", + "@typescript-eslint/scope-manager": "7.10.0", + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/typescript-estree": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0", "debug": "^4.3.4" }, "engines": { @@ -1795,13 +1795,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", - "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz", + "integrity": "sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0" + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1812,13 +1812,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz", - "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz", + "integrity": "sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/utils": "7.9.0", + "@typescript-eslint/typescript-estree": "7.10.0", + "@typescript-eslint/utils": "7.10.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1839,9 +1839,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", - "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.10.0.tgz", + "integrity": "sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1852,13 +1852,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", - "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz", + "integrity": "sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1904,15 +1904,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz", - "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz", + "integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0" + "@typescript-eslint/scope-manager": "7.10.0", + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/typescript-estree": "7.10.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1926,12 +1926,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", - "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz", + "integrity": "sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/types": "7.10.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -5780,9 +5780,9 @@ } }, "node_modules/ts-jest": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", - "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", + "version": "29.1.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.3.tgz", + "integrity": "sha512-6L9qz3ginTd1NKhOxmkP0qU3FyKjj5CPoY+anszfVn6Pmv/RIKzhiMCsH7Yb7UvJR9I2A64rm4zQl531s2F1iw==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -5798,10 +5798,11 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^16.10.0 || ^18.0.0 || >=20.0.0" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", @@ -5811,6 +5812,9 @@ "@babel/core": { "optional": true }, + "@jest/transform": { + "optional": true + }, "@jest/types": { "optional": true }, @@ -7415,16 +7419,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz", - "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz", + "integrity": "sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/type-utils": "7.9.0", - "@typescript-eslint/utils": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", + "@typescript-eslint/scope-manager": "7.10.0", + "@typescript-eslint/type-utils": "7.10.0", + "@typescript-eslint/utils": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7432,54 +7436,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", - "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.10.0.tgz", + "integrity": "sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", + "@typescript-eslint/scope-manager": "7.10.0", + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/typescript-estree": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", - "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz", + "integrity": "sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0" + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0" } }, "@typescript-eslint/type-utils": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz", - "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz", + "integrity": "sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/utils": "7.9.0", + "@typescript-eslint/typescript-estree": "7.10.0", + "@typescript-eslint/utils": "7.10.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", - "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.10.0.tgz", + "integrity": "sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", - "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz", + "integrity": "sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==", "dev": true, "requires": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/visitor-keys": "7.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7509,24 +7513,24 @@ } }, "@typescript-eslint/utils": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz", - "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz", + "integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0" + "@typescript-eslint/scope-manager": "7.10.0", + "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/typescript-estree": "7.10.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", - "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz", + "integrity": "sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/types": "7.10.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -10214,9 +10218,9 @@ "requires": {} }, "ts-jest": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", - "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", + "version": "29.1.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.3.tgz", + "integrity": "sha512-6L9qz3ginTd1NKhOxmkP0qU3FyKjj5CPoY+anszfVn6Pmv/RIKzhiMCsH7Yb7UvJR9I2A64rm4zQl531s2F1iw==", "dev": true, "requires": { "bs-logger": "0.x", diff --git a/package.json b/package.json index 80d73d6af2..ab7f0639fc 100644 --- a/package.json +++ b/package.json @@ -113,8 +113,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.12", - "@typescript-eslint/eslint-plugin": "^7.9.0", - "@typescript-eslint/parser": "^7.9.0", + "@typescript-eslint/eslint-plugin": "^7.10.0", + "@typescript-eslint/parser": "^7.10.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.5.0", @@ -125,7 +125,7 @@ "pick-port": "^2.0.1", "prettier": "^3.2.5", "sctp": "^1.0.0", - "ts-jest": "^29.1.2", + "ts-jest": "^29.1.3", "typescript": "^5.4.5" } } From 672727bbe38e2ebb6005e05cf1165a86ee346fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 May 2024 13:56:58 +0200 Subject: [PATCH 442/525] 3.14.7 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae24b981d4..403a499a96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### NEXT +### 3.14.7 - `SimulcastConsumer`: Fix increase layer when current layer has not receive SR ([PR #1098](https://github.com/versatica/mediasoup/pull/1098) by @penguinol). - Ignore RTP packets with empty payload ([PR #1403](https://github.com/versatica/mediasoup/pull/1403), credits to @ggarber). diff --git a/package-lock.json b/package-lock.json index 1240d45e6d..05214944d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.6", + "version": "3.14.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.6", + "version": "3.14.7", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index ab7f0639fc..b67a564bf0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.6", + "version": "3.14.7", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 8409661a1663bf3dd2d7e70f26b5531c698d4dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 10 Jun 2024 10:33:48 +0200 Subject: [PATCH 443/525] update npm deps --- package-lock.json | 284 +++++++++++++++++++++++----------------------- package.json | 20 ++-- 2 files changed, 152 insertions(+), 152 deletions(-) diff --git a/package-lock.json b/package-lock.json index 05214944d9..83f7171170 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,33 +10,33 @@ "hasInstallScript": true, "license": "ISC", "dependencies": { - "@types/ini": "^4.1.0", - "debug": "^4.3.4", + "@types/ini": "^4.1.1", + "debug": "^4.3.5", "flatbuffers": "^24.3.25", "h264-profile-level-id": "^2.0.0", - "ini": "^4.1.2", + "ini": "^4.1.3", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^7.1.0" + "tar": "^7.2.0" }, "devDependencies": { "@octokit/rest": "^20.1.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.12", - "@typescript-eslint/eslint-plugin": "^7.10.0", - "@typescript-eslint/parser": "^7.10.0", + "@types/node": "^20.14.2", + "@typescript-eslint/eslint-plugin": "^7.12.0", + "@typescript-eslint/parser": "^7.12.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.5.0", + "eslint-plugin-jest": "^28.6.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.2", "open-cli": "^8.0.0", "pick-port": "^2.0.1", - "prettier": "^3.2.5", + "prettier": "^3.3.1", "sctp": "^1.0.0", - "ts-jest": "^29.1.3", + "ts-jest": "^29.1.4", "typescript": "^5.4.5" }, "engines": { @@ -1660,9 +1660,9 @@ } }, "node_modules/@types/ini": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@types/ini/-/ini-4.1.0.tgz", - "integrity": "sha512-mTehMtc+xtnWBBvqizcqYCktKDBH2WChvx1GU3Sfe4PysFDXiNe+1YwtpVX1MDtCa4NQrSPw2+3HmvXHY3gt1w==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-MIyNUZipBTbyUNnhvuXJTY7B6qNI78meck9Jbv3wk0OgNwRyOOVEKDutAkOs1snB/tx0FafyR6/SN4Ps0hZPeg==" }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", @@ -1704,9 +1704,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.12.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", - "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1734,16 +1734,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz", - "integrity": "sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz", + "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/type-utils": "7.10.0", - "@typescript-eslint/utils": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/type-utils": "7.12.0", + "@typescript-eslint/utils": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1767,15 +1767,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.10.0.tgz", - "integrity": "sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz", + "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/typescript-estree": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/typescript-estree": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", "debug": "^4.3.4" }, "engines": { @@ -1795,13 +1795,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz", - "integrity": "sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", + "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0" + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1812,13 +1812,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz", - "integrity": "sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz", + "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.10.0", - "@typescript-eslint/utils": "7.10.0", + "@typescript-eslint/typescript-estree": "7.12.0", + "@typescript-eslint/utils": "7.12.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1839,9 +1839,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.10.0.tgz", - "integrity": "sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz", + "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1852,13 +1852,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz", - "integrity": "sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", + "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1904,15 +1904,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz", - "integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", + "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/typescript-estree": "7.10.0" + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/typescript-estree": "7.12.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1926,12 +1926,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz", - "integrity": "sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", + "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/types": "7.12.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2487,9 +2487,9 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -2745,9 +2745,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz", - "integrity": "sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==", + "version": "28.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz", + "integrity": "sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" @@ -3456,9 +3456,9 @@ "dev": true }, "node_modules/ini": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", - "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -5058,9 +5058,9 @@ } }, "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", + "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -5629,9 +5629,9 @@ "dev": true }, "node_modules/tar": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.1.0.tgz", - "integrity": "sha512-ENhg4W6BmjYxl8GTaE7/h99f0aXiSWv4kikRZ9n2/JRxypZniE84ILZqimAhxxX7Zb8Px6pFdheW3EeHfhnXQQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.2.0.tgz", + "integrity": "sha512-hctwP0Nb4AB60bj8WQgRYaMOuJYRAPMGiQUAotms5igN8ppfQM+IvjQ5HcKu1MaZh2Wy2KWVTe563Yj8dfc14w==", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", @@ -5780,9 +5780,9 @@ } }, "node_modules/ts-jest": { - "version": "29.1.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.3.tgz", - "integrity": "sha512-6L9qz3ginTd1NKhOxmkP0qU3FyKjj5CPoY+anszfVn6Pmv/RIKzhiMCsH7Yb7UvJR9I2A64rm4zQl531s2F1iw==", + "version": "29.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz", + "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -7345,9 +7345,9 @@ } }, "@types/ini": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@types/ini/-/ini-4.1.0.tgz", - "integrity": "sha512-mTehMtc+xtnWBBvqizcqYCktKDBH2WChvx1GU3Sfe4PysFDXiNe+1YwtpVX1MDtCa4NQrSPw2+3HmvXHY3gt1w==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-MIyNUZipBTbyUNnhvuXJTY7B6qNI78meck9Jbv3wk0OgNwRyOOVEKDutAkOs1snB/tx0FafyR6/SN4Ps0hZPeg==" }, "@types/istanbul-lib-coverage": { "version": "2.0.4", @@ -7389,9 +7389,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.12.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", - "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7419,16 +7419,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz", - "integrity": "sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz", + "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/type-utils": "7.10.0", - "@typescript-eslint/utils": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/type-utils": "7.12.0", + "@typescript-eslint/utils": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7436,54 +7436,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.10.0.tgz", - "integrity": "sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz", + "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/typescript-estree": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/typescript-estree": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz", - "integrity": "sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", + "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0" + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0" } }, "@typescript-eslint/type-utils": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz", - "integrity": "sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz", + "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.10.0", - "@typescript-eslint/utils": "7.10.0", + "@typescript-eslint/typescript-estree": "7.12.0", + "@typescript-eslint/utils": "7.12.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.10.0.tgz", - "integrity": "sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz", + "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz", - "integrity": "sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", + "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7513,24 +7513,24 @@ } }, "@typescript-eslint/utils": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz", - "integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", + "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/typescript-estree": "7.10.0" + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/typescript-estree": "7.12.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz", - "integrity": "sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", + "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/types": "7.12.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -7926,9 +7926,9 @@ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "requires": { "ms": "2.1.2" } @@ -8107,9 +8107,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "28.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz", - "integrity": "sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==", + "version": "28.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz", + "integrity": "sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg==", "dev": true, "requires": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" @@ -8582,9 +8582,9 @@ "dev": true }, "ini": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", - "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==" + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==" }, "ip": { "version": "1.1.9", @@ -9739,9 +9739,9 @@ "dev": true }, "prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", + "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", "dev": true }, "prettier-linter-helpers": { @@ -10111,9 +10111,9 @@ } }, "tar": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.1.0.tgz", - "integrity": "sha512-ENhg4W6BmjYxl8GTaE7/h99f0aXiSWv4kikRZ9n2/JRxypZniE84ILZqimAhxxX7Zb8Px6pFdheW3EeHfhnXQQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.2.0.tgz", + "integrity": "sha512-hctwP0Nb4AB60bj8WQgRYaMOuJYRAPMGiQUAotms5igN8ppfQM+IvjQ5HcKu1MaZh2Wy2KWVTe563Yj8dfc14w==", "requires": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", @@ -10218,9 +10218,9 @@ "requires": {} }, "ts-jest": { - "version": "29.1.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.3.tgz", - "integrity": "sha512-6L9qz3ginTd1NKhOxmkP0qU3FyKjj5CPoY+anszfVn6Pmv/RIKzhiMCsH7Yb7UvJR9I2A64rm4zQl531s2F1iw==", + "version": "29.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz", + "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==", "dev": true, "requires": { "bs-logger": "0.x", diff --git a/package.json b/package.json index b67a564bf0..6da5862f79 100644 --- a/package.json +++ b/package.json @@ -99,33 +99,33 @@ ] }, "dependencies": { - "@types/ini": "^4.1.0", - "debug": "^4.3.4", + "@types/ini": "^4.1.1", + "debug": "^4.3.5", "flatbuffers": "^24.3.25", "h264-profile-level-id": "^2.0.0", - "ini": "^4.1.2", + "ini": "^4.1.3", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^7.1.0" + "tar": "^7.2.0" }, "devDependencies": { "@octokit/rest": "^20.1.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.12", - "@typescript-eslint/eslint-plugin": "^7.10.0", - "@typescript-eslint/parser": "^7.10.0", + "@types/node": "^20.14.2", + "@typescript-eslint/eslint-plugin": "^7.12.0", + "@typescript-eslint/parser": "^7.12.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.5.0", + "eslint-plugin-jest": "^28.6.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.2", "open-cli": "^8.0.0", "pick-port": "^2.0.1", - "prettier": "^3.2.5", + "prettier": "^3.3.1", "sctp": "^1.0.0", - "ts-jest": "^29.1.3", + "ts-jest": "^29.1.4", "typescript": "^5.4.5" } } From f207a5fba10a98dbb806a440c07572f06bf9ec35 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Mon, 10 Jun 2024 13:00:18 +0300 Subject: [PATCH 444/525] Replace support template message with a link (#1406) --- .github/ISSUE_TEMPLATE/Support_Question.md | 12 ------------ .github/ISSUE_TEMPLATE/config.yml | 7 +++++++ Cargo.lock | 4 ++-- 3 files changed, 9 insertions(+), 14 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/Support_Question.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/Support_Question.md b/.github/ISSUE_TEMPLATE/Support_Question.md deleted file mode 100644 index 2ea1f7895f..0000000000 --- a/.github/ISSUE_TEMPLATE/Support_Question.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: 🙈 Support Question -about: If you have any questions use the mediasoup Discourse Group ---- - -**IMPORTANT:** We primarily use GitHub as an issue tracker. Please, use the mediasoup Discourse Group if you have questions or doubts or if you need support about mediasoup and its ecosystem: - -https://mediasoup.discourse.group - -Before asking any questions, please check the mediasoup official documentation: - -https://mediasoup.org/documentation diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..b82133b787 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +blank_issues_enabled: true +contact_links: + - name: 🙈 Support Question + url: https://mediasoup.discourse.group + about: | + We primarily use GitHub as an issue tracker. Please, use the mediasoup Discourse Group if you have questions or doubts or if you need support about mediasoup and its ecosystem. + Before asking any questions, please check the mediasoup official documentation: diff --git a/Cargo.lock b/Cargo.lock index b354e488c9..aa2c9cddaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1354,7 +1354,7 @@ checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" [[package]] name = "mediasoup" -version = "0.16.0" +version = "0.17.0" dependencies = [ "actix", "actix-web", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "mediasoup-sys" -version = "0.8.0" +version = "0.9.0" dependencies = [ "planus", "planus-codegen", From 5cc099462eca16e4a9b199164960d643d0897a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 10 Jun 2024 12:04:49 +0200 Subject: [PATCH 445/525] cosmetic --- .github/ISSUE_TEMPLATE/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index b82133b787..415576c32d 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -4,4 +4,4 @@ contact_links: url: https://mediasoup.discourse.group about: | We primarily use GitHub as an issue tracker. Please, use the mediasoup Discourse Group if you have questions or doubts or if you need support about mediasoup and its ecosystem. - Before asking any questions, please check the mediasoup official documentation: + Before asking any questions, please check the mediasoup official documentation at https://mediasoup.org/documentation From b3017e2d578e26c15fce2b53b7eb5ff2697a541d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 11 Jun 2024 14:41:49 +0200 Subject: [PATCH 446/525] Update NPM dev deps --- package-lock.json | 186 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 96 insertions(+), 96 deletions(-) diff --git a/package-lock.json b/package-lock.json index 83f7171170..9e7c4e6cfe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,8 +24,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.14.2", - "@typescript-eslint/eslint-plugin": "^7.12.0", - "@typescript-eslint/parser": "^7.12.0", + "@typescript-eslint/eslint-plugin": "^7.13.0", + "@typescript-eslint/parser": "^7.13.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", @@ -34,7 +34,7 @@ "marked": "^12.0.2", "open-cli": "^8.0.0", "pick-port": "^2.0.1", - "prettier": "^3.3.1", + "prettier": "^3.3.2", "sctp": "^1.0.0", "ts-jest": "^29.1.4", "typescript": "^5.4.5" @@ -1734,16 +1734,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz", - "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz", + "integrity": "sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/type-utils": "7.12.0", - "@typescript-eslint/utils": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/type-utils": "7.13.0", + "@typescript-eslint/utils": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1767,15 +1767,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz", - "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.0.tgz", + "integrity": "sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "debug": "^4.3.4" }, "engines": { @@ -1795,13 +1795,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", - "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", + "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0" + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1812,13 +1812,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz", - "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz", + "integrity": "sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/utils": "7.12.0", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/utils": "7.13.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1839,9 +1839,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz", - "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1852,13 +1852,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", - "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", + "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1904,15 +1904,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", - "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", + "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0" + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1926,12 +1926,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", - "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", + "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/types": "7.13.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -5058,9 +5058,9 @@ } }, "node_modules/prettier": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", - "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -7419,16 +7419,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz", - "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz", + "integrity": "sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/type-utils": "7.12.0", - "@typescript-eslint/utils": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/type-utils": "7.13.0", + "@typescript-eslint/utils": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7436,54 +7436,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz", - "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.0.tgz", + "integrity": "sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", - "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", + "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", "dev": true, "requires": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0" + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0" } }, "@typescript-eslint/type-utils": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz", - "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz", + "integrity": "sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/utils": "7.12.0", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/utils": "7.13.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz", - "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", - "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", + "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7513,24 +7513,24 @@ } }, "@typescript-eslint/utils": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", - "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", + "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0" + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", - "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", + "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/types": "7.13.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -9739,9 +9739,9 @@ "dev": true }, "prettier": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", - "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", "dev": true }, "prettier-linter-helpers": { diff --git a/package.json b/package.json index 6da5862f79..f5c288af3f 100644 --- a/package.json +++ b/package.json @@ -113,8 +113,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.14.2", - "@typescript-eslint/eslint-plugin": "^7.12.0", - "@typescript-eslint/parser": "^7.12.0", + "@typescript-eslint/eslint-plugin": "^7.13.0", + "@typescript-eslint/parser": "^7.13.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", @@ -123,7 +123,7 @@ "marked": "^12.0.2", "open-cli": "^8.0.0", "pick-port": "^2.0.1", - "prettier": "^3.3.1", + "prettier": "^3.3.2", "sctp": "^1.0.0", "ts-jest": "^29.1.4", "typescript": "^5.4.5" From e055a870ae0bf752af2a64e40024f34089eeaf7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:49:05 +0200 Subject: [PATCH 447/525] Bump braces in the npm_and_yarn group across 1 directory (#1408) Bumps the npm_and_yarn group with 1 update in the / directory: [braces](https://github.com/micromatch/braces). Updates `braces` from 3.0.2 to 3.0.3 - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9e7c4e6cfe..efe53f0b07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2175,12 +2175,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -3069,9 +3069,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -7709,12 +7709,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browserslist": { @@ -8320,9 +8320,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" From 81e2099126f4f470d10963aa8e9348971fd01803 Mon Sep 17 00:00:00 2001 From: satoren Date: Wed, 19 Jun 2024 19:43:21 +0900 Subject: [PATCH 448/525] fix asan error for new-delete-type-mismatch (#1411) --- worker/src/handles/UnixStreamSocketHandle.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/worker/src/handles/UnixStreamSocketHandle.cpp b/worker/src/handles/UnixStreamSocketHandle.cpp index 1696cb3736..8b34b8a2ce 100644 --- a/worker/src/handles/UnixStreamSocketHandle.cpp +++ b/worker/src/handles/UnixStreamSocketHandle.cpp @@ -57,11 +57,6 @@ inline static void onClosePipe(uv_handle_t* handle) delete reinterpret_cast(handle); } -inline static void onCloseShutdown(uv_handle_t* handle) -{ - delete reinterpret_cast(handle); -} - inline static void onShutdown(uv_shutdown_t* req, int /*status*/) { auto* handle = req->handle; @@ -69,7 +64,7 @@ inline static void onShutdown(uv_shutdown_t* req, int /*status*/) delete req; // Now do close the handle. - uv_close(reinterpret_cast(handle), static_cast(onCloseShutdown)); + uv_close(reinterpret_cast(handle), static_cast(onClosePipe)); } /* Instance methods. */ From 08bdf564ed4210d14437d6102b879020265191c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 19 Jun 2024 12:47:18 +0200 Subject: [PATCH 449/525] TcpConnectionHandle.cpp: properly close handle This is the same change as done in PR #1411 but here in `TcpConnectionHandle.cpp`. --- worker/src/handles/TcpConnectionHandle.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/worker/src/handles/TcpConnectionHandle.cpp b/worker/src/handles/TcpConnectionHandle.cpp index 5a7c39ba30..475a078ad0 100644 --- a/worker/src/handles/TcpConnectionHandle.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -56,11 +56,6 @@ inline static void onCloseTcp(uv_handle_t* handle) delete reinterpret_cast(handle); } -inline static void onCloseShutdown(uv_handle_t* handle) -{ - delete reinterpret_cast(handle); -} - inline static void onShutdown(uv_shutdown_t* req, int /*status*/) { auto* handle = req->handle; @@ -68,7 +63,7 @@ inline static void onShutdown(uv_shutdown_t* req, int /*status*/) delete req; // Now do close the handle. - uv_close(reinterpret_cast(handle), static_cast(onCloseShutdown)); + uv_close(reinterpret_cast(handle), static_cast(onCloseTcp)); } /* Instance methods. */ From dab1a225ceccf0552abcb16e01ef5780fcd98d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 19 Jun 2024 12:51:35 +0200 Subject: [PATCH 450/525] Update NPM deps --- package-lock.json | 244 +++++++++++++++++++++++----------------------- package.json | 12 +-- 2 files changed, 128 insertions(+), 128 deletions(-) diff --git a/package-lock.json b/package-lock.json index efe53f0b07..bb2afc004c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,26 +17,26 @@ "ini": "^4.1.3", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^7.2.0" + "tar": "^7.4.0" }, "devDependencies": { "@octokit/rest": "^20.1.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.2", - "@typescript-eslint/eslint-plugin": "^7.13.0", - "@typescript-eslint/parser": "^7.13.0", + "@types/node": "^20.14.5", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^12.0.2", + "marked": "^13.0.0", "open-cli": "^8.0.0", "pick-port": "^2.0.1", "prettier": "^3.3.2", "sctp": "^1.0.0", - "ts-jest": "^29.1.4", + "ts-jest": "^29.1.5", "typescript": "^5.4.5" }, "engines": { @@ -1704,9 +1704,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "20.14.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.5.tgz", + "integrity": "sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1734,16 +1734,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz", - "integrity": "sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", + "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.13.0", - "@typescript-eslint/type-utils": "7.13.0", - "@typescript-eslint/utils": "7.13.0", - "@typescript-eslint/visitor-keys": "7.13.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/type-utils": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1767,15 +1767,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.0.tgz", - "integrity": "sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", + "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.13.0", - "@typescript-eslint/types": "7.13.0", - "@typescript-eslint/typescript-estree": "7.13.0", - "@typescript-eslint/visitor-keys": "7.13.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", "debug": "^4.3.4" }, "engines": { @@ -1795,13 +1795,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", - "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", + "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.13.0", - "@typescript-eslint/visitor-keys": "7.13.0" + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1812,13 +1812,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz", - "integrity": "sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", + "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.13.0", - "@typescript-eslint/utils": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/utils": "7.13.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1839,9 +1839,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", - "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", + "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1852,13 +1852,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", - "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", + "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.13.0", - "@typescript-eslint/visitor-keys": "7.13.0", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1904,15 +1904,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", - "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", + "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.13.0", - "@typescript-eslint/types": "7.13.0", - "@typescript-eslint/typescript-estree": "7.13.0" + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1926,12 +1926,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", - "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", + "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/types": "7.13.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -4467,9 +4467,9 @@ } }, "node_modules/marked": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", - "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.0.tgz", + "integrity": "sha512-VTeDCd9txf4KLLljUZ0nljE/Incb9SrWuueE44QVuU0pkOdh4sfCeW1Z6lPcxyDRSVY6rm8db/0OPaN75RNUmw==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -4540,9 +4540,9 @@ } }, "node_modules/minipass": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", - "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "engines": { "node": ">=16 || 14 >=14.17" } @@ -5629,13 +5629,13 @@ "dev": true }, "node_modules/tar": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.2.0.tgz", - "integrity": "sha512-hctwP0Nb4AB60bj8WQgRYaMOuJYRAPMGiQUAotms5igN8ppfQM+IvjQ5HcKu1MaZh2Wy2KWVTe563Yj8dfc14w==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.0.tgz", + "integrity": "sha512-XQs0S8fuAkQWuqhDeCdMlJXDX80D7EOVLDPVFkna9yQfzS+PHKgfxcei0jf6/+QAWcjqrnC8uM3fSAnrQl+XYg==", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", - "minipass": "^7.1.0", + "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" @@ -5780,9 +5780,9 @@ } }, "node_modules/ts-jest": { - "version": "29.1.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz", - "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==", + "version": "29.1.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.5.tgz", + "integrity": "sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -7389,9 +7389,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "20.14.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.5.tgz", + "integrity": "sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7419,16 +7419,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz", - "integrity": "sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", + "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.13.0", - "@typescript-eslint/type-utils": "7.13.0", - "@typescript-eslint/utils": "7.13.0", - "@typescript-eslint/visitor-keys": "7.13.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/type-utils": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7436,54 +7436,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.0.tgz", - "integrity": "sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", + "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.13.0", - "@typescript-eslint/types": "7.13.0", - "@typescript-eslint/typescript-estree": "7.13.0", - "@typescript-eslint/visitor-keys": "7.13.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", - "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", + "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.13.0", - "@typescript-eslint/visitor-keys": "7.13.0" + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1" } }, "@typescript-eslint/type-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz", - "integrity": "sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", + "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.13.0", - "@typescript-eslint/utils": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/utils": "7.13.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", - "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", + "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", - "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", + "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.13.0", - "@typescript-eslint/visitor-keys": "7.13.0", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7513,24 +7513,24 @@ } }, "@typescript-eslint/utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", - "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", + "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.13.0", - "@typescript-eslint/types": "7.13.0", - "@typescript-eslint/typescript-estree": "7.13.0" + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1" } }, "@typescript-eslint/visitor-keys": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", - "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", + "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/types": "7.13.1", "eslint-visitor-keys": "^3.4.3" } }, @@ -9340,9 +9340,9 @@ } }, "marked": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", - "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.0.tgz", + "integrity": "sha512-VTeDCd9txf4KLLljUZ0nljE/Incb9SrWuueE44QVuU0pkOdh4sfCeW1Z6lPcxyDRSVY6rm8db/0OPaN75RNUmw==", "dev": true }, "meow": { @@ -9389,9 +9389,9 @@ } }, "minipass": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", - "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==" + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" }, "minizlib": { "version": "3.0.1", @@ -10111,13 +10111,13 @@ } }, "tar": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.2.0.tgz", - "integrity": "sha512-hctwP0Nb4AB60bj8WQgRYaMOuJYRAPMGiQUAotms5igN8ppfQM+IvjQ5HcKu1MaZh2Wy2KWVTe563Yj8dfc14w==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.0.tgz", + "integrity": "sha512-XQs0S8fuAkQWuqhDeCdMlJXDX80D7EOVLDPVFkna9yQfzS+PHKgfxcei0jf6/+QAWcjqrnC8uM3fSAnrQl+XYg==", "requires": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", - "minipass": "^7.1.0", + "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" @@ -10218,9 +10218,9 @@ "requires": {} }, "ts-jest": { - "version": "29.1.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz", - "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==", + "version": "29.1.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.5.tgz", + "integrity": "sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg==", "dev": true, "requires": { "bs-logger": "0.x", diff --git a/package.json b/package.json index f5c288af3f..f90a94ceee 100644 --- a/package.json +++ b/package.json @@ -106,26 +106,26 @@ "ini": "^4.1.3", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^7.2.0" + "tar": "^7.4.0" }, "devDependencies": { "@octokit/rest": "^20.1.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.2", - "@typescript-eslint/eslint-plugin": "^7.13.0", - "@typescript-eslint/parser": "^7.13.0", + "@types/node": "^20.14.5", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^12.0.2", + "marked": "^13.0.0", "open-cli": "^8.0.0", "pick-port": "^2.0.1", "prettier": "^3.3.2", "sctp": "^1.0.0", - "ts-jest": "^29.1.4", + "ts-jest": "^29.1.5", "typescript": "^5.4.5" } } From 26e03ba9c891e0686cc3dcd3766aff369afc3e3a Mon Sep 17 00:00:00 2001 From: Lynnworld Date: Wed, 19 Jun 2024 19:56:12 +0900 Subject: [PATCH 451/525] fix Simulcast IncreaseLayer bug when producer score is zero (#1410) --- worker/src/RTC/SimulcastConsumer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index d55ba6af58..ab2cdcf483 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -476,6 +476,12 @@ namespace RTC continue; } + // Ignore spatial layers for Producer stream score 0. + if (producerRtpStream->GetScore() == 0) + { + continue; + } + // If the stream has not been active time enough and we have an active one // already, move to the next spatial layer. // clang-format off From 0cb131cd3d1dc95cc09ee6e82dc556d8f4822117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 19 Jun 2024 12:56:50 +0200 Subject: [PATCH 452/525] cosmetic --- worker/src/RTC/SimulcastConsumer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index ab2cdcf483..847d4beb64 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -476,7 +476,7 @@ namespace RTC continue; } - // Ignore spatial layers for Producer stream score 0. + // Ignore spatial layers (streams) with score 0. if (producerRtpStream->GetScore() == 0) { continue; From dedfb24a6a5c5c25ee91744b10bc426e3dbdf5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 20 Jun 2024 14:08:27 +0200 Subject: [PATCH 453/525] Fix issue #1374 --- node/src/test/test-PipeTransport.ts | 31 ++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 74809b320b..59038997aa 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -1,7 +1,12 @@ import { pickPort } from 'pick-port'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, ConsumerEvents, DataConsumerEvents } from '../types'; +import { + WorkerEvents, + ConsumerEvents, + ProducerObserverEvents, + DataConsumerEvents, +} from '../types'; import * as utils from '../utils'; type TestContext = { @@ -809,7 +814,13 @@ test('transport.consume() for a pipe Producer succeeds', async () => { test('producer.pause() and producer.resume() are transmitted to pipe Consumer', async () => { await ctx.videoProducer!.pause(); - await ctx.router1!.pipeToRouter({ + + // We need to obtain the pipeProducer to await for its 'puase' and 'resume' + // events, otherwise we may get errors like this: + // InvalidStateError: Channel closed, pending request aborted [method:PRODUCER_PAUSE, id:8] + // See related fixed issue: + // https://github.com/versatica/mediasoup/issues/1374 + const { pipeProducer: pipeVideoProducer } = await ctx.router1!.pipeToRouter({ producerId: ctx.videoProducer!.id, router: ctx.router2!, }); @@ -829,20 +840,30 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', videoConsumer, 'producerresume' ); + const promise2 = enhancedOnce( + pipeVideoProducer!.observer, + 'resume' + ); await ctx.videoProducer!.resume(); - await promise1; + await Promise.all([promise1, promise2]); expect(videoConsumer.producerPaused).toBe(false); expect(videoConsumer.paused).toBe(false); + expect(pipeVideoProducer!.paused).toBe(false); - const promise2 = enhancedOnce(videoConsumer, 'producerpause'); + const promise3 = enhancedOnce(videoConsumer, 'producerpause'); + const promise4 = enhancedOnce( + pipeVideoProducer!.observer, + 'pause' + ); await ctx.videoProducer!.pause(); - await promise2; + await Promise.all([promise3, promise4]); expect(videoConsumer.producerPaused).toBe(true); expect(videoConsumer.paused).toBe(false); + expect(pipeVideoProducer!.paused).toBe(true); }, 2000); test('producer.close() is transmitted to pipe Consumer', async () => { From e88517de522806c01bca8482b36922cdb42456bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 24 Jun 2024 18:47:10 +0200 Subject: [PATCH 454/525] Update npm deps --- package-lock.json | 328 ++++++++++++++++++++++++++++++++++++---------- package.json | 10 +- 2 files changed, 263 insertions(+), 75 deletions(-) diff --git a/package-lock.json b/package-lock.json index bb2afc004c..e99d387bc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,10 +20,10 @@ "tar": "^7.4.0" }, "devDependencies": { - "@octokit/rest": "^20.1.1", + "@octokit/rest": "^21.0.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.5", + "@types/node": "^20.14.8", "@typescript-eslint/eslint-plugin": "^7.13.1", "@typescript-eslint/parser": "^7.13.1", "eslint": "^8.57.0", @@ -31,13 +31,13 @@ "eslint-plugin-jest": "^28.6.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^13.0.0", + "marked": "^13.0.1", "open-cli": "^8.0.0", - "pick-port": "^2.0.1", + "pick-port": "^2.1.0", "prettier": "^3.3.2", "sctp": "^1.0.0", "ts-jest": "^29.1.5", - "typescript": "^5.4.5" + "typescript": "^5.5.2" }, "engines": { "node": ">=18" @@ -1400,6 +1400,7 @@ "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", "dev": true, + "peer": true, "engines": { "node": ">= 18" } @@ -1409,6 +1410,7 @@ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", "dev": true, + "peer": true, "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.1.0", @@ -1427,6 +1429,7 @@ "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", "dev": true, + "peer": true, "dependencies": { "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" @@ -1440,6 +1443,7 @@ "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", "dev": true, + "peer": true, "dependencies": { "@octokit/request": "^8.3.0", "@octokit/types": "^13.0.0", @@ -1470,18 +1474,6 @@ "@octokit/core": "5" } }, - "node_modules/@octokit/plugin-request-log": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", - "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", - "dev": true, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=5" - } - }, "node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "13.2.2", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.2.tgz", @@ -1502,6 +1494,7 @@ "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.3.1.tgz", "integrity": "sha512-fin4cl5eHN5Ybmb/gtn7YZ+ycyUlcyqqkg5lfxeSChqj7sUt6TNaJPehREi+0PABKLREYL8pfaUhH3TicEWNoA==", "dev": true, + "peer": true, "dependencies": { "@octokit/endpoint": "^9.0.1", "@octokit/request-error": "^5.1.0", @@ -1517,6 +1510,7 @@ "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", "dev": true, + "peer": true, "dependencies": { "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", @@ -1527,20 +1521,125 @@ } }, "node_modules/@octokit/rest": { - "version": "20.1.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.1.tgz", - "integrity": "sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw==", + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.0.tgz", + "integrity": "sha512-XudXXOmiIjivdjNZ+fN71NLrnDM00sxSZlhqmPR3v0dVoJwyP628tSlc12xqn8nX3N0965583RBw5GPo6r8u4Q==", + "dev": true, + "dependencies": { + "@octokit/core": "^6.1.2", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-request-log": "^5.1.0", + "@octokit/plugin-rest-endpoint-methods": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz", + "integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==", + "dev": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/core": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.2.tgz", + "integrity": "sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.0.0", + "@octokit/request": "^9.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/endpoint": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", + "integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", "dev": true, "dependencies": { - "@octokit/core": "^5.0.2", - "@octokit/plugin-paginate-rest": "11.3.1", - "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "13.2.2" + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.2" }, "engines": { "node": ">= 18" } }, + "node_modules/@octokit/rest/node_modules/@octokit/graphql": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz", + "integrity": "sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==", + "dev": true, + "dependencies": { + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.0.tgz", + "integrity": "sha512-FiGcyjdtYPlr03ExBk/0ysIlEFIFGJQAVoPPMxL19B24bVSEiZQnVGBunNtaAF1YnvE/EFoDpXmITtRnyCiypQ==", + "dev": true, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.1.tgz", + "integrity": "sha512-pyAguc0p+f+GbQho0uNetNQMmLG1e80WjkIaqqgUkihqUp0boRU6nKItXO4VWnr+nbZiLGEyy4TeKRwqaLvYgw==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^10.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request-error": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.1.tgz", + "integrity": "sha512-1mw1gqT3fR/WFvnoVpY/zUM2o/XkMs/2AszUUG9I69xn0JFLv6PGkPhNk5lbfvROs79wiS0bqiJNxfCZcRJJdg==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest/node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "dev": true + }, + "node_modules/@octokit/rest/node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "dev": true + }, "node_modules/@octokit/types": { "version": "13.5.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", @@ -1704,9 +1803,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.14.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.5.tgz", - "integrity": "sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==", + "version": "20.14.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.8.tgz", + "integrity": "sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -2162,7 +2261,8 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true + "dev": true, + "peer": true }, "node_modules/brace-expansion": { "version": "1.1.11", @@ -2575,7 +2675,8 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true + "dev": true, + "peer": true }, "node_modules/detect-newline": { "version": "3.1.0", @@ -4467,9 +4568,9 @@ } }, "node_modules/marked": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.0.tgz", - "integrity": "sha512-VTeDCd9txf4KLLljUZ0nljE/Incb9SrWuueE44QVuU0pkOdh4sfCeW1Z6lPcxyDRSVY6rm8db/0OPaN75RNUmw==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.1.tgz", + "integrity": "sha512-7kBohS6GrZKvCsNXZyVVXSW7/hGBHe49ng99YPkDCckSUrrG7MSFLCexsRxptzOmyW2eT5dySh4Md1V6my52fA==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -4940,15 +5041,15 @@ } }, "node_modules/pick-port": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.0.1.tgz", - "integrity": "sha512-8GSFuOCelctwcW0CkNGFahrGJyKxx2hMOmzDxVaHTknsikh4Zi+edCFUMgfAcBLRkV0GYQT64QivSi4SxDeKdA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.1.0.tgz", + "integrity": "sha512-nqdK+0cmJLGMHKZCNh6PfA/ZeIhHYKSlLLwyfH/IFQVv9SqwNUdbm+08olnd+PbmLqrHk8Twhq6yO9viqOGkkw==", "dev": true, "dependencies": { "debug": "^4.3.4" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/picocolors": { @@ -5860,9 +5961,9 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", + "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5897,7 +5998,8 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true + "dev": true, + "peer": true }, "node_modules/update-browserslist-db": { "version": "1.0.10", @@ -7131,13 +7233,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", - "dev": true + "dev": true, + "peer": true }, "@octokit/core": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", "dev": true, + "peer": true, "requires": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.1.0", @@ -7153,6 +7257,7 @@ "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", "dev": true, + "peer": true, "requires": { "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" @@ -7163,6 +7268,7 @@ "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", "dev": true, + "peer": true, "requires": { "@octokit/request": "^8.3.0", "@octokit/types": "^13.0.0", @@ -7184,13 +7290,6 @@ "@octokit/types": "^13.5.0" } }, - "@octokit/plugin-request-log": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", - "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", - "dev": true, - "requires": {} - }, "@octokit/plugin-rest-endpoint-methods": { "version": "13.2.2", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.2.tgz", @@ -7205,6 +7304,7 @@ "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.3.1.tgz", "integrity": "sha512-fin4cl5eHN5Ybmb/gtn7YZ+ycyUlcyqqkg5lfxeSChqj7sUt6TNaJPehREi+0PABKLREYL8pfaUhH3TicEWNoA==", "dev": true, + "peer": true, "requires": { "@octokit/endpoint": "^9.0.1", "@octokit/request-error": "^5.1.0", @@ -7217,6 +7317,7 @@ "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", "dev": true, + "peer": true, "requires": { "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", @@ -7224,15 +7325,99 @@ } }, "@octokit/rest": { - "version": "20.1.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.1.tgz", - "integrity": "sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw==", + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.0.tgz", + "integrity": "sha512-XudXXOmiIjivdjNZ+fN71NLrnDM00sxSZlhqmPR3v0dVoJwyP628tSlc12xqn8nX3N0965583RBw5GPo6r8u4Q==", "dev": true, "requires": { - "@octokit/core": "^5.0.2", - "@octokit/plugin-paginate-rest": "11.3.1", - "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "13.2.2" + "@octokit/core": "^6.1.2", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-request-log": "^5.1.0", + "@octokit/plugin-rest-endpoint-methods": "^13.0.0" + }, + "dependencies": { + "@octokit/auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz", + "integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==", + "dev": true + }, + "@octokit/core": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.2.tgz", + "integrity": "sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==", + "dev": true, + "requires": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.0.0", + "@octokit/request": "^9.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + } + }, + "@octokit/endpoint": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", + "integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", + "dev": true, + "requires": { + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.2" + } + }, + "@octokit/graphql": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz", + "integrity": "sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==", + "dev": true, + "requires": { + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + } + }, + "@octokit/plugin-request-log": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.0.tgz", + "integrity": "sha512-FiGcyjdtYPlr03ExBk/0ysIlEFIFGJQAVoPPMxL19B24bVSEiZQnVGBunNtaAF1YnvE/EFoDpXmITtRnyCiypQ==", + "dev": true, + "requires": {} + }, + "@octokit/request": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.1.tgz", + "integrity": "sha512-pyAguc0p+f+GbQho0uNetNQMmLG1e80WjkIaqqgUkihqUp0boRU6nKItXO4VWnr+nbZiLGEyy4TeKRwqaLvYgw==", + "dev": true, + "requires": { + "@octokit/endpoint": "^10.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^7.0.2" + } + }, + "@octokit/request-error": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.1.tgz", + "integrity": "sha512-1mw1gqT3fR/WFvnoVpY/zUM2o/XkMs/2AszUUG9I69xn0JFLv6PGkPhNk5lbfvROs79wiS0bqiJNxfCZcRJJdg==", + "dev": true, + "requires": { + "@octokit/types": "^13.0.0" + } + }, + "before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "dev": true + }, + "universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "dev": true + } } }, "@octokit/types": { @@ -7389,9 +7574,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.14.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.5.tgz", - "integrity": "sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==", + "version": "20.14.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.8.tgz", + "integrity": "sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7696,7 +7881,8 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true + "dev": true, + "peer": true }, "brace-expansion": { "version": "1.1.11", @@ -7978,7 +8164,8 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true + "dev": true, + "peer": true }, "detect-newline": { "version": "3.1.0", @@ -9340,9 +9527,9 @@ } }, "marked": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.0.tgz", - "integrity": "sha512-VTeDCd9txf4KLLljUZ0nljE/Incb9SrWuueE44QVuU0pkOdh4sfCeW1Z6lPcxyDRSVY6rm8db/0OPaN75RNUmw==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.1.tgz", + "integrity": "sha512-7kBohS6GrZKvCsNXZyVVXSW7/hGBHe49ng99YPkDCckSUrrG7MSFLCexsRxptzOmyW2eT5dySh4Md1V6my52fA==", "dev": true }, "meow": { @@ -9652,9 +9839,9 @@ "dev": true }, "pick-port": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.0.1.tgz", - "integrity": "sha512-8GSFuOCelctwcW0CkNGFahrGJyKxx2hMOmzDxVaHTknsikh4Zi+edCFUMgfAcBLRkV0GYQT64QivSi4SxDeKdA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.1.0.tgz", + "integrity": "sha512-nqdK+0cmJLGMHKZCNh6PfA/ZeIhHYKSlLLwyfH/IFQVv9SqwNUdbm+08olnd+PbmLqrHk8Twhq6yO9viqOGkkw==", "dev": true, "requires": { "debug": "^4.3.4" @@ -10255,9 +10442,9 @@ "dev": true }, "typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", + "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", "dev": true }, "undici-types": { @@ -10279,7 +10466,8 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true + "dev": true, + "peer": true }, "update-browserslist-db": { "version": "1.0.10", diff --git a/package.json b/package.json index f90a94ceee..2b67d5f7dd 100644 --- a/package.json +++ b/package.json @@ -109,10 +109,10 @@ "tar": "^7.4.0" }, "devDependencies": { - "@octokit/rest": "^20.1.1", + "@octokit/rest": "^21.0.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.5", + "@types/node": "^20.14.8", "@typescript-eslint/eslint-plugin": "^7.13.1", "@typescript-eslint/parser": "^7.13.1", "eslint": "^8.57.0", @@ -120,12 +120,12 @@ "eslint-plugin-jest": "^28.6.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^13.0.0", + "marked": "^13.0.1", "open-cli": "^8.0.0", - "pick-port": "^2.0.1", + "pick-port": "^2.1.0", "prettier": "^3.3.2", "sctp": "^1.0.0", "ts-jest": "^29.1.5", - "typescript": "^5.4.5" + "typescript": "^5.5.2" } } From a16f047e55a9f6f498e2ceb5e3c8efb285bc5d0e Mon Sep 17 00:00:00 2001 From: DavidNegro Date: Tue, 25 Jun 2024 14:01:55 +0200 Subject: [PATCH 455/525] Add support for playout-delay extension (#1412) --- node/src/RtpParameters.ts | 11 ++++++- node/src/supportedRtpCapabilities.ts | 14 +++++++++ node/src/test/test-PipeTransport.ts | 30 +++++++++++++++++++ rust/src/rtp_parameters.rs | 14 +++++++++ rust/src/supported_rtp_capabilities.rs | 14 +++++++++ rust/tests/integration/pipe_transport.rs | 27 ++++++++++++++++- worker/fbs/rtpParameters.fbs | 1 + worker/include/RTC/RtpDictionaries.hpp | 1 + worker/include/RTC/RtpHeaderExtensionIds.hpp | 1 + worker/include/RTC/RtpPacket.hpp | 22 ++++++++++++++ worker/src/RTC/Consumer.cpp | 5 ++++ worker/src/RTC/Producer.cpp | 20 +++++++++++++ .../RtpDictionaries/RtpHeaderExtensionUri.cpp | 10 +++++++ worker/src/RTC/RtpPacket.cpp | 16 ++++++++++ 14 files changed, 184 insertions(+), 2 deletions(-) diff --git a/node/src/RtpParameters.ts b/node/src/RtpParameters.ts index 0c0ea65532..08d02cf3e6 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/RtpParameters.ts @@ -321,7 +321,8 @@ export type RtpHeaderExtensionUri = | 'urn:ietf:params:rtp-hdrext:toffset' | 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' | 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' - | 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time'; + | 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time' + | 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay'; /** * Defines a RTP header extension within the RTP parameters. The list of RTP @@ -758,6 +759,10 @@ export function rtpHeaderExtensionUriFromFbs( case FbsRtpHeaderExtensionUri.AbsCaptureTime: { return 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time'; } + + case FbsRtpHeaderExtensionUri.PlayoutDelay: { + return 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay'; + } } } @@ -809,6 +814,10 @@ export function rtpHeaderExtensionUriToFbs( return FbsRtpHeaderExtensionUri.AbsCaptureTime; } + case 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay': { + return FbsRtpHeaderExtensionUri.PlayoutDelay; + } + default: { throw new TypeError(`invalid RtpHeaderExtensionUri: ${uri}`); } diff --git a/node/src/supportedRtpCapabilities.ts b/node/src/supportedRtpCapabilities.ts index a1aa48164e..042e2746cb 100644 --- a/node/src/supportedRtpCapabilities.ts +++ b/node/src/supportedRtpCapabilities.ts @@ -328,6 +328,20 @@ const supportedRtpCapabilities: RtpCapabilities = { preferredEncrypt: false, direction: 'sendrecv', }, + { + kind: 'audio', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay', + preferredId: 14, + preferredEncrypt: false, + direction: 'sendrecv', + }, + { + kind: 'video', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay', + preferredId: 14, + preferredEncrypt: false, + direction: 'sendrecv', + }, ], }; diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 59038997aa..4f2c24363d 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -271,6 +271,12 @@ test('router.pipeToRouter() succeeds with audio', async () => { encrypt: false, parameters: {}, }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay', + id: 14, + encrypt: false, + parameters: {}, + }, ]); expect(pipeConsumer.type).toBe('pipe'); expect(pipeConsumer.paused).toBe(false); @@ -313,6 +319,12 @@ test('router.pipeToRouter() succeeds with audio', async () => { encrypt: false, parameters: {}, }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay', + id: 14, + encrypt: false, + parameters: {}, + }, ]); expect(pipeProducer.paused).toBe(false); }, 2000); @@ -387,6 +399,12 @@ test('router.pipeToRouter() succeeds with video', async () => { encrypt: false, parameters: {}, }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay', + id: 14, + encrypt: false, + parameters: {}, + }, ]); expect(pipeConsumer.type).toBe('pipe'); @@ -448,6 +466,12 @@ test('router.pipeToRouter() succeeds with video', async () => { encrypt: false, parameters: {}, }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay', + id: 14, + encrypt: false, + parameters: {}, + }, ]); expect(pipeProducer.paused).toBe(true); }, 2000); @@ -561,6 +585,12 @@ test('router.createPipeTransport() with enableRtx succeeds', async () => { encrypt: false, parameters: {}, }, + { + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay', + id: 14, + encrypt: false, + parameters: {}, + }, ]); expect(pipeConsumer.type).toBe('pipe'); diff --git a/rust/src/rtp_parameters.rs b/rust/src/rtp_parameters.rs index 2eec79a101..5747ebe700 100644 --- a/rust/src/rtp_parameters.rs +++ b/rust/src/rtp_parameters.rs @@ -585,6 +585,10 @@ pub enum RtpHeaderExtensionUri { /// #[serde(rename = "http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time")] AbsCaptureTime, + /// + #[serde(rename = "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay")] + PlayoutDelay, + #[doc(hidden)] #[serde(other, rename = "unsupported")] Unsupported, @@ -620,6 +624,9 @@ impl RtpHeaderExtensionUri { RtpHeaderExtensionUri::AbsCaptureTime => { rtp_parameters::RtpHeaderExtensionUri::AbsCaptureTime } + RtpHeaderExtensionUri::PlayoutDelay => { + rtp_parameters::RtpHeaderExtensionUri::PlayoutDelay + } RtpHeaderExtensionUri::Unsupported => panic!("Invalid RTP extension header URI"), } } @@ -653,6 +660,9 @@ impl RtpHeaderExtensionUri { rtp_parameters::RtpHeaderExtensionUri::AbsCaptureTime => { RtpHeaderExtensionUri::AbsCaptureTime } + rtp_parameters::RtpHeaderExtensionUri::PlayoutDelay => { + RtpHeaderExtensionUri::PlayoutDelay + } } } } @@ -679,6 +689,7 @@ impl FromStr for RtpHeaderExtensionUri { "http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time" => { Ok(Self::AbsCaptureTime) } + "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay" => Ok(Self::PlayoutDelay), _ => Err(RtpHeaderExtensionUriParseError::Unsupported), } } @@ -710,6 +721,9 @@ impl RtpHeaderExtensionUri { RtpHeaderExtensionUri::AbsCaptureTime => { "http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time" } + RtpHeaderExtensionUri::PlayoutDelay => { + "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay" + } RtpHeaderExtensionUri::Unsupported => "unsupported", } } diff --git a/rust/src/supported_rtp_capabilities.rs b/rust/src/supported_rtp_capabilities.rs index 2f49fc6c7a..a7a9369520 100644 --- a/rust/src/supported_rtp_capabilities.rs +++ b/rust/src/supported_rtp_capabilities.rs @@ -386,6 +386,20 @@ pub fn get_supported_rtp_capabilities() -> RtpCapabilities { preferred_encrypt: false, direction: RtpHeaderExtensionDirection::SendRecv, }, + RtpHeaderExtension { + kind: MediaKind::Audio, + uri: RtpHeaderExtensionUri::PlayoutDelay, + preferred_id: 14, + preferred_encrypt: false, + direction: RtpHeaderExtensionDirection::SendRecv, + }, + RtpHeaderExtension { + kind: MediaKind::Video, + uri: RtpHeaderExtensionUri::PlayoutDelay, + preferred_id: 14, + preferred_encrypt: false, + direction: RtpHeaderExtensionDirection::SendRecv, + }, ], } } diff --git a/rust/tests/integration/pipe_transport.rs b/rust/tests/integration/pipe_transport.rs index bf7bd01e80..c11ff0d32a 100644 --- a/rust/tests/integration/pipe_transport.rs +++ b/rust/tests/integration/pipe_transport.rs @@ -350,6 +350,11 @@ fn pipe_to_router_succeeds_with_audio() { uri: RtpHeaderExtensionUri::AbsCaptureTime, id: 13, encrypt: false, + }, + RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::PlayoutDelay, + id: 14, + encrypt: false, } ], ); @@ -395,7 +400,12 @@ fn pipe_to_router_succeeds_with_audio() { uri: RtpHeaderExtensionUri::AbsCaptureTime, id: 13, encrypt: false, - } + }, + RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::PlayoutDelay, + id: 14, + encrypt: false, + }, ], ); assert!(!pipe_producer.paused()); @@ -499,6 +509,11 @@ fn pipe_to_router_succeeds_with_video() { id: 13, encrypt: false, }, + RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::PlayoutDelay, + id: 14, + encrypt: false, + }, ], ); assert_eq!(pipe_consumer.r#type(), ConsumerType::Pipe); @@ -556,6 +571,11 @@ fn pipe_to_router_succeeds_with_video() { id: 13, encrypt: false, }, + RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::PlayoutDelay, + id: 14, + encrypt: false, + }, ], ); assert!(pipe_producer.paused()); @@ -753,6 +773,11 @@ fn create_with_enable_rtx_succeeds() { id: 13, encrypt: false, }, + RtpHeaderExtensionParameters { + uri: RtpHeaderExtensionUri::PlayoutDelay, + id: 14, + encrypt: false, + }, ], ); assert_eq!(pipe_consumer.r#type(), ConsumerType::Pipe); diff --git a/worker/fbs/rtpParameters.fbs b/worker/fbs/rtpParameters.fbs index 8bd8d7066c..c3b61fe55a 100644 --- a/worker/fbs/rtpParameters.fbs +++ b/worker/fbs/rtpParameters.fbs @@ -73,6 +73,7 @@ enum RtpHeaderExtensionUri: uint8 { TransportWideCcDraft01, AbsSendTime, AbsCaptureTime, + PlayoutDelay, } table RtpHeaderExtensionParameters { diff --git a/worker/include/RTC/RtpDictionaries.hpp b/worker/include/RTC/RtpDictionaries.hpp index e9a266b5a5..f9fa22a5dd 100644 --- a/worker/include/RTC/RtpDictionaries.hpp +++ b/worker/include/RTC/RtpDictionaries.hpp @@ -127,6 +127,7 @@ namespace RTC VIDEO_ORIENTATION = 11, TOFFSET = 12, ABS_CAPTURE_TIME = 13, + PLAYOUT_DELAY = 14, }; public: diff --git a/worker/include/RTC/RtpHeaderExtensionIds.hpp b/worker/include/RTC/RtpHeaderExtensionIds.hpp index 355b25137c..78cd262fe5 100644 --- a/worker/include/RTC/RtpHeaderExtensionIds.hpp +++ b/worker/include/RTC/RtpHeaderExtensionIds.hpp @@ -19,6 +19,7 @@ namespace RTC uint8_t videoOrientation{ 0u }; uint8_t toffset{ 0u }; uint8_t absCaptureTime{ 0u }; + uint8_t playoutDelay{ 0u }; }; } // namespace RTC diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index 2058058365..e737b5b868 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -309,6 +309,11 @@ namespace RTC this->videoOrientationExtensionId = id; } + void SetPlayoutDelayExtensionId(uint8_t id) + { + this->playoutDelayExtensionId = id; + } + bool ReadMid(std::string& mid) const { uint8_t extenLen; @@ -489,6 +494,22 @@ namespace RTC return true; } + bool ReadPlayoutDelay(uint16_t& minDelay, uint16_t& maxDelay) const + { + uint8_t extenLen; + uint8_t* extenValue = GetExtension(this->playoutDelayExtensionId, extenLen); + + if (extenLen != 3) + { + return false; + } + + uint32_t v = Utils::Byte::Get3Bytes(extenValue, 0); + minDelay = v >> 12u; + maxDelay = v & 0xFFFu; + return true; + } + bool HasExtension(uint8_t id) const { if (id == 0u) @@ -672,6 +693,7 @@ namespace RTC uint8_t frameMarkingExtensionId{ 0u }; uint8_t ssrcAudioLevelExtensionId{ 0u }; uint8_t videoOrientationExtensionId{ 0u }; + uint8_t playoutDelayExtensionId{ 0u }; uint8_t* payload{ nullptr }; size_t payloadLength{ 0u }; uint8_t payloadPadding{ 0u }; diff --git a/worker/src/RTC/Consumer.cpp b/worker/src/RTC/Consumer.cpp index 7ab2699645..832b083e3c 100644 --- a/worker/src/RTC/Consumer.cpp +++ b/worker/src/RTC/Consumer.cpp @@ -85,6 +85,11 @@ namespace RTC this->rtpHeaderExtensionIds.videoOrientation = exten.id; } + if (this->rtpHeaderExtensionIds.playoutDelay == 0u && exten.type == RTC::RtpHeaderExtensionUri::Type::PLAYOUT_DELAY) + { + this->rtpHeaderExtensionIds.playoutDelay = exten.id; + } + if (this->rtpHeaderExtensionIds.absSendTime == 0u && exten.type == RTC::RtpHeaderExtensionUri::Type::ABS_SEND_TIME) { this->rtpHeaderExtensionIds.absSendTime = exten.id; diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index 4e2a4a90b7..e7f93b2792 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -192,6 +192,11 @@ namespace RTC { this->rtpHeaderExtensionIds.absCaptureTime = exten.id; } + + if (this->rtpHeaderExtensionIds.playoutDelay == 0u && exten.type == RTC::RtpHeaderExtensionUri::Type::PLAYOUT_DELAY) + { + this->rtpHeaderExtensionIds.playoutDelay = exten.id; + } } // Set the RTCP report generation interval. @@ -1264,6 +1269,19 @@ namespace RTC bufferPtr += extenLen; } + // Proxy http://www.webrtc.org/experiments/rtp-hdrext/playout-delay + extenValue = packet->GetExtension(this->rtpHeaderExtensionIds.playoutDelay, extenLen); + + if (extenValue) + { + std::memcpy(bufferPtr, extenValue, extenLen); + + extensions.emplace_back( + static_cast(RTC::RtpHeaderExtensionUri::Type::PLAYOUT_DELAY), extenLen, bufferPtr); + + bufferPtr += extenLen; + } + if (this->kind == RTC::Media::Kind::AUDIO) { // Proxy urn:ietf:params:rtp-hdrext:ssrc-audio-level. @@ -1396,6 +1414,8 @@ namespace RTC static_cast(RTC::RtpHeaderExtensionUri::Type::SSRC_AUDIO_LEVEL)); packet->SetVideoOrientationExtensionId( static_cast(RTC::RtpHeaderExtensionUri::Type::VIDEO_ORIENTATION)); + packet->SetPlayoutDelayExtensionId( + static_cast(RTC::RtpHeaderExtensionUri::Type::PLAYOUT_DELAY)); } return true; diff --git a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp index d8c90e5641..f451e7c7ba 100644 --- a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp @@ -48,6 +48,11 @@ namespace RTC return RtpHeaderExtensionUri::Type::VIDEO_ORIENTATION; } + case FBS::RtpParameters::RtpHeaderExtensionUri::PlayoutDelay: + { + return RtpHeaderExtensionUri::Type::PLAYOUT_DELAY; + } + case FBS::RtpParameters::RtpHeaderExtensionUri::TimeOffset: { return RtpHeaderExtensionUri::Type::TOFFSET; @@ -120,6 +125,11 @@ namespace RTC return FBS::RtpParameters::RtpHeaderExtensionUri::VideoOrientation; } + case RtpHeaderExtensionUri::Type::PLAYOUT_DELAY: + { + return FBS::RtpParameters::RtpHeaderExtensionUri::PlayoutDelay; + } + case RtpHeaderExtensionUri::Type::TOFFSET: { return FBS::RtpParameters::RtpHeaderExtensionUri::TimeOffset; diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index 8bf92ed232..0196234f89 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -300,6 +300,20 @@ namespace RTC rotation); } } + if (this->playoutDelayExtensionId != 0u) + { + uint16_t minDelay; + uint16_t maxDelay; + + if (ReadPlayoutDelay(minDelay, maxDelay)) + { + MS_DUMP( + " playoutDelay: extId:%" PRIu8 ", minDelay:%" PRIu16 ", maxDelay:%" PRIu16, + this->videoOrientationExtensionId, + minDelay, + maxDelay); + } + } MS_DUMP(" csrc count: %" PRIu8, this->header->csrcCount); MS_DUMP(" marker: %s", HasMarker() ? "true" : "false"); MS_DUMP(" payload type: %" PRIu8, GetPayloadType()); @@ -387,6 +401,7 @@ namespace RTC this->frameMarkingExtensionId = 0u; this->ssrcAudioLevelExtensionId = 0u; this->videoOrientationExtensionId = 0u; + this->playoutDelayExtensionId = 0u; // Clear the One-Byte and Two-Bytes extension elements maps. std::fill(std::begin(this->oneByteExtensions), std::end(this->oneByteExtensions), nullptr); @@ -748,6 +763,7 @@ namespace RTC packet->frameMarkingExtensionId = this->frameMarkingExtensionId; packet->ssrcAudioLevelExtensionId = this->ssrcAudioLevelExtensionId; packet->videoOrientationExtensionId = this->videoOrientationExtensionId; + packet->playoutDelayExtensionId = this->playoutDelayExtensionId; // Assign the payload descriptor handler. packet->payloadDescriptorHandler = this->payloadDescriptorHandler; // Store allocated buffer. From 13a29e1854ee21e459e038a69838bf545b044273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 25 Jun 2024 13:56:18 +0200 Subject: [PATCH 456/525] Update NPM dev deps --- package-lock.json | 172 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 88 insertions(+), 88 deletions(-) diff --git a/package-lock.json b/package-lock.json index e99d387bc7..fd5a346d75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,8 +24,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.14.8", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", + "@typescript-eslint/eslint-plugin": "^7.14.1", + "@typescript-eslint/parser": "^7.14.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", @@ -1833,16 +1833,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", - "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", + "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/type-utils": "7.13.1", - "@typescript-eslint/utils": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/type-utils": "7.14.1", + "@typescript-eslint/utils": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1866,15 +1866,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", - "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", + "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/typescript-estree": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/typescript-estree": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "debug": "^4.3.4" }, "engines": { @@ -1894,13 +1894,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", - "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", + "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1" + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1911,13 +1911,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", - "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", + "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.13.1", - "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/typescript-estree": "7.14.1", + "@typescript-eslint/utils": "7.14.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1938,9 +1938,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", - "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", + "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1951,13 +1951,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", - "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", + "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2003,15 +2003,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", - "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", + "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/typescript-estree": "7.13.1" + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/typescript-estree": "7.14.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2025,12 +2025,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", - "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", + "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/types": "7.14.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -7604,16 +7604,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", - "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", + "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/type-utils": "7.13.1", - "@typescript-eslint/utils": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/type-utils": "7.14.1", + "@typescript-eslint/utils": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7621,54 +7621,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", - "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", + "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/typescript-estree": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/typescript-estree": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", - "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", + "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1" + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1" } }, "@typescript-eslint/type-utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", - "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", + "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.13.1", - "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/typescript-estree": "7.14.1", + "@typescript-eslint/utils": "7.14.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", - "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", + "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", - "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", + "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7698,24 +7698,24 @@ } }, "@typescript-eslint/utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", - "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", + "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/typescript-estree": "7.13.1" + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/typescript-estree": "7.14.1" } }, "@typescript-eslint/visitor-keys": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", - "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", + "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/types": "7.14.1", "eslint-visitor-keys": "^3.4.3" } }, diff --git a/package.json b/package.json index 2b67d5f7dd..718f7a7f36 100644 --- a/package.json +++ b/package.json @@ -113,8 +113,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.14.8", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", + "@typescript-eslint/eslint-plugin": "^7.14.1", + "@typescript-eslint/parser": "^7.14.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", From 40d22812273d020308c7256802239b0d919434f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 25 Jun 2024 14:12:46 +0200 Subject: [PATCH 457/525] FuzzerRtpPacket: use PlayoutDelayExtension --- worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp b/worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp index 8375a4e627..1d6e56a4ce 100644 --- a/worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp +++ b/worker/fuzzer/src/RTC/FuzzerRtpPacket.cpp @@ -23,6 +23,8 @@ void Fuzzer::RTC::RtpPacket::Fuzz(const uint8_t* data, size_t len) bool flip; uint16_t rotation; uint32_t absSendTime; + uint16_t playoutDelayMinDelay; + uint16_t playoutDelayMaxDelay; uint16_t wideSeqNumber; std::string mid; std::string rid; @@ -91,6 +93,11 @@ void Fuzzer::RTC::RtpPacket::Fuzz(const uint8_t* data, size_t len) packet->GetExtension(2, extenLen); packet->ReadVideoOrientation(camera, flip, rotation); + packet->SetPlayoutDelayExtensionId(8); + packet->HasExtension(8); + packet->GetExtension(8, extenLen); + packet->ReadPlayoutDelay(playoutDelayMinDelay, playoutDelayMaxDelay); + packet->HasExtension(6); packet->HasExtension(7); packet->HasExtension(8); @@ -178,6 +185,11 @@ void Fuzzer::RTC::RtpPacket::Fuzz(const uint8_t* data, size_t len) packet->GetExtension(12, extenLen); packet->ReadVideoOrientation(camera, flip, rotation); + packet->SetPlayoutDelayExtensionId(15); + packet->HasExtension(15); + packet->GetExtension(15, extenLen); + packet->ReadPlayoutDelay(playoutDelayMinDelay, playoutDelayMaxDelay); + packet->GetPayload(); packet->GetPayloadLength(); packet->GetPayloadPadding(); From 5c4b6ce1431e5a974bec0e8888309578b75e8321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 25 Jun 2024 14:20:20 +0200 Subject: [PATCH 458/525] 3.14.8 --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 403a499a96..8e1e72e35e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### 3.14.8 + +- Add support for 'playout-delay' RTP extension ([PR #1412](https://github.com/versatica/mediasoup/pull/1412) by @DavidNegro). + ### 3.14.7 - `SimulcastConsumer`: Fix increase layer when current layer has not receive SR ([PR #1098](https://github.com/versatica/mediasoup/pull/1098) by @penguinol). diff --git a/package-lock.json b/package-lock.json index fd5a346d75..8f8a1bc8c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.7", + "version": "3.14.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.7", + "version": "3.14.8", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 718f7a7f36..502d509806 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.7", + "version": "3.14.8", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 949054696f4fb6519c43196c88ac211ff3856022 Mon Sep 17 00:00:00 2001 From: dhilipsiva Date: Wed, 26 Jun 2024 19:05:44 +0530 Subject: [PATCH 459/525] refactor: make `hex_as_bytes` DRY (#1409) --- rust-toolchain.toml | 2 +- rust/src/data_structures.rs | 25 +++++++------------ rust/src/ortc.rs | 6 ++--- rust/src/ortc/tests.rs | 28 +++++++++++----------- rust/src/router.rs | 8 +++++-- rust/src/router/producer.rs | 2 +- rust/src/rtp_parameters.rs | 1 - rust/src/scalability_modes.rs | 6 ++--- rust/src/worker/common.rs | 4 +--- rust/src/worker/utils/channel_read_fn.rs | 17 +++++++++---- rust/src/worker/utils/channel_write_fn.rs | 17 ++++++++++--- rust/tests/integration/consumer.rs | 23 ++++++++++++------ rust/tests/integration/webrtc_server.rs | 20 ++++------------ rust/tests/integration/webrtc_transport.rs | 6 ++--- worker/build.rs | 1 - worker/src/lib.rs | 7 +++++- 16 files changed, 95 insertions(+), 78 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index be838d8604..874939176e 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.72.0" +channel = "1.79.0" components = ["rustfmt", "clippy"] diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index 3019b6ed1f..a2043f3c08 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -528,12 +528,15 @@ pub enum DtlsFingerprint { }, } -fn hex_as_bytes(input: &str, output: &mut [u8]) { +fn hex_as_bytes(input: &str) -> [u8; N] { + let mut output = [0_u8; N]; for (i, o) in input.split(':').zip(&mut output.iter_mut()) { *o = u8::from_str_radix(i, 16).unwrap_or_else(|error| { panic!("Failed to parse value {i} as series of hex bytes: {error}") }); } + + output } impl DtlsFingerprint { @@ -565,45 +568,35 @@ impl DtlsFingerprint { pub(crate) fn from_fbs(fingerprint: &web_rtc_transport::Fingerprint) -> DtlsFingerprint { match fingerprint.algorithm { web_rtc_transport::FingerprintAlgorithm::Sha1 => { - let mut value_result = [0_u8; 20]; - - hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + let value_result = hex_as_bytes::<20>(fingerprint.value.as_str()); DtlsFingerprint::Sha1 { value: value_result, } } web_rtc_transport::FingerprintAlgorithm::Sha224 => { - let mut value_result = [0_u8; 28]; - - hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + let value_result = hex_as_bytes::<28>(fingerprint.value.as_str()); DtlsFingerprint::Sha224 { value: value_result, } } web_rtc_transport::FingerprintAlgorithm::Sha256 => { - let mut value_result = [0_u8; 32]; - - hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + let value_result = hex_as_bytes::<32>(fingerprint.value.as_str()); DtlsFingerprint::Sha256 { value: value_result, } } web_rtc_transport::FingerprintAlgorithm::Sha384 => { - let mut value_result = [0_u8; 48]; - - hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + let value_result = hex_as_bytes::<48>(fingerprint.value.as_str()); DtlsFingerprint::Sha384 { value: value_result, } } web_rtc_transport::FingerprintAlgorithm::Sha512 => { - let mut value_result = [0_u8; 64]; - - hex_as_bytes(fingerprint.value.as_str(), &mut value_result); + let value_result = hex_as_bytes::<64>(fingerprint.value.as_str()); DtlsFingerprint::Sha512 { value: value_result, diff --git a/rust/src/ortc.rs b/rust/src/ortc.rs index c5dd9ca3b4..7bec5dc701 100644 --- a/rust/src/ortc.rs +++ b/rust/src/ortc.rs @@ -681,7 +681,7 @@ pub(crate) fn can_consume( if caps .codecs .iter() - .any(|cap_codec| match_codecs(cap_codec.deref().into(), codec.into(), true).is_ok()) + .any(|cap_codec| match_codecs(cap_codec.into(), codec.into(), true).is_ok()) { matching_codecs.push(codec); } @@ -689,7 +689,7 @@ pub(crate) fn can_consume( // Ensure there is at least one media codec. Ok(matching_codecs - .get(0) + .first() .map(|codec| !codec.is_rtx()) .unwrap_or_default()) } @@ -841,7 +841,7 @@ pub(crate) fn get_consumer_rtp_parameters( // (assume all encodings have the same value). let mut scalability_mode = consumable_rtp_parameters .encodings - .get(0) + .first() .map(|encoding| encoding.scalability_mode.clone()) .unwrap_or_default(); diff --git a/rust/src/ortc/tests.rs b/rust/src/ortc/tests.rs index 564980aa5f..7fb411da9a 100644 --- a/rust/src/ortc/tests.rs +++ b/rust/src/ortc/tests.rs @@ -255,8 +255,8 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume ] ); - assert_eq!(rtp_mapping.encodings.get(0).unwrap().ssrc, Some(11111111)); - assert_eq!(rtp_mapping.encodings.get(0).unwrap().rid, None); + assert_eq!(rtp_mapping.encodings.first().unwrap().ssrc, Some(11111111)); + assert_eq!(rtp_mapping.encodings.first().unwrap().rid, None); assert_eq!(rtp_mapping.encodings.get(1).unwrap().ssrc, Some(21111111)); assert_eq!(rtp_mapping.encodings.get(1).unwrap().rid, None); assert_eq!(rtp_mapping.encodings.get(2).unwrap().ssrc, None); @@ -303,13 +303,13 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume ); assert_eq!( - consumable_rtp_parameters.encodings.get(0).unwrap().ssrc, - Some(rtp_mapping.encodings.get(0).unwrap().mapped_ssrc), + consumable_rtp_parameters.encodings.first().unwrap().ssrc, + Some(rtp_mapping.encodings.first().unwrap().mapped_ssrc), ); assert_eq!( consumable_rtp_parameters .encodings - .get(0) + .first() .unwrap() .max_bitrate, Some(111111), @@ -317,7 +317,7 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume assert_eq!( consumable_rtp_parameters .encodings - .get(0) + .first() .unwrap() .scalability_mode, ScalabilityMode::L1T3, @@ -489,20 +489,20 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume assert_eq!(consumer_rtp_parameters.encodings.len(), 1); assert!(consumer_rtp_parameters .encodings - .get(0) + .first() .unwrap() .ssrc .is_some()); assert!(consumer_rtp_parameters .encodings - .get(0) + .first() .unwrap() .rtx .is_some()); assert_eq!( consumer_rtp_parameters .encodings - .get(0) + .first() .unwrap() .scalability_mode, ScalabilityMode::L3T3, @@ -510,7 +510,7 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume assert_eq!( consumer_rtp_parameters .encodings - .get(0) + .first() .unwrap() .max_bitrate, Some(333333), @@ -566,26 +566,26 @@ fn get_producer_rtp_parameters_mapping_get_consumable_rtp_parameters_get_consume assert_eq!(pipe_consumer_rtp_parameters.encodings.len(), 3); assert!(pipe_consumer_rtp_parameters .encodings - .get(0) + .first() .unwrap() .ssrc .is_some()); assert!(pipe_consumer_rtp_parameters .encodings - .get(0) + .first() .unwrap() .rtx .is_none()); assert!(pipe_consumer_rtp_parameters .encodings - .get(0) + .first() .unwrap() .max_bitrate .is_some()); assert_eq!( pipe_consumer_rtp_parameters .encodings - .get(0) + .first() .unwrap() .scalability_mode, ScalabilityMode::L1T3, diff --git a/rust/src/router.rs b/rust/src/router.rs index 95049e18fa..1a5bc219d5 100644 --- a/rust/src/router.rs +++ b/rust/src/router.rs @@ -1303,8 +1303,12 @@ impl Router { // We've created `DataConsumer` with SCTP above, so this should never panic pipe_data_consumer.sctp_stream_parameters().unwrap(), ); - producer_options.label = pipe_data_consumer.label().clone(); - producer_options.protocol = pipe_data_consumer.protocol().clone(); + producer_options + .label + .clone_from(pipe_data_consumer.label()); + producer_options + .protocol + .clone_from(pipe_data_consumer.protocol()); producer_options.app_data = data_producer.app_data().clone(); producer_options diff --git a/rust/src/router/producer.rs b/rust/src/router/producer.rs index ec60283239..3b64975e35 100644 --- a/rust/src/router/producer.rs +++ b/rust/src/router/producer.rs @@ -759,7 +759,7 @@ impl Producer { match Notification::from_fbs(notification) { Ok(notification) => match notification { Notification::Score(scores) => { - *score.lock() = scores.clone(); + score.lock().clone_from(&scores); handlers.score.call(|callback| { callback(&scores); }); diff --git a/rust/src/rtp_parameters.rs b/rust/src/rtp_parameters.rs index 5747ebe700..ce9fcb422c 100644 --- a/rust/src/rtp_parameters.rs +++ b/rust/src/rtp_parameters.rs @@ -919,7 +919,6 @@ impl RtpParameters { }) } - #[allow(dead_code)] pub(crate) fn into_fbs(self) -> rtp_parameters::RtpParameters { rtp_parameters::RtpParameters { mid: self.mid, diff --git a/rust/src/scalability_modes.rs b/rust/src/scalability_modes.rs index de7510f5b4..f072cf026c 100644 --- a/rust/src/scalability_modes.rs +++ b/rust/src/scalability_modes.rs @@ -184,9 +184,9 @@ impl FromStr for ScalabilityMode { } } -impl ToString for ScalabilityMode { - fn to_string(&self) -> String { - self.as_str().to_string() +impl std::fmt::Display for ScalabilityMode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.as_str()) } } diff --git a/rust/src/worker/common.rs b/rust/src/worker/common.rs index 7259809ab2..100560b1e3 100644 --- a/rust/src/worker/common.rs +++ b/rust/src/worker/common.rs @@ -35,9 +35,7 @@ impl EventHandlers { let index; { let mut event_handlers = self.handlers.lock(); - let list = event_handlers - .entry(target_id.clone()) - .or_insert_with(EventHandlersList::default); + let list = event_handlers.entry(target_id.clone()).or_default(); index = list.index; list.index += 1; list.callbacks.insert(index, callback); diff --git a/rust/src/worker/utils/channel_read_fn.rs b/rust/src/worker/utils/channel_read_fn.rs index 57cf3b0bf8..d84617cc7c 100644 --- a/rust/src/worker/utils/channel_read_fn.rs +++ b/rust/src/worker/utils/channel_read_fn.rs @@ -8,9 +8,18 @@ unsafe extern "C" fn free_vec(message: *mut u8, message_len: u32, message_capaci Vec::from_raw_parts(message, message_len as usize, message_capacity); } -pub(super) struct ChannelReadCallback( - Box Option>) + Send + 'static>, -); +pub(super) struct ChannelReadCallback { + // Silence clippy warnings + _callback: Box Option>) + Send + 'static>, +} + +impl ChannelReadCallback { + pub(super) fn new( + _callback: Box Option>) + Send + 'static>, + ) -> Self { + Self { _callback } + } +} pub(crate) struct PreparedChannelRead { channel_read_fn: ChannelReadFn, @@ -71,6 +80,6 @@ where PreparedChannelRead { channel_read_fn: wrapper::, channel_read_ctx: ChannelReadCtx(read_callback.as_ref() as *const F as *const c_void), - write_callback: ChannelReadCallback(read_callback), + write_callback: ChannelReadCallback::new(read_callback), } } diff --git a/rust/src/worker/utils/channel_write_fn.rs b/rust/src/worker/utils/channel_write_fn.rs index c9e72077c9..5cace7fd2e 100644 --- a/rust/src/worker/utils/channel_write_fn.rs +++ b/rust/src/worker/utils/channel_write_fn.rs @@ -2,8 +2,19 @@ pub(super) use mediasoup_sys::{ChannelWriteCtx, ChannelWriteFn}; use std::os::raw::c_void; use std::slice; -#[allow(clippy::type_complexity)] -pub(super) struct ChannelReadCallback(Box); +/// TypeAlias to silience clippy::type_complexity warnings +type CallbackType = Box; + +pub(super) struct ChannelReadCallback { + // Silence clippy warnings + _callback: CallbackType, +} + +impl ChannelReadCallback { + pub(super) fn new(_callback: CallbackType) -> Self { + Self { _callback } + } +} pub(crate) struct PreparedChannelWrite { channel_write_fn: ChannelWriteFn, @@ -54,6 +65,6 @@ where PreparedChannelWrite { channel_write_fn: wrapper::, channel_write_ctx: ChannelWriteCtx(read_callback.as_ref() as *const F as *const c_void), - read_callback: ChannelReadCallback(read_callback), + read_callback: ChannelReadCallback::new(read_callback), } } diff --git a/rust/tests/integration/consumer.rs b/rust/tests/integration/consumer.rs index e1abdf88e6..a2d3272f52 100644 --- a/rust/tests/integration/consumer.rs +++ b/rust/tests/integration/consumer.rs @@ -291,7 +291,16 @@ fn consumer_device_capabilities() -> RtpCapabilities { } // Keeps executor threads running until dropped -struct ExecutorGuard(Vec>); +struct ExecutorGuard { + // Silence clippy warnings + _senders: Vec>, +} + +impl ExecutorGuard { + fn new(_senders: Vec>) -> Self { + Self { _senders } + } +} fn create_executor() -> (ExecutorGuard, Arc>) { let executor = Arc::new(Executor::new()); @@ -318,7 +327,7 @@ fn create_executor() -> (ExecutorGuard, Arc>) { }) .collect(); - (ExecutorGuard(senders), executor) + (ExecutorGuard::new(senders), executor) } async fn init() -> ( @@ -977,7 +986,7 @@ fn dump_succeeds() { ssrc: audio_consumer .rtp_parameters() .encodings - .get(0) + .first() .unwrap() .ssrc, rid: None, @@ -1086,13 +1095,13 @@ fn dump_succeeds() { ssrc: video_consumer .rtp_parameters() .encodings - .get(0) + .first() .unwrap() .ssrc, rtx: video_consumer .rtp_parameters() .encodings - .get(0) + .first() .unwrap() .rtx, dtx: None, @@ -1165,7 +1174,7 @@ fn get_stats_succeeds() { audio_consumer .rtp_parameters() .encodings - .get(0) + .first() .unwrap() .ssrc .unwrap() @@ -1214,7 +1223,7 @@ fn get_stats_succeeds() { video_consumer .rtp_parameters() .encodings - .get(0) + .first() .unwrap() .ssrc .unwrap() diff --git a/rust/tests/integration/webrtc_server.rs b/rust/tests/integration/webrtc_server.rs index a052d0653b..6e75f5a144 100644 --- a/rust/tests/integration/webrtc_server.rs +++ b/rust/tests/integration/webrtc_server.rs @@ -10,6 +10,11 @@ use std::net::{IpAddr, Ipv4Addr}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; +#[derive(Debug, PartialEq)] +struct CustomAppData { + foo: u32, +} + async fn init() -> (Worker, Worker) { { let mut builder = env_logger::builder(); @@ -52,11 +57,6 @@ fn create_webrtc_server_succeeds() { }) .detach(); - #[derive(Debug, PartialEq)] - struct CustomAppData { - foo: u32, - } - let webrtc_server = worker1 .create_webrtc_server({ let listen_infos = WebRtcServerListenInfos::new(ListenInfo { @@ -150,11 +150,6 @@ fn create_webrtc_server_without_specifying_port_succeeds() { }) .detach(); - #[derive(Debug, PartialEq)] - struct CustomAppData { - foo: u32, - } - let webrtc_server = worker1 .create_webrtc_server({ let listen_infos = WebRtcServerListenInfos::new(ListenInfo { @@ -233,11 +228,6 @@ fn unavailable_infos_fails() { }) .detach(); - #[derive(Debug, PartialEq)] - struct CustomAppData { - foo: u32, - } - // Using an unavailable listen IP. { let create_result = worker1 diff --git a/rust/tests/integration/webrtc_transport.rs b/rust/tests/integration/webrtc_transport.rs index e59caab44c..a58c835439 100644 --- a/rust/tests/integration/webrtc_transport.rs +++ b/rust/tests/integration/webrtc_transport.rs @@ -280,7 +280,7 @@ fn create_with_fixed_port_succeeds() { .await .expect("Failed to create WebRTC transport"); - assert_eq!(transport.ice_candidates().get(0).unwrap().port, port); + assert_eq!(transport.ice_candidates().first().unwrap().port, port); }); } @@ -306,7 +306,7 @@ fn create_with_port_range_succeeds() { .await .expect("Failed to create WebRTC transport"); - let port1 = transport1.ice_candidates().get(0).unwrap().port; + let port1 = transport1.ice_candidates().first().unwrap().port; assert!(port1 >= *port_range.start() && port1 <= *port_range.end()); let transport2 = router @@ -325,7 +325,7 @@ fn create_with_port_range_succeeds() { .await .expect("Failed to create WebRTC transport"); - let port2 = transport2.ice_candidates().get(0).unwrap().port; + let port2 = transport2.ice_candidates().first().unwrap().port; assert!(port2 >= *port_range.start() && port2 <= *port_range.end()); assert!(matches!( diff --git a/worker/build.rs b/worker/build.rs index 920d185d7b..7fe5d544ea 100644 --- a/worker/build.rs +++ b/worker/build.rs @@ -39,7 +39,6 @@ fn main() { .expect("Failed to generate Rust code from flatbuffers"), ) .expect("Failed to write generated Rust flatbuffers into fbs.rs"); - if env::var("DOCS_RS").is_ok() { // Skip everything when building docs on docs.rs return; diff --git a/worker/src/lib.rs b/worker/src/lib.rs index 60bd8131ff..f686458385 100644 --- a/worker/src/lib.rs +++ b/worker/src/lib.rs @@ -1,6 +1,11 @@ use std::os::raw::{c_char, c_int, c_void}; -include!(concat!(env!("OUT_DIR"), "/fbs.rs")); +pub use planus_codegen::*; + +mod planus_codegen { + #![allow(clippy::all)] + include!(concat!(env!("OUT_DIR"), "/fbs.rs")); +} #[repr(transparent)] #[derive(Copy, Clone)] From a80630aa107204fee677e4cf3b11f0f7b22fb064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 26 Jun 2024 15:37:43 +0200 Subject: [PATCH 460/525] update rust/CHANGELOG.md --- rust/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index 71e2a340fa..a4c76f1835 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +# NEXT + +- Update Rust toolchain channel to version 1.79.0 (PR #1409). + # 0.17.0 - Updates from mediasoup TypeScript `3.13.18..=3.14.6`. From 4ef1161fab493707df867d97b1a046931002e73d Mon Sep 17 00:00:00 2001 From: satoren Date: Mon, 1 Jul 2024 17:46:48 +0900 Subject: [PATCH 461/525] add tests with ASAN to node CI (#1415) --- .github/workflows/mediasoup-node.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index b035e0c56f..462bbe6492 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -11,12 +11,22 @@ concurrency: jobs: ci: strategy: + fail-fast: false matrix: ci: - os: ubuntu-20.04 node: 18 - os: ubuntu-22.04 node: 20 + - os: ubuntu-24.04 + node: 20 + meson_args: '-Db_sanitize=address' + - os: ubuntu-24.04 + node: 20 + meson_args: '-Db_sanitize=undefined' + - os: ubuntu-24.04 + node: 20 + meson_args: '-Db_sanitize=thread' - os: macos-12 node: 18 - os: macos-14 @@ -33,6 +43,7 @@ jobs: MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' MEDIASOUP_BUILDTYPE: ${{ matrix.build-type }} + MESON_ARGS: ${{ matrix.ci.meson_args }} steps: - name: Checkout @@ -54,6 +65,8 @@ jobs: - name: npm ci run: npm ci --foreground-scripts + env: + ASAN_OPTIONS: 'detect_leaks=0' # Disable leak detection because it is detected by the tool flatc used to build - name: npm run lint:node run: npm run lint:node From c0518ec1f0d70dccf42d805900edaa14bb07b79c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jul 2024 10:48:34 +0200 Subject: [PATCH 462/525] cosmetic --- .github/workflows/mediasoup-node.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 462bbe6492..b5747060e0 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -66,7 +66,8 @@ jobs: - name: npm ci run: npm ci --foreground-scripts env: - ASAN_OPTIONS: 'detect_leaks=0' # Disable leak detection because it is detected by the tool flatc used to build + # Disable leak detection because it's detected by the tool flatc uses to build. + ASAN_OPTIONS: 'detect_leaks=0' - name: npm run lint:node run: npm run lint:node From f641b6c2572967cc1bb35fc9649a25e18044f72c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jul 2024 10:48:51 +0200 Subject: [PATCH 463/525] cosmetic --- .github/workflows/mediasoup-node.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index b5747060e0..c98d7e74f5 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -11,7 +11,6 @@ concurrency: jobs: ci: strategy: - fail-fast: false matrix: ci: - os: ubuntu-20.04 From 73be1dd846b79de0e16482d6c949023755b508fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 1 Jul 2024 14:43:33 +0200 Subject: [PATCH 464/525] CI: Run worker tests with Address Sanitizer (only Linux) (disabled for now) (#1416) --- .github/workflows/mediasoup-worker.yaml | 21 +++++++ doc/Building.md | 12 +++- worker/Makefile | 14 ++++- worker/meson.build | 68 +++++++++++++++++++++-- worker/subprojects/catch2.wrap | 12 ++-- worker/subprojects/liburing.wrap | 18 +++--- worker/tasks.py | 74 +++++++++++++++++++++++-- worker/test/src/RTC/TestRtpPacket.cpp | 1 + 8 files changed, 189 insertions(+), 31 deletions(-) diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 584d4c47e4..a75f85435c 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -96,3 +96,24 @@ jobs: run: invoke -r worker test # TODO: Maybe fix this one day. if: runner.os != 'Windows' + + # TODO: Uncomment once https://github.com/versatica/mediasoup/issues/1417 + # is fixed. + # - name: invoke -r worker test-asan-address + # run: invoke -r worker test-asan-address + # # Address Sanitizer only works on Linux. + # if: runner.os == 'Linux' + + # TODO: Uncomment once https://github.com/versatica/mediasoup/issues/1417 + # is fixed. + # - name: invoke -r worker test-asan-undefined + # run: invoke -r worker test-asan-undefined + # # Address Sanitizer only works on Linux. + # if: runner.os == 'Linux' + + # TODO: Uncomment once https://github.com/versatica/mediasoup/issues/1417 + # is fixed. + # - name: invoke -r worker test-asan-thread + # run: invoke -r worker test-asan-thread + # # Address Sanitizer only works on Linux. + # if: runner.os == 'Linux' diff --git a/doc/Building.md b/doc/Building.md index fa5364bfd4..aaf183591a 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -188,9 +188,17 @@ Rewrites mediasoup worker C++ files using [clang-format](https://clang.llvm.org/ Builds and runs the `mediasoup-worker-test` binary at `worker/out/Release` (or at `worker/out/Debug` if the "MEDIASOUP_BUILDTYPE" environment variable is set to "Debug"), which uses [Catch2](https://github.com/catchorg/Catch2) to run test units located at `worker/test` folder. -### `invoke test-asan` +### `invoke test-asan-address` -Run test with Address Sanitizer. +Run test with Address Sanitizer with `-fsanitize=address`. + +### `invoke test-asan-undefined` + +Run test with Address Sanitizer with `-fsanitize=undefined`. + +### `invoke test-asan-thread` + +Run test with Address Sanitizer with `-fsanitize=thread`. ### `invoke tidy` diff --git a/worker/Makefile b/worker/Makefile index 0463766e7e..1f27d6e65f 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -32,7 +32,9 @@ endif lint \ format \ test \ - test-asan \ + test-asan-address \ + test-asan-undefined \ + test-asan-thread \ tidy \ fuzzer \ fuzzer-run-all \ @@ -96,8 +98,14 @@ format: invoke test: invoke "$(PYTHON)" -m invoke test -test-asan: invoke - "$(PYTHON)" -m invoke test-asan +test-asan-address: invoke + "$(PYTHON)" -m invoke test-asan-address + +test-asan-undefined: invoke + "$(PYTHON)" -m invoke test-asan-undefined + +test-asan-thread: invoke + "$(PYTHON)" -m invoke test-asan-thread tidy: invoke "$(PYTHON)" -m invoke tidy diff --git a/worker/meson.build b/worker/meson.build index 1be338815b..8de14990a4 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -393,11 +393,11 @@ test( workdir: meson.project_source_root(), ) -mediasoup_worker_test_asan = executable( - 'mediasoup-worker-test-asan', +mediasoup_worker_test_asan_address = executable( + 'mediasoup-worker-test-asan-address', build_by_default: false, install: true, - install_tag: 'mediasoup-worker-test-asan', + install_tag: 'mediasoup-worker-test-asan-address', dependencies: dependencies + [ catch2_proj.get_variable('catch2_dep'), ], @@ -417,8 +417,66 @@ mediasoup_worker_test_asan = executable( ) test( - 'mediasoup-worker-test-asan', - mediasoup_worker_test_asan, + 'mediasoup-worker-test-asan-address', + mediasoup_worker_test_asan_address, + workdir: meson.project_source_root(), +) + +mediasoup_worker_test_asan_undefined = executable( + 'mediasoup-worker-test-asan-undefined', + build_by_default: false, + install: true, + install_tag: 'mediasoup-worker-test-asan-undefined', + dependencies: dependencies + [ + catch2_proj.get_variable('catch2_dep'), + ], + sources: common_sources + test_sources, + include_directories: include_directories( + 'include', + 'test/include', + ), + cpp_args: cpp_args + [ + '-DMS_LOG_STD', + '-DMS_TEST', + '-fsanitize=undefined', + ], + link_args: [ + '-fsanitize=undefined', + ], +) + +test( + 'mediasoup-worker-test-asan-undefined', + mediasoup_worker_test_asan_undefined, + workdir: meson.project_source_root(), +) + +mediasoup_worker_test_asan_thread = executable( + 'mediasoup-worker-test-asan-thread', + build_by_default: false, + install: true, + install_tag: 'mediasoup-worker-test-asan-thread', + dependencies: dependencies + [ + catch2_proj.get_variable('catch2_dep'), + ], + sources: common_sources + test_sources, + include_directories: include_directories( + 'include', + 'test/include', + ), + cpp_args: cpp_args + [ + '-DMS_LOG_STD', + '-DMS_TEST', + '-fsanitize=thread', + ], + link_args: [ + '-fsanitize=thread', + ], +) + +test( + 'mediasoup-worker-test-asan-thread', + mediasoup_worker_test_asan_thread, workdir: meson.project_source_root(), ) diff --git a/worker/subprojects/catch2.wrap b/worker/subprojects/catch2.wrap index 9566401a2d..90bcddd3bc 100644 --- a/worker/subprojects/catch2.wrap +++ b/worker/subprojects/catch2.wrap @@ -1,10 +1,10 @@ [wrap-file] -directory = Catch2-3.5.3 -source_url = https://github.com/catchorg/Catch2/archive/v3.5.3.tar.gz -source_filename = Catch2-3.5.3.tar.gz -source_hash = 8d723b0535c94860ef8cf6231580fa47d67a3416757ecb10639e40d748ab6c71 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.5.3-1/Catch2-3.5.3.tar.gz -wrapdb_version = 3.5.3-1 +directory = Catch2-3.6.0 +source_url = https://github.com/catchorg/Catch2/archive/v3.6.0.tar.gz +source_filename = Catch2-3.6.0.tar.gz +source_hash = 485932259a75c7c6b72d4b874242c489ea5155d17efa345eb8cc72159f49f356 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.6.0-1/Catch2-3.6.0.tar.gz +wrapdb_version = 3.6.0-1 [provide] catch2 = catch2_dep diff --git a/worker/subprojects/liburing.wrap b/worker/subprojects/liburing.wrap index 40e019eb9c..00de3a7614 100644 --- a/worker/subprojects/liburing.wrap +++ b/worker/subprojects/liburing.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = liburing-liburing-2.4 -source_url = https://github.com/axboe/liburing/archive/refs/tags/liburing-2.4.tar.gz -source_filename = liburing-2.4.tar.gz -source_hash = 2398ec82d967a6f903f3ae1fd4541c754472d3a85a584dc78c5da2fabc90706b -patch_filename = liburing_2.4-2_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/liburing_2.4-2/get_patch -patch_hash = 0435ae1012065fa96a22e1068c2e39e2f7c7c03b58a812774434a6e7455d7f20 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/liburing_2.4-2/liburing-2.4.tar.gz -wrapdb_version = 2.4-2 +directory = liburing-liburing-2.5 +source_url = https://github.com/axboe/liburing/archive/refs/tags/liburing-2.5.tar.gz +source_filename = liburing-2.5.tar.gz +source_hash = 456f5f882165630f0dc7b75e8fd53bd01a955d5d4720729b4323097e6e9f2a98 +patch_filename = liburing_2.5-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/liburing_2.5-1/get_patch +patch_hash = d72f651e0edd8102535af575d682ce86c3fc2fdabb40b8faa2659d0f7d437f44 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/liburing_2.5-1/liburing-2.5.tar.gz +wrapdb_version = 2.5-1 [provide] dependency_names = liburing diff --git a/worker/tasks.py b/worker/tasks.py index d24ad3ed70..f9fb125d43 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -389,21 +389,83 @@ def test(ctx): ); -@task(pre=[setup, flatc]) -def test_asan(ctx): +@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=address'), flatc]) +def test_asan_address(ctx): + """ + Run worker test with Address Sanitizer with '-fsanitize=address' + """ + with ctx.cd(f'"{WORKER_DIR}"'): + ctx.run( + f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test-asan-address', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + with ctx.cd(f'"{WORKER_DIR}"'): + ctx.run( + f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test-asan-address', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or ''; + + with ctx.cd(f'"{WORKER_DIR}"'): + ctx.run( + f'ASAN_OPTIONS=detect_leaks=1 "{BUILD_DIR}/mediasoup-worker-test-asan-address" --invisibles {mediasoup_test_tags}', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=undefined'), flatc]) +def test_asan_undefined(ctx): + """ + Run worker test with undefined Sanitizer with -fsanitize=undefined + """ + with ctx.cd(f'"{WORKER_DIR}"'): + ctx.run( + f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test-asan-undefined', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + with ctx.cd(f'"{WORKER_DIR}"'): + ctx.run( + f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test-asan-undefined', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or ''; + + with ctx.cd(f'"{WORKER_DIR}"'): + ctx.run( + f'ASAN_OPTIONS=detect_leaks=1 "{BUILD_DIR}/mediasoup-worker-test-asan-undefined" --invisibles {mediasoup_test_tags}', + echo=True, + pty=PTY_SUPPORTED, + shell=SHELL + ); + + +@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=thread'), flatc]) +def test_asan_thread(ctx): """ - Run worker test with Address Sanitizer + Run worker test with thread Sanitizer with -fsanitize=thread """ with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( - f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test-asan', + f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test-asan-thread', echo=True, pty=PTY_SUPPORTED, shell=SHELL ); with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( - f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test-asan', + f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test-asan-thread', echo=True, pty=PTY_SUPPORTED, shell=SHELL @@ -413,7 +475,7 @@ def test_asan(ctx): with ctx.cd(f'"{WORKER_DIR}"'): ctx.run( - f'ASAN_OPTIONS=detect_leaks=1 "{BUILD_DIR}/mediasoup-worker-test-asan" --invisibles --use-colour=yes {mediasoup_test_tags}', + f'ASAN_OPTIONS=detect_leaks=1 "{BUILD_DIR}/mediasoup-worker-test-asan-thread" --invisibles {mediasoup_test_tags}', echo=True, pty=PTY_SUPPORTED, shell=SHELL diff --git a/worker/test/src/RTC/TestRtpPacket.cpp b/worker/test/src/RTC/TestRtpPacket.cpp index 699cd14bbd..e931697c9e 100644 --- a/worker/test/src/RTC/TestRtpPacket.cpp +++ b/worker/test/src/RTC/TestRtpPacket.cpp @@ -526,6 +526,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; // clang-format on From 99909535bf6bfe32e1322db07dc6b74290d913bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 1 Jul 2024 17:49:32 +0200 Subject: [PATCH 465/525] TestRtpStreamSend: ASAN, fix buffer overflow (#1419) TestRtpStreamSend: ASAN, fix buffer overflow --- CHANGELOG.md | 4 ++ worker/test/src/RTC/TestRtpStreamSend.cpp | 56 +++++++++++------------ 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e1e72e35e..44ae6bdaa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Worker: Test, fix buffer overflow ([PR #1419](https://github.com/versatica/mediasoup/pull/1419)). + ### 3.14.8 - Add support for 'playout-delay' RTP extension ([PR #1412](https://github.com/versatica/mediasoup/pull/1412) by @DavidNegro). diff --git a/worker/test/src/RTC/TestRtpStreamSend.cpp b/worker/test/src/RTC/TestRtpStreamSend.cpp index 8e61af7bd6..6c3bee17bb 100644 --- a/worker/test/src/RTC/TestRtpStreamSend.cpp +++ b/worker/test/src/RTC/TestRtpStreamSend.cpp @@ -10,9 +10,9 @@ using namespace RTC; -static RtpPacket* CreateRtpPacket(uint8_t* buffer, uint16_t seq, uint32_t timestamp) +static RtpPacket* CreateRtpPacket(uint8_t* buffer, size_t len, uint16_t seq, uint32_t timestamp) { - auto* packet = RtpPacket::Parse(buffer, 1500); + auto* packet = RtpPacket::Parse(buffer, len); packet->SetSequenceNumber(seq); packet->SetTimestamp(timestamp); @@ -78,15 +78,15 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get retransmitted packets") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); + auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); + auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901); // packet3 [pt:123, seq:21008, timestamp:1533793871] - auto* packet3 = CreateRtpPacket(rtpBuffer3, 21008, 1533793871); + auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871); // packet4 [pt:123, seq:21009, timestamp:1533793871] - auto* packet4 = CreateRtpPacket(rtpBuffer4, 21009, 1533793871); + auto* packet4 = CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871); // packet5 [pt:123, seq:21010, timestamp:1533796931] - auto* packet5 = CreateRtpPacket(rtpBuffer5, 21010, 1533796931); + auto* packet5 = CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -143,15 +143,15 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get zero retransmitted packets if useNack is not set") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); + auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); + auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901); // packet3 [pt:123, seq:21008, timestamp:1533793871] - auto* packet3 = CreateRtpPacket(rtpBuffer3, 21008, 1533793871); + auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871); // packet4 [pt:123, seq:21009, timestamp:1533793871] - auto* packet4 = CreateRtpPacket(rtpBuffer4, 21009, 1533793871); + auto* packet4 = CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871); // packet5 [pt:123, seq:21010, timestamp:1533796931] - auto* packet5 = CreateRtpPacket(rtpBuffer5, 21010, 1533796931); + auto* packet5 = CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -196,15 +196,15 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get zero retransmitted packets for audio") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); + auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); + auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901); // packet3 [pt:123, seq:21008, timestamp:1533793871] - auto* packet3 = CreateRtpPacket(rtpBuffer3, 21008, 1533793871); + auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871); // packet4 [pt:123, seq:21009, timestamp:1533793871] - auto* packet4 = CreateRtpPacket(rtpBuffer4, 21009, 1533793871); + auto* packet4 = CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871); // packet5 [pt:123, seq:21010, timestamp:1533796931] - auto* packet5 = CreateRtpPacket(rtpBuffer5, 21010, 1533796931); + auto* packet5 = CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -249,9 +249,9 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK in different RtpStreamSend instances and get retransmitted packets") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, 1533790901); + auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, 1533790901); + auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901); // Create two RtpStreamSend instances. TestRtpStreamListener testRtpStreamListener1; @@ -326,8 +326,8 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayForVideoMs * clockRate / 1000; uint32_t secondTs = firstTs + diffTs; - auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); - auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, secondTs - 1); + auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs); + auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs - 1); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -381,9 +381,9 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") // Send a third packet so it will clean old packets from the buffer. uint32_t thirdTs = firstTs + (2 * diffTs); - auto* packet1 = CreateRtpPacket(rtpBuffer1, 21006, firstTs); - auto* packet2 = CreateRtpPacket(rtpBuffer2, 21007, secondTs); - auto* packet3 = CreateRtpPacket(rtpBuffer3, 21008, thirdTs); + auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs); + auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs); + auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, thirdTs); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -430,14 +430,14 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") { // This scenario reproduce the "too bad sequence number" and "bad sequence // number" scenarios in RtpStream::UpdateSeq(). - auto* packet1 = CreateRtpPacket(rtpBuffer1, 50001, 1000001); - auto* packet2 = CreateRtpPacket(rtpBuffer2, 50002, 1000002); + auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 50001, 1000001); + auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 50002, 1000002); // Third packet has bad sequence number (its seq is more than MaxDropout=3000 // older than current max seq) and will be dropped. - auto* packet3 = CreateRtpPacket(rtpBuffer3, 40003, 1000003); + auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 40003, 1000003); // Forth packet has seq=badSeq+1 so will be accepted and will trigger a // stream reset. - auto* packet4 = CreateRtpPacket(rtpBuffer4, 40004, 1000004); + auto* packet4 = CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 40004, 1000004); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; From 9d9e358b18c1853ba2b76b16067fee6470db63a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 1 Jul 2024 20:17:47 +0200 Subject: [PATCH 466/525] TestRtpStreamSend: ASAN, fix memory leaks (#1420) Use std::unique_pointer rather than raw pointers --- worker/test/src/RTC/TestRtpStreamSend.cpp | 173 ++++++++++++---------- 1 file changed, 92 insertions(+), 81 deletions(-) diff --git a/worker/test/src/RTC/TestRtpStreamSend.cpp b/worker/test/src/RTC/TestRtpStreamSend.cpp index 6c3bee17bb..3d18323c1b 100644 --- a/worker/test/src/RTC/TestRtpStreamSend.cpp +++ b/worker/test/src/RTC/TestRtpStreamSend.cpp @@ -78,15 +78,20 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get retransmitted packets") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901); + std::unique_ptr packet1( + CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901); + std::unique_ptr packet2( + CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); // packet3 [pt:123, seq:21008, timestamp:1533793871] - auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871); + std::unique_ptr packet3( + CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871)); // packet4 [pt:123, seq:21009, timestamp:1533793871] - auto* packet4 = CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871); + std::unique_ptr packet4( + CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871)); // packet5 [pt:123, seq:21010, timestamp:1533796931] - auto* packet5 = CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931); + std::unique_ptr packet5( + CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -99,16 +104,16 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - auto* stream = new RtpStreamSend(&testRtpStreamListener, params, mid); + std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params, mid)); // Receive all the packets (some of them not in order and/or duplicated). - SendRtpPacket({ { stream, params.ssrc } }, packet1); - SendRtpPacket({ { stream, params.ssrc } }, packet3); - SendRtpPacket({ { stream, params.ssrc } }, packet2); - SendRtpPacket({ { stream, params.ssrc } }, packet3); - SendRtpPacket({ { stream, params.ssrc } }, packet4); - SendRtpPacket({ { stream, params.ssrc } }, packet5); - SendRtpPacket({ { stream, params.ssrc } }, packet5); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet1.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet3.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet2.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet3.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet4.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet5.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet5.get()); // Create a NACK item that request for all the packets. RTCP::FeedbackRtpNackPacket nackPacket(0, params.ssrc); @@ -136,22 +141,25 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") CheckRtxPacket(rtxPacket3, packet3->GetSequenceNumber(), packet3->GetTimestamp()); CheckRtxPacket(rtxPacket4, packet4->GetSequenceNumber(), packet4->GetTimestamp()); CheckRtxPacket(rtxPacket5, packet5->GetSequenceNumber(), packet5->GetTimestamp()); - - delete stream; } SECTION("receive NACK and get zero retransmitted packets if useNack is not set") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901); + std::unique_ptr packet1( + CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901); + std::unique_ptr packet2( + CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); // packet3 [pt:123, seq:21008, timestamp:1533793871] - auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871); + std::unique_ptr packet3( + CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871)); // packet4 [pt:123, seq:21009, timestamp:1533793871] - auto* packet4 = CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871); + std::unique_ptr packet4( + CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871)); // packet5 [pt:123, seq:21010, timestamp:1533796931] - auto* packet5 = CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931); + std::unique_ptr packet5( + CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -164,16 +172,16 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - auto* stream = new RtpStreamSend(&testRtpStreamListener, params, mid); + std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params, mid)); // Receive all the packets (some of them not in order and/or duplicated). - SendRtpPacket({ { stream, params.ssrc } }, packet1); - SendRtpPacket({ { stream, params.ssrc } }, packet3); - SendRtpPacket({ { stream, params.ssrc } }, packet2); - SendRtpPacket({ { stream, params.ssrc } }, packet3); - SendRtpPacket({ { stream, params.ssrc } }, packet4); - SendRtpPacket({ { stream, params.ssrc } }, packet5); - SendRtpPacket({ { stream, params.ssrc } }, packet5); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet1.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet3.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet2.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet3.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet4.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet5.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet5.get()); // Create a NACK item that request for all the packets. RTCP::FeedbackRtpNackPacket nackPacket(0, params.ssrc); @@ -189,22 +197,25 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") REQUIRE(testRtpStreamListener.retransmittedPackets.size() == 0); testRtpStreamListener.retransmittedPackets.clear(); - - delete stream; } SECTION("receive NACK and get zero retransmitted packets for audio") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901); + std::unique_ptr packet1( + CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901); + std::unique_ptr packet2( + CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); // packet3 [pt:123, seq:21008, timestamp:1533793871] - auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871); + std::unique_ptr packet3( + CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871)); // packet4 [pt:123, seq:21009, timestamp:1533793871] - auto* packet4 = CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871); + std::unique_ptr packet4( + CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871)); // packet5 [pt:123, seq:21010, timestamp:1533796931] - auto* packet5 = CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931); + std::unique_ptr packet5( + CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -217,16 +228,16 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params.mimeType.type = RTC::RtpCodecMimeType::Type::AUDIO; std::string mid; - auto* stream = new RtpStreamSend(&testRtpStreamListener, params, mid); + std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params, mid)); // Receive all the packets (some of them not in order and/or duplicated). - SendRtpPacket({ { stream, params.ssrc } }, packet1); - SendRtpPacket({ { stream, params.ssrc } }, packet3); - SendRtpPacket({ { stream, params.ssrc } }, packet2); - SendRtpPacket({ { stream, params.ssrc } }, packet3); - SendRtpPacket({ { stream, params.ssrc } }, packet4); - SendRtpPacket({ { stream, params.ssrc } }, packet5); - SendRtpPacket({ { stream, params.ssrc } }, packet5); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet1.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet3.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet2.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet3.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet4.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet5.get()); + SendRtpPacket({ { stream.get(), params.ssrc } }, packet5.get()); // Create a NACK item that request for all the packets. RTCP::FeedbackRtpNackPacket nackPacket(0, params.ssrc); @@ -242,16 +253,16 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") REQUIRE(testRtpStreamListener.retransmittedPackets.size() == 0); testRtpStreamListener.retransmittedPackets.clear(); - - delete stream; } SECTION("receive NACK in different RtpStreamSend instances and get retransmitted packets") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901); + std::unique_ptr packet1( + CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); // packet2 [pt:123, seq:21007, timestamp:1533790901] - auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901); + std::unique_ptr packet2( + CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); // Create two RtpStreamSend instances. TestRtpStreamListener testRtpStreamListener1; @@ -265,7 +276,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - auto* stream1 = new RtpStreamSend(&testRtpStreamListener1, params1, mid); + std::unique_ptr stream1(new RtpStreamSend(&testRtpStreamListener1, params1, mid)); RtpStream::Params params2; @@ -274,11 +285,11 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params2.useNack = true; params2.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; - auto* stream2 = new RtpStreamSend(&testRtpStreamListener2, params2, mid); + std::unique_ptr stream2(new RtpStreamSend(&testRtpStreamListener2, params2, mid)); // Receive all the packets in both streams. - SendRtpPacket({ { stream1, params1.ssrc }, { stream2, params2.ssrc } }, packet1); - SendRtpPacket({ { stream1, params1.ssrc }, { stream2, params2.ssrc } }, packet2); + SendRtpPacket({ { stream1.get(), params1.ssrc }, { stream2.get(), params2.ssrc } }, packet1.get()); + SendRtpPacket({ { stream1.get(), params1.ssrc }, { stream2.get(), params2.ssrc } }, packet2.get()); // Create a NACK item that request for all the packets. RTCP::FeedbackRtpNackPacket nackPacket(0, params1.ssrc); @@ -314,9 +325,6 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") CheckRtxPacket(rtxPacket1, packet1->GetSequenceNumber(), packet1->GetTimestamp()); CheckRtxPacket(rtxPacket2, packet2->GetSequenceNumber(), packet2->GetTimestamp()); - - delete stream1; - delete stream2; } SECTION("packets get retransmitted as long as they don't exceed MaxRetransmissionDelayForVideoMs") @@ -326,8 +334,10 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayForVideoMs * clockRate / 1000; uint32_t secondTs = firstTs + diffTs; - auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs); - auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs - 1); + std::unique_ptr packet1( + CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs)); + std::unique_ptr packet2( + CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs - 1)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -340,11 +350,11 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - auto* stream = new RtpStreamSend(&testRtpStreamListener, params1, mid); + std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params1, mid)); // Receive all the packets. - SendRtpPacket({ { stream, params1.ssrc } }, packet1); - SendRtpPacket({ { stream, params1.ssrc } }, packet2); + SendRtpPacket({ { stream.get(), params1.ssrc } }, packet1.get()); + SendRtpPacket({ { stream.get(), params1.ssrc } }, packet2.get()); // Create a NACK item that request for all the packets. RTCP::FeedbackRtpNackPacket nackPacket(0, params1.ssrc); @@ -367,8 +377,6 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") CheckRtxPacket(rtxPacket1, packet1->GetSequenceNumber(), packet1->GetTimestamp()); CheckRtxPacket(rtxPacket2, packet2->GetSequenceNumber(), packet2->GetTimestamp()); - - delete stream; } SECTION("packets don't get retransmitted if MaxRetransmissionDelayForVideoMs is exceeded") @@ -381,9 +389,12 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") // Send a third packet so it will clean old packets from the buffer. uint32_t thirdTs = firstTs + (2 * diffTs); - auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs); - auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs); - auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, thirdTs); + std::unique_ptr packet1( + CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs)); + std::unique_ptr packet2( + CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs)); + std::unique_ptr packet3( + CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, thirdTs)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -396,12 +407,12 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - auto* stream = new RtpStreamSend(&testRtpStreamListener, params1, mid); + std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params1, mid)); // Receive all the packets. - SendRtpPacket({ { stream, params1.ssrc } }, packet1); - SendRtpPacket({ { stream, params1.ssrc } }, packet2); - SendRtpPacket({ { stream, params1.ssrc } }, packet3); + SendRtpPacket({ { stream.get(), params1.ssrc } }, packet1.get()); + SendRtpPacket({ { stream.get(), params1.ssrc } }, packet2.get()); + SendRtpPacket({ { stream.get(), params1.ssrc } }, packet3.get()); // Create a NACK item that requests for all packets. RTCP::FeedbackRtpNackPacket nackPacket(0, params1.ssrc); @@ -422,22 +433,24 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") testRtpStreamListener.retransmittedPackets.clear(); CheckRtxPacket(rtxPacket2, packet2->GetSequenceNumber(), packet2->GetTimestamp()); - - delete stream; } SECTION("packets get removed from the retransmission buffer if seq number of the stream is reset") { // This scenario reproduce the "too bad sequence number" and "bad sequence // number" scenarios in RtpStream::UpdateSeq(). - auto* packet1 = CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 50001, 1000001); - auto* packet2 = CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 50002, 1000002); + std::unique_ptr packet1( + CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 50001, 1000001)); + std::unique_ptr packet2( + CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 50002, 1000002)); // Third packet has bad sequence number (its seq is more than MaxDropout=3000 // older than current max seq) and will be dropped. - auto* packet3 = CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 40003, 1000003); + std::unique_ptr packet3( + CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 40003, 1000003)); // Forth packet has seq=badSeq+1 so will be accepted and will trigger a // stream reset. - auto* packet4 = CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 40004, 1000004); + std::unique_ptr packet4( + CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 40004, 1000004)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -450,12 +463,12 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - auto* stream = new RtpStreamSend(&testRtpStreamListener, params1, mid); + std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params1, mid)); - SendRtpPacket({ { stream, params1.ssrc } }, packet1); - SendRtpPacket({ { stream, params1.ssrc } }, packet2); - SendRtpPacket({ { stream, params1.ssrc } }, packet3); - SendRtpPacket({ { stream, params1.ssrc } }, packet4); + SendRtpPacket({ { stream.get(), params1.ssrc } }, packet1.get()); + SendRtpPacket({ { stream.get(), params1.ssrc } }, packet2.get()); + SendRtpPacket({ { stream.get(), params1.ssrc } }, packet3.get()); + SendRtpPacket({ { stream.get(), params1.ssrc } }, packet4.get()); // Create a NACK item that requests for packets 1 and 2. RTCP::FeedbackRtpNackPacket nackPacket2(0, params1.ssrc); @@ -467,8 +480,6 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") stream->ReceiveNack(&nackPacket2); REQUIRE(testRtpStreamListener.retransmittedPackets.size() == 0); - - delete stream; } #ifdef PERFORMANCE_TEST From 2f30a84a57d8d7cdc5d92f38e7b5ec98a1cd965f Mon Sep 17 00:00:00 2001 From: Lynnworld Date: Thu, 4 Jul 2024 20:08:32 +0900 Subject: [PATCH 467/525] flatbuffer builder reuse (#1422) --- worker/include/Channel/ChannelNotifier.hpp | 4 ++-- worker/include/Channel/ChannelRequest.hpp | 8 ++++---- worker/src/Channel/ChannelRequest.cpp | 14 +++++++++----- worker/src/Channel/ChannelSocket.cpp | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/worker/include/Channel/ChannelNotifier.hpp b/worker/include/Channel/ChannelNotifier.hpp index c896ca3958..097c1398c0 100644 --- a/worker/include/Channel/ChannelNotifier.hpp +++ b/worker/include/Channel/ChannelNotifier.hpp @@ -34,7 +34,7 @@ namespace Channel builder.FinishSizePrefixed(message); this->channel->Send(builder.GetBufferPointer(), builder.GetSize()); - builder.Reset(); + builder.Clear(); } void Emit(const std::string& targetId, FBS::Notification::Event event) @@ -48,7 +48,7 @@ namespace Channel builder.FinishSizePrefixed(message); this->channel->Send(builder.GetBufferPointer(), builder.GetSize()); - builder.Reset(); + builder.Clear(); } private: diff --git a/worker/include/Channel/ChannelRequest.hpp b/worker/include/Channel/ChannelRequest.hpp index 1f1b48c242..2df2d5dea2 100644 --- a/worker/include/Channel/ChannelRequest.hpp +++ b/worker/include/Channel/ChannelRequest.hpp @@ -22,6 +22,7 @@ namespace Channel public: static absl::flat_hash_map method2String; + thread_local static flatbuffers::FlatBufferBuilder bufferBuilder; public: ChannelRequest(Channel::ChannelSocket* channel, const FBS::Request::Request* request); @@ -29,7 +30,7 @@ namespace Channel flatbuffers::FlatBufferBuilder& GetBufferBuilder() { - return this->bufferBuilder; + return ChannelRequest::bufferBuilder; } void Accept(); template @@ -39,7 +40,7 @@ namespace Channel this->replied = true; - auto& builder = this->bufferBuilder; + auto& builder = ChannelRequest::bufferBuilder; auto response = FBS::Response::CreateResponse(builder, this->id, true, type, body.Union()); auto message = @@ -47,7 +48,7 @@ namespace Channel builder.FinishSizePrefixed(message); this->Send(builder.GetBufferPointer(), builder.GetSize()); - builder.Reset(); + builder.Clear(); } void Error(const char* reason = nullptr); void TypeError(const char* reason = nullptr); @@ -61,7 +62,6 @@ namespace Channel Channel::ChannelSocket* channel{ nullptr }; const FBS::Request::Request* data{ nullptr }; // Others. - flatbuffers::FlatBufferBuilder bufferBuilder{}; uint32_t id{ 0u }; Method method; const char* methodCStr; diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index f268d94f21..82830bef7c 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -7,6 +7,10 @@ namespace Channel { + /* Static variables. */ + + thread_local flatbuffers::FlatBufferBuilder ChannelRequest::bufferBuilder{}; + /* Class variables. */ // clang-format off @@ -119,7 +123,7 @@ namespace Channel this->replied = true; - auto& builder = this->bufferBuilder; + auto& builder = ChannelRequest::bufferBuilder; auto response = FBS::Response::CreateResponse(builder, this->id, true, FBS::Response::Body::NONE, 0); @@ -134,7 +138,7 @@ namespace Channel this->replied = true; - auto& builder = this->bufferBuilder; + auto& builder = ChannelRequest::bufferBuilder; auto response = FBS::Response::CreateResponseDirect( builder, this->id, false /*accepted*/, FBS::Response::Body::NONE, 0, "Error" /*Error*/, reason); @@ -149,7 +153,7 @@ namespace Channel this->replied = true; - auto& builder = this->bufferBuilder; + auto& builder = ChannelRequest::bufferBuilder; auto response = FBS::Response::CreateResponseDirect( builder, this->id, false /*accepted*/, FBS::Response::Body::NONE, 0, "TypeError" /*Error*/, reason); @@ -163,12 +167,12 @@ namespace Channel void ChannelRequest::SendResponse(const flatbuffers::Offset& response) { - auto& builder = this->bufferBuilder; + auto& builder = ChannelRequest::bufferBuilder; auto message = FBS::Message::CreateMessage(builder, FBS::Message::Body::Response, response.Union()); builder.FinishSizePrefixed(message); this->Send(builder.GetBufferPointer(), builder.GetSize()); - builder.Reset(); + builder.Clear(); } } // namespace Channel diff --git a/worker/src/Channel/ChannelSocket.cpp b/worker/src/Channel/ChannelSocket.cpp index cb99e8472b..144712501b 100644 --- a/worker/src/Channel/ChannelSocket.cpp +++ b/worker/src/Channel/ChannelSocket.cpp @@ -162,7 +162,7 @@ namespace Channel this->bufferBuilder.FinishSizePrefixed(message); this->Send(this->bufferBuilder.GetBufferPointer(), this->bufferBuilder.GetSize()); - this->bufferBuilder.Reset(); + this->bufferBuilder.Clear(); } bool ChannelSocket::CallbackRead() From 8b46a2b5ebc86ca248896266f32fedea56f9cfd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 6 Jul 2024 14:39:28 +0200 Subject: [PATCH 468/525] Worker tests: use unique pointers when possible (#1421) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Luis Millán --- .github/workflows/mediasoup-worker.yaml | 10 +- worker/Dockerfile | 6 +- worker/test/src/RTC/Codecs/TestH264.cpp | 5 +- worker/test/src/RTC/Codecs/TestH264_SVC.cpp | 36 +++--- worker/test/src/RTC/Codecs/TestVP8.cpp | 10 +- worker/test/src/RTC/RTCP/TestBye.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackPsAfb.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackPsFir.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackPsLei.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackPsPli.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackPsRemb.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackPsSli.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackPsTst.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp | 6 +- .../test/src/RTC/RTCP/TestFeedbackRtpNack.cpp | 7 +- .../src/RTC/RTCP/TestFeedbackRtpSrReq.cpp | 7 +- .../src/RTC/RTCP/TestFeedbackRtpTllei.cpp | 7 +- .../test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp | 14 +-- .../src/RTC/RTCP/TestFeedbackRtpTransport.cpp | 85 +++++--------- worker/test/src/RTC/RTCP/TestPacket.cpp | 20 +--- .../test/src/RTC/RTCP/TestReceiverReport.cpp | 20 ++-- worker/test/src/RTC/RTCP/TestSdes.cpp | 34 ++---- worker/test/src/RTC/RTCP/TestSenderReport.cpp | 14 +-- worker/test/src/RTC/RTCP/TestXr.cpp | 27 +++-- worker/test/src/RTC/TestNackGenerator.cpp | 4 +- worker/test/src/RTC/TestRtpPacket.cpp | 53 +++------ worker/test/src/RTC/TestRtpPacketH264Svc.cpp | 76 +++++-------- .../src/RTC/TestRtpRetransmissionBuffer.cpp | 4 +- worker/test/src/RTC/TestRtpStreamRecv.cpp | 20 ++-- worker/test/src/RTC/TestRtpStreamSend.cpp | 107 +++++++----------- .../TestTransportCongestionControlServer.cpp | 4 +- 33 files changed, 244 insertions(+), 392 deletions(-) diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index a75f85435c..6ff7dc5ec1 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -97,12 +97,10 @@ jobs: # TODO: Maybe fix this one day. if: runner.os != 'Windows' - # TODO: Uncomment once https://github.com/versatica/mediasoup/issues/1417 - # is fixed. - # - name: invoke -r worker test-asan-address - # run: invoke -r worker test-asan-address - # # Address Sanitizer only works on Linux. - # if: runner.os == 'Linux' + - name: invoke -r worker test-asan-address + run: invoke -r worker test-asan-address + # Address Sanitizer only works on Linux. + if: runner.os == 'Linux' # TODO: Uncomment once https://github.com/versatica/mediasoup/issues/1417 # is fixed. diff --git a/worker/Dockerfile b/worker/Dockerfile index 64ae430df2..3a0dd68de8 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -6,7 +6,7 @@ RUN set -x \ && apt-get install --yes \ gcc g++ clang pkg-config bash-completion wget curl \ screen python3-pip python3-yaml pkg-config zlib1g-dev \ - libgss-dev libssl-dev libxml2-dev + libgss-dev libssl-dev libxml2-dev gdb # Install node 20. RUN set -x \ @@ -21,6 +21,10 @@ RUN set -x \ && apt-get update \ && apt-get install nodejs --yes +# Enable core dumps. +RUN set -x \ + && echo "mkdir -p /tmp/cores && chmod 777 /tmp/cores && echo \"/tmp/cores/core.%e.sig%s.%p\" > /proc/sys/kernel/core_pattern && ulimit -c unlimited" >> ~/.bashrc + # Make CC and CXX point to clang/clang++ installed above. ENV LANG="C.UTF-8" ENV CC="clang" diff --git a/worker/test/src/RTC/Codecs/TestH264.cpp b/worker/test/src/RTC/Codecs/TestH264.cpp index 67b573682f..47132e96cc 100644 --- a/worker/test/src/RTC/Codecs/TestH264.cpp +++ b/worker/test/src/RTC/Codecs/TestH264.cpp @@ -21,10 +21,9 @@ SCENARIO("parse H264 payload descriptor", "[codecs][h264]") std::memcpy(buffer, originalBuffer, sizeof(buffer)); - const auto* payloadDescriptor = Codecs::H264::Parse(buffer, sizeof(buffer)); + std::unique_ptr payloadDescriptor{ Codecs::H264::Parse( + buffer, sizeof(buffer)) }; REQUIRE(payloadDescriptor); - - delete payloadDescriptor; } } diff --git a/worker/test/src/RTC/Codecs/TestH264_SVC.cpp b/worker/test/src/RTC/Codecs/TestH264_SVC.cpp index 16c5726ac6..dc7380959d 100644 --- a/worker/test/src/RTC/Codecs/TestH264_SVC.cpp +++ b/worker/test/src/RTC/Codecs/TestH264_SVC.cpp @@ -21,7 +21,9 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") std::memcpy(buffer, originalBuffer, sizeof(buffer)); - const auto* payloadDescriptor = Codecs::H264_SVC::Parse(buffer, sizeof(buffer)); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(buffer, sizeof(buffer)) + }; REQUIRE(payloadDescriptor); @@ -31,8 +33,6 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") REQUIRE(payloadDescriptor->isKeyFrame == true); REQUIRE(payloadDescriptor->hasTlIndex == false); REQUIRE(payloadDescriptor->hasSlIndex == false); - - delete payloadDescriptor; } SECTION("parse payload descriptor for NALU 8") @@ -49,7 +49,9 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") std::memcpy(buffer, originalBuffer, sizeof(buffer)); - const auto* payloadDescriptor = Codecs::H264_SVC::Parse(buffer, sizeof(buffer)); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(buffer, sizeof(buffer)) + }; REQUIRE(payloadDescriptor); @@ -59,8 +61,6 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") REQUIRE(payloadDescriptor->isKeyFrame == false); REQUIRE(payloadDescriptor->hasTlIndex == false); REQUIRE(payloadDescriptor->hasSlIndex == false); - - delete payloadDescriptor; } SECTION("parse payload descriptor for NALU 1") @@ -77,7 +77,9 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") std::memcpy(buffer, originalBuffer, sizeof(buffer)); - const auto* payloadDescriptor = Codecs::H264_SVC::Parse(buffer, sizeof(buffer)); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(buffer, sizeof(buffer)) + }; REQUIRE(payloadDescriptor); @@ -87,8 +89,6 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") REQUIRE(payloadDescriptor->isKeyFrame == false); REQUIRE(payloadDescriptor->hasTlIndex == false); REQUIRE(payloadDescriptor->hasSlIndex == false); - - delete payloadDescriptor; } SECTION("parse payload descriptor for NALU 5") @@ -105,7 +105,9 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") std::memcpy(buffer, originalBuffer, sizeof(buffer)); - const auto* payloadDescriptor = Codecs::H264_SVC::Parse(buffer, sizeof(buffer)); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(buffer, sizeof(buffer)) + }; REQUIRE(payloadDescriptor); @@ -115,8 +117,6 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") REQUIRE(payloadDescriptor->isKeyFrame == true); REQUIRE(payloadDescriptor->hasTlIndex == false); REQUIRE(payloadDescriptor->hasSlIndex == false); - - delete payloadDescriptor; } SECTION("parse payload descriptor for NALU 14") @@ -133,7 +133,9 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") std::memcpy(buffer, originalBuffer, sizeof(buffer)); - const auto* payloadDescriptor = Codecs::H264_SVC::Parse(buffer, sizeof(buffer)); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(buffer, sizeof(buffer)) + }; REQUIRE(payloadDescriptor); @@ -145,8 +147,6 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") REQUIRE(payloadDescriptor->isKeyFrame == false); REQUIRE(payloadDescriptor->hasTlIndex == true); REQUIRE(payloadDescriptor->hasSlIndex == true); - - delete payloadDescriptor; } SECTION("parse payload descriptor for NALU 20") @@ -163,7 +163,9 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") std::memcpy(buffer, originalBuffer, sizeof(buffer)); - const auto* payloadDescriptor = Codecs::H264_SVC::Parse(buffer, sizeof(buffer)); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(buffer, sizeof(buffer)) + }; REQUIRE(payloadDescriptor); @@ -175,7 +177,5 @@ SCENARIO("parse H264_SVC payload descriptor", "[codecs][h264_svc]") REQUIRE(payloadDescriptor->isKeyFrame == false); REQUIRE(payloadDescriptor->hasTlIndex == true); REQUIRE(payloadDescriptor->hasSlIndex == true); - - delete payloadDescriptor; } } diff --git a/worker/test/src/RTC/Codecs/TestVP8.cpp b/worker/test/src/RTC/Codecs/TestVP8.cpp index 545240d78c..a5b663aaea 100644 --- a/worker/test/src/RTC/Codecs/TestVP8.cpp +++ b/worker/test/src/RTC/Codecs/TestVP8.cpp @@ -38,7 +38,8 @@ SCENARIO("parse VP8 payload descriptor", "[codecs][vp8]") std::memcpy(buffer, originalBuffer, sizeof(buffer)); - const auto* payloadDescriptor = Codecs::VP8::Parse(buffer, sizeof(buffer)); + std::unique_ptr payloadDescriptor{ Codecs::VP8::Parse( + buffer, sizeof(buffer)) }; REQUIRE(payloadDescriptor); @@ -77,8 +78,6 @@ SCENARIO("parse VP8 payload descriptor", "[codecs][vp8]") REQUIRE(std::memcmp(buffer, originalBuffer, sizeof(buffer)) == 0); } } - - delete payloadDescriptor; } SECTION("parse payload descriptor 2") @@ -113,7 +112,8 @@ SCENARIO("parse VP8 payload descriptor", "[codecs][vp8]") std::memcpy(buffer, originalBuffer, sizeof(buffer)); // Parse the buffer. - const auto* payloadDescriptor = Codecs::VP8::Parse(buffer, sizeof(buffer)); + std::unique_ptr payloadDescriptor{ Codecs::VP8::Parse( + buffer, sizeof(buffer)) }; REQUIRE(payloadDescriptor); @@ -152,8 +152,6 @@ SCENARIO("parse VP8 payload descriptor", "[codecs][vp8]") REQUIRE(std::memcmp(buffer, originalBuffer, sizeof(buffer)) == 0); } } - - delete payloadDescriptor; }; SECTION("parse payload descriptor. I flag set but no space for pictureId") diff --git a/worker/test/src/RTC/RTCP/TestBye.cpp b/worker/test/src/RTC/RTCP/TestBye.cpp index fa77458c35..2085e0791c 100644 --- a/worker/test/src/RTC/RTCP/TestBye.cpp +++ b/worker/test/src/RTC/RTCP/TestBye.cpp @@ -47,11 +47,11 @@ SCENARIO("RTCP BYE parsing", "[parser][rtcp][bye]") { SECTION("parse BYE packet") { - ByePacket* packet = ByePacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ ByePacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -64,8 +64,6 @@ SCENARIO("RTCP BYE parsing", "[parser][rtcp][bye]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("create ByePacket") diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsAfb.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsAfb.cpp index cbea3a75cd..3d7f8227a1 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsAfb.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsAfb.cpp @@ -39,11 +39,11 @@ SCENARIO("RTCP Feedback PS AFB parsing", "[parser][rtcp][feedback-ps][afb]") { using namespace TestFeedbackPsAfb; - FeedbackPsAfbPacket* packet = FeedbackPsAfbPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackPsAfbPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -56,7 +56,5 @@ SCENARIO("RTCP Feedback PS AFB parsing", "[parser][rtcp][feedback-ps][afb]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } } diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsFir.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsFir.cpp index 7bd3a71585..b5781802e9 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsFir.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsFir.cpp @@ -44,11 +44,11 @@ SCENARIO("RTCP Feedback PS FIR parsing", "[parser][rtcp][feedback-ps][fir]") SECTION("parse FeedbackPsFirPacket") { - FeedbackPsFirPacket* packet = FeedbackPsFirPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackPsFirPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -61,8 +61,6 @@ SCENARIO("RTCP Feedback PS FIR parsing", "[parser][rtcp][feedback-ps][fir]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("create FeedbackPsFirPacket") diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsLei.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsLei.cpp index 98196a2e0e..485a6382cc 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsLei.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsLei.cpp @@ -41,11 +41,11 @@ SCENARIO("RTCP Feedback PS LEI parsing", "[parser][rtcp][feedback-ps][lei]") SECTION("parse FeedbackPsLeiPacket") { - FeedbackPsLeiPacket* packet = FeedbackPsLeiPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackPsLeiPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -58,8 +58,6 @@ SCENARIO("RTCP Feedback PS LEI parsing", "[parser][rtcp][feedback-ps][lei]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("create FeedbackPsLeiPacket") diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsPli.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsPli.cpp index 3182ddcf04..762f9e5b72 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsPli.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsPli.cpp @@ -35,11 +35,11 @@ SCENARIO("RTCP Feeback RTP PLI parsing", "[parser][rtcp][feedback-ps][pli]") SECTION("parse FeedbackPsPliPacket") { - FeedbackPsPliPacket* packet = FeedbackPsPliPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackPsPliPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -52,8 +52,6 @@ SCENARIO("RTCP Feeback RTP PLI parsing", "[parser][rtcp][feedback-ps][pli]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("create FeedbackPsPliPacket") diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp index c0c9b21f88..e71eb05f95 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp @@ -43,11 +43,11 @@ SCENARIO("RTCP Feedback PS parsing", "[parser][rtcp][feedback-ps][remb]") SECTION("parse FeedbackPsRembPacket") { - FeedbackPsRembPacket* packet = FeedbackPsRembPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackPsRembPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -60,8 +60,6 @@ SCENARIO("RTCP Feedback PS parsing", "[parser][rtcp][feedback-ps][remb]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("create FeedbackPsRembPacket") diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp index 796868ad50..2b5fe999af 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp @@ -49,11 +49,11 @@ SCENARIO("RTCP Feedback PS RPSI parsing", "[parser][rtcp][feedback-ps][rpsi]") SECTION("parse FeedbackPsRpsiPacket") { - FeedbackPsRpsiPacket* packet = FeedbackPsRpsiPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackPsRpsiPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -66,7 +66,5 @@ SCENARIO("RTCP Feedback PS RPSI parsing", "[parser][rtcp][feedback-ps][rpsi]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } } diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsSli.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsSli.cpp index f01999a39d..d3def79324 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsSli.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsSli.cpp @@ -46,11 +46,11 @@ SCENARIO("RTCP Feedback PS SLI parsing", "[parser][rtcp][feedback-ps][sli]") SECTION("parse FeedbackPsSliPacket") { - FeedbackPsSliPacket* packet = FeedbackPsSliPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackPsSliPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -63,7 +63,5 @@ SCENARIO("RTCP Feedback PS SLI parsing", "[parser][rtcp][feedback-ps][sli]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } } diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsTst.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsTst.cpp index de8fc4d1ef..99427598ee 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsTst.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsTst.cpp @@ -45,11 +45,11 @@ SCENARIO("RTCP Feedback PS TSTN parsing", "[parser][rtcp][feedback-ps][tstn]") SECTION("parse FeedbackPsTstPacket") { - FeedbackPsTstnPacket* packet = FeedbackPsTstnPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackPsTstnPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -62,8 +62,6 @@ SCENARIO("RTCP Feedback PS TSTN parsing", "[parser][rtcp][feedback-ps][tstn]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("create FeedbackPsTstPacket") diff --git a/worker/test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp b/worker/test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp index 3067c7367c..9743091158 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp @@ -55,11 +55,11 @@ SCENARIO("RTCP Feedback PS VBCM parsing", "[parser][rtcp][feedback-ps][vbcm]") SECTION("parse FeedbackPsVbcmPacket") { - FeedbackPsVbcmPacket* packet = FeedbackPsVbcmPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackPsVbcmPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -72,7 +72,5 @@ SCENARIO("RTCP Feedback PS VBCM parsing", "[parser][rtcp][feedback-ps][vbcm]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } } diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp index 06c1d93dd9..1536de5130 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp @@ -61,11 +61,11 @@ SCENARIO("RTCP Feeback RTP ECN parsing", "[parser][rtcp][feedback-rtp][ecn]") { using namespace TestFeedbackRtpEcn; - FeedbackRtpEcnPacket* packet = FeedbackRtpEcnPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackRtpEcnPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -78,7 +78,5 @@ SCENARIO("RTCP Feeback RTP ECN parsing", "[parser][rtcp][feedback-rtp][ecn]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } } diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpNack.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpNack.cpp index 64ed4ee994..2d62caa2bd 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpNack.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpNack.cpp @@ -45,11 +45,12 @@ SCENARIO("RTCP Feeback RTP NACK parsing", "[parser][rtcp][feedback-rtp][nack]") SECTION("parse FeedbackRtpNackItem") { - FeedbackRtpNackPacket* packet = FeedbackRtpNackPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackRtpNackPacket::Parse( + buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -62,8 +63,6 @@ SCENARIO("RTCP Feeback RTP NACK parsing", "[parser][rtcp][feedback-rtp][nack]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("create FeedbackRtpNackPacket") diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp index 8b1e4036cd..1604dfabc4 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp @@ -35,11 +35,12 @@ SCENARIO("RTCP Feeback RTP SR-REQ parsing", "[parser][rtcp][feedback-rtp][sr-req SECTION("parse FeedbackRtpSrReqPacket") { - FeedbackRtpSrReqPacket* packet = FeedbackRtpSrReqPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackRtpSrReqPacket::Parse( + buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -52,8 +53,6 @@ SCENARIO("RTCP Feeback RTP SR-REQ parsing", "[parser][rtcp][feedback-rtp][sr-req REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("create FeedbackRtpSrReqPacket") diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp index 654a11d251..f39ff48e7a 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp @@ -45,11 +45,12 @@ SCENARIO("RTCP Feeback RTP TLLEI parsing", "[parser][rtcp][feedback-rtp][tllei]" { using namespace TestFeedbackRtpTllei; - FeedbackRtpTlleiPacket* packet = FeedbackRtpTlleiPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackRtpTlleiPacket::Parse( + buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -62,7 +63,5 @@ SCENARIO("RTCP Feeback RTP TLLEI parsing", "[parser][rtcp][feedback-rtp][tllei]" REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } } diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp index fc17fcf23f..b099aa448e 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp @@ -48,11 +48,12 @@ SCENARIO("RTCP Feeback RTP TMMBR parsing", "[parser][rtcp][feedback-rtp][tmmb]") SECTION("parse FeedbackRtpTmmbrPacket") { - FeedbackRtpTmmbrPacket* packet = FeedbackRtpTmmbrPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackRtpTmmbrPacket::Parse( + buffer, sizeof(buffer)) }; REQUIRE(packet); - verify(packet); + verify(packet.get()); SECTION("serialize packet instance") { @@ -64,15 +65,12 @@ SCENARIO("RTCP Feeback RTP TMMBR parsing", "[parser][rtcp][feedback-rtp][tmmb]") // represent the same content. SECTION("create a packet out of the serialized buffer") { - FeedbackRtpTmmbrPacket* packet = FeedbackRtpTmmbrPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ FeedbackRtpTmmbrPacket::Parse( + buffer, sizeof(buffer)) }; - verify(packet); - - delete packet; + verify(packet.get()); } } - - delete packet; } SECTION("create FeedbackRtpTmmbrPacket") diff --git a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp index 0204f81480..68fc15d258 100644 --- a/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp +++ b/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp @@ -69,7 +69,7 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" SECTION( "create FeedbackRtpTransportPacket, small delta run length chunk and single large delta status packet") { - auto* packet = new FeedbackRtpTransportPacket(senderSsrc, mediaSsrc); + auto packet = std::make_unique(senderSsrc, mediaSsrc); REQUIRE(packet); @@ -141,7 +141,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" SECTION("parse serialized buffer") { - auto* packet2 = FeedbackRtpTransportPacket::Parse(buffer, len); + std::unique_ptr packet2{ FeedbackRtpTransportPacket::Parse( + buffer, len) }; REQUIRE(packet2); REQUIRE(packet2->GetBaseSequenceNumber() == 1000); @@ -155,17 +156,13 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(len == len2); REQUIRE(std::memcmp(buffer, buffer2, len) == 0); REQUIRE(packet2->GetSize() == len2); - - delete packet2; } } - - delete packet; } SECTION("create FeedbackRtpTransportPacket, run length chunk (2)") { - auto* packet = new FeedbackRtpTransportPacket(senderSsrc, mediaSsrc); + auto packet = std::make_unique(senderSsrc, mediaSsrc); /* clang-format off */ std::vector inputs = @@ -209,7 +206,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" SECTION("parse serialized buffer") { - auto* packet2 = FeedbackRtpTransportPacket::Parse(buffer, len); + std::unique_ptr packet2{ FeedbackRtpTransportPacket::Parse( + buffer, len) }; REQUIRE(packet2); REQUIRE(packet2->GetBaseSequenceNumber() == 1000); @@ -223,12 +221,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(len == len2); REQUIRE(std::memcmp(buffer, buffer2, len) == 0); REQUIRE(packet2->GetSize() == len2); - - delete packet2; } } - - delete packet; } SECTION("create FeedbackRtpTransportPacket, mixed chunks") @@ -246,7 +240,7 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" }; /* clang-format on */ - auto* packet = new FeedbackRtpTransportPacket(senderSsrc, mediaSsrc); + auto packet = std::make_unique(senderSsrc, mediaSsrc); packet->SetFeedbackPacketCount(1); @@ -281,7 +275,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" SECTION("parse serialized buffer") { - auto* packet2 = FeedbackRtpTransportPacket::Parse(buffer, len); + std::unique_ptr packet2{ FeedbackRtpTransportPacket::Parse( + buffer, len) }; REQUIRE(packet2); REQUIRE(packet2->GetBaseSequenceNumber() == 1000); @@ -295,12 +290,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(len == len2); REQUIRE(std::memcmp(buffer, buffer2, len) == 0); REQUIRE(packet2->GetSize() == len2); - - delete packet2; } } - - delete packet; } SECTION("create FeedbackRtpTransportPacket, incomplete two bit vector chunk") @@ -311,7 +302,7 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" { 1001, 1000000700, RtcpMtu }, }; - auto* packet = new FeedbackRtpTransportPacket(senderSsrc, mediaSsrc); + auto packet = std::make_unique(senderSsrc, mediaSsrc); packet->SetFeedbackPacketCount(1); @@ -346,7 +337,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" SECTION("parse serialized buffer") { - auto* packet2 = FeedbackRtpTransportPacket::Parse(buffer, len); + std::unique_ptr packet2{ FeedbackRtpTransportPacket::Parse( + buffer, len) }; REQUIRE(packet2); REQUIRE(packet2->GetBaseSequenceNumber() == 1000); @@ -360,12 +352,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(len == len2); REQUIRE(std::memcmp(buffer, buffer2, len) == 0); REQUIRE(packet2->GetSize() == len2); - - delete packet2; } } - - delete packet; } SECTION("create two sequential FeedbackRtpTransportPackets") @@ -385,7 +373,7 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" }; /* clang-format on */ - auto* packet = new FeedbackRtpTransportPacket(senderSsrc, mediaSsrc); + auto packet = std::make_unique(senderSsrc, mediaSsrc); packet->SetFeedbackPacketCount(1); @@ -418,7 +406,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" SECTION("parse serialized buffer") { - auto* packet2 = FeedbackRtpTransportPacket::Parse(buffer, len); + std::unique_ptr packet2{ FeedbackRtpTransportPacket::Parse( + buffer, len) }; REQUIRE(packet2); REQUIRE(packet2->GetBaseSequenceNumber() == 1000); @@ -432,8 +421,6 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(len == len2); REQUIRE(std::memcmp(buffer, buffer2, len) == 0); REQUIRE(packet2->GetSize() == len2); - - delete packet2; } auto latestWideSeqNumber = packet->GetLatestSequenceNumber(); @@ -453,7 +440,7 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" }; /* clang-format on */ - auto* packet2 = new FeedbackRtpTransportPacket(senderSsrc, mediaSsrc); + auto packet2 = std::make_unique(senderSsrc, mediaSsrc); packet2->SetFeedbackPacketCount(2); @@ -485,7 +472,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" SECTION("parse serialized buffer") { - auto* packet3 = FeedbackRtpTransportPacket::Parse(buffer, len); + std::unique_ptr packet3{ FeedbackRtpTransportPacket::Parse( + buffer, len) }; REQUIRE(packet3); REQUIRE(packet3->GetBaseSequenceNumber() == 1008); @@ -499,12 +487,7 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(len == len2); REQUIRE(std::memcmp(buffer, buffer2, len) == 0); REQUIRE(packet3->GetSize() == len2); - - delete packet3; } - - delete packet2; - delete packet; } SECTION("parse FeedbackRtpTransportPacket, one bit vector chunk") @@ -523,7 +506,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" }; // clang-format on - auto* packet = FeedbackRtpTransportPacket::Parse(data, sizeof(data)); + std::unique_ptr packet{ FeedbackRtpTransportPacket::Parse( + data, sizeof(data)) }; REQUIRE(packet); REQUIRE(packet->GetSize() == sizeof(data)); @@ -544,8 +528,6 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(len == sizeof(data)); REQUIRE(std::memcmp(data, buffer, len) == 0); } - - delete packet; } SECTION("parse FeedbackRtpTransportPacket with negative reference time") @@ -561,7 +543,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" }; // clang-format on - auto* packet = FeedbackRtpTransportPacket::Parse(data, sizeof(data)); + std::unique_ptr packet{ FeedbackRtpTransportPacket::Parse( + data, sizeof(data)) }; REQUIRE(packet); REQUIRE(packet->GetSize() == sizeof(data)); @@ -582,8 +565,6 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(len == sizeof(data)); REQUIRE(std::memcmp(data, buffer, len) == 0); } - - delete packet; } SECTION("parse FeedbackRtpTransportPacket generated by Chrome") @@ -600,7 +581,8 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" }; // clang-format on - auto* packet = FeedbackRtpTransportPacket::Parse(data, sizeof(data)); + std::unique_ptr packet{ FeedbackRtpTransportPacket::Parse( + data, sizeof(data)) }; REQUIRE(packet); REQUIRE(packet->GetSize() == sizeof(data)); @@ -622,8 +604,6 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(len == sizeof(data)); REQUIRE(std::memcmp(data, buffer, len) == 0); } - - delete packet; } SECTION("parse FeedbackRtpTransportPacket generated by Chrome with libwebrtc as a reference") @@ -766,8 +746,10 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" for (const auto& packetMeta : feedbackPacketsMeta) { - auto buffer = packetMeta.buffer; - auto* feedback = FeedbackRtpTransportPacket::Parse(buffer.data(), buffer.size()); + auto buffer = packetMeta.buffer; + + std::unique_ptr feedback{ FeedbackRtpTransportPacket::Parse( + buffer.data(), buffer.size()) }; REQUIRE(feedback->GetReferenceTime() == packetMeta.baseTimeRaw); REQUIRE(feedback->GetReferenceTimestamp() == packetMeta.baseTimeMs); @@ -783,7 +765,6 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(static_cast(resultDelta / 4) == delta); deltasIt++; } - delete feedback; } } @@ -791,9 +772,9 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" { auto MaxBaseTime = FeedbackRtpTransportPacket::TimeWrapPeriod - FeedbackRtpTransportPacket::BaseTimeTick; - auto* packet1 = new FeedbackRtpTransportPacket(senderSsrc, mediaSsrc); - auto* packet2 = new FeedbackRtpTransportPacket(senderSsrc, mediaSsrc); - auto* packet3 = new FeedbackRtpTransportPacket(senderSsrc, mediaSsrc); + auto packet1 = std::make_unique(senderSsrc, mediaSsrc); + auto packet2 = std::make_unique(senderSsrc, mediaSsrc); + auto packet3 = std::make_unique(senderSsrc, mediaSsrc); packet1->SetReferenceTime(MaxBaseTime); packet2->SetReferenceTime(MaxBaseTime + FeedbackRtpTransportPacket::BaseTimeTick); @@ -813,9 +794,5 @@ SCENARIO("RTCP Feeback RTP transport", "[parser][rtcp][feedback-rtp][transport]" REQUIRE(packet2->GetBaseDelta(packet1->GetReferenceTimestamp()) == 64); REQUIRE(packet3->GetBaseDelta(packet2->GetReferenceTimestamp()) == 64); REQUIRE(packet3->GetBaseDelta(packet1->GetReferenceTimestamp()) == 128); - - delete packet1; - delete packet2; - delete packet3; } } diff --git a/worker/test/src/RTC/RTCP/TestPacket.cpp b/worker/test/src/RTC/RTCP/TestPacket.cpp index 7755e0be38..48218dbb12 100644 --- a/worker/test/src/RTC/RTCP/TestPacket.cpp +++ b/worker/test/src/RTC/RTCP/TestPacket.cpp @@ -18,11 +18,9 @@ SCENARIO("RTCP parsing", "[parser][rtcp][packet]") SECTION("a RTCP packet may only contain the RTCP common header") { - Packet* packet = Packet::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ Packet::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet); - - delete packet; } SECTION("a too small RTCP packet should fail") @@ -30,11 +28,9 @@ SCENARIO("RTCP parsing", "[parser][rtcp][packet]") // Provide a wrong packet length. size_t length = sizeof(buffer) - 1; - Packet* packet = Packet::Parse(buffer, length); + std::unique_ptr packet{ Packet::Parse(buffer, length) }; REQUIRE_FALSE(packet); - - delete packet; } SECTION("a RTCP packet with incorrect version should fail") @@ -42,11 +38,9 @@ SCENARIO("RTCP parsing", "[parser][rtcp][packet]") // Set an incorrect version value (0). buffer[0] &= 0b00111111; - Packet* packet = Packet::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ Packet::Parse(buffer, sizeof(buffer)) }; REQUIRE_FALSE(packet); - - delete packet; } SECTION("a RTCP packet with incorrect length should fail") @@ -54,11 +48,9 @@ SCENARIO("RTCP parsing", "[parser][rtcp][packet]") // Set the packet length to zero. buffer[3] = 1; - Packet* packet = Packet::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ Packet::Parse(buffer, sizeof(buffer)) }; REQUIRE_FALSE(packet); - - delete packet; } SECTION("a RTCP packet with unknown type should fail") @@ -66,10 +58,8 @@ SCENARIO("RTCP parsing", "[parser][rtcp][packet]") // Set and unknown packet type (0). buffer[1] = 0; - Packet* packet = Packet::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ Packet::Parse(buffer, sizeof(buffer)) }; REQUIRE_FALSE(packet); - - delete packet; } } diff --git a/worker/test/src/RTC/RTCP/TestReceiverReport.cpp b/worker/test/src/RTC/RTCP/TestReceiverReport.cpp index a184856ab6..914d4c1de8 100644 --- a/worker/test/src/RTC/RTCP/TestReceiverReport.cpp +++ b/worker/test/src/RTC/RTCP/TestReceiverReport.cpp @@ -53,7 +53,7 @@ SCENARIO("RTCP RR parsing", "[parser][rtcp][rr]") { SECTION("parse RR packet with a single report") { - ReceiverReportPacket* packet = ReceiverReportPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ ReceiverReportPacket::Parse(buffer, sizeof(buffer)) }; REQUIRE(packet->GetCount() == 1); @@ -67,7 +67,8 @@ SCENARIO("RTCP RR parsing", "[parser][rtcp][rr]") packet->Serialize(serialized); - ReceiverReportPacket* packet2 = ReceiverReportPacket::Parse(serialized, sizeof(buffer)); + std::unique_ptr packet2{ ReceiverReportPacket::Parse( + serialized, sizeof(buffer)) }; REQUIRE(packet2->GetType() == Type::RR); REQUIRE(packet2->GetCount() == 1); @@ -81,26 +82,21 @@ SCENARIO("RTCP RR parsing", "[parser][rtcp][rr]") verify(report); - delete packet2; - SECTION("compare serialized packet with original buffer") { REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("parse RR") { - ReceiverReport* report = ReceiverReport::Parse(rrBuffer, ReceiverReport::HeaderSize); + std::unique_ptr report{ ReceiverReport::Parse( + rrBuffer, ReceiverReport::HeaderSize) }; REQUIRE(report); - verify(report); - - delete report; + verify(report.get()); } SECTION("create RR packet with more than 31 reports") @@ -132,7 +128,8 @@ SCENARIO("RTCP RR parsing", "[parser][rtcp][rr]") // Serialization must contain 2 RR packets since report count exceeds 31. packet.Serialize(buffer); - auto* packet2 = static_cast(Packet::Parse(buffer, sizeof(buffer))); + std::unique_ptr packet2{ static_cast( + Packet::Parse(buffer, sizeof(buffer))) }; REQUIRE(packet2 != nullptr); REQUIRE(packet2->GetCount() == 31); @@ -172,7 +169,6 @@ SCENARIO("RTCP RR parsing", "[parser][rtcp][rr]") REQUIRE(report->GetDelaySinceLastSenderReport() == 31 + i); } - delete packet2; delete packet3; } diff --git a/worker/test/src/RTC/RTCP/TestSdes.cpp b/worker/test/src/RTC/RTCP/TestSdes.cpp index a875dbf2ba..b03df3c855 100644 --- a/worker/test/src/RTC/RTCP/TestSdes.cpp +++ b/worker/test/src/RTC/RTCP/TestSdes.cpp @@ -97,8 +97,8 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") { SECTION("parse packet 1") { - SdesPacket* packet = SdesPacket::Parse(buffer1, sizeof(buffer1)); - auto* header = reinterpret_cast(buffer1); + std::unique_ptr packet{ SdesPacket::Parse(buffer1, sizeof(buffer1)) }; + auto* header = reinterpret_cast(buffer1); REQUIRE(packet); REQUIRE(ntohs(header->length) == 6); @@ -164,14 +164,12 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") REQUIRE(std::memcmp(chunk1Buffer, serialized1, 24) == 0); } - - delete packet; } SECTION("parse packet 2") { - SdesPacket* packet = SdesPacket::Parse(buffer2, sizeof(buffer2)); - auto* header = reinterpret_cast(buffer2); + std::unique_ptr packet{ SdesPacket::Parse(buffer2, sizeof(buffer2)) }; + auto* header = reinterpret_cast(buffer2); REQUIRE(packet); REQUIRE(ntohs(header->length) == 13); @@ -292,14 +290,12 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") REQUIRE(std::memcmp(chunk2Buffer, serialized2, 24) == 0); } - - delete packet; } SECTION("parse packet 3") { - SdesPacket* packet = SdesPacket::Parse(buffer3, sizeof(buffer3)); - auto* header = reinterpret_cast(buffer3); + std::unique_ptr packet{ SdesPacket::Parse(buffer3, sizeof(buffer3)) }; + auto* header = reinterpret_cast(buffer3); REQUIRE(packet); REQUIRE(ntohs(header->length) == 3); @@ -364,8 +360,6 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") REQUIRE(std::memcmp(chunk1Buffer, serialized1, 12) == 0); } - - delete packet; } SECTION("parsing a packet with missing null octects fails") @@ -390,7 +384,7 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") SdesPacket packet; // Create a chunk and an item to obtain their size. - SdesChunk* chunk = new SdesChunk(1234 /*ssrc*/); + auto chunk = std::make_unique(1234 /*ssrc*/); auto* item1 = new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str()); @@ -398,8 +392,6 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") auto chunkSize = chunk->GetSize(); - delete chunk; - for (auto i{ 1 }; i <= count; ++i) { // Create chunk and add to packet. @@ -422,7 +414,7 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") // exceed 31. packet.Serialize(buffer1); - auto* packet2 = static_cast(Packet::Parse(buffer1, sizeof(buffer1))); + std::unique_ptr packet2{static_cast(Packet::Parse(buffer1, sizeof(buffer1)))}; REQUIRE(packet2 != nullptr); REQUIRE(packet2->GetCount() == count); @@ -443,11 +435,10 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") REQUIRE(std::string(item->GetValue()) == item1Value); } - SdesPacket* packet3 = static_cast(packet2->GetNext()); + std::unique_ptr packet3{static_cast(packet2->GetNext())}; REQUIRE(packet3 == nullptr); - delete packet3; } SECTION("create SDES packet with more than 31 chunks") @@ -456,7 +447,7 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") SdesPacket packet; // Create a chunk and an item to obtain their size. - SdesChunk* chunk = new SdesChunk(1234 /*ssrc*/); + auto chunk = std::make_unique(1234 /*ssrc*/); auto* item1 = new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str()); @@ -464,8 +455,6 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") auto chunkSize = chunk->GetSize(); - delete chunk; - for (auto i{ 1 }; i <= count; ++i) { // Create chunk and add to packet. @@ -487,7 +476,7 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") // Serialization must contain 2 SDES packets since report count exceeds 31. packet.Serialize(buffer1); - auto* packet2 = static_cast(Packet::Parse(buffer1, sizeof(buffer1))); + std::unique_ptr packet2 {static_cast(Packet::Parse(buffer1, sizeof(buffer1)))}; REQUIRE(packet2 != nullptr); REQUIRE(packet2->GetCount() == 31); @@ -529,7 +518,6 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]") REQUIRE(std::string(item->GetValue()) == item1Value); } - delete packet2; delete packet3; } diff --git a/worker/test/src/RTC/RTCP/TestSenderReport.cpp b/worker/test/src/RTC/RTCP/TestSenderReport.cpp index 38f7862e8f..e874ba92a1 100644 --- a/worker/test/src/RTC/RTCP/TestSenderReport.cpp +++ b/worker/test/src/RTC/RTCP/TestSenderReport.cpp @@ -50,7 +50,7 @@ SCENARIO("RTCP SR parsing", "[parser][rtcp][sr]") { SECTION("parse SR packet") { - SenderReportPacket* packet = SenderReportPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ SenderReportPacket::Parse(buffer, sizeof(buffer)) }; auto* report = *(packet->Begin()); @@ -67,17 +67,15 @@ SCENARIO("RTCP SR parsing", "[parser][rtcp][sr]") REQUIRE(std::memcmp(buffer, serialized, sizeof(buffer)) == 0); } } - - delete packet; } SECTION("parse SR") { - SenderReport* report = SenderReport::Parse(srBuffer, SenderReport::HeaderSize); + std::unique_ptr report{ SenderReport::Parse(srBuffer, SenderReport::HeaderSize) }; REQUIRE(report); - verify(report); + verify(report.get()); SECTION("serialize SenderReport instance") { @@ -90,8 +88,6 @@ SCENARIO("RTCP SR parsing", "[parser][rtcp][sr]") REQUIRE(std::memcmp(srBuffer, serialized, SenderReport::HeaderSize) == 0); } } - - delete report; } SECTION("create SR packet multiple reports") @@ -122,7 +118,8 @@ SCENARIO("RTCP SR parsing", "[parser][rtcp][sr]") SenderReport* reports[count]{ nullptr }; - auto* packet2 = static_cast(Packet::Parse(buffer, sizeof(buffer))); + std::unique_ptr packet2{ static_cast( + Packet::Parse(buffer, sizeof(buffer))) }; REQUIRE(packet2 != nullptr); @@ -154,7 +151,6 @@ SCENARIO("RTCP SR parsing", "[parser][rtcp][sr]") REQUIRE(report->GetOctetCount() == i); } - delete packet2; delete packet3; delete packet4; } diff --git a/worker/test/src/RTC/RTCP/TestXr.cpp b/worker/test/src/RTC/RTCP/TestXr.cpp index b047d32389..b1569bddc8 100644 --- a/worker/test/src/RTC/RTCP/TestXr.cpp +++ b/worker/test/src/RTC/RTCP/TestXr.cpp @@ -28,7 +28,7 @@ SCENARIO("RTCP XR parsing", "[parser][rtcp][xr]") SECTION("parse XR packet") { - auto* packet = ExtendedReportPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet(ExtendedReportPacket::Parse(buffer, sizeof(buffer))); REQUIRE(packet); // Despite total buffer size is 40 bytes, our GetSize() method doesn't not @@ -113,18 +113,15 @@ SCENARIO("RTCP XR parsing", "[parser][rtcp][xr]") packet->Serialize(serialized); - auto* packet2 = ExtendedReportPacket::Parse(serialized, serializedBufferLength); + std::unique_ptr packet2( + ExtendedReportPacket::Parse(serialized, serializedBufferLength)); REQUIRE(packet2->GetType() == Type::XR); REQUIRE(packet2->GetCount() == 0); REQUIRE(packet2->GetSize() == 36); REQUIRE(std::memcmp(clonedBuffer, serialized, serializedBufferLength) == 0); - - delete packet2; } - - delete packet; } } @@ -133,6 +130,8 @@ SCENARIO("RTCP XrDelaySinceLastRt parsing", "[parser][rtcp][xr-dlrr]") SECTION("create RRT") { // Create local report and check content. + // NOTE: We cannot use unique_ptr here since the instance lifecycle will be + // managed by the packet. auto* report1 = new ReceiverReferenceTime(); report1->SetNtpSec(11111111); @@ -148,6 +147,8 @@ SCENARIO("RTCP XrDelaySinceLastRt parsing", "[parser][rtcp][xr-dlrr]") report1->Serialize(bufferReport1); // Create a new report out of the external buffer. + // NOTE: We cannot use unique_ptr here since the instance lifecycle will be + // managed by the packet. auto report2 = ReceiverReferenceTime::Parse(bufferReport1, report1->GetSize()); REQUIRE(report1->GetType() == report2->GetType()); @@ -179,7 +180,8 @@ SCENARIO("RTCP XrDelaySinceLastRt parsing", "[parser][rtcp][xr-dlrr]") packet1->Serialize(bufferPacket1); // Create a new packet out of the external buffer. - auto packet2 = ExtendedReportPacket::Parse(bufferPacket1, packet1->GetSize()); + std::unique_ptr packet2( + ExtendedReportPacket::Parse(bufferPacket1, packet1->GetSize())); REQUIRE(packet2->GetType() == packet1->GetType()); REQUIRE(packet2->GetCount() == packet1->GetCount()); @@ -194,7 +196,11 @@ SCENARIO("RTCP XrDelaySinceLastRt parsing", "[parser][rtcp][xr-dlrr]") SECTION("create DLRR") { // Create local report and check content. - auto* report1 = new DelaySinceLastRr(); + // NOTE: We cannot use unique_ptr here since the instance lifecycle will be + // managed by the packet. + auto* report1 = new DelaySinceLastRr(); + // NOTE: We cannot use unique_ptr here since the instance lifecycle will be + // managed by the report. auto* ssrcInfo1 = new DelaySinceLastRr::SsrcInfo(); ssrcInfo1->SetSsrc(1234); @@ -214,6 +220,8 @@ SCENARIO("RTCP XrDelaySinceLastRt parsing", "[parser][rtcp][xr-dlrr]") report1->Serialize(bufferReport1); // Create a new report out of the external buffer. + // NOTE: We cannot use unique_ptr here since the instance lifecycle will be + // managed by the packet. auto report2 = DelaySinceLastRr::Parse(bufferReport1, report1->GetSize()); REQUIRE(report1->GetType() == report2->GetType()); @@ -252,7 +260,8 @@ SCENARIO("RTCP XrDelaySinceLastRt parsing", "[parser][rtcp][xr-dlrr]") packet1->Serialize(bufferPacket1); // Create a new packet out of the external buffer. - auto packet2 = ExtendedReportPacket::Parse(bufferPacket1, packet1->GetSize()); + std::unique_ptr packet2( + ExtendedReportPacket::Parse(bufferPacket1, packet1->GetSize())); REQUIRE(packet2->GetType() == packet1->GetType()); REQUIRE(packet2->GetCount() == packet1->GetCount()); diff --git a/worker/test/src/RTC/TestNackGenerator.cpp b/worker/test/src/RTC/TestNackGenerator.cpp index bb9744188b..caaefdbe4a 100644 --- a/worker/test/src/RTC/TestNackGenerator.cpp +++ b/worker/test/src/RTC/TestNackGenerator.cpp @@ -118,7 +118,7 @@ uint8_t rtpBuffer[] = // clang-format on // [pt:123, seq:21006, timestamp:1533790901] -RtpPacket* packet = RtpPacket::Parse(rtpBuffer, sizeof(rtpBuffer)); +std::unique_ptr packet(RtpPacket::Parse(rtpBuffer, sizeof(rtpBuffer))); void validate(std::vector& inputs) { @@ -133,7 +133,7 @@ void validate(std::vector& inputs) packet->SetPayloadDescriptorHandler(tpdh); packet->SetSequenceNumber(input.seq); - nackGenerator.ReceivePacket(packet, /*isRecovered*/ false); + nackGenerator.ReceivePacket(packet.get(), /*isRecovered*/ false); listener.Check(nackGenerator); } diff --git a/worker/test/src/RTC/TestRtpPacket.cpp b/worker/test/src/RTC/TestRtpPacket.cpp index e931697c9e..0afd766d9e 100644 --- a/worker/test/src/RTC/TestRtpPacket.cpp +++ b/worker/test/src/RTC/TestRtpPacket.cpp @@ -24,7 +24,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") FAIL("cannot open file"); } - RtpPacket* packet = RtpPacket::Parse(buffer, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -50,8 +50,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(extenValue == nullptr); REQUIRE(packet->ReadRid(rid) == false); REQUIRE(rid == ""); - - delete packet; } SECTION("parse packet2.raw") @@ -63,7 +61,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") FAIL("cannot open file"); } - RtpPacket* packet = RtpPacket::Parse(buffer, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -80,8 +78,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->GetHeaderExtensionLength() == 0); REQUIRE(packet->HasOneByteExtensions() == false); REQUIRE(packet->HasTwoBytesExtensions() == false); - - delete packet; } SECTION("parse packet3.raw") @@ -98,7 +94,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") FAIL("cannot open file"); } - RtpPacket* packet = RtpPacket::Parse(buffer, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -139,7 +135,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->ReadAbsSendTime(absSendTime) == true); REQUIRE(absSendTime == 0x65341e); - auto* clonedPacket = packet->Clone(); + std::unique_ptr clonedPacket{ packet->Clone() }; std::memset(buffer, '0', sizeof(buffer)); @@ -174,9 +170,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(extenValue[2] == 0x1e); REQUIRE(clonedPacket->ReadAbsSendTime(absSendTime) == true); REQUIRE(absSendTime == 0x65341e); - - delete packet; - delete clonedPacket; } SECTION("create RtpPacket without header extension") @@ -190,7 +183,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") }; // clang-format on - RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ RtpPacket::Parse(buffer, sizeof(buffer)) }; if (!packet) { @@ -205,8 +198,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasOneByteExtensions() == false); REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetSsrc() == 5); - - delete packet; } SECTION("create RtpPacket with One-Byte header extension") @@ -224,7 +215,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") }; // clang-format on - RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ RtpPacket::Parse(buffer, sizeof(buffer)) }; if (!packet) { @@ -248,8 +239,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->GetPayloadLength() == 1000); REQUIRE(packet->GetSize() == 1028); - - delete packet; } SECTION("create RtpPacket with Two-Bytes header extension") @@ -271,7 +260,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") uint8_t extenLen; uint8_t* extenValue; - RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ RtpPacket::Parse(buffer, sizeof(buffer)) }; if (!packet) { @@ -316,8 +305,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasExtension(5) == false); REQUIRE(extenValue == nullptr); REQUIRE(extenLen == 0); - - delete packet; } SECTION("rtx encryption-decryption") @@ -340,7 +327,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") uint32_t rtxSsrc{ 6 }; uint16_t rtxSeq{ 80 }; - RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ RtpPacket::Parse(buffer, sizeof(buffer)) }; if (!packet) { @@ -358,9 +345,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasOneByteExtensions() == false); REQUIRE(packet->HasTwoBytesExtensions()); - auto* rtxPacket = packet->Clone(); - - delete packet; + std::unique_ptr rtxPacket{ packet->Clone() }; std::memset(buffer, '0', sizeof(buffer)); @@ -389,8 +374,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(rtxPacket->GetHeaderExtensionLength() == 12); REQUIRE(rtxPacket->HasOneByteExtensions() == false); REQUIRE(rtxPacket->HasTwoBytesExtensions()); - - delete rtxPacket; } SECTION("create RtpPacket and apply payload shift to it") @@ -415,8 +398,8 @@ SCENARIO("parse RTP packets", "[parser][rtp]") }; // clang-format on - size_t len = 40; - RtpPacket* packet = RtpPacket::Parse(buffer, len); + size_t len = 40; + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -504,8 +487,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->GetPayloadLength() == 1000); REQUIRE(packet->GetPayloadPadding() == 0); REQUIRE(packet->GetSize() == 1028); - - delete packet; } SECTION("set One-Byte header extensions") @@ -530,7 +511,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") }; // clang-format on - RtpPacket* packet = RtpPacket::Parse(buffer, 28); + std::unique_ptr packet{ RtpPacket::Parse(buffer, 28) }; std::vector extensions; uint8_t extenLen; uint8_t* extenValue; @@ -675,8 +656,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(extenValue[1] == 0x02); REQUIRE(extenValue[2] == 0x03); REQUIRE(extenValue[3] == 0x00); - - delete packet; } SECTION("set Two-Bytes header extensions") @@ -703,7 +682,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") }; // clang-format on - RtpPacket* packet = RtpPacket::Parse(buffer, 28); + std::unique_ptr packet{ RtpPacket::Parse(buffer, 28) }; std::vector extensions; uint8_t extenLen; uint8_t* extenValue; @@ -830,8 +809,6 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->GetExtension(24, extenLen)); REQUIRE(packet->HasExtension(24) == true); REQUIRE(extenLen == 4); - - delete packet; } SECTION("read frame-marking extension") @@ -848,7 +825,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") }; // clang-format on - RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ RtpPacket::Parse(buffer, sizeof(buffer)) }; if (!packet) { @@ -882,7 +859,5 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(frameMarking->tid == 3); REQUIRE(frameMarking->lid == 1); REQUIRE(frameMarking->tl0picidx == 5); - - delete packet; } } diff --git a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp index e2407ff1ff..844bfe3853 100644 --- a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp +++ b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp @@ -26,7 +26,7 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") FAIL("cannot open file"); } - RtpPacket* packet = RtpPacket::Parse(buffer, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -59,8 +59,9 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") // Read frame-marking. packet->ReadFrameMarking(&frameMarking, frameMarkingLen); - const auto* payloadDescriptor = - Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen) + }; REQUIRE(payloadDescriptor); @@ -73,10 +74,6 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") REQUIRE(payloadDescriptor->tlIndex == 0); REQUIRE(payloadDescriptor->hasSlIndex == false); REQUIRE(payloadDescriptor->isKeyFrame == true); - - delete payloadDescriptor; - - delete packet; } SECTION("parse I0-8.bin") @@ -90,7 +87,7 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") FAIL("cannot open file"); } - RtpPacket* packet = RtpPacket::Parse(buffer, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -123,8 +120,9 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") // Read frame-marking. packet->ReadFrameMarking(&frameMarking, frameMarkingLen); - const auto* payloadDescriptor = - Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen) + }; REQUIRE(payloadDescriptor); @@ -137,10 +135,6 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") REQUIRE(payloadDescriptor->tlIndex == 0); REQUIRE(payloadDescriptor->hasSlIndex == false); REQUIRE(payloadDescriptor->isKeyFrame == false); - - delete payloadDescriptor; - - delete packet; } SECTION("parse I0-5.bin") @@ -154,7 +148,7 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") FAIL("cannot open file"); } - RtpPacket* packet = RtpPacket::Parse(buffer, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -187,8 +181,9 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") // Read frame-marking. packet->ReadFrameMarking(&frameMarking, frameMarkingLen); - const auto* payloadDescriptor = - Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen) + }; REQUIRE(payloadDescriptor); @@ -200,10 +195,6 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") REQUIRE(payloadDescriptor->isKeyFrame == true); REQUIRE(payloadDescriptor->hasSlIndex == false); REQUIRE(payloadDescriptor->hasTlIndex == false); - - delete payloadDescriptor; - - delete packet; } SECTION("parse I1-15.bin") @@ -217,7 +208,7 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") FAIL("cannot open file"); } - RtpPacket* packet = RtpPacket::Parse(buffer, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -250,8 +241,9 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") // Read frame-marking. packet->ReadFrameMarking(&frameMarking, frameMarkingLen); - const auto* payloadDescriptor = - Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen) + }; REQUIRE(payloadDescriptor); @@ -264,10 +256,6 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") REQUIRE(payloadDescriptor->tlIndex == 0); REQUIRE(payloadDescriptor->hasSlIndex == false); REQUIRE(payloadDescriptor->isKeyFrame == false); - - delete payloadDescriptor; - - delete packet; } SECTION("parse I0-14.bin") @@ -281,7 +269,7 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") FAIL("cannot open file"); } - RtpPacket* packet = RtpPacket::Parse(buffer, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -314,8 +302,9 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") // Read frame-marking. packet->ReadFrameMarking(&frameMarking, frameMarkingLen); - const auto* payloadDescriptor = - Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen) + }; REQUIRE(payloadDescriptor); @@ -328,10 +317,6 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") REQUIRE(payloadDescriptor->tlIndex == 0); REQUIRE(payloadDescriptor->hasSlIndex == false); REQUIRE(payloadDescriptor->isKeyFrame == true); - - delete payloadDescriptor; - - delete packet; } SECTION("parse 2SL-I14.bin") @@ -345,7 +330,7 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") FAIL("cannot open file"); } - RtpPacket* packet = RtpPacket::Parse(buffer, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer, len) }; if (!packet) { @@ -378,8 +363,9 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") // Read frame-marking. packet->ReadFrameMarking(&frameMarking, frameMarkingLen); - const auto* payloadDescriptor = - Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(payload, sizeof(payload), frameMarking, frameMarkingLen) + }; REQUIRE(payloadDescriptor); @@ -393,10 +379,6 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") REQUIRE(payloadDescriptor->hasSlIndex); REQUIRE(payloadDescriptor->slIndex == 0); REQUIRE(payloadDescriptor->isKeyFrame == true); - - delete payloadDescriptor; - - delete packet; } SECTION("create and test RTP files") @@ -453,7 +435,7 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") FAIL("Failed to write RTP packet!\n"); } - RtpPacket* packet = RtpPacket::Parse(buffer2, len); + std::unique_ptr packet{ RtpPacket::Parse(buffer2, len) }; if (!packet) { @@ -469,8 +451,9 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") // Read frame-marking. packet->ReadFrameMarking(&frameMarking, frameMarkingLen); - const auto* payloadDescriptor = Codecs::H264_SVC::Parse( - payload, packet->GetPayloadLength(), frameMarking, frameMarkingLen); + std::unique_ptr payloadDescriptor{ + Codecs::H264_SVC::Parse(payload, packet->GetPayloadLength(), frameMarking, frameMarkingLen) + }; REQUIRE(payloadDescriptor); @@ -478,9 +461,6 @@ SCENARIO("parse RTP packets with H264 SVC", "[parser][rtp]") pos += bytes; rows++; - - delete payloadDescriptor; - delete packet; } nf.close(); diff --git a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp index ab038ba0e7..7158509ed2 100644 --- a/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp +++ b/worker/test/src/RTC/TestRtpRetransmissionBuffer.cpp @@ -36,14 +36,14 @@ class RtpMyRetransmissionBuffer : public RtpRetransmissionBuffer }; // clang-format on - auto* packet = RtpPacket::Parse(rtpBuffer, sizeof(rtpBuffer)); + std::unique_ptr packet{ RtpPacket::Parse(rtpBuffer, sizeof(rtpBuffer)) }; packet->SetSequenceNumber(seq); packet->SetTimestamp(timestamp); std::shared_ptr sharedPacket; - RtpRetransmissionBuffer::Insert(packet, sharedPacket); + RtpRetransmissionBuffer::Insert(packet.get(), sharedPacket); } void AssertBuffer(std::vector verificationBuffer) diff --git a/worker/test/src/RTC/TestRtpStreamRecv.cpp b/worker/test/src/RTC/TestRtpStreamRecv.cpp index feaf8e7c03..388513fc71 100644 --- a/worker/test/src/RTC/TestRtpStreamRecv.cpp +++ b/worker/test/src/RTC/TestRtpStreamRecv.cpp @@ -128,7 +128,7 @@ SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") }; // clang-format on - RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ RtpPacket::Parse(buffer, sizeof(buffer)) }; if (!packet) { @@ -149,25 +149,25 @@ SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") RtpStreamRecv rtpStream(&listener, params, SendNackDelay, UseRtpInactivityCheck); packet->SetSequenceNumber(1); - rtpStream.ReceivePacket(packet); + rtpStream.ReceivePacket(packet.get()); packet->SetSequenceNumber(3); listener.shouldTriggerNack = true; listener.shouldTriggerPLI = false; listener.shouldTriggerFIR = false; - rtpStream.ReceivePacket(packet); + rtpStream.ReceivePacket(packet.get()); REQUIRE(listener.nackedSeqNumbers.size() == 1); REQUIRE(listener.nackedSeqNumbers[0] == 2); listener.nackedSeqNumbers.clear(); packet->SetSequenceNumber(2); - rtpStream.ReceivePacket(packet); + rtpStream.ReceivePacket(packet.get()); REQUIRE(listener.nackedSeqNumbers.size() == 0); packet->SetSequenceNumber(4); - rtpStream.ReceivePacket(packet); + rtpStream.ReceivePacket(packet.get()); REQUIRE(listener.nackedSeqNumbers.size() == 0); } @@ -178,13 +178,13 @@ SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") RtpStreamRecv rtpStream(&listener, params, SendNackDelay, UseRtpInactivityCheck); packet->SetSequenceNumber(0xfffe); - rtpStream.ReceivePacket(packet); + rtpStream.ReceivePacket(packet.get()); packet->SetSequenceNumber(1); listener.shouldTriggerNack = true; listener.shouldTriggerPLI = false; listener.shouldTriggerFIR = false; - rtpStream.ReceivePacket(packet); + rtpStream.ReceivePacket(packet.get()); REQUIRE(listener.nackedSeqNumbers.size() == 2); REQUIRE(listener.nackedSeqNumbers[0] == 0xffff); @@ -198,18 +198,16 @@ SCENARIO("receive RTP packets and trigger NACK", "[rtp][rtpstream]") RtpStreamRecv rtpStream(&listener, params, SendNackDelay, UseRtpInactivityCheck); packet->SetSequenceNumber(1); - rtpStream.ReceivePacket(packet); + rtpStream.ReceivePacket(packet.get()); // Seq different is bigger than MaxNackPackets in NackGenerator, so it // triggers a key frame. packet->SetSequenceNumber(1003); listener.shouldTriggerPLI = true; listener.shouldTriggerFIR = false; - rtpStream.ReceivePacket(packet); + rtpStream.ReceivePacket(packet.get()); } // Must run the loop to wait for UV timers and close them. DepLibUV::RunLoop(); - - delete packet; } diff --git a/worker/test/src/RTC/TestRtpStreamSend.cpp b/worker/test/src/RTC/TestRtpStreamSend.cpp index 3d18323c1b..de52e87f83 100644 --- a/worker/test/src/RTC/TestRtpStreamSend.cpp +++ b/worker/test/src/RTC/TestRtpStreamSend.cpp @@ -10,14 +10,15 @@ using namespace RTC; -static RtpPacket* CreateRtpPacket(uint8_t* buffer, size_t len, uint16_t seq, uint32_t timestamp) +static std::unique_ptr CreateRtpPacket( + uint8_t* buffer, size_t len, uint16_t seq, uint32_t timestamp) { auto* packet = RtpPacket::Parse(buffer, len); packet->SetSequenceNumber(seq); packet->SetTimestamp(timestamp); - return packet; + return std::unique_ptr(packet); } static void SendRtpPacket(std::vector> streams, RtpPacket* packet) @@ -78,20 +79,15 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get retransmitted packets") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - std::unique_ptr packet1( - CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); + auto packet1(CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); // packet2 [pt:123, seq:21007, timestamp:1533790901] - std::unique_ptr packet2( - CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); + auto packet2(CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); // packet3 [pt:123, seq:21008, timestamp:1533793871] - std::unique_ptr packet3( - CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871)); + auto packet3(CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871)); // packet4 [pt:123, seq:21009, timestamp:1533793871] - std::unique_ptr packet4( - CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871)); + auto packet4(CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871)); // packet5 [pt:123, seq:21010, timestamp:1533796931] - std::unique_ptr packet5( - CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931)); + auto packet5(CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -104,7 +100,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params, mid)); + auto stream = std::make_unique(&testRtpStreamListener, params, mid); // Receive all the packets (some of them not in order and/or duplicated). SendRtpPacket({ { stream.get(), params.ssrc } }, packet1.get()); @@ -146,20 +142,15 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get zero retransmitted packets if useNack is not set") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - std::unique_ptr packet1( - CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); + auto packet1(CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); // packet2 [pt:123, seq:21007, timestamp:1533790901] - std::unique_ptr packet2( - CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); + auto packet2(CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); // packet3 [pt:123, seq:21008, timestamp:1533793871] - std::unique_ptr packet3( - CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871)); + auto packet3(CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871)); // packet4 [pt:123, seq:21009, timestamp:1533793871] - std::unique_ptr packet4( - CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871)); + auto packet4(CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871)); // packet5 [pt:123, seq:21010, timestamp:1533796931] - std::unique_ptr packet5( - CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931)); + auto packet5(CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -172,7 +163,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params, mid)); + auto stream = std::make_unique(&testRtpStreamListener, params, mid); // Receive all the packets (some of them not in order and/or duplicated). SendRtpPacket({ { stream.get(), params.ssrc } }, packet1.get()); @@ -202,20 +193,15 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK and get zero retransmitted packets for audio") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - std::unique_ptr packet1( - CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); + auto packet1(CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); // packet2 [pt:123, seq:21007, timestamp:1533790901] - std::unique_ptr packet2( - CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); + auto packet2(CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); // packet3 [pt:123, seq:21008, timestamp:1533793871] - std::unique_ptr packet3( - CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871)); + auto packet3(CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, 1533793871)); // packet4 [pt:123, seq:21009, timestamp:1533793871] - std::unique_ptr packet4( - CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871)); + auto packet4(CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 21009, 1533793871)); // packet5 [pt:123, seq:21010, timestamp:1533796931] - std::unique_ptr packet5( - CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931)); + auto packet5(CreateRtpPacket(rtpBuffer5, sizeof(rtpBuffer5), 21010, 1533796931)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -228,7 +214,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params.mimeType.type = RTC::RtpCodecMimeType::Type::AUDIO; std::string mid; - std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params, mid)); + auto stream = std::make_unique(&testRtpStreamListener, params, mid); // Receive all the packets (some of them not in order and/or duplicated). SendRtpPacket({ { stream.get(), params.ssrc } }, packet1.get()); @@ -258,11 +244,9 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") SECTION("receive NACK in different RtpStreamSend instances and get retransmitted packets") { // packet1 [pt:123, seq:21006, timestamp:1533790901] - std::unique_ptr packet1( - CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); + auto packet1(CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, 1533790901)); // packet2 [pt:123, seq:21007, timestamp:1533790901] - std::unique_ptr packet2( - CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); + auto packet2(CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, 1533790901)); // Create two RtpStreamSend instances. TestRtpStreamListener testRtpStreamListener1; @@ -334,10 +318,8 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") uint32_t diffTs = RtpStreamSend::MaxRetransmissionDelayForVideoMs * clockRate / 1000; uint32_t secondTs = firstTs + diffTs; - std::unique_ptr packet1( - CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs)); - std::unique_ptr packet2( - CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs - 1)); + auto packet1(CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs)); + auto packet2(CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs - 1)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -350,7 +332,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params1, mid)); + auto stream = std::make_unique(&testRtpStreamListener, params1, mid); // Receive all the packets. SendRtpPacket({ { stream.get(), params1.ssrc } }, packet1.get()); @@ -389,12 +371,9 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") // Send a third packet so it will clean old packets from the buffer. uint32_t thirdTs = firstTs + (2 * diffTs); - std::unique_ptr packet1( - CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs)); - std::unique_ptr packet2( - CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs)); - std::unique_ptr packet3( - CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, thirdTs)); + auto packet1(CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 21006, firstTs)); + auto packet2(CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 21007, secondTs)); + auto packet3(CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 21008, thirdTs)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -407,7 +386,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params1, mid)); + auto stream = std::make_unique(&testRtpStreamListener, params1, mid); // Receive all the packets. SendRtpPacket({ { stream.get(), params1.ssrc } }, packet1.get()); @@ -439,18 +418,14 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") { // This scenario reproduce the "too bad sequence number" and "bad sequence // number" scenarios in RtpStream::UpdateSeq(). - std::unique_ptr packet1( - CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 50001, 1000001)); - std::unique_ptr packet2( - CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 50002, 1000002)); + auto packet1(CreateRtpPacket(rtpBuffer1, sizeof(rtpBuffer1), 50001, 1000001)); + auto packet2(CreateRtpPacket(rtpBuffer2, sizeof(rtpBuffer2), 50002, 1000002)); // Third packet has bad sequence number (its seq is more than MaxDropout=3000 // older than current max seq) and will be dropped. - std::unique_ptr packet3( - CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 40003, 1000003)); + auto packet3(CreateRtpPacket(rtpBuffer3, sizeof(rtpBuffer3), 40003, 1000003)); // Forth packet has seq=badSeq+1 so will be accepted and will trigger a // stream reset. - std::unique_ptr packet4( - CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 40004, 1000004)); + auto packet4(CreateRtpPacket(rtpBuffer4, sizeof(rtpBuffer4), 40004, 1000004)); // Create a RtpStreamSend instance. TestRtpStreamListener testRtpStreamListener; @@ -463,7 +438,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params1.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - std::unique_ptr stream(new RtpStreamSend(&testRtpStreamListener, params1, mid)); + auto stream = std::make_unique(&testRtpStreamListener, params1, mid); SendRtpPacket({ { stream.get(), params1.ssrc } }, packet1.get()); SendRtpPacket({ { stream.get(), params1.ssrc } }, packet2.get()); @@ -496,7 +471,7 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") params.mimeType.type = RTC::RtpCodecMimeType::Type::VIDEO; std::string mid; - auto* stream = new RtpStreamSend(&testRtpStreamListener, params, mid); + std::unique_ptr stream1(new RtpStreamSend(&testRtpStreamListener, params, mid)); size_t iterations = 10000000; @@ -510,16 +485,14 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") std::shared_ptr sharedPacket(packet); - stream->ReceivePacket(packet, sharedPacket); + stream1->ReceivePacket(packet, sharedPacket); } std::chrono::duration dur = std::chrono::system_clock::now() - start; std::cout << "nullptr && initialized shared_ptr: \t" << dur.count() << " seconds" << std::endl; - delete stream; - params.mimeType.type = RTC::RtpCodecMimeType::Type::AUDIO; - stream = new RtpStreamSend(&testRtpStreamListener, params, mid); + std::unique_ptr stream2(new RtpStreamSend(&testRtpStreamListener, params, mid)); start = std::chrono::system_clock::now(); @@ -531,13 +504,11 @@ SCENARIO("NACK and RTP packets retransmission", "[rtp][rtcp][nack]") auto* packet = RtpPacket::Parse(rtpBuffer1, 1500); packet->SetSsrc(1111); - stream->ReceivePacket(packet, sharedPacket); + stream2->ReceivePacket(packet, sharedPacket); } dur = std::chrono::system_clock::now() - start; std::cout << "raw && empty shared_ptr duration: \t" << dur.count() << " seconds" << std::endl; - - delete stream; } #endif } diff --git a/worker/test/src/RTC/TestTransportCongestionControlServer.cpp b/worker/test/src/RTC/TestTransportCongestionControlServer.cpp index 27512b2b37..3a02b433ba 100644 --- a/worker/test/src/RTC/TestTransportCongestionControlServer.cpp +++ b/worker/test/src/RTC/TestTransportCongestionControlServer.cpp @@ -93,7 +93,7 @@ void validate(std::vector& inputs, Te tccServer.SetMaxIncomingBitrate(150000); tccServer.TransportConnected(); - RtpPacket* packet = RtpPacket::Parse(buffer, sizeof(buffer)); + std::unique_ptr packet{ RtpPacket::Parse(buffer, sizeof(buffer)) }; packet->SetTransportWideCc01ExtensionId(5); packet->SetSequenceNumber(1); @@ -116,7 +116,7 @@ void validate(std::vector& inputs, Te } packet->UpdateTransportWideCc01(input.wideSeqNumber); - tccServer.IncomingPacket(input.nowMs, packet); + tccServer.IncomingPacket(input.nowMs, packet.get()); } tccServer.FillAndSendTransportCcFeedback(); From 24dc5723f928feedcbaf2eb7f7a5edec7b0c3f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 6 Jul 2024 17:42:31 +0200 Subject: [PATCH 469/525] Update NPM deps --- .github/workflows/mediasoup-worker.yaml | 1 + package-lock.json | 226 ++++++++++++------------ package.json | 10 +- 3 files changed, 119 insertions(+), 118 deletions(-) diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 6ff7dc5ec1..57a2099a77 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -11,6 +11,7 @@ concurrency: jobs: ci: strategy: + fail-fast: false matrix: build: - os: ubuntu-20.04 diff --git a/package-lock.json b/package-lock.json index 8f8a1bc8c2..b464868b37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,21 +23,21 @@ "@octokit/rest": "^21.0.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.8", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", + "@types/node": "^20.14.10", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^13.0.1", + "marked": "^13.0.2", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.2", "sctp": "^1.0.0", "ts-jest": "^29.1.5", - "typescript": "^5.5.2" + "typescript": "^5.5.3" }, "engines": { "node": ">=18" @@ -1803,9 +1803,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.14.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.8.tgz", - "integrity": "sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==", + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1833,16 +1833,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", - "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz", + "integrity": "sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/type-utils": "7.14.1", - "@typescript-eslint/utils": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/type-utils": "7.15.0", + "@typescript-eslint/utils": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1866,15 +1866,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.15.0.tgz", + "integrity": "sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/typescript-estree": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "debug": "^4.3.4" }, "engines": { @@ -1894,13 +1894,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", - "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz", + "integrity": "sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1" + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1911,13 +1911,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", - "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.15.0.tgz", + "integrity": "sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/utils": "7.14.1", + "@typescript-eslint/typescript-estree": "7.15.0", + "@typescript-eslint/utils": "7.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1938,9 +1938,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.15.0.tgz", + "integrity": "sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1951,13 +1951,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", - "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz", + "integrity": "sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1988,9 +1988,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -2003,15 +2003,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", - "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.15.0.tgz", + "integrity": "sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1" + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/typescript-estree": "7.15.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2025,12 +2025,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz", + "integrity": "sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/types": "7.15.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -4568,9 +4568,9 @@ } }, "node_modules/marked": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.1.tgz", - "integrity": "sha512-7kBohS6GrZKvCsNXZyVVXSW7/hGBHe49ng99YPkDCckSUrrG7MSFLCexsRxptzOmyW2eT5dySh4Md1V6my52fA==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.2.tgz", + "integrity": "sha512-J6CPjP8pS5sgrRqxVRvkCIkZ6MFdRIjDkwUwgJ9nL2fbmM6qGQeB2C16hi8Cc9BOzj6xXzy0jyi0iPIfnMHYzA==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -5961,9 +5961,9 @@ } }, "node_modules/typescript": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", - "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -7574,9 +7574,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.14.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.8.tgz", - "integrity": "sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==", + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7604,16 +7604,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", - "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz", + "integrity": "sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/type-utils": "7.14.1", - "@typescript-eslint/utils": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/type-utils": "7.15.0", + "@typescript-eslint/utils": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7621,54 +7621,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.15.0.tgz", + "integrity": "sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/typescript-estree": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", - "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz", + "integrity": "sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1" + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0" } }, "@typescript-eslint/type-utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", - "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.15.0.tgz", + "integrity": "sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/utils": "7.14.1", + "@typescript-eslint/typescript-estree": "7.15.0", + "@typescript-eslint/utils": "7.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.15.0.tgz", + "integrity": "sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", - "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz", + "integrity": "sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7687,9 +7687,9 @@ } }, "minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -7698,24 +7698,24 @@ } }, "@typescript-eslint/utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", - "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.15.0.tgz", + "integrity": "sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1" + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/typescript-estree": "7.15.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz", + "integrity": "sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/types": "7.15.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -9527,9 +9527,9 @@ } }, "marked": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.1.tgz", - "integrity": "sha512-7kBohS6GrZKvCsNXZyVVXSW7/hGBHe49ng99YPkDCckSUrrG7MSFLCexsRxptzOmyW2eT5dySh4Md1V6my52fA==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.2.tgz", + "integrity": "sha512-J6CPjP8pS5sgrRqxVRvkCIkZ6MFdRIjDkwUwgJ9nL2fbmM6qGQeB2C16hi8Cc9BOzj6xXzy0jyi0iPIfnMHYzA==", "dev": true }, "meow": { @@ -10442,9 +10442,9 @@ "dev": true }, "typescript": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", - "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "dev": true }, "undici-types": { diff --git a/package.json b/package.json index 502d509806..44f8c172e5 100644 --- a/package.json +++ b/package.json @@ -112,20 +112,20 @@ "@octokit/rest": "^21.0.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.8", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", + "@types/node": "^20.14.10", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^13.0.1", + "marked": "^13.0.2", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.2", "sctp": "^1.0.0", "ts-jest": "^29.1.5", - "typescript": "^5.5.2" + "typescript": "^5.5.3" } } From 1c0121b247409df1ce3296cae94c269b291b32de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 18 Jul 2024 12:48:34 +0200 Subject: [PATCH 470/525] Update Meson to 1.5.0 (#1424) --- .github/workflows/mediasoup-worker.yaml | 21 ++++++++++++++++++++- CHANGELOG.md | 3 ++- worker/tasks.py | 11 +++++------ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 57a2099a77..66dac4ce23 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -11,6 +11,7 @@ concurrency: jobs: ci: strategy: + # Here we want to see all errors, not just the first one. fail-fast: false matrix: build: @@ -48,7 +49,7 @@ jobs: CC: ${{ matrix.build.cc }} CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' - MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_LOCAL_DEV: 'false' MEDIASOUP_BUILDTYPE: ${{ matrix.build-type }} steps: @@ -98,11 +99,23 @@ jobs: # TODO: Maybe fix this one day. if: runner.os != 'Windows' + # Let's clean everything before rebuilding worker tests with ASAN. + - name: invoke -r worker clean-all + run: invoke -r worker clean-all + # Address Sanitizer only works on Linux. + if: runner.os == 'Linux' + - name: invoke -r worker test-asan-address run: invoke -r worker test-asan-address # Address Sanitizer only works on Linux. if: runner.os == 'Linux' + # Let's clean everything before rebuilding worker tests with ASAN. + # - name: invoke -r worker clean-all + # run: invoke -r worker clean-all + # # Address Sanitizer only works on Linux. + # if: runner.os == 'Linux' + # TODO: Uncomment once https://github.com/versatica/mediasoup/issues/1417 # is fixed. # - name: invoke -r worker test-asan-undefined @@ -110,6 +123,12 @@ jobs: # # Address Sanitizer only works on Linux. # if: runner.os == 'Linux' + # Let's clean everything before rebuilding worker tests with ASAN. + # - name: invoke -r worker clean-all + # run: invoke -r worker clean-all + # # Address Sanitizer only works on Linux. + # if: runner.os == 'Linux' + # TODO: Uncomment once https://github.com/versatica/mediasoup/issues/1417 # is fixed. # - name: invoke -r worker test-asan-thread diff --git a/CHANGELOG.md b/CHANGELOG.md index 44ae6bdaa2..d333e2c610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT - Worker: Test, fix buffer overflow ([PR #1419](https://github.com/versatica/mediasoup/pull/1419)). +- Bump up Meson from 1.3.0 to 1.5.0 ([PR #1424](https://github.com/versatica/mediasoup/pull/1424)). ### 3.14.8 @@ -434,7 +435,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.10.2 -- Fix release contents by including meson_options.txt ([PR #863](https://github.com/versatica/mediasoup/pull/863)). +- Fix release contents by including `meson_options.txt` ([PR #863](https://github.com/versatica/mediasoup/pull/863)). ### 3.10.1 diff --git a/worker/tasks.py b/worker/tasks.py index f9fb125d43..9bb71f4bb2 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -50,7 +50,7 @@ NUM_CORES = len(os.sched_getaffinity(0)) if hasattr(os, 'sched_getaffinity') else os.cpu_count(); PYTHON = os.getenv('PYTHON') or sys.executable; MESON = os.getenv('MESON') or f'{PIP_MESON_NINJA_DIR}/bin/meson'; -MESON_VERSION = os.getenv('MESON_VERSION') or '1.3.0'; +MESON_VERSION = os.getenv('MESON_VERSION') or '1.5.0'; # MESON_ARGS can be used to provide extra configuration parameters to meson, # such as adding defines or changing optimization options. For instance, use # `MESON_ARGS="-Dms_log_trace=true -Dms_log_file_line=true" npm i` to compile @@ -61,7 +61,6 @@ # Let's use a specific version of ninja to avoid buggy version 1.11.1: # https://mediasoup.discourse.group/t/partly-solved-could-not-detect-ninja-v1-8-2-or-newer/ # https://github.com/ninja-build/ninja/issues/2211 -# https://github.com/ninja-build/ninja/issues/2212 NINJA_VERSION = os.getenv('NINJA_VERSION') or '1.10.2.4'; PYLINT_VERSION = os.getenv('PYLINT_VERSION') or '3.0.2'; NPM = os.getenv('NPM') or 'npm'; @@ -389,7 +388,7 @@ def test(ctx): ); -@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=address'), flatc]) +@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=address -Db_lundef=false'), flatc]) def test_asan_address(ctx): """ Run worker test with Address Sanitizer with '-fsanitize=address' @@ -420,7 +419,7 @@ def test_asan_address(ctx): ); -@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=undefined'), flatc]) +@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=undefined -Db_lundef=false'), flatc]) def test_asan_undefined(ctx): """ Run worker test with undefined Sanitizer with -fsanitize=undefined @@ -451,7 +450,7 @@ def test_asan_undefined(ctx): ); -@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=thread'), flatc]) +@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=thread -Db_lundef=false'), flatc]) def test_asan_thread(ctx): """ Run worker test with thread Sanitizer with -fsanitize=thread @@ -511,7 +510,7 @@ def tidy(ctx): ); -@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=address'), flatc]) +@task(pre=[call(setup, meson_args=MESON_ARGS + ' -Db_sanitize=address -Db_lundef=false'), flatc]) def fuzzer(ctx): """ Build the mediasoup-worker-fuzzer binary (which uses libFuzzer) From 09810e97d4861e5c2271152660ef811939570884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 18 Jul 2024 17:49:06 +0200 Subject: [PATCH 471/525] CI: Uncomment more worker ASAN tests (#1427) --- .../workflows/mediasoup-worker-fuzzer.yaml | 8 +- .github/workflows/mediasoup-worker.yaml | 78 ++++++++----------- 2 files changed, 38 insertions(+), 48 deletions(-) diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index 60798016db..8f47946802 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -34,14 +34,14 @@ jobs: uses: actions/checkout@v4 # We need to install pip invoke manually. - - name: pip3 install invoke + - if: runner.os != 'macOS' + name: pip3 install invoke run: pip3 install invoke - if: runner.os != 'macOS' # In macOS we need to specify this option. - - name: pip3 install --break-system-packages invoke + - if: runner.os == 'macOS' + name: pip3 install --break-system-packages invoke run: pip3 install --break-system-packages invoke - if: runner.os == 'macOS' # Build the mediasoup-worker-fuzzer binary (which uses libFuzzer). - name: invoke -r worker fuzzer diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 66dac4ce23..9fb3c68b72 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -18,9 +18,13 @@ jobs: - os: ubuntu-20.04 cc: gcc cxx: g++ + # Workaround for this issue in Ubunt 20.04: + # https://github.com/versatica/mediasoup/actions/runs/9992113733/job/27616379442?pr=1427 + workaround-ubuntu-20-04: true - os: ubuntu-20.04 cc: clang cxx: clang++ + workaround-ubuntu-20-04: true - os: ubuntu-22.04 cc: gcc cxx: g++ @@ -71,67 +75,53 @@ jobs: ${{ matrix.build.os }}-node-${{matrix.build.cc}}- # We need to install pip invoke manually. - - name: pip3 install invoke + - if: runner.os != 'macOS' + name: pip3 install invoke run: pip3 install invoke - if: runner.os != 'macOS' # In macOS we need to specify this option. - - name: pip3 install --break-system-packages invoke + - if: runner.os == 'macOS' + name: pip3 install --break-system-packages invoke run: pip3 install --break-system-packages invoke - if: runner.os == 'macOS' # We need to install npm deps of worker/scripts/package.json. - - name: npm ci --prefix worker/scripts + - if: runner.os != 'Windows' + name: npm ci --prefix worker/scripts run: npm ci --prefix worker/scripts --foreground-scripts - # TODO: Maybe fix this one day. - if: runner.os != 'Windows' - - name: invoke -r worker lint + # Workaround for this issue in Ubuntu 20.04: + # https://github.com/versatica/mediasoup/actions/runs/9992113733/job/27616379442?pr=1427 + - if: ${{ matrix.build.workaround-ubuntu-20-04 }} + name: workaround for Ubuntu 20.04 + run: sudo apt install -y libgcc-10-dev && sudo ln -s /usr/lib/gcc/x86_64-linux-gnu/10/libtsan_preinit.o /usr/lib/libtsan_preinit.o + + # NOTE: Maybe make it work on Windows someday. + - if: runner.os != 'Windows' + name: invoke -r worker lint run: invoke -r worker lint - # TODO: Maybe fix this one day. - if: runner.os != 'Windows' - name: invoke -r worker mediasoup-worker run: invoke -r worker mediasoup-worker - - name: invoke -r worker test + # NOTE: Maybe make it work on Windows someday. + - if: runner.os != 'Windows' + name: invoke -r worker test run: invoke -r worker test - # TODO: Maybe fix this one day. - if: runner.os != 'Windows' + # Address Sanitizer only works on Linux. # Let's clean everything before rebuilding worker tests with ASAN. - - name: invoke -r worker clean-all - run: invoke -r worker clean-all - # Address Sanitizer only works on Linux. - if: runner.os == 'Linux' - - - name: invoke -r worker test-asan-address - run: invoke -r worker test-asan-address - # Address Sanitizer only works on Linux. - if: runner.os == 'Linux' + - if: runner.os == 'Linux' + name: invoke -r worker test-asan-address + run: invoke -r worker clean-all && invoke -r worker test-asan-address + # Address Sanitizer only works on Linux. # Let's clean everything before rebuilding worker tests with ASAN. - # - name: invoke -r worker clean-all - # run: invoke -r worker clean-all - # # Address Sanitizer only works on Linux. - # if: runner.os == 'Linux' - - # TODO: Uncomment once https://github.com/versatica/mediasoup/issues/1417 - # is fixed. - # - name: invoke -r worker test-asan-undefined - # run: invoke -r worker test-asan-undefined - # # Address Sanitizer only works on Linux. - # if: runner.os == 'Linux' + - if: runner.os == 'Linux' + name: invoke -r worker test-asan-undefined + run: invoke -r worker clean-all && invoke -r worker test-asan-undefined + # Address Sanitizer only works on Linux. # Let's clean everything before rebuilding worker tests with ASAN. - # - name: invoke -r worker clean-all - # run: invoke -r worker clean-all - # # Address Sanitizer only works on Linux. - # if: runner.os == 'Linux' - - # TODO: Uncomment once https://github.com/versatica/mediasoup/issues/1417 - # is fixed. - # - name: invoke -r worker test-asan-thread - # run: invoke -r worker test-asan-thread - # # Address Sanitizer only works on Linux. - # if: runner.os == 'Linux' + - if: runner.os == 'Linux' + name: invoke -r worker test-asan-thread + run: invoke -r worker clean-all && invoke -r worker test-asan-thread From 06f66e62874ede5f4bb4a166ba2629280b9edada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 18 Jul 2024 17:55:51 +0200 Subject: [PATCH 472/525] Update npm deps --- package-lock.json | 463 +++++++++++++++++++++++++++++----------------- package.json | 14 +- 2 files changed, 301 insertions(+), 176 deletions(-) diff --git a/package-lock.json b/package-lock.json index b464868b37..bf58d3e3ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,23 +20,23 @@ "tar": "^7.4.0" }, "devDependencies": { - "@octokit/rest": "^21.0.0", + "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.10", - "@typescript-eslint/eslint-plugin": "^7.15.0", - "@typescript-eslint/parser": "^7.15.0", + "@types/node": "^20.14.11", + "@typescript-eslint/eslint-plugin": "^7.16.1", + "@typescript-eslint/parser": "^7.16.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.2.1", "jest": "^29.7.0", "marked": "^13.0.2", "open-cli": "^8.0.0", "pick-port": "^2.1.0", - "prettier": "^3.3.2", + "prettier": "^3.3.3", "sctp": "^1.0.0", - "ts-jest": "^29.1.5", + "ts-jest": "^29.2.3", "typescript": "^5.5.3" }, "engines": { @@ -1521,14 +1521,14 @@ } }, "node_modules/@octokit/rest": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.0.tgz", - "integrity": "sha512-XudXXOmiIjivdjNZ+fN71NLrnDM00sxSZlhqmPR3v0dVoJwyP628tSlc12xqn8nX3N0965583RBw5GPo6r8u4Q==", + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.1.tgz", + "integrity": "sha512-RWA6YU4CqK0h0J6tfYlUFnH3+YgBADlxaHXaKSG+BVr2y4PTfbU2tlKuaQoQZ83qaTbi4CUxLNAmbAqR93A6mQ==", "dev": true, "dependencies": { "@octokit/core": "^6.1.2", "@octokit/plugin-paginate-rest": "^11.0.0", - "@octokit/plugin-request-log": "^5.1.0", + "@octokit/plugin-request-log": "^5.3.1", "@octokit/plugin-rest-endpoint-methods": "^13.0.0" }, "engines": { @@ -1590,9 +1590,9 @@ } }, "node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.0.tgz", - "integrity": "sha512-FiGcyjdtYPlr03ExBk/0ysIlEFIFGJQAVoPPMxL19B24bVSEiZQnVGBunNtaAF1YnvE/EFoDpXmITtRnyCiypQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", "dev": true, "engines": { "node": ">= 18" @@ -1602,9 +1602,9 @@ } }, "node_modules/@octokit/rest/node_modules/@octokit/request": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.1.tgz", - "integrity": "sha512-pyAguc0p+f+GbQho0uNetNQMmLG1e80WjkIaqqgUkihqUp0boRU6nKItXO4VWnr+nbZiLGEyy4TeKRwqaLvYgw==", + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz", + "integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==", "dev": true, "dependencies": { "@octokit/endpoint": "^10.0.0", @@ -1617,9 +1617,9 @@ } }, "node_modules/@octokit/rest/node_modules/@octokit/request-error": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.1.tgz", - "integrity": "sha512-1mw1gqT3fR/WFvnoVpY/zUM2o/XkMs/2AszUUG9I69xn0JFLv6PGkPhNk5lbfvROs79wiS0bqiJNxfCZcRJJdg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.4.tgz", + "integrity": "sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==", "dev": true, "dependencies": { "@octokit/types": "^13.0.0" @@ -1659,9 +1659,9 @@ } }, "node_modules/@pkgr/core": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", - "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" @@ -1803,9 +1803,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.14.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", + "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1833,16 +1833,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz", - "integrity": "sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz", + "integrity": "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.15.0", - "@typescript-eslint/type-utils": "7.15.0", - "@typescript-eslint/utils": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0", + "@typescript-eslint/scope-manager": "7.16.1", + "@typescript-eslint/type-utils": "7.16.1", + "@typescript-eslint/utils": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1866,15 +1866,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.15.0.tgz", - "integrity": "sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.1.tgz", + "integrity": "sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.15.0", - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/typescript-estree": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0", + "@typescript-eslint/scope-manager": "7.16.1", + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/typescript-estree": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4" }, "engines": { @@ -1894,13 +1894,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz", - "integrity": "sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz", + "integrity": "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0" + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1911,13 +1911,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.15.0.tgz", - "integrity": "sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz", + "integrity": "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.15.0", - "@typescript-eslint/utils": "7.15.0", + "@typescript-eslint/typescript-estree": "7.16.1", + "@typescript-eslint/utils": "7.16.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1938,9 +1938,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.15.0.tgz", - "integrity": "sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz", + "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1951,13 +1951,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz", - "integrity": "sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz", + "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0", + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2003,15 +2003,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.15.0.tgz", - "integrity": "sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz", + "integrity": "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.15.0", - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/typescript-estree": "7.15.0" + "@typescript-eslint/scope-manager": "7.16.1", + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/typescript-estree": "7.16.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2025,12 +2025,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz", - "integrity": "sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz", + "integrity": "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/types": "7.16.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2161,6 +2161,12 @@ "node": ">=8" } }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -2725,6 +2731,21 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -2871,13 +2892,13 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "synckit": "^0.9.1" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -3169,6 +3190,36 @@ "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3822,6 +3873,24 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/jake": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz", + "integrity": "sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -5159,9 +5228,9 @@ } }, "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -5708,9 +5777,9 @@ } }, "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", "dev": true, "dependencies": { "@pkgr/core": "^0.1.0", @@ -5723,12 +5792,6 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/synckit/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, "node_modules/tar": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.0.tgz", @@ -5881,12 +5944,13 @@ } }, "node_modules/ts-jest": { - "version": "29.1.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.5.tgz", - "integrity": "sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg==", + "version": "29.2.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.3.tgz", + "integrity": "sha512-yCcfVdiBFngVz9/keHin9EnsrQtQtEu3nRykNy9RVp+FiPFFbPJ3Sg6Qg4+TkmH0vMP5qsTKgXSsk80HRwvdgQ==", "dev": true, "dependencies": { "bs-logger": "0.x", + "ejs": "^3.1.10", "fast-json-stable-stringify": "2.x", "jest-util": "^29.0.0", "json5": "^2.2.3", @@ -5927,6 +5991,12 @@ } } }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -7325,14 +7395,14 @@ } }, "@octokit/rest": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.0.tgz", - "integrity": "sha512-XudXXOmiIjivdjNZ+fN71NLrnDM00sxSZlhqmPR3v0dVoJwyP628tSlc12xqn8nX3N0965583RBw5GPo6r8u4Q==", + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.1.tgz", + "integrity": "sha512-RWA6YU4CqK0h0J6tfYlUFnH3+YgBADlxaHXaKSG+BVr2y4PTfbU2tlKuaQoQZ83qaTbi4CUxLNAmbAqR93A6mQ==", "dev": true, "requires": { "@octokit/core": "^6.1.2", "@octokit/plugin-paginate-rest": "^11.0.0", - "@octokit/plugin-request-log": "^5.1.0", + "@octokit/plugin-request-log": "^5.3.1", "@octokit/plugin-rest-endpoint-methods": "^13.0.0" }, "dependencies": { @@ -7379,16 +7449,16 @@ } }, "@octokit/plugin-request-log": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.0.tgz", - "integrity": "sha512-FiGcyjdtYPlr03ExBk/0ysIlEFIFGJQAVoPPMxL19B24bVSEiZQnVGBunNtaAF1YnvE/EFoDpXmITtRnyCiypQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", "dev": true, "requires": {} }, "@octokit/request": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.1.tgz", - "integrity": "sha512-pyAguc0p+f+GbQho0uNetNQMmLG1e80WjkIaqqgUkihqUp0boRU6nKItXO4VWnr+nbZiLGEyy4TeKRwqaLvYgw==", + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz", + "integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==", "dev": true, "requires": { "@octokit/endpoint": "^10.0.0", @@ -7398,9 +7468,9 @@ } }, "@octokit/request-error": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.1.tgz", - "integrity": "sha512-1mw1gqT3fR/WFvnoVpY/zUM2o/XkMs/2AszUUG9I69xn0JFLv6PGkPhNk5lbfvROs79wiS0bqiJNxfCZcRJJdg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.4.tgz", + "integrity": "sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==", "dev": true, "requires": { "@octokit/types": "^13.0.0" @@ -7436,9 +7506,9 @@ "optional": true }, "@pkgr/core": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", - "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true }, "@sinclair/typebox": { @@ -7574,9 +7644,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.14.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", + "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7604,16 +7674,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz", - "integrity": "sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz", + "integrity": "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.15.0", - "@typescript-eslint/type-utils": "7.15.0", - "@typescript-eslint/utils": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0", + "@typescript-eslint/scope-manager": "7.16.1", + "@typescript-eslint/type-utils": "7.16.1", + "@typescript-eslint/utils": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7621,54 +7691,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.15.0.tgz", - "integrity": "sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.1.tgz", + "integrity": "sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.15.0", - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/typescript-estree": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0", + "@typescript-eslint/scope-manager": "7.16.1", + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/typescript-estree": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz", - "integrity": "sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz", + "integrity": "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0" + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1" } }, "@typescript-eslint/type-utils": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.15.0.tgz", - "integrity": "sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz", + "integrity": "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.15.0", - "@typescript-eslint/utils": "7.15.0", + "@typescript-eslint/typescript-estree": "7.16.1", + "@typescript-eslint/utils": "7.16.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.15.0.tgz", - "integrity": "sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz", + "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz", - "integrity": "sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz", + "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0", + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7698,24 +7768,24 @@ } }, "@typescript-eslint/utils": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.15.0.tgz", - "integrity": "sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz", + "integrity": "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.15.0", - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/typescript-estree": "7.15.0" + "@typescript-eslint/scope-manager": "7.16.1", + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/typescript-estree": "7.16.1" } }, "@typescript-eslint/visitor-keys": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz", - "integrity": "sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz", + "integrity": "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/types": "7.16.1", "eslint-visitor-keys": "^3.4.3" } }, @@ -7802,6 +7872,12 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, "babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -8202,6 +8278,15 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, "electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -8303,13 +8388,13 @@ } }, "eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "synckit": "^0.9.1" } }, "eslint-scope": { @@ -8506,6 +8591,35 @@ "token-types": "^5.0.1" } }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -8952,6 +9066,18 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "jake": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz", + "integrity": "sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + } + }, "jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -9926,9 +10052,9 @@ "dev": true }, "prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true }, "prettier-linter-helpers": { @@ -10280,21 +10406,13 @@ "dev": true }, "synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", "dev": true, "requires": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" - }, - "dependencies": { - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - } } }, "tar": { @@ -10405,12 +10523,13 @@ "requires": {} }, "ts-jest": { - "version": "29.1.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.5.tgz", - "integrity": "sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg==", + "version": "29.2.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.3.tgz", + "integrity": "sha512-yCcfVdiBFngVz9/keHin9EnsrQtQtEu3nRykNy9RVp+FiPFFbPJ3Sg6Qg4+TkmH0vMP5qsTKgXSsk80HRwvdgQ==", "dev": true, "requires": { "bs-logger": "0.x", + "ejs": "^3.1.10", "fast-json-stable-stringify": "2.x", "jest-util": "^29.0.0", "json5": "^2.2.3", @@ -10420,6 +10539,12 @@ "yargs-parser": "^21.0.1" } }, + "tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 44f8c172e5..6bc1676cb7 100644 --- a/package.json +++ b/package.json @@ -109,23 +109,23 @@ "tar": "^7.4.0" }, "devDependencies": { - "@octokit/rest": "^21.0.0", + "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.10", - "@typescript-eslint/eslint-plugin": "^7.15.0", - "@typescript-eslint/parser": "^7.15.0", + "@types/node": "^20.14.11", + "@typescript-eslint/eslint-plugin": "^7.16.1", + "@typescript-eslint/parser": "^7.16.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.2.1", "jest": "^29.7.0", "marked": "^13.0.2", "open-cli": "^8.0.0", "pick-port": "^2.1.0", - "prettier": "^3.3.2", + "prettier": "^3.3.3", "sctp": "^1.0.0", - "ts-jest": "^29.1.5", + "ts-jest": "^29.2.3", "typescript": "^5.5.3" } } From 8e769dbccb06c8f680b78ae69fe4eac32ff488e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 25 Jul 2024 19:55:29 +0200 Subject: [PATCH 473/525] Fix TS Observers type (#1430) --- CHANGELOG.md | 1 + node/src/ActiveSpeakerObserver.ts | 15 ++++++++++++--- node/src/AudioLevelObserver.ts | 18 ++++++++++++++--- node/src/Consumer.ts | 7 +++++-- node/src/DataConsumer.ts | 8 ++++++-- node/src/DataProducer.ts | 8 ++++++-- node/src/DirectTransport.ts | 20 +++++++++++++++++-- node/src/PipeTransport.ts | 20 +++++++++++++++++-- node/src/PlainTransport.ts | 20 +++++++++++++++++-- node/src/Producer.ts | 7 +++++-- node/src/Router.ts | 7 +++++-- node/src/RtpObserver.ts | 26 ++++++++++++++++--------- node/src/Transport.ts | 32 ++++++++++++++++++------------- node/src/WebRtcServer.ts | 8 ++++++-- node/src/WebRtcTransport.ts | 20 +++++++++++++++++-- node/src/Worker.ts | 7 +++++-- node/src/index.ts | 4 +++- 17 files changed, 177 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d333e2c610..ce2f166941 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Worker: Test, fix buffer overflow ([PR #1419](https://github.com/versatica/mediasoup/pull/1419)). - Bump up Meson from 1.3.0 to 1.5.0 ([PR #1424](https://github.com/versatica/mediasoup/pull/1424)). +- Node: Export new `WorkerObserver`, `ProducerObserver`, etc. TypeScript types ([PR #1430](https://github.com/versatica/mediasoup/pull/1430)). ### 3.14.8 diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index 88229731dc..9187175115 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -33,6 +33,9 @@ export type ActiveSpeakerObserverEvents = RtpObserverEvents & { dominantspeaker: [ActiveSpeakerObserverDominantSpeaker]; }; +export type ActiveSpeakerObserverObserver = + EnhancedEventEmitter; + export type ActiveSpeakerObserverObserverEvents = RtpObserverObserverEvents & { dominantspeaker: [ActiveSpeakerObserverDominantSpeaker]; }; @@ -46,7 +49,8 @@ export class ActiveSpeakerObserver< ActiveSpeakerObserverAppData extends AppData = AppData, > extends RtpObserver< ActiveSpeakerObserverAppData, - ActiveSpeakerObserverEvents + ActiveSpeakerObserverEvents, + ActiveSpeakerObserverObserver > { /** * @private @@ -54,15 +58,20 @@ export class ActiveSpeakerObserver< constructor( options: RtpObserverObserverConstructorOptions ) { - super(options); + const observer: ActiveSpeakerObserverObserver = + new EnhancedEventEmitter(); + + super(options, observer); this.handleWorkerNotifications(); } /** * Observer. + * + * @override */ - get observer(): EnhancedEventEmitter { + get observer(): ActiveSpeakerObserverObserver { return super.observer; } diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index f24e5d6b16..e0a91e408d 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -55,6 +55,9 @@ export type AudioLevelObserverEvents = RtpObserverEvents & { silence: []; }; +export type AudioLevelObserverObserver = + EnhancedEventEmitter; + export type AudioLevelObserverObserverEvents = RtpObserverObserverEvents & { volumes: [AudioLevelObserverVolume[]]; silence: []; @@ -67,22 +70,31 @@ const logger = new Logger('AudioLevelObserver'); export class AudioLevelObserver< AudioLevelObserverAppData extends AppData = AppData, -> extends RtpObserver { +> extends RtpObserver< + AudioLevelObserverAppData, + AudioLevelObserverEvents, + AudioLevelObserverObserver +> { /** * @private */ constructor( options: AudioLevelObserverConstructorOptions ) { - super(options); + const observer: AudioLevelObserverObserver = + new EnhancedEventEmitter(); + + super(options, observer); this.handleWorkerNotifications(); } /** * Observer. + * + * @override */ - get observer(): EnhancedEventEmitter { + get observer(): AudioLevelObserverObserver { return super.observer; } diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 8ada889603..8de9fc4cff 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -179,6 +179,8 @@ export type ConsumerEvents = { '@producerclose': []; }; +export type ConsumerObserver = EnhancedEventEmitter; + export type ConsumerObserverEvents = { close: []; pause: []; @@ -318,7 +320,8 @@ export class Consumer< #currentLayers?: ConsumerLayers; // Observer instance. - readonly #observer = new EnhancedEventEmitter(); + readonly #observer: ConsumerObserver = + new EnhancedEventEmitter(); /** * @private @@ -459,7 +462,7 @@ export class Consumer< /** * Observer. */ - get observer(): EnhancedEventEmitter { + get observer(): ConsumerObserver { return this.#observer; } diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index d0ff2ace7c..8a987f143d 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -92,6 +92,9 @@ export type DataConsumerEvents = { '@dataproducerclose': []; }; +export type DataConsumerObserver = + EnhancedEventEmitter; + export type DataConsumerObserverEvents = { close: []; pause: []; @@ -148,7 +151,8 @@ export class DataConsumer< #appData: DataConsumerAppData; // Observer instance. - readonly #observer = new EnhancedEventEmitter(); + readonly #observer: DataConsumerObserver = + new EnhancedEventEmitter(); /** * @private @@ -272,7 +276,7 @@ export class DataConsumer< /** * Observer. */ - get observer(): EnhancedEventEmitter { + get observer(): DataConsumerObserver { return this.#observer; } diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index af7ef5c716..5a6ced5aa0 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -67,6 +67,9 @@ export type DataProducerEvents = { '@close': []; }; +export type DataProducerObserver = + EnhancedEventEmitter; + export type DataProducerObserverEvents = { close: []; pause: []; @@ -113,7 +116,8 @@ export class DataProducer< #appData: DataProducerAppData; // Observer instance. - readonly #observer = new EnhancedEventEmitter(); + readonly #observer: DataProducerObserver = + new EnhancedEventEmitter(); /** * @private @@ -210,7 +214,7 @@ export class DataProducer< /** * Observer. */ - get observer(): EnhancedEventEmitter { + get observer(): DataProducerObserver { return this.#observer; } diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index f37edd379b..3417e0bb46 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -1,4 +1,5 @@ import { Logger } from './Logger'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { UnsupportedError } from './errors'; import { BaseTransportDump, @@ -44,6 +45,9 @@ export type DirectTransportEvents = TransportEvents & { rtcp: [Buffer]; }; +export type DirectTransportObserver = + EnhancedEventEmitter; + export type DirectTransportObserverEvents = TransportObserverEvents & { rtcp: [Buffer]; }; @@ -64,7 +68,7 @@ export class DirectTransport< > extends Transport< DirectTransportAppData, DirectTransportEvents, - DirectTransportObserverEvents + DirectTransportObserver > { // DirectTransport data. readonly #data: DirectTransportData; @@ -75,7 +79,10 @@ export class DirectTransport< constructor( options: DirectTransportConstructorOptions ) { - super(options); + const observer: DirectTransportObserver = + new EnhancedEventEmitter(); + + super(options, observer); logger.debug('constructor()'); @@ -86,6 +93,15 @@ export class DirectTransport< this.handleWorkerNotifications(); } + /** + * Observer. + * + * @override + */ + get observer(): DirectTransportObserver { + return super.observer; + } + /** * Close the DirectTransport. * diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index 3bd9eb0dd1..6fea0d56ad 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -1,5 +1,6 @@ import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; +import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; import { BaseTransportDump, @@ -131,6 +132,9 @@ export type PipeTransportEvents = TransportEvents & { sctpstatechange: [SctpState]; }; +export type PipeTransportObserver = + EnhancedEventEmitter; + export type PipeTransportObserverEvents = TransportObserverEvents & { sctpstatechange: [SctpState]; }; @@ -161,7 +165,7 @@ export class PipeTransport< > extends Transport< PipeTransportAppData, PipeTransportEvents, - PipeTransportObserverEvents + PipeTransportObserver > { // PipeTransport data. readonly #data: PipeTransportData; @@ -170,7 +174,10 @@ export class PipeTransport< * @private */ constructor(options: PipeTransportConstructorOptions) { - super(options); + const observer: PipeTransportObserver = + new EnhancedEventEmitter(); + + super(options, observer); logger.debug('constructor()'); @@ -187,6 +194,15 @@ export class PipeTransport< this.handleWorkerNotifications(); } + /** + * Observer. + * + * @override + */ + get observer(): PipeTransportObserver { + return super.observer; + } + /** * Transport tuple. */ diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index 7d118207c0..c4202eec7e 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -1,5 +1,6 @@ import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { parseSctpState, BaseTransportDump, @@ -130,6 +131,9 @@ export type PlainTransportEvents = TransportEvents & { sctpstatechange: [SctpState]; }; +export type PlainTransportObserver = + EnhancedEventEmitter; + export type PlainTransportObserverEvents = TransportObserverEvents & { tuple: [TransportTuple]; rtcptuple: [TransportTuple]; @@ -166,7 +170,7 @@ export class PlainTransport< > extends Transport< PlainTransportAppData, PlainTransportEvents, - PlainTransportObserverEvents + PlainTransportObserver > { // PlainTransport data. readonly #data: PlainTransportData; @@ -177,7 +181,10 @@ export class PlainTransport< constructor( options: PlainTransportConstructorOptions ) { - super(options); + const observer: PlainTransportObserver = + new EnhancedEventEmitter(); + + super(options, observer); logger.debug('constructor()'); @@ -196,6 +203,15 @@ export class PlainTransport< this.handleWorkerNotifications(); } + /** + * Observer. + * + * @override + */ + get observer(): PlainTransportObserver { + return super.observer; + } + /** * Transport tuple. */ diff --git a/node/src/Producer.ts b/node/src/Producer.ts index afadbc8255..317091e0d8 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -140,6 +140,8 @@ export type ProducerEvents = { '@close': []; }; +export type ProducerObserver = EnhancedEventEmitter; + export type ProducerObserverEvents = { close: []; pause: []; @@ -198,7 +200,8 @@ export class Producer< #score: ProducerScore[] = []; // Observer instance. - readonly #observer = new EnhancedEventEmitter(); + readonly #observer: ProducerObserver = + new EnhancedEventEmitter(); /** * @private @@ -304,7 +307,7 @@ export class Producer< /** * Observer. */ - get observer(): EnhancedEventEmitter { + get observer(): ProducerObserver { return this.#observer; } diff --git a/node/src/Router.ts b/node/src/Router.ts index c604768053..fb05298187 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -198,6 +198,8 @@ export type RouterEvents = { '@close': []; }; +export type RouterObserver = EnhancedEventEmitter; + export type RouterObserverEvents = { close: []; newtransport: [Transport]; @@ -252,7 +254,8 @@ export class Router< > = new Map(); // Observer instance. - readonly #observer = new EnhancedEventEmitter(); + readonly #observer: RouterObserver = + new EnhancedEventEmitter(); /** * @private @@ -316,7 +319,7 @@ export class Router< /** * Observer. */ - get observer(): EnhancedEventEmitter { + get observer(): RouterObserver { return this.#observer; } diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 1756880755..9bc808e5ce 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -15,6 +15,9 @@ export type RtpObserverEvents = { '@close': []; }; +export type RtpObserverObserver = + EnhancedEventEmitter; + export type RtpObserverObserverEvents = { close: []; pause: []; @@ -43,9 +46,10 @@ export type RtpObserverAddRemoveProducerOptions = { producerId: string; }; -export class RtpObserver< +export abstract class RtpObserver< RtpObserverAppData extends AppData = AppData, Events extends RtpObserverEvents = RtpObserverEvents, + Observer extends RtpObserverObserver = RtpObserverObserver, > extends EnhancedEventEmitter { // Internal data. protected readonly internal: RtpObserverObserverInternal; @@ -68,18 +72,21 @@ export class RtpObserver< ) => Producer | undefined; // Observer instance. - readonly #observer = new EnhancedEventEmitter(); + readonly #observer: Observer; /** * @private * @interface */ - constructor({ - internal, - channel, - appData, - getProducerById, - }: RtpObserverConstructorOptions) { + constructor( + { + internal, + channel, + appData, + getProducerById, + }: RtpObserverConstructorOptions, + observer: Observer + ) { super(); logger.debug('constructor()'); @@ -88,6 +95,7 @@ export class RtpObserver< this.channel = channel; this.#appData = appData || ({} as RtpObserverAppData); this.getProducerById = getProducerById; + this.#observer = observer; } /** @@ -128,7 +136,7 @@ export class RtpObserver< /** * Observer. */ - get observer(): EnhancedEventEmitter { + get observer(): Observer { return this.#observer; } diff --git a/node/src/Transport.ts b/node/src/Transport.ts index f748b9e9c1..2b6bced94d 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -223,6 +223,8 @@ export type TransportEvents = { '@listenserverclose': []; }; +export type TransportObserver = EnhancedEventEmitter; + export type TransportObserverEvents = { close: []; newproducer: [Producer]; @@ -317,10 +319,10 @@ type RecvRtpHeaderExtensions = { const logger = new Logger('Transport'); -export class Transport< +export abstract class Transport< TransportAppData extends AppData = AppData, Events extends TransportEvents = TransportEvents, - ObserverEvents extends TransportObserverEvents = TransportObserverEvents, + Observer extends TransportObserver = TransportObserver, > extends EnhancedEventEmitter { // Internal data. protected readonly internal: TransportInternal; @@ -375,21 +377,24 @@ export class Transport< #nextSctpStreamId = 0; // Observer instance. - readonly #observer = new EnhancedEventEmitter(); + readonly #observer: Observer; /** * @private * @interface */ - constructor({ - internal, - data, - channel, - appData, - getRouterRtpCapabilities, - getProducerById, - getDataProducerById, - }: TransportConstructorOptions) { + constructor( + { + internal, + data, + channel, + appData, + getRouterRtpCapabilities, + getProducerById, + getDataProducerById, + }: TransportConstructorOptions, + observer: Observer + ) { super(); logger.debug('constructor()'); @@ -401,6 +406,7 @@ export class Transport< this.#getRouterRtpCapabilities = getRouterRtpCapabilities; this.getProducerById = getProducerById; this.getDataProducerById = getDataProducerById; + this.#observer = observer; } /** @@ -434,7 +440,7 @@ export class Transport< /** * Observer. */ - get observer(): EnhancedEventEmitter { + get observer(): Observer { return this.#observer; } diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index a820bfda3d..29082d80c8 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -34,6 +34,9 @@ export type WebRtcServerEvents = { '@close': []; }; +export type WebRtcServerObserver = + EnhancedEventEmitter; + export type WebRtcServerObserverEvents = { close: []; webrtctransporthandled: [WebRtcTransport]; @@ -89,7 +92,8 @@ export class WebRtcServer< readonly #webRtcTransports: Map = new Map(); // Observer instance. - readonly #observer = new EnhancedEventEmitter(); + readonly #observer: WebRtcServerObserver = + new EnhancedEventEmitter(); /** * @private @@ -143,7 +147,7 @@ export class WebRtcServer< /** * Observer. */ - get observer(): EnhancedEventEmitter { + get observer(): WebRtcServerObserver { return this.#observer; } diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 1e0a8d5b49..11977b6cfd 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -1,5 +1,6 @@ import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { parseSctpState, parseBaseTransportDump, @@ -215,6 +216,9 @@ export type WebRtcTransportEvents = TransportEvents & { sctpstatechange: [SctpState]; }; +export type WebRtcTransportObserver = + EnhancedEventEmitter; + export type WebRtcTransportObserverEvents = TransportObserverEvents & { icestatechange: [IceState]; iceselectedtuplechange: [TransportTuple]; @@ -258,7 +262,7 @@ export class WebRtcTransport< > extends Transport< WebRtcTransportAppData, WebRtcTransportEvents, - WebRtcTransportObserverEvents + WebRtcTransportObserver > { // WebRtcTransport data. readonly #data: WebRtcTransportData; @@ -269,7 +273,10 @@ export class WebRtcTransport< constructor( options: WebRtcTransportConstructorOptions ) { - super(options); + const observer: WebRtcTransportObserver = + new EnhancedEventEmitter(); + + super(options, observer); logger.debug('constructor()'); @@ -291,6 +298,15 @@ export class WebRtcTransport< this.handleWorkerNotifications(); } + /** + * Observer. + * + * @override + */ + get observer(): WebRtcTransportObserver { + return super.observer; + } + /** * ICE role. */ diff --git a/node/src/Worker.ts b/node/src/Worker.ts index b69d2c9c29..151211fa61 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -210,6 +210,8 @@ export type WorkerEvents = { '@failure': [Error]; }; +export type WorkerObserver = EnhancedEventEmitter; + export type WorkerObserverEvents = { close: []; newwebrtcserver: [WebRtcServer]; @@ -275,7 +277,8 @@ export class Worker< readonly #routers: Set = new Set(); // Observer instance. - readonly #observer = new EnhancedEventEmitter(); + readonly #observer: WorkerObserver = + new EnhancedEventEmitter(); /** * @private @@ -545,7 +548,7 @@ export class Worker< /** * Observer. */ - get observer(): EnhancedEventEmitter { + get observer(): WorkerObserver { return this.#observer; } diff --git a/node/src/index.ts b/node/src/index.ts index 28c41f361d..38410c419a 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -22,11 +22,13 @@ export const version: string = require('../../package.json').version; */ export { parse as parseScalabilityMode } from './scalabilityModes'; +export type Observer = EnhancedEventEmitter; + export type ObserverEvents = { newworker: [Worker]; }; -const observer = new EnhancedEventEmitter(); +const observer: Observer = new EnhancedEventEmitter(); /** * Observer. From ecbeea6b74baf237dd5c4d709f695ecccaaf3671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 26 Jul 2024 10:48:39 +0200 Subject: [PATCH 474/525] Fix frozen video in simulcast due to wrong dropping of padding only packets (#1431) Fixes #1429 ### Details - In `SimulcastConsumer` we must drop padding only packets ONLY if the packet belong to the current simulcast stream being sent to the consuming endpoint. - Changes in other `XxxxConsumer` classes are just cosmetic for consistency. --- CHANGELOG.md | 1 + worker/src/RTC/PipeConsumer.cpp | 18 +++++++++--------- worker/src/RTC/SimpleConsumer.cpp | 24 ++++++++++++------------ worker/src/RTC/SimulcastConsumer.cpp | 25 +++++++++++++------------ worker/src/RTC/SvcConsumer.cpp | 24 ++++++++++++------------ 5 files changed, 47 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce2f166941..d8c305d495 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Worker: Test, fix buffer overflow ([PR #1419](https://github.com/versatica/mediasoup/pull/1419)). - Bump up Meson from 1.3.0 to 1.5.0 ([PR #1424](https://github.com/versatica/mediasoup/pull/1424)). - Node: Export new `WorkerObserver`, `ProducerObserver`, etc. TypeScript types ([PR #1430](https://github.com/versatica/mediasoup/pull/1430)). +- Fix frozen video in simulcast due to wrong dropping of padding only packets ([PR #1431](https://github.com/versatica/mediasoup/pull/1431), thanks to @quanli168). ### 3.14.8 diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index 35a0c3d1a9..cde4fbfc76 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -250,24 +250,24 @@ namespace RTC auto& syncRequired = this->mapRtpStreamSyncRequired.at(rtpStream); auto& rtpSeqManager = this->mapRtpStreamRtpSeqManager.at(rtpStream); - // Packets with only padding are not forwarded. - if (packet->GetPayloadLength() == 0) + // If we need to sync, support key frames and this is not a key frame, ignore + // the packet. + if (syncRequired && this->keyFrameSupported && !packet->IsKeyFrame()) { - rtpSeqManager.Drop(packet->GetSequenceNumber()); - #ifdef MS_RTC_LOGGER_RTP - packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); #endif return; } - // If we need to sync, support key frames and this is not a key frame, ignore - // the packet. - if (syncRequired && this->keyFrameSupported && !packet->IsKeyFrame()) + // Packets with only padding are not forwarded. + if (packet->GetPayloadLength() == 0) { + rtpSeqManager.Drop(packet->GetSequenceNumber()); + #ifdef MS_RTC_LOGGER_RTP - packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME); + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); #endif return; diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index ce7fa9283c..d2b635babe 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -314,18 +314,6 @@ namespace RTC return; } - // Packets with only padding are not forwarded. - if (packet->GetPayloadLength() == 0) - { - this->rtpSeqManager.Drop(packet->GetSequenceNumber()); - -#ifdef MS_RTC_LOGGER_RTP - packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); -#endif - - return; - } - auto payloadType = packet->GetPayloadType(); // NOTE: This may happen if this Consumer supports just some codecs of those @@ -372,6 +360,18 @@ namespace RTC return; } + // Packets with only padding are not forwarded. + if (packet->GetPayloadLength() == 0) + { + this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + +#ifdef MS_RTC_LOGGER_RTP + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); +#endif + + return; + } + // Whether this is the first packet after re-sync. const bool isSyncPacket = this->syncRequired; diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index 847d4beb64..bc54bf3424 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -730,18 +730,6 @@ namespace RTC return; } - // Packets with only padding are not forwarded. - if (packet->GetPayloadLength() == 0) - { - this->rtpSeqManager.Drop(packet->GetSequenceNumber()); - -#ifdef MS_RTC_LOGGER_RTP - packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); -#endif - - return; - } - if (this->targetTemporalLayer == -1) { #ifdef MS_RTC_LOGGER_RTP @@ -810,6 +798,19 @@ namespace RTC return; } + // If the packet belongs to current spatial layer being sent and packet does + // not have payload other than padding, then drop it. + if (spatialLayer == this->currentSpatialLayer && packet->GetPayloadLength() == 0) + { + this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + +#ifdef MS_RTC_LOGGER_RTP + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); +#endif + + return; + } + // Whether this is the first packet after re-sync. const bool isSyncPacket = this->syncRequired; diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index bc0ce1417b..a2337b4f81 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -639,18 +639,6 @@ namespace RTC return; } - // Packets with only padding are not forwarded. - if (packet->GetPayloadLength() == 0) - { - this->rtpSeqManager.Drop(packet->GetSequenceNumber()); - -#ifdef MS_RTC_LOGGER_RTP - packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); -#endif - - return; - } - // clang-format off if ( this->encodingContext->GetTargetSpatialLayer() == -1 || @@ -690,6 +678,18 @@ namespace RTC return; } + // Packets with only padding are not forwarded. + if (packet->GetPayloadLength() == 0) + { + this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + +#ifdef MS_RTC_LOGGER_RTP + packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); +#endif + + return; + } + // Whether this is the first packet after re-sync. const bool isSyncPacket = this->syncRequired; From b4836a02bb7ed65728d1dfc292665cb328e14977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 26 Jul 2024 10:50:24 +0200 Subject: [PATCH 475/525] Update npm deps --- package-lock.json | 214 +++++++++++++++++++++++----------------------- package.json | 10 +-- 2 files changed, 112 insertions(+), 112 deletions(-) diff --git a/package-lock.json b/package-lock.json index bf58d3e3ce..37d3f47b05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,15 +17,15 @@ "ini": "^4.1.3", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^7.4.0" + "tar": "^7.4.3" }, "devDependencies": { "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.11", - "@typescript-eslint/eslint-plugin": "^7.16.1", - "@typescript-eslint/parser": "^7.16.1", + "@types/node": "^20.14.12", + "@typescript-eslint/eslint-plugin": "^7.17.0", + "@typescript-eslint/parser": "^7.17.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", @@ -37,7 +37,7 @@ "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.3", - "typescript": "^5.5.3" + "typescript": "^5.5.4" }, "engines": { "node": ">=18" @@ -1803,9 +1803,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.14.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", - "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "version": "20.14.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", + "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1833,16 +1833,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz", - "integrity": "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", + "integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/type-utils": "7.16.1", - "@typescript-eslint/utils": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/scope-manager": "7.17.0", + "@typescript-eslint/type-utils": "7.17.0", + "@typescript-eslint/utils": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1866,15 +1866,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.1.tgz", - "integrity": "sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz", + "integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/typescript-estree": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/scope-manager": "7.17.0", + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/typescript-estree": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0", "debug": "^4.3.4" }, "engines": { @@ -1894,13 +1894,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz", - "integrity": "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz", + "integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1" + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1911,13 +1911,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz", - "integrity": "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz", + "integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.1", - "@typescript-eslint/utils": "7.16.1", + "@typescript-eslint/typescript-estree": "7.17.0", + "@typescript-eslint/utils": "7.17.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1938,9 +1938,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz", - "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz", + "integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1951,13 +1951,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz", - "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz", + "integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2003,15 +2003,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz", - "integrity": "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz", + "integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/typescript-estree": "7.16.1" + "@typescript-eslint/scope-manager": "7.17.0", + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/typescript-estree": "7.17.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2025,12 +2025,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz", - "integrity": "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz", + "integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/types": "7.17.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -5793,9 +5793,9 @@ } }, "node_modules/tar": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.0.tgz", - "integrity": "sha512-XQs0S8fuAkQWuqhDeCdMlJXDX80D7EOVLDPVFkna9yQfzS+PHKgfxcei0jf6/+QAWcjqrnC8uM3fSAnrQl+XYg==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", @@ -6031,9 +6031,9 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -7644,9 +7644,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.14.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", - "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "version": "20.14.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", + "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7674,16 +7674,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz", - "integrity": "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", + "integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/type-utils": "7.16.1", - "@typescript-eslint/utils": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/scope-manager": "7.17.0", + "@typescript-eslint/type-utils": "7.17.0", + "@typescript-eslint/utils": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7691,54 +7691,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.1.tgz", - "integrity": "sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz", + "integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/typescript-estree": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/scope-manager": "7.17.0", + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/typescript-estree": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz", - "integrity": "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz", + "integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1" + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0" } }, "@typescript-eslint/type-utils": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz", - "integrity": "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz", + "integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.16.1", - "@typescript-eslint/utils": "7.16.1", + "@typescript-eslint/typescript-estree": "7.17.0", + "@typescript-eslint/utils": "7.17.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz", - "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz", + "integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz", - "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz", + "integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7768,24 +7768,24 @@ } }, "@typescript-eslint/utils": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz", - "integrity": "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz", + "integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/typescript-estree": "7.16.1" + "@typescript-eslint/scope-manager": "7.17.0", + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/typescript-estree": "7.17.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz", - "integrity": "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz", + "integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==", "dev": true, "requires": { - "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/types": "7.17.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -10416,9 +10416,9 @@ } }, "tar": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.0.tgz", - "integrity": "sha512-XQs0S8fuAkQWuqhDeCdMlJXDX80D7EOVLDPVFkna9yQfzS+PHKgfxcei0jf6/+QAWcjqrnC8uM3fSAnrQl+XYg==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "requires": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", @@ -10567,9 +10567,9 @@ "dev": true }, "typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true }, "undici-types": { diff --git a/package.json b/package.json index 6bc1676cb7..31e3bd707f 100644 --- a/package.json +++ b/package.json @@ -106,15 +106,15 @@ "ini": "^4.1.3", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^7.4.0" + "tar": "^7.4.3" }, "devDependencies": { "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.11", - "@typescript-eslint/eslint-plugin": "^7.16.1", - "@typescript-eslint/parser": "^7.16.1", + "@types/node": "^20.14.12", + "@typescript-eslint/eslint-plugin": "^7.17.0", + "@typescript-eslint/parser": "^7.17.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.6.0", @@ -126,6 +126,6 @@ "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.3", - "typescript": "^5.5.3" + "typescript": "^5.5.4" } } From 734806aefb5b46651b134a9563bda272acd1b0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 26 Jul 2024 10:52:17 +0200 Subject: [PATCH 476/525] 3.14.9 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8c305d495..8e87d51a3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +### 3.14.9 + - Worker: Test, fix buffer overflow ([PR #1419](https://github.com/versatica/mediasoup/pull/1419)). - Bump up Meson from 1.3.0 to 1.5.0 ([PR #1424](https://github.com/versatica/mediasoup/pull/1424)). - Node: Export new `WorkerObserver`, `ProducerObserver`, etc. TypeScript types ([PR #1430](https://github.com/versatica/mediasoup/pull/1430)). diff --git a/package-lock.json b/package-lock.json index 37d3f47b05..873f48c379 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.8", + "version": "3.14.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.8", + "version": "3.14.9", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 31e3bd707f..a225a10840 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.8", + "version": "3.14.9", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 71e23fbb41118b0b70137679ae2ba0e228f45c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 4 Aug 2024 18:46:34 +0200 Subject: [PATCH 477/525] cosmetic --- worker/src/RTC/SeqManager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/worker/src/RTC/SeqManager.cpp b/worker/src/RTC/SeqManager.cpp index 2a7bad5cdc..2debeecd7f 100644 --- a/worker/src/RTC/SeqManager.cpp +++ b/worker/src/RTC/SeqManager.cpp @@ -121,8 +121,7 @@ namespace RTC if (!this->started) { - this->started = true; - + this->started = true; this->maxInput = input; this->maxOutput = output; } From 5963cb3fff0d452f598e265b6a7d08e73b816169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 4 Aug 2024 18:49:20 +0200 Subject: [PATCH 478/525] cosmetic --- worker/include/RTC/SeqManager.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/worker/include/RTC/SeqManager.hpp b/worker/include/RTC/SeqManager.hpp index 3a0fd3cdab..8a7d4beb42 100644 --- a/worker/include/RTC/SeqManager.hpp +++ b/worker/include/RTC/SeqManager.hpp @@ -26,14 +26,14 @@ namespace RTC bool operator()(T lhs, T rhs) const; }; - private: - static const SeqLowerThan isSeqLowerThan; // NOLINT(readability-identifier-naming) - static const SeqHigherThan isSeqHigherThan; // NOLINT(readability-identifier-naming) - public: static bool IsSeqLowerThan(T lhs, T rhs); static bool IsSeqHigherThan(T lhs, T rhs); + private: + static const SeqLowerThan isSeqLowerThan; // NOLINT(readability-identifier-naming) + static const SeqHigherThan isSeqHigherThan; // NOLINT(readability-identifier-naming) + public: SeqManager() = default; From 87a3dffc74361ea755c6dd8714600ce95287c4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 4 Aug 2024 19:15:00 +0200 Subject: [PATCH 479/525] update npm deps --- package-lock.json | 62 +++++++++++++++++++++++------------------------ package.json | 8 +++--- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index 873f48c379..7352d3c4f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "license": "ISC", "dependencies": { "@types/ini": "^4.1.1", - "debug": "^4.3.5", + "debug": "^4.3.6", "flatbuffers": "^24.3.25", "h264-profile-level-id": "^2.0.0", "ini": "^4.1.3", @@ -28,15 +28,15 @@ "@typescript-eslint/parser": "^7.17.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.6.0", + "eslint-plugin-jest": "^28.7.0", "eslint-plugin-prettier": "^5.2.1", "jest": "^29.7.0", - "marked": "^13.0.2", + "marked": "^13.0.3", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", - "ts-jest": "^29.2.3", + "ts-jest": "^29.2.4", "typescript": "^5.5.4" }, "engines": { @@ -2593,9 +2593,9 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dependencies": { "ms": "2.1.2" }, @@ -2867,18 +2867,18 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz", - "integrity": "sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg==", + "version": "28.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.7.0.tgz", + "integrity": "sha512-fzPGN7awL2ftVRQh/bsCi+16ArUZWujZnD1b8EGJqy8nr4//7tZ3BIdc/9edcJBtB3hpci3GtdMNFVDwHU0Eag==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "engines": { "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0 || ^8.0.0", "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", "jest": "*" }, @@ -4637,9 +4637,9 @@ } }, "node_modules/marked": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.2.tgz", - "integrity": "sha512-J6CPjP8pS5sgrRqxVRvkCIkZ6MFdRIjDkwUwgJ9nL2fbmM6qGQeB2C16hi8Cc9BOzj6xXzy0jyi0iPIfnMHYzA==", + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", + "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -5944,9 +5944,9 @@ } }, "node_modules/ts-jest": { - "version": "29.2.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.3.tgz", - "integrity": "sha512-yCcfVdiBFngVz9/keHin9EnsrQtQtEu3nRykNy9RVp+FiPFFbPJ3Sg6Qg4+TkmH0vMP5qsTKgXSsk80HRwvdgQ==", + "version": "29.2.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", + "integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -8188,9 +8188,9 @@ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" }, "debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "requires": { "ms": "2.1.2" } @@ -8379,12 +8379,12 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "28.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz", - "integrity": "sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg==", + "version": "28.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.7.0.tgz", + "integrity": "sha512-fzPGN7awL2ftVRQh/bsCi+16ArUZWujZnD1b8EGJqy8nr4//7tZ3BIdc/9edcJBtB3hpci3GtdMNFVDwHU0Eag==", "dev": true, "requires": { - "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "eslint-plugin-prettier": { @@ -9653,9 +9653,9 @@ } }, "marked": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.2.tgz", - "integrity": "sha512-J6CPjP8pS5sgrRqxVRvkCIkZ6MFdRIjDkwUwgJ9nL2fbmM6qGQeB2C16hi8Cc9BOzj6xXzy0jyi0iPIfnMHYzA==", + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", + "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", "dev": true }, "meow": { @@ -10523,9 +10523,9 @@ "requires": {} }, "ts-jest": { - "version": "29.2.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.3.tgz", - "integrity": "sha512-yCcfVdiBFngVz9/keHin9EnsrQtQtEu3nRykNy9RVp+FiPFFbPJ3Sg6Qg4+TkmH0vMP5qsTKgXSsk80HRwvdgQ==", + "version": "29.2.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", + "integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==", "dev": true, "requires": { "bs-logger": "0.x", diff --git a/package.json b/package.json index a225a10840..4010187354 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ }, "dependencies": { "@types/ini": "^4.1.1", - "debug": "^4.3.5", + "debug": "^4.3.6", "flatbuffers": "^24.3.25", "h264-profile-level-id": "^2.0.0", "ini": "^4.1.3", @@ -117,15 +117,15 @@ "@typescript-eslint/parser": "^7.17.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.6.0", + "eslint-plugin-jest": "^28.7.0", "eslint-plugin-prettier": "^5.2.1", "jest": "^29.7.0", - "marked": "^13.0.2", + "marked": "^13.0.3", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", - "ts-jest": "^29.2.3", + "ts-jest": "^29.2.4", "typescript": "^5.5.4" } } From 5d445e397950dd7e4f150743fae197b9341acbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 4 Aug 2024 22:35:29 +0200 Subject: [PATCH 480/525] Support Node 22 (#1434) --- .github/workflows/mediasoup-node.yaml | 12 +++++-- .../workflows/mediasoup-worker-prebuild.yaml | 2 +- .github/workflows/mediasoup-worker.yaml | 2 +- CHANGELOG.md | 2 ++ package-lock.json | 34 ++++++++++--------- package.json | 2 +- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index c98d7e74f5..915b62ebf2 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -17,21 +17,27 @@ jobs: node: 18 - os: ubuntu-22.04 node: 20 + - os: ubuntu-22.04 + node: 22 - os: ubuntu-24.04 - node: 20 + node: 22 meson_args: '-Db_sanitize=address' - os: ubuntu-24.04 - node: 20 + node: 22 meson_args: '-Db_sanitize=undefined' - os: ubuntu-24.04 - node: 20 + node: 22 meson_args: '-Db_sanitize=thread' - os: macos-12 node: 18 - os: macos-14 node: 20 + - os: macos-14 + node: 22 - os: windows-2022 node: 20 + - os: windows-2022 + node: 22 build-type: - Release - Debug diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 762361367b..e0c458a903 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -32,7 +32,7 @@ jobs: cc: cl cxx: cl node: - - 20 + - 22 runs-on: ${{ matrix.build.os }} diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 9fb3c68b72..b9522d2215 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -42,7 +42,7 @@ jobs: cxx: cl # A single Node.js version should be fine for C++. node: - - 20 + - 22 build-type: - Release - Debug diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e87d51a3f..e937d97a5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +- CI: Support Node 22 ([PR #1434](https://github.com/versatica/mediasoup/pull/1434)). + ### 3.14.9 - Worker: Test, fix buffer overflow ([PR #1419](https://github.com/versatica/mediasoup/pull/1419)). diff --git a/package-lock.json b/package-lock.json index 7352d3c4f7..6e37d19f61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.12", + "@types/node": "^22.1.0", "@typescript-eslint/eslint-plugin": "^7.17.0", "@typescript-eslint/parser": "^7.17.0", "eslint": "^8.57.0", @@ -1803,12 +1803,13 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.14.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", - "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.13.0" } }, "node_modules/@types/stack-utils": { @@ -6044,10 +6045,11 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true, + "license": "MIT" }, "node_modules/unique-string": { "version": "3.0.0", @@ -7644,12 +7646,12 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.14.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", - "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", "dev": true, "requires": { - "undici-types": "~5.26.4" + "undici-types": "~6.13.0" } }, "@types/stack-utils": { @@ -10573,9 +10575,9 @@ "dev": true }, "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", "dev": true }, "unique-string": { diff --git a/package.json b/package.json index 4010187354..35437050aa 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.14.12", + "@types/node": "^22.1.0", "@typescript-eslint/eslint-plugin": "^7.17.0", "@typescript-eslint/parser": "^7.17.0", "eslint": "^8.57.0", From e5ed2c3bbc0bd0bd4fe6d012babe63ba9807d6d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 5 Aug 2024 15:46:40 +0200 Subject: [PATCH 481/525] Update to ESLint 9 (#1436) --- .eslintrc.js | 2 +- CHANGELOG.md | 3 +- eslint.config.mjs | 185 +++++ node/src/Channel.ts | 9 +- node/src/Consumer.ts | 17 +- node/src/DataConsumer.ts | 2 +- node/src/DataProducer.ts | 2 +- node/src/DirectTransport.ts | 8 +- node/src/PipeTransport.ts | 2 +- node/src/Producer.ts | 6 +- node/src/Router.ts | 140 ++-- node/src/RtpObserver.ts | 2 +- node/src/RtpParameters.ts | 17 +- node/src/Transport.ts | 39 +- node/src/WebRtcServer.ts | 4 +- node/src/WebRtcTransport.ts | 2 +- node/src/Worker.ts | 18 +- node/src/enhancedEvents.ts | 2 + node/src/index.ts | 5 +- node/src/scalabilityModes.ts | 2 +- node/src/test/test-ActiveSpeakerObserver.ts | 4 +- node/src/test/test-AudioLevelObserver.ts | 6 +- node/src/test/test-Consumer.ts | 38 +- node/src/test/test-DataConsumer.ts | 10 +- node/src/test/test-DataProducer.ts | 12 +- node/src/test/test-DirectTransport.ts | 6 +- node/src/test/test-PipeTransport.ts | 24 +- node/src/test/test-PlainTransport.ts | 22 +- node/src/test/test-Producer.ts | 29 +- node/src/test/test-Router.ts | 4 +- node/src/test/test-WebRtcServer.ts | 6 +- node/src/test/test-WebRtcTransport.ts | 30 +- node/src/test/test-Worker.ts | 6 +- node/src/test/test-mediasoup.ts | 2 +- node/src/test/test-multiopus.ts | 2 +- node/src/test/test-node-sctp.ts | 24 +- node/src/utils.ts | 4 +- npm-scripts.mjs | 19 +- package-lock.json | 729 +++++++++++--------- package.json | 9 +- node/tsconfig.json => tsconfig.json | 6 +- worker/scripts/clang-format.mjs | 2 +- 42 files changed, 855 insertions(+), 606 deletions(-) create mode 100644 eslint.config.mjs rename node/tsconfig.json => tsconfig.json (83%) diff --git a/.eslintrc.js b/.eslintrc.js index e69646071b..ed761bb558 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -88,7 +88,7 @@ const eslintConfig = { 'no-undef': 2, 'no-unmodified-loop-condition': 2, 'no-unreachable': 2, - 'no-unused-vars': [1, { vars: 'all', args: 'after-used' }], + 'no-unused-vars': [2, { vars: 'all', args: 'after-used' }], 'no-use-before-define': 0, 'no-useless-call': 2, 'no-useless-computed-key': 2, diff --git a/CHANGELOG.md b/CHANGELOG.md index e937d97a5f..a77548bb59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT - CI: Support Node 22 ([PR #1434](https://github.com/versatica/mediasoup/pull/1434)). +- Update ESLint to version 9 ([PR #1435](https://github.com/versatica/mediasoup/pull/1435)). ### 3.14.9 @@ -864,7 +865,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.6.6 - Update `usrsctp` library. -- Update ESlint and TypeScript related dependencies. +- Update ESLint and TypeScript related dependencies. ### 3.6.5 diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..c49dcb532f --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,185 @@ +import eslint from '@eslint/js'; +import tsEslint from 'typescript-eslint'; +import jestEslint from 'eslint-plugin-jest'; +import prettierRecommendedEslint from 'eslint-plugin-prettier/recommended'; +import globals from 'globals'; + +const config = tsEslint.config( + { + languageOptions: { + sourceType: 'module', + globals: { ...globals.node }, + }, + linterOptions: { + noInlineConfig: false, + reportUnusedDisableDirectives: 'error', + }, + }, + eslint.configs.recommended, + { + rules: { + 'constructor-super': 2, + curly: [2, 'all'], + // Unfortunatelly `curly` does not apply to blocks in `switch` cases so + // this is needed. + 'no-restricted-syntax': [ + 2, + { + selector: 'SwitchCase > *.consequent[type!="BlockStatement"]', + message: 'Switch cases without blocks are disallowed', + }, + ], + 'guard-for-in': 2, + 'newline-after-var': 2, + 'newline-before-return': 2, + 'no-alert': 2, + 'no-caller': 2, + 'no-case-declarations': 2, + 'no-catch-shadow': 2, + 'no-class-assign': 2, + 'no-console': 2, + 'no-const-assign': 2, + 'no-debugger': 2, + 'no-dupe-args': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-div-regex': 2, + 'no-empty': [2, { allowEmptyCatch: true }], + 'no-empty-pattern': 2, + 'no-eval': 2, + 'no-extend-native': 2, + 'no-ex-assign': 2, + 'no-extra-bind': 2, + 'no-extra-boolean-cast': 2, + 'no-extra-label': 2, + 'no-fallthrough': 2, + 'no-func-assign': 2, + 'no-global-assign': 2, + 'no-implicit-coercion': 2, + 'no-implicit-globals': 2, + 'no-inner-declarations': 2, + 'no-invalid-regexp': 2, + 'no-invalid-this': 2, + 'no-irregular-whitespace': 2, + 'no-lonely-if': 2, + 'no-multi-str': 2, + 'no-native-reassign': 2, + 'no-negated-in-lhs': 2, + 'no-new': 2, + 'no-new-func': 2, + 'no-new-wrappers': 2, + 'no-obj-calls': 2, + 'no-proto': 2, + 'no-prototype-builtins': 0, + 'no-redeclare': 2, + 'no-regex-spaces': 2, + 'no-restricted-imports': 2, + 'no-return-assign': 2, + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow': 2, + 'no-shadow-restricted-names': 2, + 'no-sparse-arrays': 2, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-undef': 2, + 'no-unmodified-loop-condition': 2, + 'no-unreachable': 2, + 'no-unused-vars': [ + 2, + { vars: 'all', args: 'after-used', caughtErrors: 'none' }, + ], + 'no-use-before-define': 0, + 'no-useless-call': 2, + 'no-useless-computed-key': 2, + 'no-useless-concat': 2, + 'no-useless-rename': 2, + 'no-var': 2, + 'object-curly-newline': 0, + 'prefer-const': 2, + 'prefer-rest-params': 2, + 'prefer-spread': 2, + 'prefer-template': 2, + 'spaced-comment': [2, 'always'], + strict: 2, + 'valid-typeof': 2, + yoda: 2, + }, + }, + // NOTE: We need to apply this only to .ts files (and not to .mjs files). + ...tsEslint.configs.recommendedTypeChecked.map(item => ({ + ...item, + files: ['node/src/**/*.ts'], + })), + // NOTE: We need to apply this only to .ts files (and not to .mjs files). + ...tsEslint.configs.stylisticTypeChecked.map(item => ({ + ...item, + files: ['node/src/**/*.ts'], + })), + { + name: 'mediasoup .ts files', + files: ['node/src/**/*.ts'], + languageOptions: { + parserOptions: { + projectService: true, + project: 'tsconfig.json', + }, + }, + rules: { + '@typescript-eslint/consistent-generic-constructors': [ + 2, + 'type-annotation', + ], + '@typescript-eslint/dot-notation': 0, + '@typescript-eslint/no-unused-vars': [ + 2, + { + vars: 'all', + args: 'after-used', + caughtErrors: 'none', + ignoreRestSiblings: false, + }, + ], + // We want to use `type` instead of `interface`. + '@typescript-eslint/consistent-type-definitions': 0, + // Sorry, we need many `any` usage. + '@typescript-eslint/no-explicit-any': 0, + '@typescript-eslint/no-unsafe-member-access': 0, + '@typescript-eslint/no-unsafe-assignment': 0, + '@typescript-eslint/no-unsafe-call': 0, + '@typescript-eslint/no-unsafe-return': 0, + '@typescript-eslint/no-unsafe-argument': 0, + '@typescript-eslint/consistent-indexed-object-style': 0, + '@typescript-eslint/no-empty-function': 0, + '@typescript-eslint/restrict-template-expressions': 0, + '@typescript-eslint/no-duplicate-type-constituents': [ + 2, + { ignoreUnions: true }, + ], + }, + }, + { + name: 'mediasoup .ts test files', + ...jestEslint.configs['flat/recommended'], + files: ['node/src/test/**/*.ts'], + rules: { + ...jestEslint.configs['flat/recommended'].rules, + 'jest/no-disabled-tests': 2, + 'jest/prefer-expect-assertions': 0, + '@typescript-eslint/no-unnecessary-type-assertion': 0, + }, + }, + prettierRecommendedEslint +); + +// console.log('*** config:***\n', config); + +// console.log( +// '---tsEslint.configs.strictTypeChecked: %o', +// tsEslint.configs.strictTypeChecked +// ); + +// process.exit(1); + +export default config; diff --git a/node/src/Channel.ts b/node/src/Channel.ts index a2fa6b3a6c..97ec868bdb 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -94,7 +94,6 @@ export class Channel extends EnhancedEventEmitter { let msgStart = 0; - // eslint-disable-next-line no-constant-condition while (true) { const readLen = this.#recvBuffer.length - msgStart; @@ -320,7 +319,11 @@ export class Channel extends EnhancedEventEmitter { ); } - this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1); + if (this.#nextId < 4294967295) { + ++this.#nextId; + } else { + this.#nextId = 1; + } const id = this.#nextId; @@ -408,7 +411,7 @@ export class Channel extends EnhancedEventEmitter { if (!sent) { logger.error( - `received response does not match any sent request [id:${response.id}]` + `received response does not match any sent request [id:${response.id()}]` ); return; diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 8de9fc4cff..cb6314eea2 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -356,7 +356,7 @@ export class Consumer< this.#producerPaused = producerPaused; this.#score = score; this.#preferredLayers = preferredLayers; - this.#appData = appData || ({} as ConsumerAppData); + this.#appData = appData ?? ({} as ConsumerAppData); this.handleWorkerNotifications(); } @@ -556,7 +556,7 @@ export class Consumer< /** * Get Consumer stats. */ - async getStats(): Promise> { + async getStats(): Promise<(ConsumerStat | ProducerStat)[]> { logger.debug('getStats()'); const response = await this.#channel.request( @@ -642,7 +642,7 @@ export class Consumer< FbsConsumer.ConsumerLayers.createConsumerLayers( builder, spatialLayer, - temporalLayer !== undefined ? temporalLayer : null + temporalLayer ?? null ); const requestOffset = FbsConsumer.SetPreferredLayersRequest.createSetPreferredLayersRequest( @@ -669,10 +669,7 @@ export class Consumer< if (status.preferredLayers) { preferredLayers = { spatialLayer: status.preferredLayers.spatialLayer, - temporalLayer: - status.preferredLayers.temporalLayer !== null - ? status.preferredLayers.temporalLayer - : undefined, + temporalLayer: status.preferredLayers.temporalLayer ?? undefined, }; } } @@ -835,7 +832,7 @@ export class Consumer< data!.body(notification); - const score: ConsumerScore = notification!.score()!.unpack(); + const score: ConsumerScore = notification.score()!.unpack(); this.#score = score; @@ -848,7 +845,7 @@ export class Consumer< } case Event.CONSUMER_LAYERS_CHANGE: { - const notification = new FbsConsumer.LayersChangeNotification()!; + const notification = new FbsConsumer.LayersChangeNotification(); data!.body(notification); @@ -1194,6 +1191,6 @@ function parseConsumerDumpResponse( function parseConsumerStats( binary: FbsConsumer.GetStatsResponse -): Array { +): (ConsumerStat | ProducerStat)[] { return utils.parseVector(binary, 'stats', parseRtpStreamStats); } diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 8a987f143d..19e66b5267 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -184,7 +184,7 @@ export class DataConsumer< this.#paused = paused; this.#dataProducerPaused = dataProducerPaused; this.#subchannels = subchannels; - this.#appData = appData || ({} as DataConsumerAppData); + this.#appData = appData ?? ({} as DataConsumerAppData); this.handleWorkerNotifications(); } diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 5a6ced5aa0..e4ac42884e 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -143,7 +143,7 @@ export class DataProducer< this.#data = data; this.#channel = channel; this.#paused = paused; - this.#appData = appData || ({} as DataProducerAppData); + this.#appData = appData ?? ({} as DataProducerAppData); this.handleWorkerNotifications(); } diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 3417e0bb46..ea5f2b8684 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -71,6 +71,7 @@ export class DirectTransport< DirectTransportObserver > { // DirectTransport data. + // eslint-disable-next-line no-unused-private-class-members readonly #data: DirectTransportData; /** @@ -178,6 +179,7 @@ export class DirectTransport< * * @override */ + // eslint-disable-next-line @typescript-eslint/require-await async connect(): Promise { logger.debug('connect()'); } @@ -185,7 +187,7 @@ export class DirectTransport< /** * @override */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async setMaxIncomingBitrate(bitrate: number): Promise { throw new UnsupportedError( 'setMaxIncomingBitrate() not implemented in DirectTransport' @@ -195,7 +197,7 @@ export class DirectTransport< /** * @override */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async setMaxOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( 'setMaxOutgoingBitrate() not implemented in DirectTransport' @@ -205,7 +207,7 @@ export class DirectTransport< /** * @override */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async setMinOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( 'setMinOutgoingBitrate() not implemented in DirectTransport' diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index 6fea0d56ad..61a30bbf07 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -390,7 +390,7 @@ export class PipeTransport< type: 'pipe' as ConsumerType, }; - const consumer = new Consumer({ + const consumer: Consumer = new Consumer({ internal: { ...this.internal, consumerId, diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 317091e0d8..4ab4b64620 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -227,7 +227,7 @@ export class Producer< this.#data = data; this.#channel = channel; this.#paused = paused; - this.#appData = appData || ({} as ProducerAppData); + this.#appData = appData ?? ({} as ProducerAppData); this.handleWorkerNotifications(); } @@ -627,6 +627,10 @@ export function producerTypeToFbs(type: ProducerType): FbsRtpParameters.Type { case 'svc': { return FbsRtpParameters.Type.SVC; } + + default: { + throw new TypeError(`invalid ProducerType: ${type}`); + } } } diff --git a/node/src/Router.ts b/node/src/Router.ts index fb05298187..70fc9ffb27 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -278,7 +278,7 @@ export class Router< this.#internal = internal; this.#data = data; this.#channel = channel; - this.#appData = appData || ({} as RouterAppData); + this.#appData = appData ?? ({} as RouterAppData); } /** @@ -627,21 +627,23 @@ export class Router< const webRtcTransportData = parseWebRtcTransportDumpResponse(data); - const transport = new WebRtcTransport({ - internal: { - ...this.#internal, - transportId: transportId, - }, - data: webRtcTransportData, - channel: this.#channel, - appData, - getRouterRtpCapabilities: (): RtpCapabilities => - this.#data.rtpCapabilities, - getProducerById: (producerId: string): Producer | undefined => - this.#producers.get(producerId), - getDataProducerById: (dataProducerId: string): DataProducer | undefined => - this.#dataProducers.get(dataProducerId), - }); + const transport: WebRtcTransport = + new WebRtcTransport({ + internal: { + ...this.#internal, + transportId: transportId, + }, + data: webRtcTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: ( + dataProducerId: string + ): DataProducer | undefined => this.#dataProducers.get(dataProducerId), + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); @@ -797,21 +799,24 @@ export class Router< const plainTransportData = parsePlainTransportDumpResponse(data); - const transport = new PlainTransport({ - internal: { - ...this.#internal, - transportId: transportId, - }, - data: plainTransportData, - channel: this.#channel, - appData, - getRouterRtpCapabilities: (): RtpCapabilities => - this.#data.rtpCapabilities, - getProducerById: (producerId: string): Producer | undefined => - this.#producers.get(producerId), - getDataProducerById: (dataProducerId: string): DataProducer | undefined => - this.#dataProducers.get(dataProducerId), - }); + const transport: PlainTransport = new PlainTransport( + { + internal: { + ...this.#internal, + transportId: transportId, + }, + data: plainTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: ( + dataProducerId: string + ): DataProducer | undefined => this.#dataProducers.get(dataProducerId), + } + ); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); @@ -935,7 +940,7 @@ export class Router< const plainTransportData = parsePipeTransportDumpResponse(data); - const transport = new PipeTransport({ + const transport: PipeTransport = new PipeTransport({ internal: { ...this.#internal, transportId, @@ -1030,21 +1035,23 @@ export class Router< const directTransportData = parseDirectTransportDumpResponse(data); - const transport = new DirectTransport({ - internal: { - ...this.#internal, - transportId: transportId, - }, - data: directTransportData, - channel: this.#channel, - appData, - getRouterRtpCapabilities: (): RtpCapabilities => - this.#data.rtpCapabilities, - getProducerById: (producerId: string): Producer | undefined => - this.#producers.get(producerId), - getDataProducerById: (dataProducerId: string): DataProducer | undefined => - this.#dataProducers.get(dataProducerId), - }); + const transport: DirectTransport = + new DirectTransport({ + internal: { + ...this.#internal, + transportId: transportId, + }, + data: directTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: ( + dataProducerId: string + ): DataProducer | undefined => this.#dataProducers.get(dataProducerId), + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); @@ -1217,7 +1224,7 @@ export class Router< remotePipeTransport.close(); } - reject(error); + reject(error instanceof Error ? error : new Error(String(error))); }); }); @@ -1242,9 +1249,9 @@ export class Router< pipeProducer = await remotePipeTransport!.produce({ id: producer.id, - kind: pipeConsumer!.kind, - rtpParameters: pipeConsumer!.rtpParameters, - paused: pipeConsumer!.producerPaused, + kind: pipeConsumer.kind, + rtpParameters: pipeConsumer.rtpParameters, + paused: pipeConsumer.producerPaused, appData: producer.appData, }); @@ -1264,9 +1271,9 @@ export class Router< } // Pipe events from the pipe Consumer to the pipe Producer. - pipeConsumer!.observer.on('close', () => pipeProducer!.close()); - pipeConsumer!.observer.on('pause', () => pipeProducer!.pause()); - pipeConsumer!.observer.on('resume', () => pipeProducer!.resume()); + pipeConsumer.observer.on('close', () => pipeProducer!.close()); + pipeConsumer.observer.on('pause', () => void pipeProducer!.pause()); + pipeConsumer.observer.on('resume', () => void pipeProducer!.resume()); // Pipe events from the pipe Producer to the pipe Consumer. pipeProducer.observer.on('close', () => pipeConsumer!.close()); @@ -1299,9 +1306,9 @@ export class Router< pipeDataProducer = await remotePipeTransport!.produceData({ id: dataProducer.id, - sctpStreamParameters: pipeDataConsumer!.sctpStreamParameters, - label: pipeDataConsumer!.label, - protocol: pipeDataConsumer!.protocol, + sctpStreamParameters: pipeDataConsumer.sctpStreamParameters, + label: pipeDataConsumer.label, + protocol: pipeDataConsumer.protocol, appData: dataProducer.appData, }); @@ -1311,7 +1318,7 @@ export class Router< } // Pipe events from the pipe DataConsumer to the pipe DataProducer. - pipeDataConsumer!.observer.on('close', () => pipeDataProducer!.close()); + pipeDataConsumer.observer.on('close', () => pipeDataProducer!.close()); // Pipe events from the pipe DataProducer to the pipe DataConsumer. pipeDataProducer.observer.on('close', () => pipeDataConsumer!.close()); @@ -1323,13 +1330,8 @@ export class Router< error ); - if (pipeDataConsumer) { - pipeDataConsumer.close(); - } - - if (pipeDataProducer) { - pipeDataProducer.close(); - } + pipeDataConsumer?.close(); + pipeDataProducer?.close(); throw error; } @@ -1412,8 +1414,8 @@ export class Router< this.#internal.routerId ); - const activeSpeakerObserver = - new ActiveSpeakerObserver({ + const activeSpeakerObserver: ActiveSpeakerObserver = + new ActiveSpeakerObserver({ internal: { ...this.#internal, rtpObserverId: rtpObserverId, @@ -1488,8 +1490,8 @@ export class Router< this.#internal.routerId ); - const audioLevelObserver = - new AudioLevelObserver({ + const audioLevelObserver: AudioLevelObserver = + new AudioLevelObserver({ internal: { ...this.#internal, rtpObserverId: rtpObserverId, diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 9bc808e5ce..a64abc3747 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -93,7 +93,7 @@ export abstract class RtpObserver< this.internal = internal; this.channel = channel; - this.#appData = appData || ({} as RtpObserverAppData); + this.#appData = appData ?? ({} as RtpObserverAppData); this.getProducerById = getProducerById; this.#observer = observer; } diff --git a/node/src/RtpParameters.ts b/node/src/RtpParameters.ts index 08d02cf3e6..4c1e7631dc 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/RtpParameters.ts @@ -640,8 +640,7 @@ export function parseParameters(data: any): any { const value = new FbsBoolean(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.value(); + parameters[String(fbsParameter.name())] = value.value(); break; } @@ -650,8 +649,7 @@ export function parseParameters(data: any): any { const value = new FbsInteger32(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.value(); + parameters[String(fbsParameter.name())] = value.value(); break; } @@ -660,8 +658,7 @@ export function parseParameters(data: any): any { const value = new FbsDouble(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.value(); + parameters[String(fbsParameter.name())] = value.value(); break; } @@ -670,8 +667,7 @@ export function parseParameters(data: any): any { const value = new FbsString(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.value(); + parameters[String(fbsParameter.name())] = value.value(); break; } @@ -680,8 +676,7 @@ export function parseParameters(data: any): any { const value = new FbsInteger32Array(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.valueArray(); + parameters[String(fbsParameter.name())] = value.valueArray(); break; } @@ -843,7 +838,7 @@ export function parseRtpEncodingParameters( rid: data.rid() ?? undefined, codecPayloadType: data.codecPayloadType() !== null ? data.codecPayloadType()! : undefined, - rtx: data.rtx() ? { ssrc: data.rtx()!.ssrc()! } : undefined, + rtx: data.rtx() ? { ssrc: data.rtx()!.ssrc() } : undefined, dtx: data.dtx(), scalabilityMode: data.scalabilityMode() ?? undefined, maxBitrate: data.maxBitrate() !== null ? data.maxBitrate()! : undefined, diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 2b6bced94d..8559b5961e 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -402,7 +402,7 @@ export abstract class Transport< this.internal = internal; this.#data = data; this.channel = channel; - this.#appData = appData || ({} as TransportAppData); + this.#appData = appData ?? ({} as TransportAppData); this.#getRouterRtpCapabilities = getRouterRtpCapabilities; this.getProducerById = getProducerById; this.getDataProducerById = getDataProducerById; @@ -635,6 +635,7 @@ export abstract class Transport< * * @abstract */ + // eslint-disable-next-line @typescript-eslint/require-await async dump(): Promise { // Should not happen. throw new Error('method implemented in the subclass'); @@ -645,6 +646,7 @@ export abstract class Transport< * * @abstract */ + // eslint-disable-next-line @typescript-eslint/require-await async getStats(): Promise { // Should not happen. throw new Error('method implemented in the subclass'); @@ -655,7 +657,7 @@ export abstract class Transport< * * @abstract */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async connect(params: any): Promise { // Should not happen. throw new Error('method implemented in the subclass'); @@ -761,11 +763,7 @@ export abstract class Transport< if (this.constructor.name !== 'PipeTransport') { // If CNAME is given and we don't have yet a CNAME for Producers in this // Transport, take it. - if ( - !this.#cnameForProducers && - clonedRtpParameters.rtcp && - clonedRtpParameters.rtcp.cname - ) { + if (!this.#cnameForProducers && clonedRtpParameters.rtcp?.cname) { this.#cnameForProducers = clonedRtpParameters.rtcp.cname; } // Otherwise if we don't have yet a CNAME for Producers and the RTP @@ -795,7 +793,7 @@ export abstract class Transport< rtpMapping ); - const producerId = id || utils.generateUUIDv4(); + const producerId = id ?? utils.generateUUIDv4(); const requestOffset = createProduceRequest({ builder: this.channel.bufferBuilder, producerId, @@ -827,7 +825,7 @@ export abstract class Transport< consumableRtpParameters, }; - const producer = new Producer({ + const producer: Producer = new Producer({ internal: { ...this.internal, producerId, @@ -954,7 +952,7 @@ export abstract class Transport< type: pipe ? 'pipe' : (producer.type as ConsumerType), }; - const consumer = new Consumer({ + const consumer: Consumer = new Consumer({ internal: { ...this.internal, consumerId, @@ -968,10 +966,7 @@ export abstract class Transport< preferredLayers: status.preferredLayers ? { spatialLayer: status.preferredLayers.spatialLayer, - temporalLayer: - status.preferredLayers.temporalLayer !== null - ? status.preferredLayers.temporalLayer - : undefined, + temporalLayer: status.preferredLayers.temporalLayer ?? undefined, } : undefined, }); @@ -1034,7 +1029,7 @@ export abstract class Transport< } } - const dataProducerId = id || utils.generateUUIDv4(); + const dataProducerId = id ?? utils.generateUUIDv4(); const requestOffset = createProduceDataRequest({ builder: this.channel.bufferBuilder, dataProducerId, @@ -1059,7 +1054,7 @@ export abstract class Transport< const dump = parseDataProducerDumpResponse(produceDataResponse); - const dataProducer = new DataProducer({ + const dataProducer: DataProducer = new DataProducer({ internal: { ...this.internal, dataProducerId, @@ -1194,7 +1189,7 @@ export abstract class Transport< const dump = parseDataConsumerDumpResponse(consumeDataResponse); - const dataConsumer = new DataConsumer({ + const dataConsumer: DataConsumer = new DataConsumer({ internal: { ...this.internal, dataConsumerId, @@ -1339,10 +1334,6 @@ export function parseSctpState(fbsSctpState: FbsSctpState): SctpState { case FbsSctpState.CLOSED: { return 'closed'; } - - default: { - throw new TypeError(`invalid SctpState: ${fbsSctpState}`); - } } } @@ -1530,7 +1521,7 @@ export function parseTransportTraceEventData( timestamp: Number(trace.timestamp()), direction: trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', - info: parseBweTraceInfo(info!), + info: parseBweTraceInfo(info), }; } @@ -1573,10 +1564,6 @@ function transportTraceEventTypeToFbs( case 'bwe': { return FbsTransport.TraceEventType.BWE; } - - default: { - throw new TypeError(`invalid TransportTraceEventType: ${eventType}`); - } } } diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 29082d80c8..385a49e638 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -113,7 +113,7 @@ export class WebRtcServer< this.#internal = internal; this.#channel = channel; - this.#appData = appData || ({} as WebRtcServerAppData); + this.#appData = appData ?? ({} as WebRtcServerAppData); } /** @@ -280,7 +280,7 @@ function parseIceUserNameFragment( function parseTupleHash(binary: FbsWebRtcServer.TupleHash): TupleHash { return { - tupleHash: Number(binary.tupleHash()!), + tupleHash: Number(binary.tupleHash()), webRtcTransportId: binary.webRtcTransportId()!, }; } diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 11977b6cfd..34ca5014a3 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -925,7 +925,7 @@ function parseDtlsParameters( return { fingerprints: fingerprints, - role: binary.role() === null ? undefined : dtlsRoleFromFbs(binary.role()!), + role: binary.role() === null ? undefined : dtlsRoleFromFbs(binary.role()), }; } diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 151211fa61..e86206d98b 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -101,8 +101,6 @@ export type WorkerUpdateableSettings = Pick< * - https://linux.die.net/man/2/getrusage */ export type WorkerResourceUsage = { - /* eslint-disable camelcase */ - /** * User CPU time used (in ms). */ @@ -182,8 +180,6 @@ export type WorkerResourceUsage = { * Involuntary context switches. */ ru_nivcsw: number; - - /* eslint-enable camelcase */ }; export type WorkerDump = { @@ -301,7 +297,7 @@ export class Worker< let spawnArgs: string[] = []; if (process.env.MEDIASOUP_USE_VALGRIND === 'true') { - spawnBin = process.env.MEDIASOUP_VALGRIND_BIN || 'valgrind'; + spawnBin = process.env.MEDIASOUP_VALGRIND_BIN ?? 'valgrind'; if (process.env.MEDIASOUP_VALGRIND_OPTIONS) { spawnArgs = spawnArgs.concat( @@ -383,7 +379,7 @@ export class Worker< pid: this.#pid, }); - this.#appData = appData || ({} as WorkerAppData); + this.#appData = appData ?? ({} as WorkerAppData); let spawnDone = false; @@ -636,7 +632,6 @@ export class Worker< const ru = resourceUsage.unpack(); - /* eslint-disable camelcase */ return { ru_utime: Number(ru.ruUtime), ru_stime: Number(ru.ruStime), @@ -655,7 +650,6 @@ export class Worker< ru_nvcsw: Number(ru.ruNvcsw), ru_nivcsw: Number(ru.ruNivcsw), }; - /* eslint-enable camelcase */ } /** @@ -729,7 +723,7 @@ export class Worker< createWebRtcServerRequestOffset ); - const webRtcServer = new WebRtcServer({ + const webRtcServer: WebRtcServer = new WebRtcServer({ internal: { webRtcServerId }, channel: this.#channel, appData, @@ -780,7 +774,7 @@ export class Worker< ); const data = { rtpCapabilities }; - const router = new Router({ + const router: Router = new Router({ internal: { routerId, }, @@ -803,7 +797,7 @@ export class Worker< return; } - logger.debug(`died() [error:${error}]`); + logger.debug(`died() [error:${error.toString()}]`); this.#closed = true; this.#died = true; @@ -834,7 +828,7 @@ export function parseWorkerDumpResponse( binary: FbsWorker.DumpResponse ): WorkerDump { const dump: WorkerDump = { - pid: binary.pid()!, + pid: binary.pid(), webRtcServerIds: utils.parseVector(binary, 'webRtcServerIds'), routerIds: utils.parseVector(binary, 'routerIds'), channelMessageHandlers: { diff --git a/node/src/enhancedEvents.ts b/node/src/enhancedEvents.ts index a5458d3a08..e2ef6a34fb 100644 --- a/node/src/enhancedEvents.ts +++ b/node/src/enhancedEvents.ts @@ -113,10 +113,12 @@ export class EnhancedEventEmitter< return super.listenerCount(eventName); } + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type listeners(eventName: K): Function[] { return super.listeners(eventName); } + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type rawListeners(eventName: K): Function[] { return super.rawListeners(eventName); } diff --git a/node/src/index.ts b/node/src/index.ts index 38410c419a..eeff81c0fa 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -4,6 +4,7 @@ import { workerBin, Worker, WorkerSettings } from './Worker'; import * as utils from './utils'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; import { RtpCapabilities } from './RtpParameters'; + import * as types from './types'; /** @@ -14,7 +15,7 @@ export { types }; /** * Expose mediasoup version. */ -// eslint-disable-next-line @typescript-eslint/no-var-requires +// eslint-disable-next-line @typescript-eslint/no-require-imports export const version: string = require('../../package.json').version; /** @@ -63,7 +64,7 @@ export async function createWorker< throw new TypeError('if given, appData must be an object'); } - const worker = new Worker({ + const worker: Worker = new Worker({ logLevel, logTags, rtcMinPort, diff --git a/node/src/scalabilityModes.ts b/node/src/scalabilityModes.ts index 2804e29b2e..291255092a 100644 --- a/node/src/scalabilityModes.ts +++ b/node/src/scalabilityModes.ts @@ -9,7 +9,7 @@ export type ScalabilityMode = { }; export function parse(scalabilityMode?: string): ScalabilityMode { - const match = ScalabilityModeRegex.exec(scalabilityMode || ''); + const match = ScalabilityModeRegex.exec(scalabilityMode ?? ''); if (match) { return { diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index f957a727c2..aaa922390d 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -59,14 +59,14 @@ test('router.createActiveSpeakerObserver() succeeds', async () => { test('router.createActiveSpeakerObserver() with wrong arguments rejects with TypeError', async () => { await expect( ctx.router!.createActiveSpeakerObserver( - // @ts-ignore + // @ts-expect-error --- Testing purposes. { interval: false } ) ).rejects.toThrow(TypeError); await expect( ctx.router!.createActiveSpeakerObserver( - // @ts-ignore + // @ts-expect-error --- Testing purposes. { appData: 'NOT-AN-OBJECT' } ) ).rejects.toThrow(TypeError); diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index f6d6f61723..f1a1a5fb17 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -66,17 +66,17 @@ test('router.createAudioLevelObserver() with wrong arguments rejects with TypeEr ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createAudioLevelObserver({ threshold: 'foo' }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createAudioLevelObserver({ interval: false }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createAudioLevelObserver({ appData: 'NOT-AN-OBJECT' }) ).rejects.toThrow(TypeError); }, 2000); diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index 436145fbc2..aad102f089 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -195,13 +195,13 @@ const ctx: TestContext = { }, { kind: 'audio', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', preferredId: 4, preferredEncrypt: false, }, { kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', preferredId: 4, preferredEncrypt: false, }, @@ -454,7 +454,7 @@ test('transport.consume() succeeds', async () => { }); expect(videoPipeConsumer.preferredLayers).toBeUndefined(); expect(videoPipeConsumer.currentLayers).toBeUndefined(); - expect(videoPipeConsumer.appData).toBeUndefined; + expect(videoPipeConsumer.appData).toEqual({}); const dump2 = await ctx.router!.dump(); @@ -818,11 +818,11 @@ test('consumer.pause() and resume() succeed', async () => { // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. - audioConsumer.pause(); - audioConsumer.resume(); - audioConsumer.pause(); - audioConsumer.pause(); - audioConsumer.pause(); + void audioConsumer.pause(); + void audioConsumer.resume(); + void audioConsumer.pause(); + void audioConsumer.pause(); + void audioConsumer.pause(); await audioConsumer.resume(); expect(onObserverPause).toHaveBeenCalledTimes(3); @@ -909,22 +909,22 @@ test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError' rtpCapabilities: ctx.consumerDeviceCapabilities, }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(videoConsumer.setPreferredLayers({})).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. videoConsumer.setPreferredLayers({ foo: '123' }) ).rejects.toThrow(TypeError); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(videoConsumer.setPreferredLayers('foo')).rejects.toThrow( TypeError ); // Missing spatialLayer. await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. videoConsumer.setPreferredLayers({ temporalLayer: 2 }) ).rejects.toThrow(TypeError); }, 2000); @@ -945,12 +945,12 @@ test('consumer.setPriority() with wrong arguments rejects with TypeError', async rtpCapabilities: ctx.consumerDeviceCapabilities, }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(videoConsumer.setPriority()).rejects.toThrow(TypeError); await expect(videoConsumer.setPriority(0)).rejects.toThrow(TypeError); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(videoConsumer.setPriority('foo')).rejects.toThrow(TypeError); }, 2000); @@ -981,7 +981,7 @@ test('consumer.enableTraceEvent() succeed', async () => { expect(dump2.traceEventTypes).toEqual(expect.arrayContaining([])); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await audioConsumer.enableTraceEvent(['nack', 'FOO', 'fir']); const dump3 = await audioConsumer.dump(); @@ -1003,16 +1003,16 @@ test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', rtpCapabilities: ctx.consumerDeviceCapabilities, }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioConsumer.enableTraceEvent(123)).rejects.toThrow(TypeError); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioConsumer.enableTraceEvent('rtp')).rejects.toThrow( TypeError ); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. audioConsumer.enableTraceEvent(['fir', 123.123]) ).rejects.toThrow(TypeError); }, 2000); @@ -1144,7 +1144,7 @@ test('Consumer methods reject if closed', async () => { await expect(audioConsumer.resume()).rejects.toThrow(Error); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioConsumer.setPreferredLayers({})).rejects.toThrow(Error); await expect(audioConsumer.setPriority(2)).rejects.toThrow(Error); diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index e51a718095..f61bb8291c 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -289,11 +289,11 @@ test('dataConsumer.pause() and resume() succeed', async () => { // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. - dataConsumer.pause(); - dataConsumer.resume(); - dataConsumer.pause(); - dataConsumer.pause(); - dataConsumer.pause(); + void dataConsumer.pause(); + void dataConsumer.resume(); + void dataConsumer.pause(); + void dataConsumer.pause(); + void dataConsumer.pause(); await dataConsumer.resume(); expect(onObserverPause).toHaveBeenCalledTimes(3); diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index ad1457caea..4f490792ce 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -146,7 +146,7 @@ test('webRtcTransport1.produceData() with wrong arguments rejects with TypeError // Missing or empty sctpStreamParameters.streamId. await expect( ctx.webRtcTransport1!.produceData({ - // @ts-ignore + // @ts-expect-error --- Testing purposes. sctpStreamParameters: { foo: 'foo' }, }) ).rejects.toThrow(TypeError); @@ -271,11 +271,11 @@ test('dataProducer.pause() and resume() succeed', async () => { // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. - dataProducer1.pause(); - dataProducer1.resume(); - dataProducer1.pause(); - dataProducer1.pause(); - dataProducer1.pause(); + void dataProducer1.pause(); + void dataProducer1.resume(); + void dataProducer1.pause(); + void dataProducer1.pause(); + void dataProducer1.pause(); await dataProducer1.resume(); expect(onObserverPause).toHaveBeenCalledTimes(3); diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index 3b7689acc1..e8812257b4 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -59,7 +59,7 @@ test('router.createDirectTransport() succeeds', async () => { test('router.createDirectTransport() with wrong arguments rejects with TypeError', async () => { await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createDirectTransport({ maxMessageSize: 'foo' }) ).rejects.toThrow(TypeError); @@ -168,7 +168,7 @@ test('dataProducer.send() succeeds', async () => { dataProducer.on('listenererror', (eventName, error) => { reject( new Error( - `dataProducer 'listenererror' [eventName:${eventName}]: ${error}` + `dataProducer 'listenererror' [eventName:${eventName}]: ${error.toString()}` ) ); }); @@ -176,7 +176,7 @@ test('dataProducer.send() succeeds', async () => { dataConsumer.on('listenererror', (eventName, error) => { reject( new Error( - `dataConsumer 'listenererror' [eventName:${eventName}]: ${error}` + `dataConsumer 'listenererror' [eventName:${eventName}]: ${error.toString()}` ) ); }); diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 4f2c24363d..854636ffa4 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -477,7 +477,7 @@ test('router.pipeToRouter() succeeds with video', async () => { }, 2000); test('router.createPipeTransport() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.router1!.createPipeTransport({})).rejects.toThrow(TypeError); await expect( @@ -495,7 +495,7 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router1!.createPipeTransport({ listenIp: ['127.0.0.1'] }) ).rejects.toThrow(TypeError); @@ -508,7 +508,7 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', await expect( ctx.router1!.createPipeTransport({ listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, - // @ts-ignore + // @ts-expect-error --- Testing purposes. appData: 'NOT-AN-OBJECT', }) ).rejects.toThrow(TypeError); @@ -658,7 +658,7 @@ test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', pipeTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: 'invalid', }) ).rejects.toThrow(TypeError); @@ -688,7 +688,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { pipeTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: 1, }) ).rejects.toThrow(TypeError); @@ -698,7 +698,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { pipeTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: { keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', @@ -711,7 +711,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { pipeTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: { cryptoSuite: 'AEAD_AES_256_GCM', }, @@ -724,7 +724,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { ip: '127.0.0.2', port: 9999, srtpParameters: { - // @ts-ignore + // @ts-expect-error --- Testing purposes. cryptoSuite: 'FOO', keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', @@ -738,7 +738,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { ip: '127.0.0.2', port: 9999, srtpParameters: { - // @ts-ignore + // @ts-expect-error --- Testing purposes. cryptoSuite: 123, keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', @@ -753,7 +753,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { port: 9999, srtpParameters: { cryptoSuite: 'AEAD_AES_256_GCM', - // @ts-ignore + // @ts-expect-error --- Testing purposes. keyBase64: [], }, }) @@ -907,7 +907,7 @@ test('producer.close() is transmitted to pipe Consumer', async () => { rtpCapabilities: ctx.consumerDeviceCapabilities, }); - await ctx.videoProducer!.close(); + ctx.videoProducer!.close(); expect(ctx.videoProducer!.closed).toBe(true); @@ -1010,7 +1010,7 @@ test('dataProducer.close() is transmitted to pipe DataConsumer', async () => { dataProducerId: ctx.dataProducer!.id, }); - await ctx.dataProducer!.close(); + ctx.dataProducer!.close(); expect(ctx.dataProducer!.closed).toBe(true); diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index 31508bbddf..abd7c326b9 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -173,7 +173,7 @@ test('router.createPlainTransport() succeeds', async () => { }, 2000); test('router.createPlainTransport() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.router!.createPlainTransport({})).rejects.toThrow(TypeError); await expect( @@ -191,7 +191,7 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createPlainTransport({ listenIp: ['127.0.0.1'] }) ).rejects.toThrow(TypeError); @@ -204,7 +204,7 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' await expect( ctx.router!.createPlainTransport({ listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, - // @ts-ignore + // @ts-expect-error --- Testing purposes. appData: 'NOT-AN-OBJECT', }) ).rejects.toThrow(TypeError); @@ -237,7 +237,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { plainTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: 1, }) ).rejects.toThrow(TypeError); @@ -247,7 +247,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { plainTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: { keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, @@ -259,7 +259,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { plainTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: { cryptoSuite: 'AES_CM_128_HMAC_SHA1_80', }, @@ -272,7 +272,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { ip: '127.0.0.2', port: 9999, srtpParameters: { - // @ts-ignore + // @ts-expect-error --- Testing purposes. cryptoSuite: 'FOO', keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, @@ -285,7 +285,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { ip: '127.0.0.2', port: 9999, srtpParameters: { - // @ts-ignore + // @ts-expect-error --- Testing purposes. cryptoSuite: 123, keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, @@ -299,7 +299,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { port: 9999, srtpParameters: { cryptoSuite: 'AES_CM_128_HMAC_SHA1_80', - // @ts-ignore + // @ts-expect-error --- Testing purposes. keyBase64: [], }, }) @@ -482,7 +482,7 @@ test('plainTransport.connect() with wrong arguments rejects with TypeError', asy plainTransport.connect({ ip: '127.0.0.1', port: 1234, - // @ts-ignore + // @ts-expect-error --- Testing purposes. __rtcpPort: 1235, }) ).rejects.toThrow(TypeError); @@ -490,7 +490,7 @@ test('plainTransport.connect() with wrong arguments rejects with TypeError', asy await expect( plainTransport.connect({ ip: '127.0.0.1', - // @ts-ignore + // @ts-expect-error --- Testing purposes. __port: 'chicken', rtcpPort: 1235, }) diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index fbf2cef5c1..661c60faf1 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -271,9 +271,9 @@ test('webRtcTransport1.produce() without header extensions and rtcp succeeds', a test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', async () => { await expect( ctx.webRtcTransport1!.produce({ - // @ts-ignore + // @ts-expect-error --- Testing purposes. kind: 'chicken', - // @ts-ignore + // @ts-expect-error --- Testing purposes. rtpParameters: {}, }) ).rejects.toThrow(TypeError); @@ -281,7 +281,7 @@ test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', a await expect( ctx.webRtcTransport1!.produce({ kind: 'audio', - // @ts-ignore + // @ts-expect-error --- Testing purposes. rtpParameters: {}, }) ).rejects.toThrow(TypeError); @@ -293,7 +293,7 @@ test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', a rtpParameters: { codecs: [], headerExtensions: [], - // @ts-ignore + // @ts-expect-error --- Testing purposes. encodings: [{ ssrc: '1111' }], rtcp: { cname: 'qwerty' }, }, @@ -633,11 +633,11 @@ test('producer.pause() and resume() succeed', async () => { // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. - audioProducer.pause(); - audioProducer.resume(); - audioProducer.pause(); - audioProducer.pause(); - audioProducer.pause(); + void audioProducer.pause(); + void audioProducer.resume(); + void audioProducer.pause(); + void audioProducer.pause(); + void audioProducer.pause(); await audioProducer.resume(); expect(onObserverPause).toHaveBeenCalledTimes(3); @@ -686,7 +686,7 @@ test('producer.enableTraceEvent() succeed', async () => { expect(dump2.traceEventTypes).toEqual(expect.arrayContaining([])); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await audioProducer.enableTraceEvent(['nack', 'FOO', 'fir']); const dump3 = await audioProducer.dump(); @@ -707,16 +707,16 @@ test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', ctx.audioProducerOptions ); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioProducer.enableTraceEvent(123)).rejects.toThrow(TypeError); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioProducer.enableTraceEvent('rtp')).rejects.toThrow( TypeError ); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. audioProducer.enableTraceEvent(['fir', 123.123]) ).rejects.toThrow(TypeError); }, 2000); @@ -806,11 +806,8 @@ test('Producer methods reject if closed', async () => { audioProducer.close(); await expect(audioProducer.dump()).rejects.toThrow(Error); - await expect(audioProducer.getStats()).rejects.toThrow(Error); - await expect(audioProducer.pause()).rejects.toThrow(Error); - await expect(audioProducer.resume()).rejects.toThrow(Error); }, 2000); diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index 50602aec32..615ff4176c 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -106,13 +106,13 @@ test('worker.createRouter() succeeds', async () => { }, 2000); test('worker.createRouter() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.worker!.createRouter({ mediaCodecs: {} })).rejects.toThrow( TypeError ); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.worker!.createRouter({ appData: 'NOT-AN-OBJECT' }) ).rejects.toThrow(TypeError); }, 2000); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index 8297941723..a6c5e8bec0 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -217,16 +217,16 @@ test('worker.createWebRtcServer() without specifying port/portRange succeeds', a }, 2000); test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.worker!.createWebRtcServer({})).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.worker!.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.worker!.createWebRtcServer({ listenInfos: ['NOT-AN-OBJECT'] }) ).rejects.toThrow(Error); diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 601073d209..400f25c11e 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -279,7 +279,7 @@ test('router.createWebRtcTransport() with portRange succeeds', async () => { }, 2000); test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.router!.createWebRtcTransport({})).rejects.toThrow( TypeError ); @@ -297,24 +297,24 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createWebRtcTransport({ listenIps: [123] }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createWebRtcTransport({ listenInfos: '127.0.0.1' }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createWebRtcTransport({ listenIps: '127.0.0.1' }) ).rejects.toThrow(TypeError); await expect( ctx.router!.createWebRtcTransport({ listenIps: ['127.0.0.1'], - // @ts-ignore + // @ts-expect-error --- Testing purposes. appData: 'NOT-AN-OBJECT', }) ).rejects.toThrow(TypeError); @@ -323,7 +323,7 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError ctx.router!.createWebRtcTransport({ listenIps: ['127.0.0.1'], enableSctp: true, - // @ts-ignore + // @ts-expect-error --- Testing purposes. numSctpStreams: 'foo', }) ).rejects.toThrow(TypeError); @@ -433,13 +433,13 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as let dtlsRemoteParameters: mediasoup.types.DtlsParameters; - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(webRtcTransport.connect({})).rejects.toThrow(TypeError); dtlsRemoteParameters = { fingerprints: [ { - // @ts-ignore. + // @ts-expect-error --- Testing purposes.. algorithm: 'sha-256000', value: '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD', @@ -460,7 +460,7 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD', }, ], - // @ts-ignore + // @ts-expect-error --- Testing purposes. role: 'chicken', }; @@ -614,7 +614,7 @@ test('transport.enableTraceEvent() succeed', async () => { ], }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await webRtcTransport.enableTraceEvent(['foo', 'probation']); await expect(webRtcTransport.dump()).resolves.toMatchObject({ traceEventTypes: ['probation'], @@ -625,7 +625,7 @@ test('transport.enableTraceEvent() succeed', async () => { traceEventTypes: [], }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await webRtcTransport.enableTraceEvent(['probation', 'FOO', 'bwe', 'BAR']); await expect(webRtcTransport.dump()).resolves.toMatchObject({ traceEventTypes: ['probation', 'bwe'], @@ -644,18 +644,18 @@ test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', ], }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(webRtcTransport.enableTraceEvent(123)).rejects.toThrow( TypeError ); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(webRtcTransport.enableTraceEvent('probation')).rejects.toThrow( TypeError ); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. webRtcTransport.enableTraceEvent(['probation', 123.123]) ).rejects.toThrow(TypeError); }, 2000); @@ -816,7 +816,7 @@ test('WebRtcTransport methods reject if closed', async () => { await expect(webRtcTransport.getStats()).rejects.toThrow(Error); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(webRtcTransport.connect({})).rejects.toThrow(Error); await expect(webRtcTransport.setMaxIncomingBitrate(200000)).rejects.toThrow( diff --git a/node/src/test/test-Worker.ts b/node/src/test/test-Worker.ts index 6f1b28dedc..78fa5740a6 100644 --- a/node/src/test/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -81,7 +81,7 @@ test('createWorker() succeeds', async () => { }, 2000); test('createWorker() with wrong settings rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(mediasoup.createWorker({ logLevel: 'chicken' })).rejects.toThrow( TypeError ); @@ -104,7 +104,7 @@ test('createWorker() with wrong settings rejects with TypeError', async () => { ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. mediasoup.createWorker({ appData: 'NOT-AN-OBJECT' }) ).rejects.toThrow(TypeError); }, 2000); @@ -124,7 +124,7 @@ test('worker.updateSettings() succeeds', async () => { test('worker.updateSettings() with wrong settings rejects with TypeError', async () => { const worker = await mediasoup.createWorker(); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(worker.updateSettings({ logLevel: 'chicken' })).rejects.toThrow( TypeError ); diff --git a/node/src/test/test-mediasoup.ts b/node/src/test/test-mediasoup.ts index 455d6472eb..4fa6db110a 100644 --- a/node/src/test/test-mediasoup.ts +++ b/node/src/test/test-mediasoup.ts @@ -22,7 +22,7 @@ test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabili // Mangle retrieved codecs to check that, if called again, // getSupportedRtpCapabilities() returns a cloned object. - // @ts-ignore + // @ts-expect-error --- Testing purposes. rtpCapabilities.codecs = 'bar'; const rtpCapabilities2 = getSupportedRtpCapabilities(); diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index d6542fb391..4b8ab50450 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -84,7 +84,7 @@ const ctx: TestContext = { }, { kind: 'audio', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', preferredId: 4, preferredEncrypt: false, }, diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index 46b2f93036..7e944661ea 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -1,5 +1,5 @@ import * as dgram from 'node:dgram'; -// @ts-ignore +// @ts-expect-error -- sctp library doesn't have TS types. import * as sctp from 'sctp'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; @@ -46,14 +46,11 @@ beforeEach(async () => { const { OS, MIS } = ctx.plainTransport.sctpParameters!; await new Promise((resolve, reject) => { - // @ts-ignore - ctx.udpSocket.connect(remoteUdpPort, remoteUdpIp, (error: Error) => { - if (error) { - reject(error); - - return; - } + ctx.udpSocket?.on('error', error => { + reject(error); + }); + ctx.udpSocket?.connect(remoteUdpPort, remoteUdpIp, () => { ctx.sctpSocket = sctp.connect({ localPort: 5000, // Required for SCTP over UDP in mediasoup. port: 5000, // Required for SCTP over UDP in mediasoup. @@ -125,18 +122,18 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn await new Promise((resolve, reject) => { sendNextMessage(); - async function sendNextMessage(): Promise { + function sendNextMessage(): void { const id = ++numSentMessages; const data = Buffer.from(String(id)); // Set ppid of type WebRTC DataChannel string. if (id < numMessages / 2) { - // @ts-ignore + // @ts-expect-errors --- sctp library needs `ppid` field.` data.ppid = sctp.PPID.WEBRTC_STRING; } // Set ppid of type WebRTC DataChannel binary. else { - // @ts-ignore + // @ts-expect-errors --- sctp library needs `ppid` field. data.ppid = sctp.PPID.WEBRTC_BINARY; } @@ -151,7 +148,7 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn ctx.sctpSocket!.on('stream', onStream); // Handle the generated SCTP incoming stream and SCTP messages receives on it. - // @ts-ignore + // @ts-expect-error --- Custom event of sctp library. ctx.sctpSocket.on('stream', (stream, streamId) => { // It must be zero because it's the first SCTP incoming stream (so first // DataConsumer). @@ -161,13 +158,12 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn return; } - // @ts-ignore stream.on('data', (data: Buffer) => { ++numReceivedMessages; recvMessageBytes += data.byteLength; const id = Number(data.toString('utf8')); - // @ts-ignore + // @ts-expect-errors --- sctp library uses `ppid` field. const ppid = data.ppid; if (id !== numReceivedMessages) { diff --git a/node/src/utils.ts b/node/src/utils.ts index eef0a53663..f7c8e8c8b9 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -72,7 +72,7 @@ export function parseVector( if (parseFn) { array.push(parseFn(binary[methodName](i))); } else { - array.push(binary[methodName](i)); + array.push(binary[methodName](i) as Type); } } @@ -165,7 +165,7 @@ export function parseStringStringArrayVector( const values: string[] = []; for (let i2 = 0; i2 < kv.valuesLength(); ++i2) { - values.push(kv.values(i2)!); + values.push(kv.values(i2)! as string); } array.push({ key: kv.key(), values }); diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 2bb7081e84..1612a46229 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -26,9 +26,12 @@ const GH_OWNER = 'versatica'; const GH_REPO = 'mediasoup'; // Paths for ESLint to check. Converted to string for convenience. -const ESLINT_PATHS = ['node/src', 'npm-scripts.mjs', 'worker/scripts'].join( - ' ' -); +const ESLINT_PATHS = [ + 'eslint.config.mjs', + 'node/src', + 'npm-scripts.mjs', + 'worker/scripts', +].join(' '); // Paths for ESLint to ignore. Converted to string argument for convenience. const ESLINT_IGNORE_PATTERN_ARGS = ['node/src/fbs'] .map(entry => `--ignore-pattern ${entry}`) @@ -42,9 +45,9 @@ const PRETTIER_PATHS = [ 'README.md', 'doc', 'node/src', - 'node/tsconfig.json', 'npm-scripts.mjs', 'package.json', + 'tsconfig.json', 'worker/scripts', ].join(' '); @@ -140,7 +143,7 @@ async function run() { case 'typescript:watch': { deleteNodeLib(); - executeCmd(`tsc --project node --watch ${args}`); + executeCmd(`tsc --watch ${args}`); break; } @@ -327,7 +330,7 @@ function buildTypescript({ force = false } = { force: false }) { logInfo('buildTypescript()'); deleteNodeLib(); - executeCmd('tsc --project node'); + executeCmd('tsc'); } function buildWorker() { @@ -356,10 +359,10 @@ function lintNode() { // Ensure there are no rules that are unnecessary or conflict with Prettier // rules. - executeCmd('eslint-config-prettier .eslintrc.js'); + executeCmd('eslint-config-prettier eslint.config.mjs'); executeCmd( - `eslint -c .eslintrc.js --ext=ts,js,mjs --max-warnings 0 ${ESLINT_IGNORE_PATTERN_ARGS} ${ESLINT_PATHS}` + `eslint -c eslint.config.mjs --max-warnings 0 ${ESLINT_IGNORE_PATTERN_ARGS} ${ESLINT_PATHS}` ); executeCmd(`prettier --check ${PRETTIER_PATHS}`); diff --git a/package-lock.json b/package-lock.json index 6e37d19f61..af31120ab7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,16 +20,16 @@ "tar": "^7.4.3" }, "devDependencies": { + "@eslint/js": "^9.8.0", "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^22.1.0", - "@typescript-eslint/eslint-plugin": "^7.17.0", - "@typescript-eslint/parser": "^7.17.0", - "eslint": "^8.57.0", + "eslint": "^9.8.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.7.0", "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.9.0", "jest": "^29.7.0", "marked": "^13.0.3", "open-cli": "^8.0.0", @@ -37,7 +37,8 @@ "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.4", - "typescript": "^5.5.4" + "typescript": "^5.5.4", + "typescript-eslint": "^8.0.0" }, "engines": { "node": ">=18" @@ -738,24 +739,38 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -763,33 +778,40 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -805,11 +827,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -1749,6 +1778,26 @@ "@types/ms": "*" } }, + "node_modules/@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -1797,6 +1846,14 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -1834,31 +1891,31 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", - "integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0.tgz", + "integrity": "sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/type-utils": "7.17.0", - "@typescript-eslint/utils": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/type-utils": "8.0.0", + "@typescript-eslint/utils": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1867,26 +1924,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz", - "integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.0.tgz", + "integrity": "sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1895,16 +1952,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz", - "integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0.tgz", + "integrity": "sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0" + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1912,26 +1969,23 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz", - "integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.0.tgz", + "integrity": "sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/utils": "7.17.0", + "@typescript-eslint/typescript-estree": "8.0.0", + "@typescript-eslint/utils": "8.0.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^8.56.0" - }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -1939,12 +1993,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz", - "integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0.tgz", + "integrity": "sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1952,13 +2006,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz", - "integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0.tgz", + "integrity": "sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1967,7 +2021,7 @@ "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2004,54 +2058,48 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz", - "integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0.tgz", + "integrity": "sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0" + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz", - "integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0.tgz", + "integrity": "sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/types": "8.0.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2715,18 +2763,6 @@ "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2801,41 +2837,37 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -2849,10 +2881,10 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" } }, "node_modules/eslint-config-prettier": { @@ -2923,16 +2955,16 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2950,18 +2982,42 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -3163,15 +3219,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-type": { @@ -3250,17 +3306,16 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatbuffers": { @@ -3421,15 +3476,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5450,21 +5502,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -6019,18 +6056,6 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", @@ -6044,6 +6069,29 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.0.tgz", + "integrity": "sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.0.0", + "@typescript-eslint/parser": "8.0.0", + "@typescript-eslint/utils": "8.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/undici-types": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", @@ -6802,44 +6850,58 @@ } }, "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true }, + "@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "requires": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + } + }, "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true + } } }, "@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true }, - "@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - } + "@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true }, "@humanwhocodes/module-importer": { "version": "1.0.1", @@ -6847,10 +6909,10 @@ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true }, - "@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true }, "@isaacs/cliui": { @@ -7592,6 +7654,26 @@ "@types/ms": "*" } }, + "@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "optional": true, + "peer": true + }, "@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -7640,6 +7722,14 @@ "pretty-format": "^29.0.0" } }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "optional": true, + "peer": true + }, "@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -7676,16 +7766,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", - "integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0.tgz", + "integrity": "sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/type-utils": "7.17.0", - "@typescript-eslint/utils": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/type-utils": "8.0.0", + "@typescript-eslint/utils": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7693,54 +7783,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz", - "integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.0.tgz", + "integrity": "sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz", - "integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0.tgz", + "integrity": "sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0" + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0" } }, "@typescript-eslint/type-utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz", - "integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.0.tgz", + "integrity": "sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/utils": "7.17.0", + "@typescript-eslint/typescript-estree": "8.0.0", + "@typescript-eslint/utils": "8.0.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz", - "integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0.tgz", + "integrity": "sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz", - "integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0.tgz", + "integrity": "sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7770,37 +7860,31 @@ } }, "@typescript-eslint/utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz", - "integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0.tgz", + "integrity": "sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0" + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz", - "integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0.tgz", + "integrity": "sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/types": "8.0.0", "eslint-visitor-keys": "^3.4.3" } }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true }, "acorn-jsx": { @@ -8266,15 +8350,6 @@ "path-type": "^4.0.0" } }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -8328,41 +8403,37 @@ "dev": true }, "eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -8371,6 +8442,14 @@ "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "text-table": "^0.2.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true + } } }, "eslint-config-prettier": { @@ -8400,9 +8479,9 @@ } }, "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -8416,14 +8495,22 @@ "dev": true }, "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "requires": { - "acorn": "^8.9.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true + } } }, "esprima": { @@ -8574,12 +8661,12 @@ } }, "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "requires": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" } }, "file-type": { @@ -8642,14 +8729,13 @@ } }, "flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "requires": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" } }, "flatbuffers": { @@ -8760,13 +8846,10 @@ } }, "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "dev": true }, "globby": { "version": "11.1.0", @@ -10193,15 +10276,6 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -10562,18 +10636,23 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, "typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true }, + "typescript-eslint": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.0.tgz", + "integrity": "sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "8.0.0", + "@typescript-eslint/parser": "8.0.0", + "@typescript-eslint/utils": "8.0.0" + } + }, "undici-types": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", diff --git a/package.json b/package.json index 35437050aa..ad23116f00 100644 --- a/package.json +++ b/package.json @@ -109,16 +109,16 @@ "tar": "^7.4.3" }, "devDependencies": { + "@eslint/js": "^9.8.0", "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^22.1.0", - "@typescript-eslint/eslint-plugin": "^7.17.0", - "@typescript-eslint/parser": "^7.17.0", - "eslint": "^8.57.0", + "eslint": "^9.8.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.7.0", "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.9.0", "jest": "^29.7.0", "marked": "^13.0.3", "open-cli": "^8.0.0", @@ -126,6 +126,7 @@ "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.4", - "typescript": "^5.5.4" + "typescript": "^5.5.4", + "typescript-eslint": "^8.0.0" } } diff --git a/node/tsconfig.json b/tsconfig.json similarity index 83% rename from node/tsconfig.json rename to tsconfig.json index 87394576c7..1ea8a48622 100644 --- a/node/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,16 @@ { "compileOnSave": true, "compilerOptions": { - "lib": ["es2021"], + "lib": ["es2022"], "target": "esnext", "module": "commonjs", "moduleResolution": "node", "strict": true, - "outDir": "lib", + "outDir": "node/lib", "declaration": true, "declarationMap": true }, - "include": ["src"], + "include": ["node/src"], "watchOptions": { "watchFile": "useFsEvents", "watchDirectory": "useFsEvents", diff --git a/worker/scripts/clang-format.mjs b/worker/scripts/clang-format.mjs index c17152998a..c6665493b8 100644 --- a/worker/scripts/clang-format.mjs +++ b/worker/scripts/clang-format.mjs @@ -4,7 +4,7 @@ import clangFormat from 'clang-format'; const task = process.argv.slice(2).join(' '); -run(); +void run(); async function run() { const clangFormatNativeBinary = clangFormat.getNativeBinary(); From 28a1483b5565f4fb6771213ca5001e2ba3994951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 5 Aug 2024 19:40:20 +0200 Subject: [PATCH 482/525] remove unused .eslintrc.js --- .eslintrc.js | 178 --------------------------------------------------- 1 file changed, 178 deletions(-) delete mode 100644 .eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index ed761bb558..0000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,178 +0,0 @@ -const eslintConfig = { - env: { - es6: true, - node: true, - }, - plugins: ['prettier'], - settings: {}, - parserOptions: { - ecmaVersion: 2022, - sourceType: 'module', - ecmaFeatures: { - impliedStrict: true, - }, - lib: ['es2022'], - }, - globals: { - NodeJS: 'readonly', - }, - extends: ['eslint:recommended', 'plugin:prettier/recommended'], - rules: { - 'prettier/prettier': 2, - 'constructor-super': 2, - curly: [2, 'all'], - // Unfortunatelly `curly` does not apply to blocks in `switch` cases so - // this is needed. - 'no-restricted-syntax': [ - 2, - { - selector: 'SwitchCase > *.consequent[type!="BlockStatement"]', - message: 'Switch cases without blocks are disallowed', - }, - ], - 'guard-for-in': 2, - 'newline-after-var': 2, - 'newline-before-return': 2, - 'no-alert': 2, - 'no-caller': 2, - 'no-case-declarations': 2, - 'no-catch-shadow': 2, - 'no-class-assign': 2, - 'no-console': 2, - 'no-const-assign': 2, - 'no-debugger': 2, - 'no-dupe-args': 2, - 'no-dupe-keys': 2, - 'no-duplicate-case': 2, - 'no-div-regex': 2, - 'no-empty': [2, { allowEmptyCatch: true }], - 'no-empty-pattern': 2, - 'no-else-return': 0, - 'no-eval': 2, - 'no-extend-native': 2, - 'no-ex-assign': 2, - 'no-extra-bind': 2, - 'no-extra-boolean-cast': 2, - 'no-extra-label': 2, - 'no-fallthrough': 2, - 'no-func-assign': 2, - 'no-global-assign': 2, - 'no-implicit-coercion': 2, - 'no-implicit-globals': 2, - 'no-inner-declarations': 2, - 'no-invalid-regexp': 2, - 'no-invalid-this': 2, - 'no-irregular-whitespace': 2, - 'no-lonely-if': 2, - 'no-multi-str': 2, - 'no-native-reassign': 2, - 'no-negated-in-lhs': 2, - 'no-new': 2, - 'no-new-func': 2, - 'no-new-wrappers': 2, - 'no-obj-calls': 2, - 'no-proto': 2, - 'no-prototype-builtins': 0, - 'no-redeclare': 2, - 'no-regex-spaces': 2, - 'no-restricted-imports': 2, - 'no-return-assign': 2, - 'no-self-assign': 2, - 'no-self-compare': 2, - 'no-sequences': 2, - 'no-shadow': 2, - 'no-shadow-restricted-names': 2, - 'no-sparse-arrays': 2, - 'no-this-before-super': 2, - 'no-throw-literal': 2, - 'no-undef': 2, - 'no-unmodified-loop-condition': 2, - 'no-unreachable': 2, - 'no-unused-vars': [2, { vars: 'all', args: 'after-used' }], - 'no-use-before-define': 0, - 'no-useless-call': 2, - 'no-useless-computed-key': 2, - 'no-useless-concat': 2, - 'no-useless-rename': 2, - 'no-var': 2, - 'object-curly-newline': 0, - 'prefer-const': 2, - 'prefer-rest-params': 2, - 'prefer-spread': 2, - 'prefer-template': 2, - 'spaced-comment': [2, 'always'], - strict: 2, - 'valid-typeof': 2, - yoda: 2, - }, - overrides: [], -}; - -const tsRules = { - 'no-unused-vars': 0, - '@typescript-eslint/ban-types': 0, - '@typescript-eslint/ban-ts-comment': 0, - '@typescript-eslint/ban-ts-ignore': 0, - '@typescript-eslint/explicit-module-boundary-types': 0, - '@typescript-eslint/semi': 2, - '@typescript-eslint/member-delimiter-style': [ - 2, - { - multiline: { delimiter: 'semi', requireLast: true }, - singleline: { delimiter: 'semi', requireLast: false }, - }, - ], - '@typescript-eslint/no-explicit-any': 0, - '@typescript-eslint/no-unused-vars': [ - 2, - { - vars: 'all', - args: 'after-used', - ignoreRestSiblings: false, - }, - ], - '@typescript-eslint/no-use-before-define': [2, { functions: false }], - '@typescript-eslint/no-empty-function': 0, - '@typescript-eslint/no-non-null-assertion': 0, -}; - -eslintConfig.overrides.push({ - files: ['*.ts'], - parser: '@typescript-eslint/parser', - parserOptions: { - ...eslintConfig.parserOptions, - project: 'node/tsconfig.json', - }, - plugins: [...eslintConfig.plugins, '@typescript-eslint'], - extends: [ - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - ...eslintConfig.extends, - ], - rules: { ...eslintConfig.rules, ...tsRules }, -}); - -eslintConfig.overrides.push({ - files: ['node/src/test/*.ts'], - parserOptions: { - ...eslintConfig.parserOptions, - project: 'node/tsconfig.json', - }, - env: { - ...eslintConfig.env, - 'jest/globals': true, - }, - extends: [ - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - ...eslintConfig.extends, - ], - plugins: [...eslintConfig.plugins, '@typescript-eslint', 'jest'], - rules: { - ...eslintConfig.rules, - ...tsRules, - 'jest/no-disabled-tests': 2, - }, -}); - -module.exports = eslintConfig; From d5facb5b55222bc9eeaddd36662db6590d1fa628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 9 Aug 2024 17:45:26 +0200 Subject: [PATCH 483/525] DepLibUring improvements (#1440) --- .github/workflows/mediasoup-rust.yaml | 1 + .../workflows/mediasoup-worker-fuzzer.yaml | 9 +- .../workflows/mediasoup-worker-prebuild.yaml | 2 + .github/workflows/mediasoup-worker.yaml | 16 ++- worker/include/DepLibUring.hpp | 10 +- worker/src/DepLibUring.cpp | 98 +++++++++---------- worker/src/DepUsrSCTP.cpp | 22 +++-- worker/src/RTC/Router.cpp | 32 ++++-- worker/src/RTC/RtpStreamSend.cpp | 14 ++- worker/src/RTC/SrtpSession.cpp | 1 + worker/src/RTC/Transport.cpp | 14 ++- worker/src/Worker.cpp | 41 +++++--- worker/src/handles/TcpConnectionHandle.cpp | 12 ++- worker/src/handles/UdpSocketHandle.cpp | 12 ++- 14 files changed, 175 insertions(+), 109 deletions(-) diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index 9b76ffcb22..812cbae213 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -18,6 +18,7 @@ jobs: ci: - os: ubuntu-20.04 - os: ubuntu-22.04 + - os: ubuntu-24.04 - os: macos-12 - os: macos-14 - os: windows-2022 diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index 8f47946802..c748ce6e67 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -13,9 +13,10 @@ jobs: strategy: matrix: build: - - os: ubuntu-22.04 + - os: ubuntu-24.04 cc: clang cxx: clang++ + pip-break-system-packages: true build-type: - Release - Debug @@ -34,12 +35,12 @@ jobs: uses: actions/checkout@v4 # We need to install pip invoke manually. - - if: runner.os != 'macOS' + - if: ${{ !matrix.build.pip-break-system-packages }} name: pip3 install invoke run: pip3 install invoke - # In macOS we need to specify this option. - - if: runner.os == 'macOS' + # In modern OSs we need to run pip with this option. + - if: ${{ matrix.build.pip-break-system-packages }} name: pip3 install --break-system-packages invoke run: pip3 install --break-system-packages invoke diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index e0c458a903..5c51a72be8 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -19,6 +19,8 @@ jobs: cc: gcc cxx: g++ # Worker prebuild for Linux with kernel version 6 Ubuntu (22.04). + # Let's not use Ubutu 24.04 to avoid same potential problem as described + # above. - os: ubuntu-22.04 cc: gcc cxx: g++ diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index b9522d2215..cfa1498022 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -31,12 +31,22 @@ jobs: - os: ubuntu-22.04 cc: clang cxx: clang++ + - os: ubuntu-24.04 + cc: gcc + cxx: g++ + pip-break-system-packages: true + - os: ubuntu-24.04 + cc: clang + cxx: clang++ + pip-break-system-packages: true - os: macos-12 cc: gcc cxx: g++ + pip-break-system-packages: true - os: macos-14 cc: clang cxx: clang++ + pip-break-system-packages: true - os: windows-2022 cc: cl cxx: cl @@ -75,12 +85,12 @@ jobs: ${{ matrix.build.os }}-node-${{matrix.build.cc}}- # We need to install pip invoke manually. - - if: runner.os != 'macOS' + - if: ${{ !matrix.build.pip-break-system-packages }} name: pip3 install invoke run: pip3 install invoke - # In macOS we need to specify this option. - - if: runner.os == 'macOS' + # In modern OSs we need to run pip with this option. + - if: ${{ matrix.build.pip-break-system-packages }} name: pip3 install --break-system-packages invoke run: pip3 install --break-system-packages invoke diff --git a/worker/include/DepLibUring.hpp b/worker/include/DepLibUring.hpp index 973acaff42..a0b041c899 100644 --- a/worker/include/DepLibUring.hpp +++ b/worker/include/DepLibUring.hpp @@ -33,9 +33,10 @@ class DepLibUring using SendBuffer = uint8_t[SendBufferSize]; - static bool IsRuntimeSupported(); static void ClassInit(); static void ClassDestroy(); + static void CheckRuntimeSupport(); + static bool IsEnabled(); static flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder); static void StartPollingCQEs(); static void StopPollingCQEs(); @@ -50,9 +51,12 @@ class DepLibUring class LibUring; + // Whether liburing is enabled or not after runtime checks. + static bool enabled; thread_local static LibUring* liburing; public: + // Singleton. class LibUring { public: @@ -98,6 +102,10 @@ class DepLibUring } private: + void SetInactive() + { + this->active = false; + } UserData* GetUserData(); bool IsDataInSendBuffers(const uint8_t* data) const { diff --git a/worker/src/DepLibUring.cpp b/worker/src/DepLibUring.cpp index 95d2b6631e..c5e8aed778 100644 --- a/worker/src/DepLibUring.cpp +++ b/worker/src/DepLibUring.cpp @@ -10,7 +10,7 @@ #include /* Static variables. */ - +bool DepLibUring::enabled{ false }; /* liburing instance per thread. */ thread_local DepLibUring::LibUring* DepLibUring::liburing{ nullptr }; /* Completion queue entry array used to retrieve processes tasks. */ @@ -114,7 +114,36 @@ inline static void onFdEvent(uv_poll_t* handle, int status, int events) /* Static class methods */ -bool DepLibUring::IsRuntimeSupported() +void DepLibUring::ClassInit() +{ + const auto mayor = io_uring_major_version(); + const auto minor = io_uring_minor_version(); + + MS_DEBUG_TAG(info, "liburing version: \"%i.%i\"", mayor, minor); + + // This must be called first. + DepLibUring::CheckRuntimeSupport(); + + if (DepLibUring::IsEnabled()) + { + DepLibUring::liburing = new LibUring(); + + MS_DEBUG_TAG(info, "liburing enabled"); + } + else + { + MS_DEBUG_TAG(info, "liburing not enabled"); + } +} + +void DepLibUring::ClassDestroy() +{ + MS_TRACE(); + + delete DepLibUring::liburing; +} + +void DepLibUring::CheckRuntimeSupport() { // clang-format off struct utsname buffer{}; @@ -134,43 +163,19 @@ bool DepLibUring::IsRuntimeSupported() // liburing `sento` capabilities are supported for kernel versions greather // than or equal to 6. - return kernelMayorLong >= 6; -} - -void DepLibUring::ClassInit() -{ - const auto mayor = io_uring_major_version(); - const auto minor = io_uring_minor_version(); - - MS_DEBUG_TAG(info, "liburing version: \"%i.%i\"", mayor, minor); - - if (DepLibUring::IsRuntimeSupported()) - { - DepLibUring::liburing = new LibUring(); - - MS_DEBUG_TAG(info, "liburing supported, enabled"); - } - else - { - MS_DEBUG_TAG(info, "liburing not supported, not enabled"); - } + DepLibUring::enabled = kernelMayorLong >= 6; } -void DepLibUring::ClassDestroy() +bool DepLibUring::IsEnabled() { - MS_TRACE(); - - delete DepLibUring::liburing; + return DepLibUring::enabled; } flatbuffers::Offset DepLibUring::FillBuffer(flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); - if (!DepLibUring::liburing) - { - return 0; - } + MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); return DepLibUring::liburing->FillBuffer(builder); } @@ -179,10 +184,7 @@ void DepLibUring::StartPollingCQEs() { MS_TRACE(); - if (!DepLibUring::liburing) - { - return; - } + MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); DepLibUring::liburing->StartPollingCQEs(); } @@ -191,10 +193,7 @@ void DepLibUring::StopPollingCQEs() { MS_TRACE(); - if (!DepLibUring::liburing) - { - return; - } + MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); DepLibUring::liburing->StopPollingCQEs(); } @@ -203,7 +202,7 @@ uint8_t* DepLibUring::GetSendBuffer() { MS_TRACE(); - MS_ASSERT(DepLibUring::liburing, "DepLibUring::liburing is not set"); + MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); return DepLibUring::liburing->GetSendBuffer(); } @@ -213,7 +212,7 @@ bool DepLibUring::PrepareSend( { MS_TRACE(); - MS_ASSERT(DepLibUring::liburing, "DepLibUring::liburing is not set"); + MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); return DepLibUring::liburing->PrepareSend(sockfd, data, len, addr, cb); } @@ -223,7 +222,7 @@ bool DepLibUring::PrepareWrite( { MS_TRACE(); - MS_ASSERT(DepLibUring::liburing, "DepLibUring::liburing is not set"); + MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); return DepLibUring::liburing->PrepareWrite(sockfd, data1, len1, data2, len2, cb); } @@ -232,10 +231,7 @@ void DepLibUring::Submit() { MS_TRACE(); - if (!DepLibUring::liburing) - { - return; - } + MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); DepLibUring::liburing->Submit(); } @@ -244,10 +240,7 @@ void DepLibUring::SetActive() { MS_TRACE(); - if (!DepLibUring::liburing) - { - return; - } + MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); DepLibUring::liburing->SetActive(); } @@ -256,10 +249,7 @@ bool DepLibUring::IsActive() { MS_TRACE(); - if (!DepLibUring::liburing) - { - return false; - } + MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); return DepLibUring::liburing->IsActive(); } @@ -580,7 +570,7 @@ void DepLibUring::LibUring::Submit() MS_TRACE(); // Unset active flag. - this->active = false; + SetInactive(); auto err = io_uring_submit(std::addressof(this->ring)); diff --git a/worker/src/DepUsrSCTP.cpp b/worker/src/DepUsrSCTP.cpp index 700bac3348..a833a5aefb 100644 --- a/worker/src/DepUsrSCTP.cpp +++ b/worker/src/DepUsrSCTP.cpp @@ -251,19 +251,25 @@ void DepUsrSCTP::Checker::OnTimer(TimerHandle* /*timer*/) const int elapsedMs = this->lastCalledAtMs ? static_cast(nowMs - this->lastCalledAtMs) : 0; #ifdef MS_LIBURING_SUPPORTED - // Activate liburing usage. - // 'usrsctp_handle_timers()' will synchronously call the send/recv - // callbacks for the pending data. If there are multiple messages to be - // sent over the network then we will send those messages within a single - // system call. - DepLibUring::SetActive(); + if (DepLibUring::IsEnabled()) + { + // Activate liburing usage. + // 'usrsctp_handle_timers()' will synchronously call the send/recv + // callbacks for the pending data. If there are multiple messages to be + // sent over the network then we will send those messages within a single + // system call. + DepLibUring::SetActive(); + } #endif usrsctp_handle_timers(elapsedMs); #ifdef MS_LIBURING_SUPPORTED - // Submit all prepared submission entries. - DepLibUring::Submit(); + if (DepLibUring::IsEnabled()) + { + // Submit all prepared submission entries. + DepLibUring::Submit(); + } #endif this->lastCalledAtMs = nowMs; diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index fab0173952..b6e8ff513c 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -665,8 +665,11 @@ namespace RTC std::shared_ptr sharedPacket; #ifdef MS_LIBURING_SUPPORTED - // Activate liburing usage. - DepLibUring::SetActive(); + if (DepLibUring::IsEnabled()) + { + // Activate liburing usage. + DepLibUring::SetActive(); + } #endif for (auto* consumer : consumers) @@ -683,8 +686,11 @@ namespace RTC } #ifdef MS_LIBURING_SUPPORTED - // Submit all prepared submission entries. - DepLibUring::Submit(); + if (DepLibUring::IsEnabled()) + { + // Submit all prepared submission entries. + DepLibUring::Submit(); + } #endif } @@ -925,10 +931,13 @@ namespace RTC if (!dataConsumers.empty()) { #ifdef MS_LIBURING_SUPPORTED - // Activate liburing usage. - // The effective sending could be synchronous, thus we would send those - // messages within a single system call. - DepLibUring::SetActive(); + if (DepLibUring::IsEnabled()) + { + // Activate liburing usage. + // The effective sending could be synchronous, thus we would send those + // messages within a single system call. + DepLibUring::SetActive(); + } #endif for (auto* dataConsumer : dataConsumers) @@ -937,8 +946,11 @@ namespace RTC } #ifdef MS_LIBURING_SUPPORTED - // Submit all prepared submission entries. - DepLibUring::Submit(); + if (DepLibUring::IsEnabled()) + { + // Submit all prepared submission entries. + DepLibUring::Submit(); + } #endif } } diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index c0c6f6ce2a..d508bce83e 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -128,8 +128,11 @@ namespace RTC this->nackCount++; #ifdef MS_LIBURING_SUPPORTED - // Activate liburing usage. - DepLibUring::SetActive(); + if (DepLibUring::IsEnabled()) + { + // Activate liburing usage. + DepLibUring::SetActive(); + } #endif for (auto it = nackPacket->Begin(); it != nackPacket->End(); ++it) @@ -173,8 +176,11 @@ namespace RTC } #ifdef MS_LIBURING_SUPPORTED - // Submit all prepared submission entries. - DepLibUring::Submit(); + if (DepLibUring::IsEnabled()) + { + // Submit all prepared submission entries. + DepLibUring::Submit(); + } #endif } diff --git a/worker/src/RTC/SrtpSession.cpp b/worker/src/RTC/SrtpSession.cpp index 20755dc656..43eb597c15 100644 --- a/worker/src/RTC/SrtpSession.cpp +++ b/worker/src/RTC/SrtpSession.cpp @@ -204,6 +204,7 @@ namespace RTC uint8_t* encryptBuffer = EncryptBuffer; #ifdef MS_LIBURING_SUPPORTED + if (DepLibUring::IsEnabled()) { if (!DepLibUring::IsActive()) { diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 89f5800ea3..eb469e70fb 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -2158,8 +2158,11 @@ namespace RTC std::unique_ptr packet{ new RTC::RTCP::CompoundPacket() }; #ifdef MS_LIBURING_SUPPORTED - // Activate liburing usage. - DepLibUring::SetActive(); + if (DepLibUring::IsEnabled()) + { + // Activate liburing usage. + DepLibUring::SetActive(); + } #endif for (auto& kv : this->mapConsumers) @@ -2207,8 +2210,11 @@ namespace RTC } #ifdef MS_LIBURING_SUPPORTED - // Submit all prepared submission entries. - DepLibUring::Submit(); + if (DepLibUring::IsEnabled()) + { + // Submit all prepared submission entries. + DepLibUring::Submit(); + } #endif } diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 5a3e7f4670..2785301357 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -44,8 +44,11 @@ Worker::Worker(::Channel::ChannelSocket* channel) : channel(channel) DepUsrSCTP::CreateChecker(); #ifdef MS_LIBURING_SUPPORTED - // Start polling CQEs, which will create a uv_pool_t handle. - DepLibUring::StartPollingCQEs(); + if (DepLibUring::IsEnabled()) + { + // Start polling CQEs, which will create a uv_pool_t handle. + DepLibUring::StartPollingCQEs(); + } #endif // Tell the Node process that we are running. @@ -106,8 +109,11 @@ void Worker::Close() DepUsrSCTP::CloseChecker(); #ifdef MS_LIBURING_SUPPORTED - // Stop polling CQEs, which will close the uv_pool_t handle. - DepLibUring::StopPollingCQEs(); + if (DepLibUring::IsEnabled()) + { + // Stop polling CQEs, which will close the uv_pool_t handle. + DepLibUring::StopPollingCQEs(); + } #endif // Close the Channel. @@ -142,17 +148,26 @@ flatbuffers::Offset Worker::FillBuffer( // Add channelMessageHandlers. auto channelMessageHandlers = this->shared->channelMessageRegistrator->FillBuffer(builder); - return FBS::Worker::CreateDumpResponseDirect( - builder, - Logger::Pid, - &webRtcServerIds, - &routerIds, - channelMessageHandlers #ifdef MS_LIBURING_SUPPORTED - , - DepLibUring::FillBuffer(builder) + if (DepLibUring::IsEnabled()) + { + return FBS::Worker::CreateDumpResponseDirect( + builder, + Logger::Pid, + &webRtcServerIds, + &routerIds, + channelMessageHandlers, + DepLibUring::FillBuffer(builder)); + } + else + { + return FBS::Worker::CreateDumpResponseDirect( + builder, Logger::Pid, &webRtcServerIds, &routerIds, channelMessageHandlers); + } +#else + return FBS::Worker::CreateDumpResponseDirect( + builder, Logger::Pid, &webRtcServerIds, &routerIds, channelMessageHandlers); #endif - ); } flatbuffers::Offset Worker::FillBufferResourceUsage( diff --git a/worker/src/handles/TcpConnectionHandle.cpp b/worker/src/handles/TcpConnectionHandle.cpp index 475a078ad0..ea53cb8ff9 100644 --- a/worker/src/handles/TcpConnectionHandle.cpp +++ b/worker/src/handles/TcpConnectionHandle.cpp @@ -168,11 +168,14 @@ void TcpConnectionHandle::Start() } #ifdef MS_LIBURING_SUPPORTED - err = uv_fileno(reinterpret_cast(this->uvHandle), std::addressof(this->fd)); - - if (err != 0) + if (DepLibUring::IsEnabled()) { - MS_THROW_ERROR("uv_fileno() failed: %s", uv_strerror(err)); + err = uv_fileno(reinterpret_cast(this->uvHandle), std::addressof(this->fd)); + + if (err != 0) + { + MS_THROW_ERROR("uv_fileno() failed: %s", uv_strerror(err)); + } } #endif } @@ -209,6 +212,7 @@ void TcpConnectionHandle::Write( } #ifdef MS_LIBURING_SUPPORTED + if (DepLibUring::IsEnabled()) { if (!DepLibUring::IsActive()) { diff --git a/worker/src/handles/UdpSocketHandle.cpp b/worker/src/handles/UdpSocketHandle.cpp index 2cb42e40c5..82da018c73 100644 --- a/worker/src/handles/UdpSocketHandle.cpp +++ b/worker/src/handles/UdpSocketHandle.cpp @@ -88,11 +88,14 @@ UdpSocketHandle::UdpSocketHandle(uv_udp_t* uvHandle) : uvHandle(uvHandle) } #ifdef MS_LIBURING_SUPPORTED - err = uv_fileno(reinterpret_cast(this->uvHandle), std::addressof(this->fd)); - - if (err != 0) + if (DepLibUring::IsEnabled()) { - MS_THROW_ERROR("uv_fileno() failed: %s", uv_strerror(err)); + err = uv_fileno(reinterpret_cast(this->uvHandle), std::addressof(this->fd)); + + if (err != 0) + { + MS_THROW_ERROR("uv_fileno() failed: %s", uv_strerror(err)); + } } #endif } @@ -144,6 +147,7 @@ void UdpSocketHandle::Send( } #ifdef MS_LIBURING_SUPPORTED + if (DepLibUring::IsEnabled()) { if (!DepLibUring::IsActive()) { From 43ef3256fdf64614d2ef223bc7c75406f0980c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 12 Aug 2024 13:01:58 +0200 Subject: [PATCH 484/525] WorkerSettings: Add disableLiburing option (enable_liburing in Rust) (#1442) --- .github/workflows/mediasoup-rust.yaml | 2 +- CHANGELOG.md | 23 ++++++++++++----------- node/src/Worker.ts | 10 ++++++++++ node/src/test/test-Worker.ts | 1 + node/src/test/test-node-sctp.ts | 2 +- rust/CHANGELOG.md | 1 + rust/src/router/tests.rs | 5 ++++- rust/src/worker.rs | 13 +++++++++++++ worker/include/DepLibUring.hpp | 2 +- worker/include/Settings.hpp | 1 + worker/src/DepLibUring.cpp | 14 +++++++++++--- worker/src/Settings.cpp | 18 ++++++++++++++++-- 12 files changed, 72 insertions(+), 20 deletions(-) diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index 812cbae213..afd8575522 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -47,7 +47,7 @@ jobs: run: cargo clippy --all-targets -- -D warnings # NOTE: In Windows this will build and test libmediasoupworker in release - # mode twice since build.rs doesn't allow debug mode for Windows. + # mode twice since build.rs doesn't allow debug mode on Windows. - name: cargo test run: | cargo test --verbose diff --git a/CHANGELOG.md b/CHANGELOG.md index a77548bb59..fd67e033b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - CI: Support Node 22 ([PR #1434](https://github.com/versatica/mediasoup/pull/1434)). - Update ESLint to version 9 ([PR #1435](https://github.com/versatica/mediasoup/pull/1435)). +- `Worker`: Add `disableLiburing` boolean option (`false` by default) to disable `io_uring` even if it's supported by the prebuilt `mediasoup-worker` and by current host ([PR #1442](https://github.com/versatica/mediasoup/pull/1442)). ### 3.14.9 @@ -246,11 +247,11 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.12.2 -- CI: Use `ubuntu-20.04` to build mediasoup-worker prebuilt on Linux ([PR #1092](https://github.com/versatica/mediasoup/pull/1092)). +- CI: Use `ubuntu-20.04` to build `mediasoup-worker` prebuilt on Linux ([PR #1092](https://github.com/versatica/mediasoup/pull/1092)). ### 3.12.1 -- mediasoup-worker prebuild: Fallback to local building if fetched binary doesn't run on current host ([PR #1090](https://github.com/versatica/mediasoup/pull/1090)). +- `mediasoup-worker` prebuild: Fallback to local building if fetched binary doesn't run on current host ([PR #1090](https://github.com/versatica/mediasoup/pull/1090)). ### 3.12.0 @@ -664,7 +665,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi - `Transport`: Implement new `setMaxOutgoingBitrate()` method ([PR #555](https://github.com/versatica/mediasoup/pull/555) by @t-mullen). - `SctpAssociation`: Don't warn if SCTP send buffer is full. - Rust: Update modules structure and other minor improvements for Rust version ([PR #558](https://github.com/versatica/mediasoup/pull/558)). -- `mediasoup-worker`: Avoid duplicated basenames so that libmediasoup-worker is compilable on macOS ([PR #557](https://github.com/versatica/mediasoup/pull/557)). +- `mediasoup-worker`: Avoid duplicated basenames so that `libmediasoup-worker` is compilable on macOS ([PR #557](https://github.com/versatica/mediasoup/pull/557)). ### 3.7.5 @@ -777,8 +778,8 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.6.20 -- Remove `-fwrapv` when building mediasoup-worker in `Debug` mode (issue #460). -- Add `MEDIASOUP_MAX_CORES` to limit `NUM_CORES` during mediasoup-worker build ([PR #462](https://github.com/versatica/mediasoup/pull/462)). +- Remove `-fwrapv` when building `mediasoup-worker` in `Debug` mode (issue #460). +- Add `MEDIASOUP_MAX_CORES` to limit `NUM_CORES` during `mediasoup-worker` build ([PR #462](https://github.com/versatica/mediasoup/pull/462)). ### 3.6.19 @@ -894,7 +895,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi - SCTP/DataChannel termination: - [PR #409](https://github.com/versatica/mediasoup/pull/409) - - Allow the Node application to directly send text/binary messages to mediasoup-worker C++ process so others can consume them using `DataConsumers`. + - Allow the Node application to directly send text/binary messages to `mediasoup-worker` C++ process so others can consume them using `DataConsumers`. - And vice-versa: allow the Node application to directly consume in Node messages send by `DataProducers`. - Add `WorkerLogTag` TypeScript enum and also add a new 'message' tag into it. @@ -944,7 +945,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.5.7 -- Fix crash in mediasoup-worker due to conversion from `uint64_t` to `int64_t` (used within `libwebrtc` code. Fixes #357. +- Fix crash in `mediasoup-worker` due to conversion from `uint64_t` to `int64_t` (used within `libwebrtc` code. Fixes #357. - Update `usrsctp` library. - Update Node deps. @@ -1058,7 +1059,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.4.1 -- Improve mediasoup-worker build system by using `sh` instead of `bash` and default to 4 cores (thanks @smoke, [PR #349](https://github.com/versatica/mediasoup/pull/349)). +- Improve `mediasoup-worker` build system by using `sh` instead of `bash` and default to 4 cores (thanks @smoke, [PR #349](https://github.com/versatica/mediasoup/pull/349)). ### 3.4.0 @@ -1133,7 +1134,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.2.1 - Add RTCP Extended Reports for RTT calculation on receiver RTP stream (thanks @yangjinechofor for initial pull request #314). -- Make mediasoup-worker compile in Armbian Debian Buster (thanks @krishisola, fixes #321). +- Make `mediasoup-worker` compile in Armbian Debian Buster (thanks @krishisola, fixes #321). ### 3.2.0 @@ -1255,7 +1256,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 2.6.13 -- Make mediasoup-worker compile in Armbian Debian Buster (thanks @krishisola, fixes #321). +- Make `mediasoup-worker` compile in Armbian Debian Buster (thanks @krishisola, fixes #321). - Update deps. ### 2.6.12 @@ -1281,7 +1282,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 2.6.7 -- Fix wrong destruction of Transports in Router.cpp that generates 100% CPU usage in mediasoup-worker processes. +- Fix wrong destruction of Transports in Router.cpp that generates 100% CPU usage in `mediasoup-worker` processes. ### 2.6.6 diff --git a/node/src/Worker.ts b/node/src/Worker.ts index e86206d98b..73480a406d 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -83,6 +83,11 @@ export type WorkerSettings = { */ libwebrtcFieldTrials?: string; + /** + * Disable liburing (io_uring) despite it's supported in current host. + */ + disableLiburing?: boolean; + /** * Custom application data. */ @@ -287,6 +292,7 @@ export class Worker< dtlsCertificateFile, dtlsPrivateKeyFile, libwebrtcFieldTrials, + disableLiburing, appData, }: WorkerSettings) { super(); @@ -338,6 +344,10 @@ export class Worker< spawnArgs.push(`--libwebrtcFieldTrials=${libwebrtcFieldTrials}`); } + if (disableLiburing) { + spawnArgs.push(`--disableLiburing=true`); + } + logger.debug( 'spawning worker process: %s %s', spawnBin, diff --git a/node/src/test/test-Worker.ts b/node/src/test/test-Worker.ts index 78fa5740a6..b9e9a1ec16 100644 --- a/node/src/test/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -63,6 +63,7 @@ test('createWorker() succeeds', async () => { dtlsCertificateFile: path.join(__dirname, 'data', 'dtls-cert.pem'), dtlsPrivateKeyFile: path.join(__dirname, 'data', 'dtls-key.pem'), libwebrtcFieldTrials: 'WebRTC-Bwe-AlrLimitedBackoff/Disabled/', + disableLiburing: true, appData: { foo: 456 }, }); diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index 7e944661ea..e344c1a484 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -23,7 +23,7 @@ beforeEach(async () => { // Set node-sctp default PMTU to 1200. sctp.defaults({ PMTU: 1200 }); - ctx.worker = await mediasoup.createWorker(); + ctx.worker = await mediasoup.createWorker({ disableLiburing: true }); ctx.router = await ctx.worker.createRouter(); ctx.plainTransport = await ctx.router.createPlainTransport({ // https://github.com/nodejs/node/issues/14900. diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index a4c76f1835..773ce3a1be 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -3,6 +3,7 @@ # NEXT - Update Rust toolchain channel to version 1.79.0 (PR #1409). +- Updates from mediasoup TypeScript `3.14.7..=3.14.10`. # 0.17.0 diff --git a/rust/src/router/tests.rs b/rust/src/router/tests.rs index e36d1c46c5..4ebc78cc75 100644 --- a/rust/src/router/tests.rs +++ b/rust/src/router/tests.rs @@ -16,7 +16,10 @@ async fn init() -> Worker { let worker_manager = WorkerManager::new(); worker_manager - .create_worker(WorkerSettings::default()) + .create_worker(WorkerSettings { + enable_liburing: false, + ..WorkerSettings::default() + }) .await .expect("Failed to create worker") } diff --git a/rust/src/worker.rs b/rust/src/worker.rs index 60a08b67f0..61085f888c 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -192,6 +192,11 @@ pub struct WorkerSettings { /// "WebRTC-Bwe-AlrLimitedBackoff/Enabled/". #[doc(hidden)] pub libwebrtc_field_trials: Option, + /// Enable liburing This option is ignored if io_uring is not supported by + /// current host. + /// + /// Default `true`. + pub enable_liburing: bool, /// Function that will be called under worker thread before worker starts, can be used for /// pinning worker threads to CPU cores. pub thread_initializer: Option>, @@ -221,6 +226,7 @@ impl Default for WorkerSettings { rtc_port_range: 10000..=59999, dtls_files: None, libwebrtc_field_trials: None, + enable_liburing: true, thread_initializer: None, app_data: AppData::default(), } @@ -235,6 +241,7 @@ impl fmt::Debug for WorkerSettings { rtc_port_range, dtls_files, libwebrtc_field_trials, + enable_liburing, thread_initializer, app_data, } = self; @@ -245,6 +252,7 @@ impl fmt::Debug for WorkerSettings { .field("rtc_port_range", &rtc_port_range) .field("dtls_files", &dtls_files) .field("libwebrtc_field_trials", &libwebrtc_field_trials) + .field("enable_liburing", &enable_liburing) .field( "thread_initializer", &thread_initializer.as_ref().map(|_| "ThreadInitializer"), @@ -356,6 +364,7 @@ impl Inner { rtc_port_range, dtls_files, libwebrtc_field_trials, + enable_liburing, thread_initializer, app_data, }: WorkerSettings, @@ -404,6 +413,10 @@ impl Inner { )); } + if !enable_liburing { + spawn_args.push("--disableLiburing=true".to_string()); + } + let id = WorkerId::new(); debug!( "spawning worker with arguments [id:{}]: {}", diff --git a/worker/include/DepLibUring.hpp b/worker/include/DepLibUring.hpp index a0b041c899..c41f308eed 100644 --- a/worker/include/DepLibUring.hpp +++ b/worker/include/DepLibUring.hpp @@ -52,7 +52,7 @@ class DepLibUring class LibUring; // Whether liburing is enabled or not after runtime checks. - static bool enabled; + thread_local static bool enabled; thread_local static LibUring* liburing; public: diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index 06a66f4bf6..1025260e3d 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -39,6 +39,7 @@ class Settings std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; std::string libwebrtcFieldTrials{ "WebRTC-Bwe-AlrLimitedBackoff/Enabled/" }; + bool liburingDisabled{ false }; }; public: diff --git a/worker/src/DepLibUring.cpp b/worker/src/DepLibUring.cpp index c5e8aed778..0195ce7b9e 100644 --- a/worker/src/DepLibUring.cpp +++ b/worker/src/DepLibUring.cpp @@ -4,16 +4,17 @@ #include "DepLibUring.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Settings.hpp" #include "Utils.hpp" #include #include #include /* Static variables. */ -bool DepLibUring::enabled{ false }; -/* liburing instance per thread. */ +thread_local bool DepLibUring::enabled{ false }; +// liburing instance per thread. thread_local DepLibUring::LibUring* DepLibUring::liburing{ nullptr }; -/* Completion queue entry array used to retrieve processes tasks. */ +// Completion queue entry array used to retrieve processes tasks. thread_local struct io_uring_cqe* cqes[DepLibUring::QueueDepth]; /* Static methods for UV callbacks. */ @@ -121,6 +122,13 @@ void DepLibUring::ClassInit() MS_DEBUG_TAG(info, "liburing version: \"%i.%i\"", mayor, minor); + if (Settings::configuration.liburingDisabled) + { + MS_DEBUG_TAG(info, "liburing disabled by user settings"); + + return; + } + // This must be called first. DepLibUring::CheckRuntimeSupport(); diff --git a/worker/src/Settings.cpp b/worker/src/Settings.cpp index a989bc44e5..f21c1f4759 100644 --- a/worker/src/Settings.cpp +++ b/worker/src/Settings.cpp @@ -60,7 +60,8 @@ void Settings::SetConfiguration(int argc, char* argv[]) { "dtlsCertificateFile", optional_argument, nullptr, 'c' }, { "dtlsPrivateKeyFile", optional_argument, nullptr, 'p' }, { "libwebrtcFieldTrials", optional_argument, nullptr, 'W' }, - { nullptr, 0, nullptr, 0 } + { "disableLiburing", optional_argument, nullptr, 'd' }, + { nullptr, 0, nullptr, 0 } }; // clang-format on std::string stringValue; @@ -73,11 +74,12 @@ void Settings::SetConfiguration(int argc, char* argv[]) optind = 1; // Set explicitly, otherwise subsequent runs will fail. opterr = 0; // Don't allow getopt to print error messages. + while ((c = getopt_long_only(argc, argv, "", options, &optionIdx)) != -1) { if (!optarg) { - MS_THROW_TYPE_ERROR("unknown configuration parameter: %s", optarg); + MS_THROW_TYPE_ERROR("missing value in command line argument in option '%c'", c); } switch (c) @@ -158,6 +160,18 @@ void Settings::SetConfiguration(int argc, char* argv[]) break; } + case 'd': + { + stringValue = std::string(optarg); + + if (stringValue == "true") + { + Settings::configuration.liburingDisabled = true; + } + + break; + } + // Invalid option. case '?': { From 87a68b83c81efa9b8e4921d0a76dcc9af9b9af52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 12 Aug 2024 13:07:44 +0200 Subject: [PATCH 485/525] Update NPM deps --- package-lock.json | 277 ++++++++++++++++++++++++---------------------- package.json | 12 +- 2 files changed, 148 insertions(+), 141 deletions(-) diff --git a/package-lock.json b/package-lock.json index af31120ab7..f9d2649306 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,25 +20,25 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.8.0", + "@eslint/js": "^9.9.0", "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^22.1.0", - "eslint": "^9.8.0", + "@types/node": "^22.2.0", + "eslint": "^9.9.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.7.0", + "eslint-plugin-jest": "^28.8.0", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "marked": "^13.0.3", + "marked": "^14.0.0", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.4", "typescript": "^5.5.4", - "typescript-eslint": "^8.0.0" + "typescript-eslint": "^8.0.1" }, "engines": { "node": ">=18" @@ -797,9 +797,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", - "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz", + "integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1860,11 +1860,10 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", - "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz", + "integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==", "dev": true, - "license": "MIT", "dependencies": { "undici-types": "~6.13.0" } @@ -1891,16 +1890,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0.tgz", - "integrity": "sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.1.tgz", + "integrity": "sha512-5g3Y7GDFsJAnY4Yhvk8sZtFfV6YNF2caLzjrRPUBzewjPCaj0yokePB4LJSobyCzGMzjZZYFbwuzbfDHlimXbQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.0.0", - "@typescript-eslint/type-utils": "8.0.0", - "@typescript-eslint/utils": "8.0.0", - "@typescript-eslint/visitor-keys": "8.0.0", + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/type-utils": "8.0.1", + "@typescript-eslint/utils": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1924,15 +1923,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.0.tgz", - "integrity": "sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.1.tgz", + "integrity": "sha512-5IgYJ9EO/12pOUwiBKFkpU7rS3IU21mtXzB81TNwq2xEybcmAZrE9qwDtsb5uQd9aVO9o0fdabFyAmKveXyujg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.0.0", - "@typescript-eslint/types": "8.0.0", - "@typescript-eslint/typescript-estree": "8.0.0", - "@typescript-eslint/visitor-keys": "8.0.0", + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/typescript-estree": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "debug": "^4.3.4" }, "engines": { @@ -1952,13 +1951,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0.tgz", - "integrity": "sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.1.tgz", + "integrity": "sha512-NpixInP5dm7uukMiRyiHjRKkom5RIFA4dfiHvalanD2cF0CLUuQqxfg8PtEUo9yqJI2bBhF+pcSafqnG3UBnRQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.0.0", - "@typescript-eslint/visitor-keys": "8.0.0" + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1969,13 +1968,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.0.tgz", - "integrity": "sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.1.tgz", + "integrity": "sha512-+/UT25MWvXeDX9YaHv1IS6KI1fiuTto43WprE7pgSMswHbn1Jm9GEM4Txp+X74ifOWV8emu2AWcbLhpJAvD5Ng==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.0.0", - "@typescript-eslint/utils": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.1", + "@typescript-eslint/utils": "8.0.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1993,9 +1992,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0.tgz", - "integrity": "sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.1.tgz", + "integrity": "sha512-PpqTVT3yCA/bIgJ12czBuE3iBlM3g4inRSC5J0QOdQFAn07TYrYEQBBKgXH1lQpglup+Zy6c1fxuwTk4MTNKIw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2006,13 +2005,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0.tgz", - "integrity": "sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.1.tgz", + "integrity": "sha512-8V9hriRvZQXPWU3bbiUV4Epo7EvgM6RTs+sUmxp5G//dBGy402S7Fx0W0QkB2fb4obCF8SInoUzvTYtc3bkb5w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.0.0", - "@typescript-eslint/visitor-keys": "8.0.0", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2058,15 +2057,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0.tgz", - "integrity": "sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.1.tgz", + "integrity": "sha512-CBFR0G0sCt0+fzfnKaciu9IBsKvEKYwN9UZ+eeogK1fYHg4Qxk1yf/wLQkLXlq8wbU2dFlgAesxt8Gi76E8RTA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.0.0", - "@typescript-eslint/types": "8.0.0", - "@typescript-eslint/typescript-estree": "8.0.0" + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/typescript-estree": "8.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2080,12 +2079,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0.tgz", - "integrity": "sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.1.tgz", + "integrity": "sha512-W5E+o0UfUcK5EgchLZsyVWqARmsM7v54/qEq6PY3YI5arkgmCzHiuk0zKSJJbm71V0xdRna4BGomkCTXz2/LkQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/types": "8.0.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2837,16 +2836,16 @@ } }, "node_modules/eslint": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", - "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.0.tgz", + "integrity": "sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.17.1", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.8.0", + "@eslint/js": "9.9.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -2885,6 +2884,14 @@ }, "funding": { "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { @@ -2900,9 +2907,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.7.0.tgz", - "integrity": "sha512-fzPGN7awL2ftVRQh/bsCi+16ArUZWujZnD1b8EGJqy8nr4//7tZ3BIdc/9edcJBtB3hpci3GtdMNFVDwHU0Eag==", + "version": "28.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz", + "integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -4690,9 +4697,9 @@ } }, "node_modules/marked": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", - "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", + "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -6070,14 +6077,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.0.tgz", - "integrity": "sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.1.tgz", + "integrity": "sha512-V3Y+MdfhawxEjE16dWpb7/IOgeXnLwAEEkS7v8oDqNcR1oYlqWhGH/iHqHdKVdpWme1VPZ0SoywXAkCqawj2eQ==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.0.0", - "@typescript-eslint/parser": "8.0.0", - "@typescript-eslint/utils": "8.0.0" + "@typescript-eslint/eslint-plugin": "8.0.1", + "@typescript-eslint/parser": "8.0.1", + "@typescript-eslint/utils": "8.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6892,9 +6899,9 @@ } }, "@eslint/js": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", - "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz", + "integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==", "dev": true }, "@eslint/object-schema": { @@ -7736,9 +7743,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", - "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz", + "integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==", "dev": true, "requires": { "undici-types": "~6.13.0" @@ -7766,16 +7773,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0.tgz", - "integrity": "sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.1.tgz", + "integrity": "sha512-5g3Y7GDFsJAnY4Yhvk8sZtFfV6YNF2caLzjrRPUBzewjPCaj0yokePB4LJSobyCzGMzjZZYFbwuzbfDHlimXbQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.0.0", - "@typescript-eslint/type-utils": "8.0.0", - "@typescript-eslint/utils": "8.0.0", - "@typescript-eslint/visitor-keys": "8.0.0", + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/type-utils": "8.0.1", + "@typescript-eslint/utils": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7783,54 +7790,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.0.tgz", - "integrity": "sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.1.tgz", + "integrity": "sha512-5IgYJ9EO/12pOUwiBKFkpU7rS3IU21mtXzB81TNwq2xEybcmAZrE9qwDtsb5uQd9aVO9o0fdabFyAmKveXyujg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.0.0", - "@typescript-eslint/types": "8.0.0", - "@typescript-eslint/typescript-estree": "8.0.0", - "@typescript-eslint/visitor-keys": "8.0.0", + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/typescript-estree": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0.tgz", - "integrity": "sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.1.tgz", + "integrity": "sha512-NpixInP5dm7uukMiRyiHjRKkom5RIFA4dfiHvalanD2cF0CLUuQqxfg8PtEUo9yqJI2bBhF+pcSafqnG3UBnRQ==", "dev": true, "requires": { - "@typescript-eslint/types": "8.0.0", - "@typescript-eslint/visitor-keys": "8.0.0" + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1" } }, "@typescript-eslint/type-utils": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.0.tgz", - "integrity": "sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.1.tgz", + "integrity": "sha512-+/UT25MWvXeDX9YaHv1IS6KI1fiuTto43WprE7pgSMswHbn1Jm9GEM4Txp+X74ifOWV8emu2AWcbLhpJAvD5Ng==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.0.0", - "@typescript-eslint/utils": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.1", + "@typescript-eslint/utils": "8.0.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0.tgz", - "integrity": "sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.1.tgz", + "integrity": "sha512-PpqTVT3yCA/bIgJ12czBuE3iBlM3g4inRSC5J0QOdQFAn07TYrYEQBBKgXH1lQpglup+Zy6c1fxuwTk4MTNKIw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0.tgz", - "integrity": "sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.1.tgz", + "integrity": "sha512-8V9hriRvZQXPWU3bbiUV4Epo7EvgM6RTs+sUmxp5G//dBGy402S7Fx0W0QkB2fb4obCF8SInoUzvTYtc3bkb5w==", "dev": true, "requires": { - "@typescript-eslint/types": "8.0.0", - "@typescript-eslint/visitor-keys": "8.0.0", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7860,24 +7867,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0.tgz", - "integrity": "sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.1.tgz", + "integrity": "sha512-CBFR0G0sCt0+fzfnKaciu9IBsKvEKYwN9UZ+eeogK1fYHg4Qxk1yf/wLQkLXlq8wbU2dFlgAesxt8Gi76E8RTA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.0.0", - "@typescript-eslint/types": "8.0.0", - "@typescript-eslint/typescript-estree": "8.0.0" + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/typescript-estree": "8.0.1" } }, "@typescript-eslint/visitor-keys": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0.tgz", - "integrity": "sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.1.tgz", + "integrity": "sha512-W5E+o0UfUcK5EgchLZsyVWqARmsM7v54/qEq6PY3YI5arkgmCzHiuk0zKSJJbm71V0xdRna4BGomkCTXz2/LkQ==", "dev": true, "requires": { - "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/types": "8.0.1", "eslint-visitor-keys": "^3.4.3" } }, @@ -8403,16 +8410,16 @@ "dev": true }, "eslint": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", - "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.0.tgz", + "integrity": "sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.17.1", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.8.0", + "@eslint/js": "9.9.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -8460,9 +8467,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "28.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.7.0.tgz", - "integrity": "sha512-fzPGN7awL2ftVRQh/bsCi+16ArUZWujZnD1b8EGJqy8nr4//7tZ3BIdc/9edcJBtB3hpci3GtdMNFVDwHU0Eag==", + "version": "28.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz", + "integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==", "dev": true, "requires": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -9738,9 +9745,9 @@ } }, "marked": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", - "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", + "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", "dev": true }, "meow": { @@ -10643,14 +10650,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.0.tgz", - "integrity": "sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.1.tgz", + "integrity": "sha512-V3Y+MdfhawxEjE16dWpb7/IOgeXnLwAEEkS7v8oDqNcR1oYlqWhGH/iHqHdKVdpWme1VPZ0SoywXAkCqawj2eQ==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.0.0", - "@typescript-eslint/parser": "8.0.0", - "@typescript-eslint/utils": "8.0.0" + "@typescript-eslint/eslint-plugin": "8.0.1", + "@typescript-eslint/parser": "8.0.1", + "@typescript-eslint/utils": "8.0.1" } }, "undici-types": { diff --git a/package.json b/package.json index ad23116f00..cbfa9cac7d 100644 --- a/package.json +++ b/package.json @@ -109,24 +109,24 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.8.0", + "@eslint/js": "^9.9.0", "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^22.1.0", - "eslint": "^9.8.0", + "@types/node": "^22.2.0", + "eslint": "^9.9.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.7.0", + "eslint-plugin-jest": "^28.8.0", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "marked": "^13.0.3", + "marked": "^14.0.0", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.4", "typescript": "^5.5.4", - "typescript-eslint": "^8.0.0" + "typescript-eslint": "^8.0.1" } } From 50d10313a2a5d89b3680a610f092766c4581f312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 12 Aug 2024 13:10:25 +0200 Subject: [PATCH 486/525] 3.14.10 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd67e033b5..7173676937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +### 3.14.10 + - CI: Support Node 22 ([PR #1434](https://github.com/versatica/mediasoup/pull/1434)). - Update ESLint to version 9 ([PR #1435](https://github.com/versatica/mediasoup/pull/1435)). - `Worker`: Add `disableLiburing` boolean option (`false` by default) to disable `io_uring` even if it's supported by the prebuilt `mediasoup-worker` and by current host ([PR #1442](https://github.com/versatica/mediasoup/pull/1442)). diff --git a/package-lock.json b/package-lock.json index f9d2649306..780224b489 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.9", + "version": "3.14.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.9", + "version": "3.14.10", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index cbfa9cac7d..823a21a637 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.9", + "version": "3.14.10", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From ed9d2d9df5271e1a804380843484040b7223b720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 12 Aug 2024 13:45:28 +0200 Subject: [PATCH 487/525] update mediasoup-rust versions --- rust/CHANGELOG.md | 4 ++++ rust/Cargo.toml | 4 ++-- worker/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index 773ce3a1be..1ba60e0256 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -2,8 +2,12 @@ # NEXT +# 0.17.1 + - Update Rust toolchain channel to version 1.79.0 (PR #1409). - Updates from mediasoup TypeScript `3.14.7..=3.14.10`. +- General mediasoup changes: + - Worker: Add `enable_liburing` boolean option (`true` by default) to disable `io_uring` even if it's supported by the prebuilt `mediasoup-worker` and by current host (PR #1442). # 0.17.0 diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 98aadbd2bd..909ba49228 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup" -version = "0.17.0" +version = "0.17.1" description = "Cutting Edge WebRTC Video Conferencing in Rust" categories = ["api-bindings", "multimedia", "network-programming"] authors = ["Nazar Mokrynskyi "] @@ -46,7 +46,7 @@ version = "0.8.1" [dependencies.mediasoup-sys] path = "../worker" -version = "0.9.0" +version = "0.9.1" [dependencies.parking_lot] version = "0.12.1" diff --git a/worker/Cargo.toml b/worker/Cargo.toml index 9ec9be69c6..d95f715da2 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mediasoup-sys" -version = "0.9.0" +version = "0.9.1" description = "FFI bindings to C++ libmediasoup-worker" authors = ["Nazar Mokrynskyi "] edition = "2021" From 44f7642ff23d79e6daaf8dd8ec9e0702436dd99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 12 Aug 2024 17:51:13 +0200 Subject: [PATCH 488/525] Fix WorkerSettings.disableLiburing option (#1444) --- CHANGELOG.md | 2 ++ node/src/index.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7173676937..00db1b1990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +- `Worker`: Fix `disableLiburing` option in `WorkerSettings` ([PR #1444](https://github.com/versatica/mediasoup/pull/1444)). + ### 3.14.10 - CI: Support Node 22 ([PR #1434](https://github.com/versatica/mediasoup/pull/1434)). diff --git a/node/src/index.ts b/node/src/index.ts index eeff81c0fa..1c02f63c23 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -56,6 +56,7 @@ export async function createWorker< dtlsCertificateFile, dtlsPrivateKeyFile, libwebrtcFieldTrials, + disableLiburing, appData, }: WorkerSettings = {}): Promise> { logger.debug('createWorker()'); @@ -72,6 +73,7 @@ export async function createWorker< dtlsCertificateFile, dtlsPrivateKeyFile, libwebrtcFieldTrials, + disableLiburing, appData, }); From 91885c8124458c9361eb2a3b6a8127817efdac27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 12 Aug 2024 17:53:06 +0200 Subject: [PATCH 489/525] 3.14.11 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00db1b1990..52c3dd8a96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +### 3.14.11 + - `Worker`: Fix `disableLiburing` option in `WorkerSettings` ([PR #1444](https://github.com/versatica/mediasoup/pull/1444)). ### 3.14.10 diff --git a/package-lock.json b/package-lock.json index 780224b489..708ff94954 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.10", + "version": "3.14.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.10", + "version": "3.14.11", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 823a21a637..2e605e5c02 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.10", + "version": "3.14.11", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From 741d99c838d3f5fcf65c0934f4ef8b112ea012fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 13 Aug 2024 10:13:44 +0200 Subject: [PATCH 490/525] Fix io_uring support detection (#1445) Fixes #1435 ### Details - Having Kernel >= 6 doesn't guarantee that `io_uring` is enabled. Some systems disable it at kernel layer. - This PR checks if `io_uring` initialization works in launch time, otherwise `io_uring` is disabled. --- CHANGELOG.md | 2 ++ worker/include/DepLibUring.hpp | 2 +- worker/src/DepLibUring.cpp | 52 +++++++++++++++++++++------------- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52c3dd8a96..181b238b1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +- `Worker`: Fix `io_uring` support detection ([PR #1445](https://github.com/versatica/mediasoup/pull/1445)). + ### 3.14.11 - `Worker`: Fix `disableLiburing` option in `WorkerSettings` ([PR #1444](https://github.com/versatica/mediasoup/pull/1444)). diff --git a/worker/include/DepLibUring.hpp b/worker/include/DepLibUring.hpp index c41f308eed..67b64fef07 100644 --- a/worker/include/DepLibUring.hpp +++ b/worker/include/DepLibUring.hpp @@ -35,7 +35,7 @@ class DepLibUring static void ClassInit(); static void ClassDestroy(); - static void CheckRuntimeSupport(); + static bool CheckRuntimeSupport(); static bool IsEnabled(); static flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder); static void StartPollingCQEs(); diff --git a/worker/src/DepLibUring.cpp b/worker/src/DepLibUring.cpp index 0195ce7b9e..651a8a025d 100644 --- a/worker/src/DepLibUring.cpp +++ b/worker/src/DepLibUring.cpp @@ -120,27 +120,34 @@ void DepLibUring::ClassInit() const auto mayor = io_uring_major_version(); const auto minor = io_uring_minor_version(); - MS_DEBUG_TAG(info, "liburing version: \"%i.%i\"", mayor, minor); + MS_DEBUG_TAG(info, "io_uring version: \"%i.%i\"", mayor, minor); if (Settings::configuration.liburingDisabled) { - MS_DEBUG_TAG(info, "liburing disabled by user settings"); + MS_DEBUG_TAG(info, "io_uring disabled by user settings"); return; } // This must be called first. - DepLibUring::CheckRuntimeSupport(); - - if (DepLibUring::IsEnabled()) + if (DepLibUring::CheckRuntimeSupport()) { - DepLibUring::liburing = new LibUring(); + try + { + DepLibUring::liburing = new LibUring(); + + MS_DEBUG_TAG(info, "io_uring enabled"); - MS_DEBUG_TAG(info, "liburing enabled"); + DepLibUring::enabled = true; + } + catch (const MediaSoupError& error) + { + MS_DEBUG_TAG(info, "io_uring initialization failed, io_uring not enabled"); + } } else { - MS_DEBUG_TAG(info, "liburing not enabled"); + MS_DEBUG_TAG(info, "io_uring not enabled"); } } @@ -151,7 +158,7 @@ void DepLibUring::ClassDestroy() delete DepLibUring::liburing; } -void DepLibUring::CheckRuntimeSupport() +bool DepLibUring::CheckRuntimeSupport() { // clang-format off struct utsname buffer{}; @@ -171,7 +178,14 @@ void DepLibUring::CheckRuntimeSupport() // liburing `sento` capabilities are supported for kernel versions greather // than or equal to 6. - DepLibUring::enabled = kernelMayorLong >= 6; + if (kernelMayorLong < 6) + { + MS_DEBUG_TAG(info, "kernel doesn't support io_uring"); + + return false; + } + + return true; } bool DepLibUring::IsEnabled() @@ -183,7 +197,7 @@ flatbuffers::Offset DepLibUring::FillBuffer(flatbuffers::Fl { MS_TRACE(); - MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); + MS_ASSERT(DepLibUring::enabled, "io_uring not enabled"); return DepLibUring::liburing->FillBuffer(builder); } @@ -192,7 +206,7 @@ void DepLibUring::StartPollingCQEs() { MS_TRACE(); - MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); + MS_ASSERT(DepLibUring::enabled, "io_uring not enabled"); DepLibUring::liburing->StartPollingCQEs(); } @@ -201,7 +215,7 @@ void DepLibUring::StopPollingCQEs() { MS_TRACE(); - MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); + MS_ASSERT(DepLibUring::enabled, "io_uring not enabled"); DepLibUring::liburing->StopPollingCQEs(); } @@ -210,7 +224,7 @@ uint8_t* DepLibUring::GetSendBuffer() { MS_TRACE(); - MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); + MS_ASSERT(DepLibUring::enabled, "io_uring not enabled"); return DepLibUring::liburing->GetSendBuffer(); } @@ -220,7 +234,7 @@ bool DepLibUring::PrepareSend( { MS_TRACE(); - MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); + MS_ASSERT(DepLibUring::enabled, "io_uring not enabled"); return DepLibUring::liburing->PrepareSend(sockfd, data, len, addr, cb); } @@ -230,7 +244,7 @@ bool DepLibUring::PrepareWrite( { MS_TRACE(); - MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); + MS_ASSERT(DepLibUring::enabled, "io_uring not enabled"); return DepLibUring::liburing->PrepareWrite(sockfd, data1, len1, data2, len2, cb); } @@ -239,7 +253,7 @@ void DepLibUring::Submit() { MS_TRACE(); - MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); + MS_ASSERT(DepLibUring::enabled, "io_uring not enabled"); DepLibUring::liburing->Submit(); } @@ -248,7 +262,7 @@ void DepLibUring::SetActive() { MS_TRACE(); - MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); + MS_ASSERT(DepLibUring::enabled, "io_uring not enabled"); DepLibUring::liburing->SetActive(); } @@ -257,7 +271,7 @@ bool DepLibUring::IsActive() { MS_TRACE(); - MS_ASSERT(DepLibUring::enabled, "DepLibUring::liburing not enabled"); + MS_ASSERT(DepLibUring::enabled, "io_uring not enabled"); return DepLibUring::liburing->IsActive(); } From 3604b1e983350c0fa9bc95621530f42e487bdd1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 13 Aug 2024 10:21:22 +0200 Subject: [PATCH 491/525] Update NPM dev deps --- package-lock.json | 194 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 98 insertions(+), 98 deletions(-) diff --git a/package-lock.json b/package-lock.json index 708ff94954..37b65b93c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.4", "typescript": "^5.5.4", - "typescript-eslint": "^8.0.1" + "typescript-eslint": "^8.1.0" }, "engines": { "node": ">=18" @@ -1890,16 +1890,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.1.tgz", - "integrity": "sha512-5g3Y7GDFsJAnY4Yhvk8sZtFfV6YNF2caLzjrRPUBzewjPCaj0yokePB4LJSobyCzGMzjZZYFbwuzbfDHlimXbQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.1.0.tgz", + "integrity": "sha512-LlNBaHFCEBPHyD4pZXb35mzjGkuGKXU5eeCA1SxvHfiRES0E82dOounfVpL4DCqYvJEKab0bZIA0gCRpdLKkCw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.0.1", - "@typescript-eslint/type-utils": "8.0.1", - "@typescript-eslint/utils": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1", + "@typescript-eslint/scope-manager": "8.1.0", + "@typescript-eslint/type-utils": "8.1.0", + "@typescript-eslint/utils": "8.1.0", + "@typescript-eslint/visitor-keys": "8.1.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1923,15 +1923,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.1.tgz", - "integrity": "sha512-5IgYJ9EO/12pOUwiBKFkpU7rS3IU21mtXzB81TNwq2xEybcmAZrE9qwDtsb5uQd9aVO9o0fdabFyAmKveXyujg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.1.0.tgz", + "integrity": "sha512-U7iTAtGgJk6DPX9wIWPPOlt1gO57097G06gIcl0N0EEnNw8RGD62c+2/DiP/zL7KrkqnnqF7gtFGR7YgzPllTA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.0.1", - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/typescript-estree": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1", + "@typescript-eslint/scope-manager": "8.1.0", + "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/typescript-estree": "8.1.0", + "@typescript-eslint/visitor-keys": "8.1.0", "debug": "^4.3.4" }, "engines": { @@ -1951,13 +1951,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.1.tgz", - "integrity": "sha512-NpixInP5dm7uukMiRyiHjRKkom5RIFA4dfiHvalanD2cF0CLUuQqxfg8PtEUo9yqJI2bBhF+pcSafqnG3UBnRQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.1.0.tgz", + "integrity": "sha512-DsuOZQji687sQUjm4N6c9xABJa7fjvfIdjqpSIIVOgaENf2jFXiM9hIBZOL3hb6DHK9Nvd2d7zZnoMLf9e0OtQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1" + "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/visitor-keys": "8.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1968,13 +1968,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.1.tgz", - "integrity": "sha512-+/UT25MWvXeDX9YaHv1IS6KI1fiuTto43WprE7pgSMswHbn1Jm9GEM4Txp+X74ifOWV8emu2AWcbLhpJAvD5Ng==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.1.0.tgz", + "integrity": "sha512-oLYvTxljVvsMnldfl6jIKxTaU7ok7km0KDrwOt1RHYu6nxlhN3TIx8k5Q52L6wR33nOwDgM7VwW1fT1qMNfFIA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.0.1", - "@typescript-eslint/utils": "8.0.1", + "@typescript-eslint/typescript-estree": "8.1.0", + "@typescript-eslint/utils": "8.1.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1992,9 +1992,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.1.tgz", - "integrity": "sha512-PpqTVT3yCA/bIgJ12czBuE3iBlM3g4inRSC5J0QOdQFAn07TYrYEQBBKgXH1lQpglup+Zy6c1fxuwTk4MTNKIw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.1.0.tgz", + "integrity": "sha512-q2/Bxa0gMOu/2/AKALI0tCKbG2zppccnRIRCW6BaaTlRVaPKft4oVYPp7WOPpcnsgbr0qROAVCVKCvIQ0tbWog==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2005,13 +2005,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.1.tgz", - "integrity": "sha512-8V9hriRvZQXPWU3bbiUV4Epo7EvgM6RTs+sUmxp5G//dBGy402S7Fx0W0QkB2fb4obCF8SInoUzvTYtc3bkb5w==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.1.0.tgz", + "integrity": "sha512-NTHhmufocEkMiAord/g++gWKb0Fr34e9AExBRdqgWdVBaKoei2dIyYKD9Q0jBnvfbEA5zaf8plUFMUH6kQ0vGg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1", + "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/visitor-keys": "8.1.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2057,15 +2057,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.1.tgz", - "integrity": "sha512-CBFR0G0sCt0+fzfnKaciu9IBsKvEKYwN9UZ+eeogK1fYHg4Qxk1yf/wLQkLXlq8wbU2dFlgAesxt8Gi76E8RTA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.1.0.tgz", + "integrity": "sha512-ypRueFNKTIFwqPeJBfeIpxZ895PQhNyH4YID6js0UoBImWYoSjBsahUn9KMiJXh94uOjVBgHD9AmkyPsPnFwJA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.0.1", - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/typescript-estree": "8.0.1" + "@typescript-eslint/scope-manager": "8.1.0", + "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/typescript-estree": "8.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2079,12 +2079,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.1.tgz", - "integrity": "sha512-W5E+o0UfUcK5EgchLZsyVWqARmsM7v54/qEq6PY3YI5arkgmCzHiuk0zKSJJbm71V0xdRna4BGomkCTXz2/LkQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.1.0.tgz", + "integrity": "sha512-ba0lNI19awqZ5ZNKh6wCModMwoZs457StTebQ0q1NP58zSi2F6MOZRXwfKZy+jB78JNJ/WH8GSh2IQNzXX8Nag==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/types": "8.1.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -6077,14 +6077,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.1.tgz", - "integrity": "sha512-V3Y+MdfhawxEjE16dWpb7/IOgeXnLwAEEkS7v8oDqNcR1oYlqWhGH/iHqHdKVdpWme1VPZ0SoywXAkCqawj2eQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.1.0.tgz", + "integrity": "sha512-prB2U3jXPJLpo1iVLN338Lvolh6OrcCZO+9Yv6AR+tvegPPptYCDBIHiEEUdqRi8gAv2bXNKfMUrgAd2ejn/ow==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.0.1", - "@typescript-eslint/parser": "8.0.1", - "@typescript-eslint/utils": "8.0.1" + "@typescript-eslint/eslint-plugin": "8.1.0", + "@typescript-eslint/parser": "8.1.0", + "@typescript-eslint/utils": "8.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7773,16 +7773,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.1.tgz", - "integrity": "sha512-5g3Y7GDFsJAnY4Yhvk8sZtFfV6YNF2caLzjrRPUBzewjPCaj0yokePB4LJSobyCzGMzjZZYFbwuzbfDHlimXbQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.1.0.tgz", + "integrity": "sha512-LlNBaHFCEBPHyD4pZXb35mzjGkuGKXU5eeCA1SxvHfiRES0E82dOounfVpL4DCqYvJEKab0bZIA0gCRpdLKkCw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.0.1", - "@typescript-eslint/type-utils": "8.0.1", - "@typescript-eslint/utils": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1", + "@typescript-eslint/scope-manager": "8.1.0", + "@typescript-eslint/type-utils": "8.1.0", + "@typescript-eslint/utils": "8.1.0", + "@typescript-eslint/visitor-keys": "8.1.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7790,54 +7790,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.1.tgz", - "integrity": "sha512-5IgYJ9EO/12pOUwiBKFkpU7rS3IU21mtXzB81TNwq2xEybcmAZrE9qwDtsb5uQd9aVO9o0fdabFyAmKveXyujg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.1.0.tgz", + "integrity": "sha512-U7iTAtGgJk6DPX9wIWPPOlt1gO57097G06gIcl0N0EEnNw8RGD62c+2/DiP/zL7KrkqnnqF7gtFGR7YgzPllTA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.0.1", - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/typescript-estree": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1", + "@typescript-eslint/scope-manager": "8.1.0", + "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/typescript-estree": "8.1.0", + "@typescript-eslint/visitor-keys": "8.1.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.1.tgz", - "integrity": "sha512-NpixInP5dm7uukMiRyiHjRKkom5RIFA4dfiHvalanD2cF0CLUuQqxfg8PtEUo9yqJI2bBhF+pcSafqnG3UBnRQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.1.0.tgz", + "integrity": "sha512-DsuOZQji687sQUjm4N6c9xABJa7fjvfIdjqpSIIVOgaENf2jFXiM9hIBZOL3hb6DHK9Nvd2d7zZnoMLf9e0OtQ==", "dev": true, "requires": { - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1" + "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/visitor-keys": "8.1.0" } }, "@typescript-eslint/type-utils": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.1.tgz", - "integrity": "sha512-+/UT25MWvXeDX9YaHv1IS6KI1fiuTto43WprE7pgSMswHbn1Jm9GEM4Txp+X74ifOWV8emu2AWcbLhpJAvD5Ng==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.1.0.tgz", + "integrity": "sha512-oLYvTxljVvsMnldfl6jIKxTaU7ok7km0KDrwOt1RHYu6nxlhN3TIx8k5Q52L6wR33nOwDgM7VwW1fT1qMNfFIA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.0.1", - "@typescript-eslint/utils": "8.0.1", + "@typescript-eslint/typescript-estree": "8.1.0", + "@typescript-eslint/utils": "8.1.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.1.tgz", - "integrity": "sha512-PpqTVT3yCA/bIgJ12czBuE3iBlM3g4inRSC5J0QOdQFAn07TYrYEQBBKgXH1lQpglup+Zy6c1fxuwTk4MTNKIw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.1.0.tgz", + "integrity": "sha512-q2/Bxa0gMOu/2/AKALI0tCKbG2zppccnRIRCW6BaaTlRVaPKft4oVYPp7WOPpcnsgbr0qROAVCVKCvIQ0tbWog==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.1.tgz", - "integrity": "sha512-8V9hriRvZQXPWU3bbiUV4Epo7EvgM6RTs+sUmxp5G//dBGy402S7Fx0W0QkB2fb4obCF8SInoUzvTYtc3bkb5w==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.1.0.tgz", + "integrity": "sha512-NTHhmufocEkMiAord/g++gWKb0Fr34e9AExBRdqgWdVBaKoei2dIyYKD9Q0jBnvfbEA5zaf8plUFMUH6kQ0vGg==", "dev": true, "requires": { - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1", + "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/visitor-keys": "8.1.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7867,24 +7867,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.1.tgz", - "integrity": "sha512-CBFR0G0sCt0+fzfnKaciu9IBsKvEKYwN9UZ+eeogK1fYHg4Qxk1yf/wLQkLXlq8wbU2dFlgAesxt8Gi76E8RTA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.1.0.tgz", + "integrity": "sha512-ypRueFNKTIFwqPeJBfeIpxZ895PQhNyH4YID6js0UoBImWYoSjBsahUn9KMiJXh94uOjVBgHD9AmkyPsPnFwJA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.0.1", - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/typescript-estree": "8.0.1" + "@typescript-eslint/scope-manager": "8.1.0", + "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/typescript-estree": "8.1.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.1.tgz", - "integrity": "sha512-W5E+o0UfUcK5EgchLZsyVWqARmsM7v54/qEq6PY3YI5arkgmCzHiuk0zKSJJbm71V0xdRna4BGomkCTXz2/LkQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.1.0.tgz", + "integrity": "sha512-ba0lNI19awqZ5ZNKh6wCModMwoZs457StTebQ0q1NP58zSi2F6MOZRXwfKZy+jB78JNJ/WH8GSh2IQNzXX8Nag==", "dev": true, "requires": { - "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/types": "8.1.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -10650,14 +10650,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.1.tgz", - "integrity": "sha512-V3Y+MdfhawxEjE16dWpb7/IOgeXnLwAEEkS7v8oDqNcR1oYlqWhGH/iHqHdKVdpWme1VPZ0SoywXAkCqawj2eQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.1.0.tgz", + "integrity": "sha512-prB2U3jXPJLpo1iVLN338Lvolh6OrcCZO+9Yv6AR+tvegPPptYCDBIHiEEUdqRi8gAv2bXNKfMUrgAd2ejn/ow==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.0.1", - "@typescript-eslint/parser": "8.0.1", - "@typescript-eslint/utils": "8.0.1" + "@typescript-eslint/eslint-plugin": "8.1.0", + "@typescript-eslint/parser": "8.1.0", + "@typescript-eslint/utils": "8.1.0" } }, "undici-types": { diff --git a/package.json b/package.json index 2e605e5c02..f46f9538d5 100644 --- a/package.json +++ b/package.json @@ -127,6 +127,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.4", "typescript": "^5.5.4", - "typescript-eslint": "^8.0.1" + "typescript-eslint": "^8.1.0" } } From d3a7ae8907db9adafd5afec004f6210d809c1def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 29 Aug 2024 13:14:36 +0200 Subject: [PATCH 492/525] Mitigate libsrtp wraparound with loss decryption failure (#1438) --- CHANGELOG.md | 1 + worker/include/RTC/PipeConsumer.hpp | 3 +- worker/include/RTC/SeqManager.hpp | 2 + worker/include/RTC/SimpleConsumer.hpp | 2 +- worker/include/RTC/SimulcastConsumer.hpp | 2 +- worker/include/RTC/SvcConsumer.hpp | 2 +- worker/src/RTC/PipeConsumer.cpp | 17 +- worker/src/RTC/SeqManager.cpp | 16 + worker/src/RTC/SimpleConsumer.cpp | 17 +- worker/src/RTC/SimulcastConsumer.cpp | 19 +- worker/src/RTC/SvcConsumer.cpp | 17 +- worker/test/src/RTC/TestSeqManager.cpp | 708 ++++++++++++++++++++++- 12 files changed, 783 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 181b238b1f..9acd0a5a6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT - `Worker`: Fix `io_uring` support detection ([PR #1445](https://github.com/versatica/mediasoup/pull/1445)). +- Mitigate libsrtp wraparound with loss decryption failure ([PR #1438](https://github.com/versatica/mediasoup/pull/1438)). ### 3.14.11 diff --git a/worker/include/RTC/PipeConsumer.hpp b/worker/include/RTC/PipeConsumer.hpp index 39066f4140..5a3e646467 100644 --- a/worker/include/RTC/PipeConsumer.hpp +++ b/worker/include/RTC/PipeConsumer.hpp @@ -73,7 +73,8 @@ namespace RTC absl::flat_hash_map mapSsrcRtpStream; bool keyFrameSupported{ false }; absl::flat_hash_map mapRtpStreamSyncRequired; - absl::flat_hash_map> mapRtpStreamRtpSeqManager; + absl::flat_hash_map>> + mapRtpStreamRtpSeqManager; }; } // namespace RTC diff --git a/worker/include/RTC/SeqManager.hpp b/worker/include/RTC/SeqManager.hpp index 8a7d4beb42..9f2cbd5374 100644 --- a/worker/include/RTC/SeqManager.hpp +++ b/worker/include/RTC/SeqManager.hpp @@ -36,6 +36,7 @@ namespace RTC public: SeqManager() = default; + SeqManager(T initialOutput); public: void Sync(T input); @@ -50,6 +51,7 @@ namespace RTC private: // Whether at least a sequence number has been inserted. bool started{ false }; + T initialOutput{ 0 }; T base{ 0 }; T maxOutput{ 0 }; T maxInput{ 0 }; diff --git a/worker/include/RTC/SimpleConsumer.hpp b/worker/include/RTC/SimpleConsumer.hpp index d502801e9b..d215d2b8ed 100644 --- a/worker/include/RTC/SimpleConsumer.hpp +++ b/worker/include/RTC/SimpleConsumer.hpp @@ -87,7 +87,7 @@ namespace RTC RTC::RtpStreamRecv* producerRtpStream{ nullptr }; bool keyFrameSupported{ false }; bool syncRequired{ false }; - RTC::SeqManager rtpSeqManager; + std::unique_ptr> rtpSeqManager; bool managingBitrate{ false }; std::unique_ptr encodingContext; }; diff --git a/worker/include/RTC/SimulcastConsumer.hpp b/worker/include/RTC/SimulcastConsumer.hpp index fcce57adb4..70c328971c 100644 --- a/worker/include/RTC/SimulcastConsumer.hpp +++ b/worker/include/RTC/SimulcastConsumer.hpp @@ -115,7 +115,7 @@ namespace RTC bool syncRequired{ false }; int16_t spatialLayerToSync{ -1 }; bool lastSentPacketHasMarker{ false }; - RTC::SeqManager rtpSeqManager; + std::unique_ptr> rtpSeqManager; int16_t preferredSpatialLayer{ -1 }; int16_t preferredTemporalLayer{ -1 }; int16_t provisionalTargetSpatialLayer{ -1 }; diff --git a/worker/include/RTC/SvcConsumer.hpp b/worker/include/RTC/SvcConsumer.hpp index c61220293f..cb860709d6 100644 --- a/worker/include/RTC/SvcConsumer.hpp +++ b/worker/include/RTC/SvcConsumer.hpp @@ -100,7 +100,7 @@ namespace RTC std::vector rtpStreams; RTC::RtpStreamRecv* producerRtpStream{ nullptr }; bool syncRequired{ false }; - RTC::SeqManager rtpSeqManager; + std::unique_ptr> rtpSeqManager; int16_t preferredSpatialLayer{ -1 }; int16_t preferredTemporalLayer{ -1 }; int16_t provisionalTargetSpatialLayer{ -1 }; diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index cde4fbfc76..8baedfefa5 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -4,6 +4,7 @@ #include "RTC/PipeConsumer.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/Codecs/Tools.hpp" namespace RTC @@ -264,7 +265,7 @@ namespace RTC // Packets with only padding are not forwarded. if (packet->GetPayloadLength() == 0) { - rtpSeqManager.Drop(packet->GetSequenceNumber()); + rtpSeqManager->Drop(packet->GetSequenceNumber()); #ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); @@ -284,7 +285,7 @@ namespace RTC MS_DEBUG_TAG(rtp, "sync key frame received"); } - rtpSeqManager.Sync(packet->GetSequenceNumber() - 1); + rtpSeqManager->Sync(packet->GetSequenceNumber() - 1); syncRequired = false; } @@ -292,7 +293,7 @@ namespace RTC // Update RTP seq number and timestamp. uint16_t seq; - rtpSeqManager.Input(packet->GetSequenceNumber(), seq); + rtpSeqManager->Input(packet->GetSequenceNumber(), seq); // Save original packet fields. auto origSsrc = packet->GetSsrc(); @@ -680,7 +681,15 @@ namespace RTC this->mapMappedSsrcSsrc[consumableEncoding.ssrc] = encoding.ssrc; this->mapSsrcRtpStream[encoding.ssrc] = rtpStream; this->mapRtpStreamSyncRequired[rtpStream] = false; - this->mapRtpStreamRtpSeqManager[rtpStream]; + + // Let's choose an initial output seq number between 1000 and 32768 to avoid + // libsrtp bug: + // https://github.com/versatica/mediasoup/issues/1437 + const uint16_t initialOutputSeq = + Utils::Crypto::GetRandomUInt(1000u, std::numeric_limits::max() / 2); + + this->mapRtpStreamRtpSeqManager[rtpStream].reset( + new RTC::SeqManager(initialOutputSeq)); } } diff --git a/worker/src/RTC/SeqManager.cpp b/worker/src/RTC/SeqManager.cpp index 2debeecd7f..119f46148a 100644 --- a/worker/src/RTC/SeqManager.cpp +++ b/worker/src/RTC/SeqManager.cpp @@ -39,9 +39,17 @@ namespace RTC return isSeqHigherThan(lhs, rhs); } + template + SeqManager::SeqManager(T initialOutput) : initialOutput(initialOutput) + { + MS_TRACE(); + } + template void SeqManager::Sync(T input) { + MS_TRACE(); + // Update base. this->base = (this->maxOutput - input) & MaxValue; @@ -55,6 +63,8 @@ namespace RTC template void SeqManager::Drop(T input) { + MS_TRACE(); + // Mark as dropped if 'input' is higher than anyone already processed. if (SeqManager::IsSeqHigherThan(input, this->maxInput)) { @@ -71,6 +81,8 @@ namespace RTC template bool SeqManager::Input(T input, T& output) { + MS_TRACE(); + auto base = this->base; // No dropped inputs to consider. @@ -140,6 +152,8 @@ namespace RTC } } + output = (output + this->initialOutput) & MaxValue; + return true; } @@ -162,6 +176,8 @@ namespace RTC template void SeqManager::ClearDropped() { + MS_TRACE(); + // Cleanup dropped values. if (this->dropped.empty()) { diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index d2b635babe..65deccbe2d 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -5,6 +5,7 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/Codecs/Tools.hpp" #include "RTC/SimpleConsumer.hpp" @@ -36,6 +37,14 @@ namespace RTC // Create RtpStreamSend instance for sending a single stream to the remote. CreateRtpStream(); + // Let's chosee an initial output seq number between 1000 and 32768 to avoid + // libsrtp bug: + // https://github.com/versatica/mediasoup/issues/1437 + const uint16_t initialOutputSeq = + Utils::Crypto::GetRandomUInt(1000u, std::numeric_limits::max() / 2); + + this->rtpSeqManager.reset(new RTC::SeqManager(initialOutputSeq)); + // Create the encoding context for Opus. if ( mediaCodec->mimeType.type == RTC::RtpCodecMimeType::Type::AUDIO && @@ -340,7 +349,7 @@ namespace RTC packet->GetSequenceNumber(), packet->GetTimestamp()); - this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + this->rtpSeqManager->Drop(packet->GetSequenceNumber()); #ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC); @@ -363,7 +372,7 @@ namespace RTC // Packets with only padding are not forwarded. if (packet->GetPayloadLength() == 0) { - this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + this->rtpSeqManager->Drop(packet->GetSequenceNumber()); #ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); @@ -383,7 +392,7 @@ namespace RTC MS_DEBUG_TAG(rtp, "sync key frame received"); } - this->rtpSeqManager.Sync(packet->GetSequenceNumber() - 1); + this->rtpSeqManager->Sync(packet->GetSequenceNumber() - 1); this->syncRequired = false; } @@ -391,7 +400,7 @@ namespace RTC // Update RTP seq number and timestamp. uint16_t seq; - this->rtpSeqManager.Input(packet->GetSequenceNumber(), seq); + this->rtpSeqManager->Input(packet->GetSequenceNumber(), seq); // Save original packet fields. auto origSsrc = packet->GetSsrc(); diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index bc54bf3424..fcd60c1c5f 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -5,6 +5,7 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/Codecs/Tools.hpp" namespace RTC @@ -98,6 +99,14 @@ namespace RTC "%s codec not supported for simulcast", mediaCodec->mimeType.ToString().c_str()); } + // Let's chosee an initial output seq number between 1000 and 32768 to avoid + // libsrtp bug: + // https://github.com/versatica/mediasoup/issues/1437 + const uint16_t initialOutputSeq = + Utils::Crypto::GetRandomUInt(1000u, std::numeric_limits::max() / 2); + + this->rtpSeqManager.reset(new RTC::SeqManager(initialOutputSeq)); + RTC::Codecs::EncodingContext::Params params; params.spatialLayers = encoding.spatialLayers; @@ -802,7 +811,7 @@ namespace RTC // not have payload other than padding, then drop it. if (spatialLayer == this->currentSpatialLayer && packet->GetPayloadLength() == 0) { - this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + this->rtpSeqManager->Drop(packet->GetSequenceNumber()); #ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); @@ -951,7 +960,7 @@ namespace RTC // 'packet->GetSequenceNumber() -2' may increase SeqManager::base and // increase the output sequence number. // https://github.com/versatica/mediasoup/issues/408 - this->rtpSeqManager.Sync(packet->GetSequenceNumber() - (this->lastSentPacketHasMarker ? 1 : 2)); + this->rtpSeqManager->Sync(packet->GetSequenceNumber() - (this->lastSentPacketHasMarker ? 1 : 2)); this->encodingContext->SyncRequired(); @@ -1013,7 +1022,7 @@ namespace RTC // Rewrite payload if needed. Drop packet if necessary. if (!packet->ProcessPayload(this->encodingContext.get(), marker)) { - this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + this->rtpSeqManager->Drop(packet->GetSequenceNumber()); #ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC); @@ -1032,7 +1041,7 @@ namespace RTC uint16_t seq; const uint32_t timestamp = packet->GetTimestamp() - this->tsOffset; - this->rtpSeqManager.Input(packet->GetSequenceNumber(), seq); + this->rtpSeqManager->Input(packet->GetSequenceNumber(), seq); // Save original packet fields. auto origSsrc = packet->GetSsrc(); @@ -1066,7 +1075,7 @@ namespace RTC // Process the packet. if (this->rtpStream->ReceivePacket(packet, sharedPacket)) { - if (this->rtpSeqManager.GetMaxOutput() == packet->GetSequenceNumber()) + if (this->rtpSeqManager->GetMaxOutput() == packet->GetSequenceNumber()) { this->lastSentPacketHasMarker = packet->HasMarker(); } diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index a2337b4f81..d5fb24d750 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -5,6 +5,7 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/Codecs/Tools.hpp" namespace RTC @@ -79,6 +80,14 @@ namespace RTC MS_THROW_TYPE_ERROR("%s codec not supported for svc", mediaCodec->mimeType.ToString().c_str()); } + // Let's chosee an initial output seq number between 1000 and 32768 to avoid + // libsrtp bug: + // https://github.com/versatica/mediasoup/issues/1437 + const uint16_t initialOutputSeq = + Utils::Crypto::GetRandomUInt(1000u, std::numeric_limits::max() / 2); + + this->rtpSeqManager.reset(new RTC::SeqManager(initialOutputSeq)); + RTC::Codecs::EncodingContext::Params params; params.spatialLayers = encoding.spatialLayers; @@ -681,7 +690,7 @@ namespace RTC // Packets with only padding are not forwarded. if (packet->GetPayloadLength() == 0) { - this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + this->rtpSeqManager->Drop(packet->GetSequenceNumber()); #ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD); @@ -701,7 +710,7 @@ namespace RTC MS_DEBUG_TAG(rtp, "sync key frame received"); } - this->rtpSeqManager.Sync(packet->GetSequenceNumber() - 1); + this->rtpSeqManager->Sync(packet->GetSequenceNumber() - 1); this->encodingContext->SyncRequired(); this->syncRequired = false; @@ -715,7 +724,7 @@ namespace RTC if (!packet->ProcessPayload(this->encodingContext.get(), marker)) { - this->rtpSeqManager.Drop(packet->GetSequenceNumber()); + this->rtpSeqManager->Drop(packet->GetSequenceNumber()); #ifdef MS_RTC_LOGGER_RTP packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC); @@ -738,7 +747,7 @@ namespace RTC // Update RTP seq number and timestamp based on NTP offset. uint16_t seq; - this->rtpSeqManager.Input(packet->GetSequenceNumber(), seq); + this->rtpSeqManager->Input(packet->GetSequenceNumber(), seq); // Save original packet fields. auto origSsrc = packet->GetSsrc(); diff --git a/worker/test/src/RTC/TestSeqManager.cpp b/worker/test/src/RTC/TestSeqManager.cpp index 564547b76a..9ae42b7ddd 100644 --- a/worker/test/src/RTC/TestSeqManager.cpp +++ b/worker/test/src/RTC/TestSeqManager.cpp @@ -6,7 +6,7 @@ using namespace RTC; -constexpr uint16_t kMaxNumberFor15Bits = (1 << 15) - 1; +constexpr uint16_t MaxNumberFor15Bits = (1 << 15) - 1; template struct TestSeqManagerInput @@ -176,6 +176,21 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") validate(seqManager2, inputs); } + SECTION("receive out of order numbers with a big jump") + { + // clang-format off + std::vector> inputs = + { + { 4, 4, false, false }, + { 3, 3, false, false }, + { 65535, 65535, false, false }, + }; + // clang-format on + + SeqManager seqManager; + validate(seqManager, inputs); + } + SECTION("receive mixed numbers with a big jump, drop before jump") { // clang-format off @@ -595,7 +610,7 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") { 0, 1, true, false, 0, }, }; for (uint16_t j = 0; j < 3; ++j) { - for (uint16_t i = 1; i < kMaxNumberFor15Bits; ++i) { + for (uint16_t i = 1; i < MaxNumberFor15Bits; ++i) { const uint16_t output = i + 1; inputs.emplace_back( i, output, false, false, i ); } @@ -726,4 +741,693 @@ SCENARIO("SeqManager", "[rtc][SeqMananger]") SeqManager seqManager; validate(seqManager, inputs); } + + SECTION("receive ordered numbers, no sync, no drop (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 1000, false, false }, + { 1, 1001, false, false }, + { 2, 1002, false, false }, + { 3, 1003, false, false }, + { 4, 1004, false, false }, + { 5, 1005, false, false }, + { 6, 1006, false, false }, + { 7, 1007, false, false }, + { 8, 1008, false, false }, + { 9, 1009, false, false }, + { 10, 1010, false, false }, + { 11, 1011, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 1000u); + SeqManager seqManager2(/*initialOutput*/ 1000u); + validate(seqManager, inputs); + validate(seqManager2, inputs); + } + + SECTION("receive ordered numbers, sync, no drop (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 2000, false, false }, + { 1, 2001, false, false }, + { 2, 2002, false, false }, + { 80, 2003, true, false }, + { 81, 2004, false, false }, + { 82, 2005, false, false }, + { 83, 2006, false, false }, + { 84, 2007, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 2000u); + SeqManager seqManager2(/*initialOutput*/ 2000u); + validate(seqManager, inputs); + validate(seqManager2, inputs); + } + + SECTION("receive ordered numbers, sync, drop (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 3000, false, false }, + { 1, 3001, false, false }, + { 2, 3002, false, false }, + { 3, 3003, false, false }, + { 4, 3004, true, false }, // sync. + { 5, 3005, false, false }, + { 6, 3006, false, false }, + { 7, 3007, true, false }, // sync. + { 8, 3000, false, true }, // drop. + { 9, 3008, false, false }, + { 11, 3000, false, true }, // drop. + { 10, 3009, false, false }, + { 12, 3010, false, false }, + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 3000u); + SeqManager seqManager2(/*initialOutput*/ 3000u); + validate(seqManager, inputs); + validate(seqManager2, inputs); + } + + SECTION("receive ordered wrapped numbers (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 65533, 997, false, false }, + { 65534, 998, false, false }, + { 65535, 999, false, false }, + { 0, 1000, false, false }, + { 1, 1001, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 1000u); + validate(seqManager, inputs); + } + + SECTION("receive sequence numbers with a big jump (with initial output)") + { + // clang-format off + std::vector> inputs1 = + { + { 0, 32000, false, false }, + { 1, 32001, false, false }, + { 1000, 33000, false, false }, + { 1001, 33001, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 32000u); + validate(seqManager, inputs1); + + // clang-format off + std::vector> inputs2 = + { + { 0, 32000, false, false }, + { 1, 32001, false, false }, + { 1000, 232, false, false }, + { 1001, 233, false, false } + }; + // clang-format on + + SeqManager seqManager2(/*initialOutput*/ 32000u); + validate(seqManager2, inputs2); + } + + SECTION("receive out of order numbers with a big jump (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 4, 1004, false, false }, + { 3, 1003, false, false }, + { 65535, 999, false, false }, + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 1000u); + validate(seqManager, inputs); + } + + SECTION("receive mixed numbers with a big jump, drop before jump (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 1000, false, false }, + { 1, 1000, false, true }, // drop. + { 100, 1099, false, false }, + { 100, 1099, false, false }, + { 103, 1000, false, true }, // drop. + { 101, 1100, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 1000); + SeqManager seqManager2(/*initialOutput*/ 1000); + validate(seqManager, inputs); + validate(seqManager2, inputs); + } + + SECTION("receive mixed numbers with a big jump, drop after jump (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 2000, false, false }, + { 1, 2001, false, false }, + { 100, 2000, false, true }, // drop. + { 103, 2000, false, true }, // drop. + { 101, 2100, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 2000); + SeqManager seqManager2(/*initialOutput*/ 2000); + validate(seqManager, inputs); + validate(seqManager2, inputs); + } + + SECTION("drop, receive numbers newer and older than the one dropped (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 2000, false, false }, + { 2, 2000, false, true }, // drop. + { 3, 2002, false, false }, + { 4, 2003, false, false }, + { 1, 2001, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 2000); + SeqManager seqManager2(/*initialOutput*/ 2000); + validate(seqManager, inputs); + validate(seqManager2, inputs); + } + + SECTION("receive mixed numbers, sync, drop (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 10000, false, false }, + { 1, 10001, false, false }, + { 2, 10002, false, false }, + { 3, 10003, false, false }, + { 7, 10007, false, false }, + { 6, 10000, false, true }, // drop. + { 8, 10008, false, false }, + { 10, 10010, false, false }, + { 9, 10009, false, false }, + { 11, 10011, false, false }, + { 0, 10012, true, false }, // sync. + { 2, 10014, false, false }, + { 3, 10015, false, false }, + { 4, 10016, false, false }, + { 5, 10017, false, false }, + { 6, 10018, false, false }, + { 7, 10019, false, false }, + { 8, 10020, false, false }, + { 9, 10021, false, false }, + { 10, 10022, false, false }, + { 9, 10000, false, true }, // drop. + { 61, 10023, true, false }, // sync. + { 62, 10024, false, false }, + { 63, 10025, false, false }, + { 64, 10026, false, false }, + { 65, 10027, false, false }, + { 11, 10028, true, false }, // sync. + { 12, 10029, false, false }, + { 13, 10030, false, false }, + { 14, 10031, false, false }, + { 15, 10032, false, false }, + { 1, 10033, true, false }, // sync. + { 2, 10034, false, false }, + { 3, 10035, false, false }, + { 4, 10036, false, false }, + { 5, 10037, false, false }, + { 65533, 10038, true, false }, // sync. + { 65534, 10039, false, false }, + { 65535, 10040, false, false }, + { 0, 10041, true, false }, // sync. + { 1, 10042, false, false }, + { 3, 10000, false, true }, // drop. + { 4, 10044, false, false }, + { 5, 10045, false, false }, + { 6, 10046, false, false }, + { 7, 10047, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 10000); + validate(seqManager, inputs); + } + + SECTION("receive ordered numbers, sync, no drop, increase input (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 1, false, false }, + { 1, 2, false, false }, + { 2, 3, false, false }, + { 80, 4, true, false }, + { 81, 5, false, false }, + { 82, 6, false, false }, + { 83, 7, false, false }, + { 84, 8, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 1); + SeqManager seqManager2(/*initialOutput*/ 1); + validate(seqManager, inputs); + validate(seqManager2, inputs); + } + + SECTION("drop many inputs at the beginning (using uint16_t) (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 1, 1001, false, false }, + { 2, 1000, false, true }, // drop. + { 3, 1000, false, true }, // drop. + { 4, 1000, false, true }, // drop. + { 5, 1000, false, true }, // drop. + { 6, 1000, false, true }, // drop. + { 7, 1000, false, true }, // drop. + { 8, 1000, false, true }, // drop. + { 9, 1000, false, true }, // drop. + { 120, 1112, false, false }, + { 121, 1113, false, false }, + { 122, 1114, false, false }, + { 123, 1115, false, false }, + { 124, 1116, false, false }, + { 125, 1117, false, false }, + { 126, 1118, false, false }, + { 127, 1119, false, false }, + { 128, 1120, false, false }, + { 129, 1121, false, false }, + { 130, 1122, false, false }, + { 131, 1123, false, false }, + { 132, 1124, false, false }, + { 133, 1125, false, false }, + { 134, 1126, false, false }, + { 135, 1127, false, false }, + { 136, 1128, false, false }, + { 137, 1129, false, false }, + { 138, 1130, false, false }, + { 139, 1131, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 1000); + SeqManager seqManager2(/*initialOutput*/ 1000); + validate(seqManager, inputs); + validate(seqManager2, inputs); + } + + SECTION("drop many inputs at the beginning (using uint8_t) (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 1, 201, false, false }, + { 2, 200, false, true }, // drop. + { 3, 200, false, true }, // drop. + { 4, 200, false, true }, // drop. + { 5, 200, false, true }, // drop. + { 6, 200, false, true }, // drop. + { 7, 200, false, true }, // drop. + { 8, 200, false, true }, // drop. + { 9, 200, false, true }, // drop. + { 120, 56, false, false }, + { 121, 57, false, false }, + { 122, 58, false, false }, + { 123, 59, false, false }, + { 124, 60, false, false }, + { 125, 61, false, false }, + { 126, 62, false, false }, + { 127, 63, false, false }, + { 128, 64, false, false }, + { 129, 65, false, false }, + { 130, 66, false, false }, + { 131, 67, false, false }, + { 132, 68, false, false }, + { 133, 69, false, false }, + { 134, 70, false, false }, + { 135, 71, false, false }, + { 136, 72, false, false }, + { 137, 73, false, false }, + { 138, 74, false, false }, + { 139, 75, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 200); + validate(seqManager, inputs); + } + + SECTION("receive mixed numbers, sync, drop in range 15 (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 100, false, false }, + { 1, 101, false, false }, + { 2, 102, false, false }, + { 3, 103, false, false }, + { 7, 107, false, false }, + { 6, 100, false, true }, // drop. + { 8, 108, false, false }, + { 10, 110, false, false }, + { 9, 109, false, false }, + { 11, 111, false, false }, + { 0, 112, true, false }, // sync. + { 2, 114, false, false }, + { 3, 115, false, false }, + { 4, 116, false, false }, + { 5, 117, false, false }, + { 6, 118, false, false }, + { 7, 119, false, false }, + { 8, 120, false, false }, + { 9, 121, false, false }, + { 10, 122, false, false }, + { 9, 100, false, true }, // drop. + { 61, 123, true, false }, // sync. + { 62, 124, false, false }, + { 63, 125, false, false }, + { 64, 126, false, false }, + { 65, 127, false, false }, + { 11, 128, true, false }, // sync. + { 12, 129, false, false }, + { 13, 130, false, false }, + { 14, 131, false, false }, + { 15, 132, false, false }, + { 1, 133, true, false }, // sync. + { 2, 134, false, false }, + { 3, 135, false, false }, + { 4, 136, false, false }, + { 5, 137, false, false }, + { 32767, 138, true, false }, // sync. + { 32768, 139, false, false }, + { 32769, 140, false, false }, + { 0, 141, true, false }, // sync. + { 1, 142, false, false }, + { 3, 100, false, true }, // drop. + { 4, 144, false, false }, + { 5, 145, false, false }, + { 6, 146, false, false }, + { 7, 147, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 100); + validate(seqManager, inputs); + } + + SECTION("drop many inputs at the beginning (using uint16_t with high values) (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 1, 201, false, false }, + { 2, 200, false, true }, // drop. + { 3, 200, false, true }, // drop. + { 4, 200, false, true }, // drop. + { 5, 200, false, true }, // drop. + { 6, 200, false, true }, // drop. + { 7, 200, false, true }, // drop. + { 8, 200, false, true }, // drop. + { 9, 200, false, true }, // drop. + { 32768, 32960, false, false }, + { 32769, 32961, false, false }, + { 32770, 32962, false, false }, + { 32771, 32963, false, false }, + { 32772, 32964, false, false }, + { 32773, 32965, false, false }, + { 32774, 32966, false, false }, + { 32775, 32967, false, false }, + { 32776, 32968, false, false }, + { 32777, 32969, false, false }, + { 32778, 32970, false, false }, + { 32779, 32971, false, false }, + { 32780, 32972, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 200); + validate(seqManager, inputs); + } + + SECTION("sync and drop some input near max-value (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 65530, 201, true, false }, + { 65531, 202, false, false }, + { 65532, 203, false, false }, + { 65533, 200, false, true }, + { 65534, 200, false, true }, + { 65535, 204, false, false }, + { 0, 205, false, false }, + { 1, 206, false, false }, + { 2, 207, false, false }, + { 3, 208, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 200); + validate(seqManager, inputs); + } + + SECTION( + "drop many inputs at the beginning (using uint16_t range 15 with high values) (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 1, 101, false, false }, + { 2, 100, false, true }, // drop. + { 3, 100, false, true }, // drop. + { 4, 100, false, true }, // drop. + { 5, 100, false, true }, // drop. + { 6, 100, false, true }, // drop. + { 7, 100, false, true }, // drop. + { 8, 100, false, true }, // drop. + { 9, 100, false, true }, // drop. + { 16384, 16476, false, false }, + { 16385, 16477, false, false }, + { 16386, 16478, false, false }, + { 16387, 16479, false, false }, + { 16388, 16480, false, false }, + { 16389, 16481, false, false }, + { 16390, 16482, false, false }, + { 16391, 16483, false, false }, + { 16392, 16484, false, false }, + { 16393, 16485, false, false }, + { 16394, 16486, false, false }, + { 16395, 16487, false, false }, + { 16396, 16488, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 100); + validate(seqManager, inputs); + } + + SECTION("sync and drop some input near max-value in a 15bit range (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 32762, 101, true, false, 32762 }, + { 32763, 102, false, false, 32763 }, + { 32764, 103, false, false, 32764 }, + { 32765, 100, false, true, 32765 }, + { 32766, 100, false, true, 32766 }, + { 32767, 104, false, false, 32767 }, + { 0, 105, false, false, 0 }, + { 1, 106, false, false, 1 }, + { 2, 107, false, false, 2 }, + { 3, 108, false, false, 3 } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 100); + validate(seqManager, inputs); + } + + SECTION("should update all values during multiple roll overs (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 101, true, false, 0 }, + }; + for (uint16_t j = 0; j < 3; ++j) { + for (uint16_t i = 1; i < std::numeric_limits::max(); ++i) { + const uint16_t output = (i + 1 + 100) & std::numeric_limits::max(); + inputs.emplace_back( i, output, false, false, i ); + } + } + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 100); + validate(seqManager, inputs); + } + + SECTION("should update all values during multiple roll overs (15 bits range) (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 0, 101, true, false, 0, }, + }; + for (uint16_t j = 0; j < 3; ++j) { + for (uint16_t i = 1; i < MaxNumberFor15Bits; ++i) { + const uint16_t output = (i + 1 + 100) & MaxNumberFor15Bits; + inputs.emplace_back( i, output, false, false, i ); + } + } + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 100); + validate(seqManager, inputs); + } + + SECTION( + "should produce same output for same old input before drop (15 bits range) (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 10, 10001, true, false }, // sync. + { 11, 10002, false, false }, + { 12, 10003, false, false }, + { 13, 10004, false, false }, + { 14, 10000, false, true }, // drop. + { 15, 10005, false, false }, + { 12, 10003, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 10000); + validate(seqManager, inputs); + } + + SECTION("should properly clean previous cycle drops (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 1, 3, false, false }, + { 2, 2, false, true }, // Drop. + { 3, 4, false, false }, + { 4, 5, false, false }, + { 5, 6, false, false }, + { 6, 7, false, false }, + { 7, 0, false, false }, + { 0, 1, false, false }, + { 1, 2, false, false }, + { 2, 3, false, false }, + { 3, 4, false, false } + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 2); + validate(seqManager, inputs); + } + + SECTION("dropped inputs to be removed going out of range, 1. (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 36964, 46964, false, false }, + { 25923, 10000, false, true }, // Drop. + { 25701, 35701, false, false }, + { 17170, 10000, false, true }, // Drop. + { 25923, 35923, false, false }, + { 4728, 10000, false, true }, // Drop. + { 17170, 27170, false, false }, + { 30738, 10000, false, true }, // Drop. + { 4728, 14728, false, false }, + { 4806, 10000, false, true }, // Drop. + { 30738, 40738, false, false }, + { 50886, 10000, false, true }, // Drop. + { 4806, 14805, false, false }, // Previously dropped. + { 50774, 10000, false, true }, // Drop. + { 50886, 14805, false, false }, // Previously dropped. + { 22136, 10000, false, true }, // Drop. + { 50774, 60773, false, false }, + { 30910, 10000, false, true }, // Drop. + { 22136, 60773, false, false }, // Previously dropped. + { 48862, 10000, false, true }, // Drop. + { 30910, 40909, false, false }, + { 56832, 10000, false, true }, // Drop. + { 48862, 58861, false, false }, + { 2, 10000, false, true }, // Drop. + { 56832, 58861, false, false }, // Previously dropped. + { 530, 10000, false, true }, // Drop. + { 2, 58861, false, false }, // Previously dropped. + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 10000); + validate(seqManager, inputs); + } + + SECTION("dropped inputs to be removed go out of range, 2. (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 36960, 37060, false, false }, + { 3328, 100, false, true }, // Drop. + { 24589, 24688, false, false }, + { 120, 100, false, true }, // Drop. + { 3328, 24688, false, false }, // Previously dropped. + { 30848, 100, false, true }, // Drop. + { 120, 220, false, false }, + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 100); + validate(seqManager, inputs); + } + + SECTION("dropped inputs to be removed go out of range, 3. (with initial output)") + { + // clang-format off + std::vector> inputs = + { + { 36964, 37964, false, false }, + { 65396 , 1000, false, true }, // Drop. + { 25855, 26854, false, false }, + { 29793 , 1000, false, true }, // Drop. + { 65396, 26854, false, false }, // Previously dropped. + { 25087, 1000, false, true }, // Drop. + { 29793, 26854, false, false }, // Previously dropped. + { 65535 , 1000, false, true }, // Drop. + { 25087, 26086, false, false }, + }; + // clang-format on + + SeqManager seqManager(/*initialOutput*/ 1000); + validate(seqManager, inputs); + } } From e8fbda69aa4a59dd1abee9f6390f52536c079b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 29 Aug 2024 15:12:08 +0200 Subject: [PATCH 493/525] update NPM deps --- package-lock.json | 483 +++++++++++++++++----------------------------- package.json | 14 +- 2 files changed, 186 insertions(+), 311 deletions(-) diff --git a/package-lock.json b/package-lock.json index 37b65b93c0..765fcf5eca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,25 +20,25 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.9.0", - "@octokit/rest": "^21.0.1", + "@eslint/js": "^9.9.1", + "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^22.2.0", - "eslint": "^9.9.0", + "@types/node": "^22.5.1", + "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.0", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "marked": "^14.0.0", + "marked": "^14.1.0", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", - "ts-jest": "^29.2.4", + "ts-jest": "^29.2.5", "typescript": "^5.5.4", - "typescript-eslint": "^8.1.0" + "typescript-eslint": "^8.3.0" }, "engines": { "node": ">=18" @@ -748,9 +748,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", - "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", "dev": true, "dependencies": { "@eslint/object-schema": "^2.1.4", @@ -797,9 +797,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz", - "integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", + "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1550,9 +1550,9 @@ } }, "node_modules/@octokit/rest": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.1.tgz", - "integrity": "sha512-RWA6YU4CqK0h0J6tfYlUFnH3+YgBADlxaHXaKSG+BVr2y4PTfbU2tlKuaQoQZ83qaTbi4CUxLNAmbAqR93A6mQ==", + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.2.tgz", + "integrity": "sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ==", "dev": true, "dependencies": { "@octokit/core": "^6.1.2", @@ -1860,12 +1860,12 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz", - "integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==", + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", + "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", "dev": true, "dependencies": { - "undici-types": "~6.13.0" + "undici-types": "~6.19.2" } }, "node_modules/@types/stack-utils": { @@ -1890,16 +1890,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.1.0.tgz", - "integrity": "sha512-LlNBaHFCEBPHyD4pZXb35mzjGkuGKXU5eeCA1SxvHfiRES0E82dOounfVpL4DCqYvJEKab0bZIA0gCRpdLKkCw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", + "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.1.0", - "@typescript-eslint/type-utils": "8.1.0", - "@typescript-eslint/utils": "8.1.0", - "@typescript-eslint/visitor-keys": "8.1.0", + "@typescript-eslint/scope-manager": "8.3.0", + "@typescript-eslint/type-utils": "8.3.0", + "@typescript-eslint/utils": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1923,15 +1923,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.1.0.tgz", - "integrity": "sha512-U7iTAtGgJk6DPX9wIWPPOlt1gO57097G06gIcl0N0EEnNw8RGD62c+2/DiP/zL7KrkqnnqF7gtFGR7YgzPllTA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz", + "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.1.0", - "@typescript-eslint/types": "8.1.0", - "@typescript-eslint/typescript-estree": "8.1.0", - "@typescript-eslint/visitor-keys": "8.1.0", + "@typescript-eslint/scope-manager": "8.3.0", + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/typescript-estree": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0", "debug": "^4.3.4" }, "engines": { @@ -1951,13 +1951,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.1.0.tgz", - "integrity": "sha512-DsuOZQji687sQUjm4N6c9xABJa7fjvfIdjqpSIIVOgaENf2jFXiM9hIBZOL3hb6DHK9Nvd2d7zZnoMLf9e0OtQ==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", + "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.1.0", - "@typescript-eslint/visitor-keys": "8.1.0" + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1968,13 +1968,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.1.0.tgz", - "integrity": "sha512-oLYvTxljVvsMnldfl6jIKxTaU7ok7km0KDrwOt1RHYu6nxlhN3TIx8k5Q52L6wR33nOwDgM7VwW1fT1qMNfFIA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", + "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.1.0", - "@typescript-eslint/utils": "8.1.0", + "@typescript-eslint/typescript-estree": "8.3.0", + "@typescript-eslint/utils": "8.3.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1992,9 +1992,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.1.0.tgz", - "integrity": "sha512-q2/Bxa0gMOu/2/AKALI0tCKbG2zppccnRIRCW6BaaTlRVaPKft4oVYPp7WOPpcnsgbr0qROAVCVKCvIQ0tbWog==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", + "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2005,15 +2005,15 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.1.0.tgz", - "integrity": "sha512-NTHhmufocEkMiAord/g++gWKb0Fr34e9AExBRdqgWdVBaKoei2dIyYKD9Q0jBnvfbEA5zaf8plUFMUH6kQ0vGg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", + "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.1.0", - "@typescript-eslint/visitor-keys": "8.1.0", + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", @@ -2057,15 +2057,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.1.0.tgz", - "integrity": "sha512-ypRueFNKTIFwqPeJBfeIpxZ895PQhNyH4YID6js0UoBImWYoSjBsahUn9KMiJXh94uOjVBgHD9AmkyPsPnFwJA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", + "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.1.0", - "@typescript-eslint/types": "8.1.0", - "@typescript-eslint/typescript-estree": "8.1.0" + "@typescript-eslint/scope-manager": "8.3.0", + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/typescript-estree": "8.3.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2079,12 +2079,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.1.0.tgz", - "integrity": "sha512-ba0lNI19awqZ5ZNKh6wCModMwoZs457StTebQ0q1NP58zSi2F6MOZRXwfKZy+jB78JNJ/WH8GSh2IQNzXX8Nag==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", + "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/types": "8.3.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2200,15 +2200,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -2750,18 +2741,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2836,16 +2815,16 @@ } }, "node_modules/eslint": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.0.tgz", - "integrity": "sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", + "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.17.1", + "@eslint/config-array": "^0.18.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.9.0", + "@eslint/js": "9.9.1", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -3494,26 +3473,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -4654,18 +4613,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -4697,9 +4644,9 @@ } }, "node_modules/marked": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", - "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.0.tgz", + "integrity": "sha512-P93GikH/Pde0hM5TAXEd8I4JAYi8IB03n8qzW8Bh1BIEFpEyBoYxi/XWZA53LSpTeLBiMQOoSMj0u5E/tiVYTA==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -5147,15 +5094,6 @@ "node": "14 || >=16.14" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/peek-readable": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", @@ -5579,13 +5517,10 @@ } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -5989,20 +5924,20 @@ } }, "node_modules/ts-jest": { - "version": "29.2.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", - "integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==", + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", "dev": true, "dependencies": { - "bs-logger": "0.x", + "bs-logger": "^0.2.6", "ejs": "^3.1.10", - "fast-json-stable-stringify": "2.x", + "fast-json-stable-stringify": "^2.1.0", "jest-util": "^29.0.0", "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" }, "bin": { "ts-jest": "cli.js" @@ -6077,14 +6012,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.1.0.tgz", - "integrity": "sha512-prB2U3jXPJLpo1iVLN338Lvolh6OrcCZO+9Yv6AR+tvegPPptYCDBIHiEEUdqRi8gAv2bXNKfMUrgAd2ejn/ow==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz", + "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.1.0", - "@typescript-eslint/parser": "8.1.0", - "@typescript-eslint/utils": "8.1.0" + "@typescript-eslint/eslint-plugin": "8.3.0", + "@typescript-eslint/parser": "8.3.0", + "@typescript-eslint/utils": "8.3.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6100,11 +6035,10 @@ } }, "node_modules/undici-types": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", - "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", - "dev": true, - "license": "MIT" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true }, "node_modules/unique-string": { "version": "3.0.0", @@ -6282,12 +6216,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -6863,9 +6791,9 @@ "dev": true }, "@eslint/config-array": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", - "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", "dev": true, "requires": { "@eslint/object-schema": "^2.1.4", @@ -6899,9 +6827,9 @@ } }, "@eslint/js": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz", - "integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", + "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", "dev": true }, "@eslint/object-schema": { @@ -7466,9 +7394,9 @@ } }, "@octokit/rest": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.1.tgz", - "integrity": "sha512-RWA6YU4CqK0h0J6tfYlUFnH3+YgBADlxaHXaKSG+BVr2y4PTfbU2tlKuaQoQZ83qaTbi4CUxLNAmbAqR93A6mQ==", + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.2.tgz", + "integrity": "sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ==", "dev": true, "requires": { "@octokit/core": "^6.1.2", @@ -7743,12 +7671,12 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz", - "integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==", + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", + "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", "dev": true, "requires": { - "undici-types": "~6.13.0" + "undici-types": "~6.19.2" } }, "@types/stack-utils": { @@ -7773,16 +7701,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.1.0.tgz", - "integrity": "sha512-LlNBaHFCEBPHyD4pZXb35mzjGkuGKXU5eeCA1SxvHfiRES0E82dOounfVpL4DCqYvJEKab0bZIA0gCRpdLKkCw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", + "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.1.0", - "@typescript-eslint/type-utils": "8.1.0", - "@typescript-eslint/utils": "8.1.0", - "@typescript-eslint/visitor-keys": "8.1.0", + "@typescript-eslint/scope-manager": "8.3.0", + "@typescript-eslint/type-utils": "8.3.0", + "@typescript-eslint/utils": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7790,56 +7718,56 @@ } }, "@typescript-eslint/parser": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.1.0.tgz", - "integrity": "sha512-U7iTAtGgJk6DPX9wIWPPOlt1gO57097G06gIcl0N0EEnNw8RGD62c+2/DiP/zL7KrkqnnqF7gtFGR7YgzPllTA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz", + "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.1.0", - "@typescript-eslint/types": "8.1.0", - "@typescript-eslint/typescript-estree": "8.1.0", - "@typescript-eslint/visitor-keys": "8.1.0", + "@typescript-eslint/scope-manager": "8.3.0", + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/typescript-estree": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.1.0.tgz", - "integrity": "sha512-DsuOZQji687sQUjm4N6c9xABJa7fjvfIdjqpSIIVOgaENf2jFXiM9hIBZOL3hb6DHK9Nvd2d7zZnoMLf9e0OtQ==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", + "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", "dev": true, "requires": { - "@typescript-eslint/types": "8.1.0", - "@typescript-eslint/visitor-keys": "8.1.0" + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0" } }, "@typescript-eslint/type-utils": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.1.0.tgz", - "integrity": "sha512-oLYvTxljVvsMnldfl6jIKxTaU7ok7km0KDrwOt1RHYu6nxlhN3TIx8k5Q52L6wR33nOwDgM7VwW1fT1qMNfFIA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", + "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.1.0", - "@typescript-eslint/utils": "8.1.0", + "@typescript-eslint/typescript-estree": "8.3.0", + "@typescript-eslint/utils": "8.3.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.1.0.tgz", - "integrity": "sha512-q2/Bxa0gMOu/2/AKALI0tCKbG2zppccnRIRCW6BaaTlRVaPKft4oVYPp7WOPpcnsgbr0qROAVCVKCvIQ0tbWog==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", + "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.1.0.tgz", - "integrity": "sha512-NTHhmufocEkMiAord/g++gWKb0Fr34e9AExBRdqgWdVBaKoei2dIyYKD9Q0jBnvfbEA5zaf8plUFMUH6kQ0vGg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", + "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", "dev": true, "requires": { - "@typescript-eslint/types": "8.1.0", - "@typescript-eslint/visitor-keys": "8.1.0", + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", @@ -7867,24 +7795,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.1.0.tgz", - "integrity": "sha512-ypRueFNKTIFwqPeJBfeIpxZ895PQhNyH4YID6js0UoBImWYoSjBsahUn9KMiJXh94uOjVBgHD9AmkyPsPnFwJA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", + "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.1.0", - "@typescript-eslint/types": "8.1.0", - "@typescript-eslint/typescript-estree": "8.1.0" + "@typescript-eslint/scope-manager": "8.3.0", + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/typescript-estree": "8.3.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.1.0.tgz", - "integrity": "sha512-ba0lNI19awqZ5ZNKh6wCModMwoZs457StTebQ0q1NP58zSi2F6MOZRXwfKZy+jB78JNJ/WH8GSh2IQNzXX8Nag==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", + "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", "dev": true, "requires": { - "@typescript-eslint/types": "8.1.0", + "@typescript-eslint/types": "8.3.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -7959,12 +7887,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, "async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -8348,15 +8270,6 @@ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -8410,16 +8323,16 @@ "dev": true }, "eslint": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.0.tgz", - "integrity": "sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", + "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.17.1", + "@eslint/config-array": "^0.18.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.9.0", + "@eslint/js": "9.9.1", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -8858,20 +8771,6 @@ "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -9711,15 +9610,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -9745,9 +9635,9 @@ } }, "marked": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", - "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.0.tgz", + "integrity": "sha512-P93GikH/Pde0hM5TAXEd8I4JAYi8IB03n8qzW8Bh1BIEFpEyBoYxi/XWZA53LSpTeLBiMQOoSMj0u5E/tiVYTA==", "dev": true }, "meow": { @@ -10044,12 +9934,6 @@ } } }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, "peek-readable": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", @@ -10316,13 +10200,10 @@ } }, "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true }, "shebang-command": { "version": "2.0.0", @@ -10606,20 +10487,20 @@ "requires": {} }, "ts-jest": { - "version": "29.2.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", - "integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==", + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", "dev": true, "requires": { - "bs-logger": "0.x", + "bs-logger": "^0.2.6", "ejs": "^3.1.10", - "fast-json-stable-stringify": "2.x", + "fast-json-stable-stringify": "^2.1.0", "jest-util": "^29.0.0", "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" } }, "tslib": { @@ -10650,20 +10531,20 @@ "dev": true }, "typescript-eslint": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.1.0.tgz", - "integrity": "sha512-prB2U3jXPJLpo1iVLN338Lvolh6OrcCZO+9Yv6AR+tvegPPptYCDBIHiEEUdqRi8gAv2bXNKfMUrgAd2ejn/ow==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz", + "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.1.0", - "@typescript-eslint/parser": "8.1.0", - "@typescript-eslint/utils": "8.1.0" + "@typescript-eslint/eslint-plugin": "8.3.0", + "@typescript-eslint/parser": "8.3.0", + "@typescript-eslint/utils": "8.3.0" } }, "undici-types": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", - "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, "unique-string": { @@ -10791,12 +10672,6 @@ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index f46f9538d5..21e50b771c 100644 --- a/package.json +++ b/package.json @@ -109,24 +109,24 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.9.0", - "@octokit/rest": "^21.0.1", + "@eslint/js": "^9.9.1", + "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^22.2.0", - "eslint": "^9.9.0", + "@types/node": "^22.5.1", + "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.0", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "marked": "^14.0.0", + "marked": "^14.1.0", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", - "ts-jest": "^29.2.4", + "ts-jest": "^29.2.5", "typescript": "^5.5.4", - "typescript-eslint": "^8.1.0" + "typescript-eslint": "^8.3.0" } } From 9fd1d5e8c39c836737ea51cf76cdb93d704e59ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 30 Aug 2024 10:54:50 +0200 Subject: [PATCH 494/525] Node: New setLogEventListeners() utility to get log events (#1448) --- CHANGELOG.md | 1 + node/src/ActiveSpeakerObserver.ts | 2 +- node/src/AudioLevelObserver.ts | 2 +- node/src/Consumer.ts | 2 +- node/src/DataConsumer.ts | 7 ++-- node/src/DirectTransport.ts | 2 +- node/src/Logger.ts | 46 ++++++++++++++++++++---- node/src/PipeTransport.ts | 2 +- node/src/PlainTransport.ts | 2 +- node/src/Producer.ts | 2 +- node/src/Router.ts | 17 ++++----- node/src/Transport.ts | 6 ++-- node/src/WebRtcTransport.ts | 2 +- node/src/Worker.ts | 34 +++++------------- node/src/enhancedEvents.ts | 5 ++- node/src/index.ts | 60 ++++++++++++++++++++++++++++++- node/src/test/test-mediasoup.ts | 22 ++++++++++++ node/src/types.ts | 41 ++++++++++----------- 18 files changed, 173 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9acd0a5a6e..24b9af5a25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - `Worker`: Fix `io_uring` support detection ([PR #1445](https://github.com/versatica/mediasoup/pull/1445)). - Mitigate libsrtp wraparound with loss decryption failure ([PR #1438](https://github.com/versatica/mediasoup/pull/1438)). +- Node: New `setLogEventListeners()` utility to get log events ([PR #1448](https://github.com/versatica/mediasoup/pull/1448)). ### 3.14.11 diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index 9187175115..609e6581e5 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -103,7 +103,7 @@ export class ActiveSpeakerObserver< } default: { - logger.error('ignoring unknown event "%s"', event); + logger.error(`ignoring unknown event "${event}"`); } } } diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index e0a91e408d..d429933954 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -147,7 +147,7 @@ export class AudioLevelObserver< } default: { - logger.error('ignoring unknown event "%s"', event); + logger.error(`ignoring unknown event "${event}"`); } } } diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index cb6314eea2..5945f8993b 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -899,7 +899,7 @@ export class Consumer< } default: { - logger.error('ignoring unknown event "%s"', event); + logger.error(`ignoring unknown event "${event}"`); } } } diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 19e66b5267..f05b998d17 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -430,7 +430,7 @@ export class DataConsumer< * Set buffered amount low threshold. */ async setBufferedAmountLowThreshold(threshold: number): Promise { - logger.debug('setBufferedAmountLowThreshold() [threshold:%s]', threshold); + logger.debug(`setBufferedAmountLowThreshold() [threshold:${threshold}]`); /* Build Request. */ const requestOffset = @@ -714,10 +714,7 @@ export class DataConsumer< } default: { - logger.error( - 'ignoring unknown event "%s" in channel listener', - event - ); + logger.error(`ignoring unknown event "${event}"`); } } } diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index ea5f2b8684..0774a088f7 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -276,7 +276,7 @@ export class DirectTransport< } default: { - logger.error('ignoring unknown event "%s"', event); + logger.error(`ignoring unknown event "${event}"`); } } } diff --git a/node/src/Logger.ts b/node/src/Logger.ts index 96f5054b75..66b5456c0c 100644 --- a/node/src/Logger.ts +++ b/node/src/Logger.ts @@ -1,12 +1,35 @@ import debug from 'debug'; +import { EnhancedEventEmitter } from './enhancedEvents'; const APP_NAME = 'mediasoup'; +export type LoggerEmitterEvents = { + debuglog: [string, string]; + warnlog: [string, string]; + errorlog: [string, string, Error?]; +}; + +export type LoggerEmitter = EnhancedEventEmitter; + export class Logger { + private static debugLogEmitter?: LoggerEmitter; + private static warnLogEmitter?: LoggerEmitter; + private static errorLogEmitter?: LoggerEmitter; + readonly #debug: debug.Debugger; readonly #warn: debug.Debugger; readonly #error: debug.Debugger; + static setEmitters( + debugLogEmitter?: LoggerEmitter, + warnLogEmitter?: LoggerEmitter, + errorLogEmitter?: LoggerEmitter + ): void { + Logger.debugLogEmitter = debugLogEmitter; + Logger.warnLogEmitter = warnLogEmitter; + Logger.errorLogEmitter = errorLogEmitter; + } + constructor(prefix?: string) { if (prefix) { this.#debug = debug(`${APP_NAME}:${prefix}`); @@ -25,15 +48,26 @@ export class Logger { /* eslint-enable no-console */ } - get debug(): debug.Debugger { - return this.#debug; + debug(log: string): void { + this.#debug(log); + + Logger.debugLogEmitter?.safeEmit('debuglog', this.#debug.namespace, log); } - get warn(): debug.Debugger { - return this.#warn; + warn(log: string): void { + this.#warn(log); + + Logger.warnLogEmitter?.safeEmit('warnlog', this.#warn.namespace, log); } - get error(): debug.Debugger { - return this.#error; + error(log: string, error?: Error): void { + this.#error(log, error); + + Logger.errorLogEmitter?.safeEmit( + 'errorlog', + this.#error.namespace, + log, + error + ); } } diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index 61a30bbf07..d15dd5025a 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -450,7 +450,7 @@ export class PipeTransport< } default: { - logger.error('ignoring unknown event "%s"', event); + logger.error(`ignoring unknown event "${event}"`); } } } diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index c4202eec7e..e1eabcac62 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -451,7 +451,7 @@ export class PlainTransport< } default: { - logger.error('ignoring unknown event "%s"', event); + logger.error(`ignoring unknown event "${event}"`); } } } diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 4ab4b64620..c9c05b2aec 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -586,7 +586,7 @@ export class Producer< } default: { - logger.error('ignoring unknown event "%s"', event); + logger.error(`ignoring unknown event "${event}"`); } } } diff --git a/node/src/Router.ts b/node/src/Router.ts index 70fc9ffb27..755d579f72 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -1212,7 +1212,7 @@ export class Router< }) .catch(error => { logger.error( - 'pipeToRouter() | error creating PipeTransport pair:%o', + 'pipeToRouter() | error creating PipeTransport pair:', error ); @@ -1281,8 +1281,8 @@ export class Router< return { pipeConsumer, pipeProducer }; } catch (error) { logger.error( - 'pipeToRouter() | error creating pipe Consumer/Producer pair:%o', - error + 'pipeToRouter() | error creating pipe Consumer/Producer pair:', + error as Error ); if (pipeConsumer) { @@ -1326,8 +1326,8 @@ export class Router< return { pipeDataConsumer, pipeDataProducer }; } catch (error) { logger.error( - 'pipeToRouter() | error creating pipe DataConsumer/DataProducer pair:%o', - error + 'pipeToRouter() | error creating pipe DataConsumer/DataProducer pair:', + error as Error ); pipeDataConsumer?.close(); @@ -1526,10 +1526,7 @@ export class Router< const producer = this.#producers.get(producerId); if (!producer) { - logger.error( - 'canConsume() | Producer with id "%s" not found', - producerId - ); + logger.error(`canConsume() | Producer with id "${producerId}" not found`); return false; } @@ -1543,7 +1540,7 @@ export class Router< clonedRtpCapabilities ); } catch (error) { - logger.error('canConsume() | unexpected error: %s', String(error)); + logger.error(`canConsume() | unexpected error: ${error}`); return false; } diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 8559b5961e..7448e8a438 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -667,7 +667,7 @@ export abstract class Transport< * Set maximum incoming bitrate for receiving media. */ async setMaxIncomingBitrate(bitrate: number): Promise { - logger.debug('setMaxIncomingBitrate() [bitrate:%s]', bitrate); + logger.debug(`setMaxIncomingBitrate() [bitrate:${bitrate}]`); /* Build Request. */ const requestOffset = @@ -688,7 +688,7 @@ export abstract class Transport< * Set maximum outgoing bitrate for sending media. */ async setMaxOutgoingBitrate(bitrate: number): Promise { - logger.debug('setMaxOutgoingBitrate() [bitrate:%s]', bitrate); + logger.debug(`setMaxOutgoingBitrate() [bitrate:${bitrate}]`); /* Build Request. */ const requestOffset = new FbsTransport.SetMaxOutgoingBitrateRequestT( @@ -707,7 +707,7 @@ export abstract class Transport< * Set minimum outgoing bitrate for sending media. */ async setMinOutgoingBitrate(bitrate: number): Promise { - logger.debug('setMinOutgoingBitrate() [bitrate:%s]', bitrate); + logger.debug(`setMinOutgoingBitrate() [bitrate:${bitrate}]`); /* Build Request. */ const requestOffset = new FbsTransport.SetMinOutgoingBitrateRequestT( diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 34ca5014a3..9f908ec19c 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -644,7 +644,7 @@ export class WebRtcTransport< } default: { - logger.error('ignoring unknown event "%s"', event); + logger.error(`ignoring unknown event "${event}"`); } } } diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 73480a406d..c1d2e20f7c 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -348,11 +348,7 @@ export class Worker< spawnArgs.push(`--disableLiburing=true`); } - logger.debug( - 'spawning worker process: %s %s', - spawnBin, - spawnArgs.join(' ') - ); + logger.debug(`spawning worker process: ${spawnBin} ${spawnArgs.join(' ')}`); this.#child = spawn( // command @@ -398,7 +394,7 @@ export class Worker< if (!spawnDone && event === Event.WORKER_RUNNING) { spawnDone = true; - logger.debug('worker process running [pid:%s]', this.#pid); + logger.debug(`worker process running [pid:${this.#pid}]`); this.emit('@success'); } @@ -415,18 +411,14 @@ export class Worker< if (code === 42) { logger.error( - 'worker process failed due to wrong settings [pid:%s]', - this.#pid + `worker process failed due to wrong settings [pid:${this.#pid}]` ); this.close(); this.emit('@failure', new TypeError('wrong settings')); } else { logger.error( - 'worker process failed unexpectedly [pid:%s, code:%s, signal:%s]', - this.#pid, - code, - signal + `worker process failed unexpectedly [pid:${this.#pid}, code:${code}, signal:${signal}]` ); this.close(); @@ -437,10 +429,7 @@ export class Worker< } } else { logger.error( - 'worker process died unexpectedly [pid:%s, code:%s, signal:%s]', - this.#pid, - code, - signal + `worker process died unexpectedly [pid:${this.#pid}, code:${code}, signal:${signal}]` ); this.workerDied( @@ -459,18 +448,14 @@ export class Worker< spawnDone = true; logger.error( - 'worker process failed [pid:%s]: %s', - this.#pid, - error.message + `worker process failed [pid:${this.#pid}]: ${error.message}` ); this.close(); this.emit('@failure', error); } else { logger.error( - 'worker process error [pid:%s]: %s', - this.#pid, - error.message + `worker process error [pid:${this.#pid}]: ${error.message}` ); this.workerDied(error); @@ -479,10 +464,7 @@ export class Worker< this.#child.on('close', (code, signal) => { logger.debug( - 'worker subprocess closed [pid:%s, code:%s, signal:%s]', - this.#pid, - code, - signal + `worker subprocess closed [pid:${this.#pid}, code:${code}, signal:${signal}]` ); this.#subprocessClosed = true; diff --git a/node/src/enhancedEvents.ts b/node/src/enhancedEvents.ts index e2ef6a34fb..a0fbfba558 100644 --- a/node/src/enhancedEvents.ts +++ b/node/src/enhancedEvents.ts @@ -25,9 +25,8 @@ export class EnhancedEventEmitter< return super.emit(eventName, ...args); } catch (error) { enhancedEventEmitterLogger.error( - 'safeEmit() | event listener threw an error [eventName:%s]:%o', - eventName, - error + `safeEmit() | event listener threw an error [eventName:${eventName}]:`, + error as Error ); try { diff --git a/node/src/index.ts b/node/src/index.ts index 1c02f63c23..9239dc77ac 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -1,4 +1,4 @@ -import { Logger } from './Logger'; +import { Logger, LoggerEmitter } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; import { workerBin, Worker, WorkerSettings } from './Worker'; import * as utils from './utils'; @@ -43,6 +43,64 @@ export { workerBin }; const logger = new Logger(); +/** + * Event listeners for mediasoup generated logs. + */ +export type LogEventListeners = { + ondebug?: (namespace: string, log: string) => void; + onwarn?: (namespace: string, log: string) => void; + onerror?: (namespace: string, log: string, error?: Error) => void; +}; + +/** + * Set event listeners for mediasoup generated logs. If called with no arguments + * then no events will be emitted. + * + * @example + * ```ts + * mediasoup.setLogEventListeners({ + * ondebug: undefined, + * onwarn: (namespace: string, log: string) => { + * MyEnterpriseLogger.warn(`${namespace} ${log}`); + * }, + * onerror: (namespace: string, log: string, error?: Error) => { + * if (error) { + * MyEnterpriseLogger.error(`${namespace} ${log}: ${error}`); + * } else { + * MyEnterpriseLogger.error(`${namespace} ${log}`); + * } + * } + * }); + * ``` + */ +export function setLogEventListeners(listeners?: LogEventListeners): void { + logger.debug('setLogEventListeners()'); + + let debugLogEmitter: LoggerEmitter | undefined; + let warnLogEmitter: LoggerEmitter | undefined; + let errorLogEmitter: LoggerEmitter | undefined; + + if (listeners?.ondebug) { + debugLogEmitter = new EnhancedEventEmitter(); + + debugLogEmitter.on('debuglog', listeners.ondebug); + } + + if (listeners?.onwarn) { + warnLogEmitter = new EnhancedEventEmitter(); + + warnLogEmitter.on('warnlog', listeners.onwarn); + } + + if (listeners?.onerror) { + errorLogEmitter = new EnhancedEventEmitter(); + + errorLogEmitter.on('errorlog', listeners.onerror); + } + + Logger.setEmitters(debugLogEmitter, warnLogEmitter, errorLogEmitter); +} + /** * Create a Worker. */ diff --git a/node/src/test/test-mediasoup.ts b/node/src/test/test-mediasoup.ts index 4fa6db110a..bfafad5f7f 100644 --- a/node/src/test/test-mediasoup.ts +++ b/node/src/test/test-mediasoup.ts @@ -1,6 +1,8 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; +import { enhancedOnce } from '../enhancedEvents'; import * as mediasoup from '../'; +import { WorkerEvents } from '../types'; const PKG = JSON.parse( fs.readFileSync(path.join(__dirname, '..', '..', '..', 'package.json'), { @@ -15,6 +17,26 @@ test('mediasoup.version matches version field in package.json', () => { expect(version).toBe(PKG.version); }); +test('setLoggerEventListeners() works', async () => { + const onDebug = jest.fn(); + + mediasoup.setLogEventListeners({ + ondebug: onDebug, + onwarn: undefined, + onerror: undefined, + }); + + const worker = await mediasoup.createWorker(); + + worker.close(); + + expect(onDebug).toHaveBeenCalled(); + + if (worker.subprocessClosed === false) { + await enhancedOnce(worker, 'subprocessclose'); + } +}, 2000); + test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabilities', () => { const rtpCapabilities = getSupportedRtpCapabilities(); diff --git a/node/src/types.ts b/node/src/types.ts index 45ef78af89..7f5ca140fa 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -1,23 +1,24 @@ -export * from './Worker'; -export * from './WebRtcServer'; -export * from './Router'; -export * from './Transport'; -export * from './WebRtcTransport'; -export * from './PlainTransport'; -export * from './PipeTransport'; -export * from './DirectTransport'; -export * from './Producer'; -export * from './Consumer'; -export * from './DataProducer'; -export * from './DataConsumer'; -export * from './RtpObserver'; -export * from './ActiveSpeakerObserver'; -export * from './AudioLevelObserver'; -export * from './RtpParameters'; -export * from './SctpParameters'; -export * from './SrtpParameters'; -export * from './errors'; -export type { ScalabilityMode } from './scalabilityModes'; +export type * from './index'; +export type * from './Worker'; +export type * from './WebRtcServer'; +export type * from './Router'; +export type * from './Transport'; +export type * from './WebRtcTransport'; +export type * from './PlainTransport'; +export type * from './PipeTransport'; +export type * from './DirectTransport'; +export type * from './Producer'; +export type * from './Consumer'; +export type * from './DataProducer'; +export type * from './DataConsumer'; +export type * from './RtpObserver'; +export type * from './ActiveSpeakerObserver'; +export type * from './AudioLevelObserver'; +export type * from './RtpParameters'; +export type * from './SctpParameters'; +export type * from './SrtpParameters'; +export type * from './scalabilityModes'; +export type * from './errors'; export type AppData = { [key: string]: unknown; From d8a875772fc640441ebccdb0bc30c07358c1b9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 30 Aug 2024 10:57:45 +0200 Subject: [PATCH 495/525] 3.14.12 --- CHANGELOG.md | 2 ++ package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24b9af5a25..d8202d429e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +### 3.14.12 + - `Worker`: Fix `io_uring` support detection ([PR #1445](https://github.com/versatica/mediasoup/pull/1445)). - Mitigate libsrtp wraparound with loss decryption failure ([PR #1438](https://github.com/versatica/mediasoup/pull/1438)). - Node: New `setLogEventListeners()` utility to get log events ([PR #1448](https://github.com/versatica/mediasoup/pull/1448)). diff --git a/package-lock.json b/package-lock.json index 765fcf5eca..6a63f10c99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.11", + "version": "3.14.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.11", + "version": "3.14.12", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -27,7 +27,7 @@ "@types/node": "^22.5.1", "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.8.0", + "eslint-plugin-jest": "^28.8.1", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", @@ -2886,9 +2886,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz", - "integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==", + "version": "28.8.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.1.tgz", + "integrity": "sha512-G46XMyYu6PtSNJUkQ0hsPjzXYpzq/O4vpCciMizTKRJG8kNsRreGoMRDG6H9FIB/xVgfFuclVnuX4XRvFUzrZQ==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -8380,9 +8380,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "28.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz", - "integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==", + "version": "28.8.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.1.tgz", + "integrity": "sha512-G46XMyYu6PtSNJUkQ0hsPjzXYpzq/O4vpCciMizTKRJG8kNsRreGoMRDG6H9FIB/xVgfFuclVnuX4XRvFUzrZQ==", "dev": true, "requires": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" diff --git a/package.json b/package.json index 21e50b771c..0098356176 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.11", + "version": "3.14.12", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -116,7 +116,7 @@ "@types/node": "^22.5.1", "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.8.0", + "eslint-plugin-jest": "^28.8.1", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", From cff9e78b33b744e7773df2ccc35c60b52ede0837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 3 Sep 2024 12:26:55 +0200 Subject: [PATCH 496/525] 3.14.13 --- CHANGELOG.md | 4 + node/src/types.ts | 33 +++---- package-lock.json | 226 +++++++++++++++++++++++----------------------- package.json | 8 +- 4 files changed, 138 insertions(+), 133 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8202d429e..aac51e67f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### NEXT +### 3.14.13 + +- Node: Fix regression in exported `mediasoup.types` (classes are now exported as classes instead of types). + ### 3.14.12 - `Worker`: Fix `io_uring` support detection ([PR #1445](https://github.com/versatica/mediasoup/pull/1445)). diff --git a/node/src/types.ts b/node/src/types.ts index 7f5ca140fa..172f6886ca 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -1,24 +1,25 @@ export type * from './index'; -export type * from './Worker'; -export type * from './WebRtcServer'; -export type * from './Router'; -export type * from './Transport'; -export type * from './WebRtcTransport'; -export type * from './PlainTransport'; -export type * from './PipeTransport'; -export type * from './DirectTransport'; -export type * from './Producer'; -export type * from './Consumer'; -export type * from './DataProducer'; -export type * from './DataConsumer'; -export type * from './RtpObserver'; -export type * from './ActiveSpeakerObserver'; -export type * from './AudioLevelObserver'; export type * from './RtpParameters'; export type * from './SctpParameters'; export type * from './SrtpParameters'; export type * from './scalabilityModes'; -export type * from './errors'; + +export * from './Worker'; +export * from './WebRtcServer'; +export * from './Router'; +export * from './Transport'; +export * from './WebRtcTransport'; +export * from './PlainTransport'; +export * from './PipeTransport'; +export * from './DirectTransport'; +export * from './Producer'; +export * from './Consumer'; +export * from './DataProducer'; +export * from './DataConsumer'; +export * from './RtpObserver'; +export * from './ActiveSpeakerObserver'; +export * from './AudioLevelObserver'; +export * from './errors'; export type AppData = { [key: string]: unknown; diff --git a/package-lock.json b/package-lock.json index 6a63f10c99..732a4ca3ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.12", + "version": "3.14.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.12", + "version": "3.14.13", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -24,10 +24,10 @@ "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^22.5.1", + "@types/node": "^22.5.2", "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.8.1", + "eslint-plugin-jest": "^28.8.2", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", @@ -38,7 +38,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.5.4", - "typescript-eslint": "^8.3.0" + "typescript-eslint": "^8.4.0" }, "engines": { "node": ">=18" @@ -1860,9 +1860,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", - "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", + "version": "22.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz", + "integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==", "dev": true, "dependencies": { "undici-types": "~6.19.2" @@ -1890,16 +1890,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", - "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.4.0.tgz", + "integrity": "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/type-utils": "8.3.0", - "@typescript-eslint/utils": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/scope-manager": "8.4.0", + "@typescript-eslint/type-utils": "8.4.0", + "@typescript-eslint/utils": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1923,15 +1923,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz", - "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.4.0.tgz", + "integrity": "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/scope-manager": "8.4.0", + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/typescript-estree": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0", "debug": "^4.3.4" }, "engines": { @@ -1951,13 +1951,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", - "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.4.0.tgz", + "integrity": "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0" + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1968,13 +1968,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", - "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.4.0.tgz", + "integrity": "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/utils": "8.3.0", + "@typescript-eslint/typescript-estree": "8.4.0", + "@typescript-eslint/utils": "8.4.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1992,9 +1992,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", - "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.4.0.tgz", + "integrity": "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2005,13 +2005,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", - "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.4.0.tgz", + "integrity": "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2057,15 +2057,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.4.0.tgz", + "integrity": "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0" + "@typescript-eslint/scope-manager": "8.4.0", + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/typescript-estree": "8.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2079,12 +2079,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", - "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.4.0.tgz", + "integrity": "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/types": "8.4.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2886,9 +2886,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.8.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.1.tgz", - "integrity": "sha512-G46XMyYu6PtSNJUkQ0hsPjzXYpzq/O4vpCciMizTKRJG8kNsRreGoMRDG6H9FIB/xVgfFuclVnuX4XRvFUzrZQ==", + "version": "28.8.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.2.tgz", + "integrity": "sha512-mC3OyklHmS5i7wYU1rGId9EnxRI8TVlnFG56AE+8U9iRy6zwaNygZR+DsdZuCL0gRG0wVeyzq+uWcPt6yJrrMA==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -6012,14 +6012,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz", - "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.4.0.tgz", + "integrity": "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.3.0", - "@typescript-eslint/parser": "8.3.0", - "@typescript-eslint/utils": "8.3.0" + "@typescript-eslint/eslint-plugin": "8.4.0", + "@typescript-eslint/parser": "8.4.0", + "@typescript-eslint/utils": "8.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7671,9 +7671,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", - "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", + "version": "22.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz", + "integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==", "dev": true, "requires": { "undici-types": "~6.19.2" @@ -7701,16 +7701,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", - "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.4.0.tgz", + "integrity": "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/type-utils": "8.3.0", - "@typescript-eslint/utils": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/scope-manager": "8.4.0", + "@typescript-eslint/type-utils": "8.4.0", + "@typescript-eslint/utils": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7718,54 +7718,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz", - "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.4.0.tgz", + "integrity": "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/scope-manager": "8.4.0", + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/typescript-estree": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", - "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.4.0.tgz", + "integrity": "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==", "dev": true, "requires": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0" + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0" } }, "@typescript-eslint/type-utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", - "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.4.0.tgz", + "integrity": "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/utils": "8.3.0", + "@typescript-eslint/typescript-estree": "8.4.0", + "@typescript-eslint/utils": "8.4.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", - "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.4.0.tgz", + "integrity": "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", - "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.4.0.tgz", + "integrity": "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==", "dev": true, "requires": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7795,24 +7795,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.4.0.tgz", + "integrity": "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0" + "@typescript-eslint/scope-manager": "8.4.0", + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/typescript-estree": "8.4.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", - "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.4.0.tgz", + "integrity": "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==", "dev": true, "requires": { - "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/types": "8.4.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -8380,9 +8380,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "28.8.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.1.tgz", - "integrity": "sha512-G46XMyYu6PtSNJUkQ0hsPjzXYpzq/O4vpCciMizTKRJG8kNsRreGoMRDG6H9FIB/xVgfFuclVnuX4XRvFUzrZQ==", + "version": "28.8.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.2.tgz", + "integrity": "sha512-mC3OyklHmS5i7wYU1rGId9EnxRI8TVlnFG56AE+8U9iRy6zwaNygZR+DsdZuCL0gRG0wVeyzq+uWcPt6yJrrMA==", "dev": true, "requires": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -10531,14 +10531,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz", - "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.4.0.tgz", + "integrity": "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.3.0", - "@typescript-eslint/parser": "8.3.0", - "@typescript-eslint/utils": "8.3.0" + "@typescript-eslint/eslint-plugin": "8.4.0", + "@typescript-eslint/parser": "8.4.0", + "@typescript-eslint/utils": "8.4.0" } }, "undici-types": { diff --git a/package.json b/package.json index 0098356176..ece37aaabd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.12", + "version": "3.14.13", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -113,10 +113,10 @@ "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^22.5.1", + "@types/node": "^22.5.2", "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.8.1", + "eslint-plugin-jest": "^28.8.2", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", @@ -127,6 +127,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.5.4", - "typescript-eslint": "^8.3.0" + "typescript-eslint": "^8.4.0" } } From fd963ff3be5154ce901794730ba066c8fddb3938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 6 Sep 2024 09:35:28 +0200 Subject: [PATCH 497/525] Sign self generated DTLS certificate with SHA256 (#1450) --- CHANGELOG.md | 2 ++ worker/src/RTC/DtlsTransport.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aac51e67f3..b405b7ac78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +- Sign self generated DTLS certificate with SHA256 ([PR #1450](https://github.com/versatica/mediasoup/pull/1450)). + ### 3.14.13 - Node: Fix regression in exported `mediasoup.types` (classes are now exported as classes instead of types). diff --git a/worker/src/RTC/DtlsTransport.cpp b/worker/src/RTC/DtlsTransport.cpp index b3458c901b..9f2ff0ae01 100644 --- a/worker/src/RTC/DtlsTransport.cpp +++ b/worker/src/RTC/DtlsTransport.cpp @@ -415,7 +415,7 @@ namespace RTC } // Sign the certificate with its own private key. - ret = X509_sign(DtlsTransport::certificate, DtlsTransport::privateKey, EVP_sha1()); + ret = X509_sign(DtlsTransport::certificate, DtlsTransport::privateKey, EVP_sha256()); if (ret == 0) { From ff1ccef8c3bda794b9beed835ece1174d3e50b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 6 Sep 2024 09:41:27 +0200 Subject: [PATCH 498/525] update npm deps --- package-lock.json | 88 +++++++++++++++++++++++------------------------ package.json | 10 +++--- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/package-lock.json b/package-lock.json index 732a4ca3ae..7dbe8d551d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,10 @@ "license": "ISC", "dependencies": { "@types/ini": "^4.1.1", - "debug": "^4.3.6", + "debug": "^4.3.7", "flatbuffers": "^24.3.25", "h264-profile-level-id": "^2.0.0", - "ini": "^4.1.3", + "ini": "^5.0.0", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^7.4.3" @@ -24,14 +24,14 @@ "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^22.5.2", + "@types/node": "^22.5.4", "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.8.2", + "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "marked": "^14.1.0", + "marked": "^14.1.1", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", @@ -1860,9 +1860,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.5.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz", - "integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==", + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", "dev": true, "dependencies": { "undici-types": "~6.19.2" @@ -2632,11 +2632,11 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2886,9 +2886,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.8.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.2.tgz", - "integrity": "sha512-mC3OyklHmS5i7wYU1rGId9EnxRI8TVlnFG56AE+8U9iRy6zwaNygZR+DsdZuCL0gRG0wVeyzq+uWcPt6yJrrMA==", + "version": "28.8.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", + "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -3627,11 +3627,11 @@ "dev": true }, "node_modules/ini": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", - "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz", + "integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/ip": { @@ -4644,9 +4644,9 @@ } }, "node_modules/marked": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.0.tgz", - "integrity": "sha512-P93GikH/Pde0hM5TAXEd8I4JAYi8IB03n8qzW8Bh1BIEFpEyBoYxi/XWZA53LSpTeLBiMQOoSMj0u5E/tiVYTA==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.1.tgz", + "integrity": "sha512-eS59oxof5eBVDCKTs+mJbvB/6Vq137GbimF9wkTIlto2/B2ppY5nigUUQgKVmA3bI2mPTIshUyDj5j612ZxlQQ==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -4811,9 +4811,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -7671,9 +7671,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.5.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz", - "integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==", + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", "dev": true, "requires": { "undici-types": "~6.19.2" @@ -8203,11 +8203,11 @@ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" }, "debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "dedent": { @@ -8380,9 +8380,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "28.8.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.2.tgz", - "integrity": "sha512-mC3OyklHmS5i7wYU1rGId9EnxRI8TVlnFG56AE+8U9iRy6zwaNygZR+DsdZuCL0gRG0wVeyzq+uWcPt6yJrrMA==", + "version": "28.8.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", + "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==", "dev": true, "requires": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -8874,9 +8874,9 @@ "dev": true }, "ini": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", - "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz", + "integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==" }, "ip": { "version": "1.1.9", @@ -9635,9 +9635,9 @@ } }, "marked": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.0.tgz", - "integrity": "sha512-P93GikH/Pde0hM5TAXEd8I4JAYi8IB03n8qzW8Bh1BIEFpEyBoYxi/XWZA53LSpTeLBiMQOoSMj0u5E/tiVYTA==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.1.tgz", + "integrity": "sha512-eS59oxof5eBVDCKTs+mJbvB/6Vq137GbimF9wkTIlto2/B2ppY5nigUUQgKVmA3bI2mPTIshUyDj5j612ZxlQQ==", "dev": true }, "meow": { @@ -9741,9 +9741,9 @@ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==" }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "natural-compare": { "version": "1.4.0", diff --git a/package.json b/package.json index ece37aaabd..e01500da07 100644 --- a/package.json +++ b/package.json @@ -100,10 +100,10 @@ }, "dependencies": { "@types/ini": "^4.1.1", - "debug": "^4.3.6", + "debug": "^4.3.7", "flatbuffers": "^24.3.25", "h264-profile-level-id": "^2.0.0", - "ini": "^4.1.3", + "ini": "^5.0.0", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", "tar": "^7.4.3" @@ -113,14 +113,14 @@ "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^22.5.2", + "@types/node": "^22.5.4", "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.8.2", + "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "marked": "^14.1.0", + "marked": "^14.1.1", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", From 06b813db9344e63303dfe2febc362622843d214b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 6 Sep 2024 09:42:43 +0200 Subject: [PATCH 499/525] DtlsTransport: remove SSL_CTX_set_read_ahead() call which is noop in DTLS --- worker/src/RTC/DtlsTransport.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/worker/src/RTC/DtlsTransport.cpp b/worker/src/RTC/DtlsTransport.cpp index 9f2ff0ae01..279f7e7ff8 100644 --- a/worker/src/RTC/DtlsTransport.cpp +++ b/worker/src/RTC/DtlsTransport.cpp @@ -549,11 +549,6 @@ namespace RTC // Don't use sessions cache. SSL_CTX_set_session_cache_mode(DtlsTransport::sslCtx, SSL_SESS_CACHE_OFF); - // Read always as much into the buffer as possible. - // NOTE: This is the default for DTLS, but a bug in non latest OpenSSL - // versions makes this call required. - SSL_CTX_set_read_ahead(DtlsTransport::sslCtx, 1); - SSL_CTX_set_verify_depth(DtlsTransport::sslCtx, 4); // Require certificate from peer. From 528f36fea85fa48260cee42a11b8b306e4fca9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 7 Sep 2024 10:15:55 +0200 Subject: [PATCH 500/525] Node: Fix types in mediasoup.types are empty/undefined (#1453) --- CHANGELOG.md | 1 + node/src/types.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b405b7ac78..ebd3e58798 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT - Sign self generated DTLS certificate with SHA256 ([PR #1450](https://github.com/versatica/mediasoup/pull/1450)). +- Node: Fix `mediasoup.types` exported types are empty ([PR #1453](https://github.com/versatica/mediasoup/pull/1453)). ### 3.14.13 diff --git a/node/src/types.ts b/node/src/types.ts index 172f6886ca..14c9e4a0c1 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -1,4 +1,4 @@ -export type * from './index'; +export type { Observer, ObserverEvents, LogEventListeners } from './index'; export type * from './RtpParameters'; export type * from './SctpParameters'; export type * from './SrtpParameters'; From 42e47d6274b2714a585106780c7493fa0382142c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 7 Sep 2024 10:17:23 +0200 Subject: [PATCH 501/525] update eslint deps --- package-lock.json | 57 ++++++++++++++++++++++++++++++++--------------- package.json | 4 ++-- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7dbe8d551d..db2bafd030 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,12 +20,12 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.9.1", + "@eslint/js": "^9.10.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^22.5.4", - "eslint": "^9.9.1", + "eslint": "^9.10.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", @@ -797,9 +797,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", - "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", + "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -814,6 +814,18 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz", + "integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==", + "dev": true, + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -2815,16 +2827,17 @@ } }, "node_modules/eslint": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", - "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", + "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.9.1", + "@eslint/js": "9.10.0", + "@eslint/plugin-kit": "^0.1.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -2847,7 +2860,6 @@ "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", @@ -6827,9 +6839,9 @@ } }, "@eslint/js": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", - "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", + "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", "dev": true }, "@eslint/object-schema": { @@ -6838,6 +6850,15 @@ "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true }, + "@eslint/plugin-kit": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz", + "integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==", + "dev": true, + "requires": { + "levn": "^0.4.1" + } + }, "@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -8323,16 +8344,17 @@ "dev": true }, "eslint": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", - "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", + "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.9.1", + "@eslint/js": "9.10.0", + "@eslint/plugin-kit": "^0.1.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -8355,7 +8377,6 @@ "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", diff --git a/package.json b/package.json index e01500da07..66f91b68ed 100644 --- a/package.json +++ b/package.json @@ -109,12 +109,12 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.9.1", + "@eslint/js": "^9.10.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^22.5.4", - "eslint": "^9.9.1", + "eslint": "^9.10.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", From efa8f5149082b4738ad5d3a8144e6b1d56e4fe73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 7 Sep 2024 10:20:04 +0200 Subject: [PATCH 502/525] 3.14.14 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebd3e58798..2180b85374 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +### 3.14.14 + - Sign self generated DTLS certificate with SHA256 ([PR #1450](https://github.com/versatica/mediasoup/pull/1450)). - Node: Fix `mediasoup.types` exported types are empty ([PR #1453](https://github.com/versatica/mediasoup/pull/1453)). diff --git a/package-lock.json b/package-lock.json index db2bafd030..ea5aa679fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.13", + "version": "3.14.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.13", + "version": "3.14.14", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 66f91b68ed..5f6b671231 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.13", + "version": "3.14.14", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", From b6e77327152c7efb4cf4adb8b92ec540da0c7655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 14 Sep 2024 21:23:27 +0200 Subject: [PATCH 503/525] update npm deps --- package-lock.json | 250 +++++++++++++++++++++++----------------------- package.json | 10 +- 2 files changed, 130 insertions(+), 130 deletions(-) diff --git a/package-lock.json b/package-lock.json index ea5aa679fe..094b2f212d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,22 +23,22 @@ "@eslint/js": "^9.10.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.12", - "@types/node": "^22.5.4", + "@types/jest": "^29.5.13", + "@types/node": "^22.5.5", "eslint": "^9.10.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "marked": "^14.1.1", + "marked": "^14.1.2", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.5", - "typescript": "^5.5.4", - "typescript-eslint": "^8.4.0" + "typescript": "^5.6.2", + "typescript-eslint": "^8.5.0" }, "engines": { "node": ">=18" @@ -1849,9 +1849,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "version": "29.5.13", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", + "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1872,9 +1872,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.5.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", - "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "version": "22.5.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz", + "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==", "dev": true, "dependencies": { "undici-types": "~6.19.2" @@ -1902,16 +1902,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.4.0.tgz", - "integrity": "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.5.0.tgz", + "integrity": "sha512-lHS5hvz33iUFQKuPFGheAB84LwcJ60G8vKnEhnfcK1l8kGVLro2SFYW6K0/tj8FUhRJ0VHyg1oAfg50QGbPPHw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.4.0", - "@typescript-eslint/type-utils": "8.4.0", - "@typescript-eslint/utils": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/type-utils": "8.5.0", + "@typescript-eslint/utils": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1935,15 +1935,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.4.0.tgz", - "integrity": "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.5.0.tgz", + "integrity": "sha512-gF77eNv0Xz2UJg/NbpWJ0kqAm35UMsvZf1GHj8D9MRFTj/V3tAciIWXfmPLsAAF/vUlpWPvUDyH1jjsr0cMVWw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.4.0", - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/typescript-estree": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "debug": "^4.3.4" }, "engines": { @@ -1963,13 +1963,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.4.0.tgz", - "integrity": "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0" + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1980,13 +1980,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.4.0.tgz", - "integrity": "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.5.0.tgz", + "integrity": "sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.4.0", - "@typescript-eslint/utils": "8.4.0", + "@typescript-eslint/typescript-estree": "8.5.0", + "@typescript-eslint/utils": "8.5.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2004,9 +2004,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.4.0.tgz", - "integrity": "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2017,13 +2017,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.4.0.tgz", - "integrity": "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2069,15 +2069,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.4.0.tgz", - "integrity": "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.4.0", - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/typescript-estree": "8.4.0" + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2091,12 +2091,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.4.0.tgz", - "integrity": "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/types": "8.5.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -4656,9 +4656,9 @@ } }, "node_modules/marked": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.1.tgz", - "integrity": "sha512-eS59oxof5eBVDCKTs+mJbvB/6Vq137GbimF9wkTIlto2/B2ppY5nigUUQgKVmA3bI2mPTIshUyDj5j612ZxlQQ==", + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.2.tgz", + "integrity": "sha512-f3r0yqpz31VXiDB/wj9GaOB0a2PRLQl6vJmXiFrniNwjkKdvakqJRULhjFKJpxOchlCRiG5fcacoUZY5Xa6PEQ==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -6011,9 +6011,9 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -6024,14 +6024,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.4.0.tgz", - "integrity": "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.5.0.tgz", + "integrity": "sha512-uD+XxEoSIvqtm4KE97etm32Tn5MfaZWgWfMMREStLxR6JzvHkc2Tkj7zhTEK5XmtpTmKHNnG8Sot6qDfhHtR1Q==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.4.0", - "@typescript-eslint/parser": "8.4.0", - "@typescript-eslint/utils": "8.4.0" + "@typescript-eslint/eslint-plugin": "8.5.0", + "@typescript-eslint/parser": "8.5.0", + "@typescript-eslint/utils": "8.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7669,9 +7669,9 @@ } }, "@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "version": "29.5.13", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", + "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", "dev": true, "requires": { "expect": "^29.0.0", @@ -7692,9 +7692,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.5.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", - "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "version": "22.5.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz", + "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==", "dev": true, "requires": { "undici-types": "~6.19.2" @@ -7722,16 +7722,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.4.0.tgz", - "integrity": "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.5.0.tgz", + "integrity": "sha512-lHS5hvz33iUFQKuPFGheAB84LwcJ60G8vKnEhnfcK1l8kGVLro2SFYW6K0/tj8FUhRJ0VHyg1oAfg50QGbPPHw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.4.0", - "@typescript-eslint/type-utils": "8.4.0", - "@typescript-eslint/utils": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/type-utils": "8.5.0", + "@typescript-eslint/utils": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7739,54 +7739,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.4.0.tgz", - "integrity": "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.5.0.tgz", + "integrity": "sha512-gF77eNv0Xz2UJg/NbpWJ0kqAm35UMsvZf1GHj8D9MRFTj/V3tAciIWXfmPLsAAF/vUlpWPvUDyH1jjsr0cMVWw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.4.0", - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/typescript-estree": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0", + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.4.0.tgz", - "integrity": "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", "dev": true, "requires": { - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0" + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" } }, "@typescript-eslint/type-utils": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.4.0.tgz", - "integrity": "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.5.0.tgz", + "integrity": "sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.4.0", - "@typescript-eslint/utils": "8.4.0", + "@typescript-eslint/typescript-estree": "8.5.0", + "@typescript-eslint/utils": "8.5.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.4.0.tgz", - "integrity": "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.4.0.tgz", - "integrity": "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", "dev": true, "requires": { - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/visitor-keys": "8.4.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7816,24 +7816,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.4.0.tgz", - "integrity": "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.4.0", - "@typescript-eslint/types": "8.4.0", - "@typescript-eslint/typescript-estree": "8.4.0" + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.4.0.tgz", - "integrity": "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", "dev": true, "requires": { - "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/types": "8.5.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -9656,9 +9656,9 @@ } }, "marked": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.1.tgz", - "integrity": "sha512-eS59oxof5eBVDCKTs+mJbvB/6Vq137GbimF9wkTIlto2/B2ppY5nigUUQgKVmA3bI2mPTIshUyDj5j612ZxlQQ==", + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.2.tgz", + "integrity": "sha512-f3r0yqpz31VXiDB/wj9GaOB0a2PRLQl6vJmXiFrniNwjkKdvakqJRULhjFKJpxOchlCRiG5fcacoUZY5Xa6PEQ==", "dev": true }, "meow": { @@ -10546,20 +10546,20 @@ "dev": true }, "typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true }, "typescript-eslint": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.4.0.tgz", - "integrity": "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.5.0.tgz", + "integrity": "sha512-uD+XxEoSIvqtm4KE97etm32Tn5MfaZWgWfMMREStLxR6JzvHkc2Tkj7zhTEK5XmtpTmKHNnG8Sot6qDfhHtR1Q==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.4.0", - "@typescript-eslint/parser": "8.4.0", - "@typescript-eslint/utils": "8.4.0" + "@typescript-eslint/eslint-plugin": "8.5.0", + "@typescript-eslint/parser": "8.5.0", + "@typescript-eslint/utils": "8.5.0" } }, "undici-types": { diff --git a/package.json b/package.json index 5f6b671231..f194a14642 100644 --- a/package.json +++ b/package.json @@ -112,21 +112,21 @@ "@eslint/js": "^9.10.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.12", - "@types/node": "^22.5.4", + "@types/jest": "^29.5.13", + "@types/node": "^22.5.5", "eslint": "^9.10.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "marked": "^14.1.1", + "marked": "^14.1.2", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.5", - "typescript": "^5.5.4", - "typescript-eslint": "^8.4.0" + "typescript": "^5.6.2", + "typescript-eslint": "^8.5.0" } } From e1309f16debba57553ae1e6b837e125eceb5c1a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 17 Sep 2024 11:41:19 +0200 Subject: [PATCH 504/525] update typescript-eslint version --- package-lock.json | 194 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 98 insertions(+), 98 deletions(-) diff --git a/package-lock.json b/package-lock.json index 094b2f212d..7f5639057f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.2", - "typescript-eslint": "^8.5.0" + "typescript-eslint": "^8.6.0" }, "engines": { "node": ">=18" @@ -1902,16 +1902,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.5.0.tgz", - "integrity": "sha512-lHS5hvz33iUFQKuPFGheAB84LwcJ60G8vKnEhnfcK1l8kGVLro2SFYW6K0/tj8FUhRJ0VHyg1oAfg50QGbPPHw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz", + "integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/type-utils": "8.5.0", - "@typescript-eslint/utils": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/type-utils": "8.6.0", + "@typescript-eslint/utils": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1935,15 +1935,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.5.0.tgz", - "integrity": "sha512-gF77eNv0Xz2UJg/NbpWJ0kqAm35UMsvZf1GHj8D9MRFTj/V3tAciIWXfmPLsAAF/vUlpWPvUDyH1jjsr0cMVWw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz", + "integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/typescript-estree": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4" }, "engines": { @@ -1963,13 +1963,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", - "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", + "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0" + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1980,13 +1980,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.5.0.tgz", - "integrity": "sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", + "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.5.0", - "@typescript-eslint/utils": "8.5.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/utils": "8.6.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2004,9 +2004,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", - "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", + "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2017,13 +2017,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", - "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", + "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2069,15 +2069,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", - "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", + "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/typescript-estree": "8.5.0" + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2091,12 +2091,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", - "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", + "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/types": "8.6.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -6024,14 +6024,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.5.0.tgz", - "integrity": "sha512-uD+XxEoSIvqtm4KE97etm32Tn5MfaZWgWfMMREStLxR6JzvHkc2Tkj7zhTEK5XmtpTmKHNnG8Sot6qDfhHtR1Q==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.6.0.tgz", + "integrity": "sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.5.0", - "@typescript-eslint/parser": "8.5.0", - "@typescript-eslint/utils": "8.5.0" + "@typescript-eslint/eslint-plugin": "8.6.0", + "@typescript-eslint/parser": "8.6.0", + "@typescript-eslint/utils": "8.6.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7722,16 +7722,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.5.0.tgz", - "integrity": "sha512-lHS5hvz33iUFQKuPFGheAB84LwcJ60G8vKnEhnfcK1l8kGVLro2SFYW6K0/tj8FUhRJ0VHyg1oAfg50QGbPPHw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz", + "integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/type-utils": "8.5.0", - "@typescript-eslint/utils": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/type-utils": "8.6.0", + "@typescript-eslint/utils": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7739,54 +7739,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.5.0.tgz", - "integrity": "sha512-gF77eNv0Xz2UJg/NbpWJ0kqAm35UMsvZf1GHj8D9MRFTj/V3tAciIWXfmPLsAAF/vUlpWPvUDyH1jjsr0cMVWw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz", + "integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/typescript-estree": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", - "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", + "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", "dev": true, "requires": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0" + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0" } }, "@typescript-eslint/type-utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.5.0.tgz", - "integrity": "sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", + "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.5.0", - "@typescript-eslint/utils": "8.5.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/utils": "8.6.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", - "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", + "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", - "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", + "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", "dev": true, "requires": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7816,24 +7816,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", - "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", + "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/typescript-estree": "8.5.0" + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", - "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", + "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", "dev": true, "requires": { - "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/types": "8.6.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -10552,14 +10552,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.5.0.tgz", - "integrity": "sha512-uD+XxEoSIvqtm4KE97etm32Tn5MfaZWgWfMMREStLxR6JzvHkc2Tkj7zhTEK5XmtpTmKHNnG8Sot6qDfhHtR1Q==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.6.0.tgz", + "integrity": "sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.5.0", - "@typescript-eslint/parser": "8.5.0", - "@typescript-eslint/utils": "8.5.0" + "@typescript-eslint/eslint-plugin": "8.6.0", + "@typescript-eslint/parser": "8.6.0", + "@typescript-eslint/utils": "8.6.0" } }, "undici-types": { diff --git a/package.json b/package.json index f194a14642..735c288221 100644 --- a/package.json +++ b/package.json @@ -127,6 +127,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.2", - "typescript-eslint": "^8.5.0" + "typescript-eslint": "^8.6.0" } } From 4a6a523503d6446dcb749fb2d1f1b3370c6a2905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 24 Sep 2024 22:14:28 +0200 Subject: [PATCH 505/525] update npm deps --- package-lock.json | 305 ++++++++++++++++++++++++---------------------- package.json | 8 +- 2 files changed, 163 insertions(+), 150 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f5639057f..bd5ec41db7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,12 +20,12 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.10.0", + "@eslint/js": "^9.11.1", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.13", - "@types/node": "^22.5.5", - "eslint": "^9.10.0", + "@types/node": "^22.6.1", + "eslint": "^9.11.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", @@ -38,7 +38,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.2", - "typescript-eslint": "^8.6.0" + "typescript-eslint": "^8.7.0" }, "engines": { "node": ">=18" @@ -761,6 +761,15 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -797,9 +806,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", - "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", + "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -815,9 +824,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz", - "integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", "dev": true, "dependencies": { "levn": "^0.4.1" @@ -1803,12 +1812,10 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "optional": true, - "peer": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true }, "node_modules/@types/graceful-fs": { "version": "4.1.6", @@ -1862,9 +1869,7 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "optional": true, - "peer": true + "dev": true }, "node_modules/@types/ms": { "version": "0.7.31", @@ -1872,9 +1877,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.5.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz", - "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==", + "version": "22.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", + "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", "dev": true, "dependencies": { "undici-types": "~6.19.2" @@ -1902,16 +1907,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz", - "integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", + "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.6.0", - "@typescript-eslint/type-utils": "8.6.0", - "@typescript-eslint/utils": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0", + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/type-utils": "8.7.0", + "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1935,15 +1940,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz", - "integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", + "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.6.0", - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/typescript-estree": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0", + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/typescript-estree": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "debug": "^4.3.4" }, "engines": { @@ -1963,13 +1968,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", - "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", + "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0" + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1980,13 +1985,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", - "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", + "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.6.0", - "@typescript-eslint/utils": "8.6.0", + "@typescript-eslint/typescript-estree": "8.7.0", + "@typescript-eslint/utils": "8.7.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2004,9 +2009,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", - "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", + "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2017,13 +2022,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", - "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", + "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2069,15 +2074,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", - "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", + "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.6.0", - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/typescript-estree": "8.6.0" + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/typescript-estree": "8.7.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2091,12 +2096,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", - "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", + "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/types": "8.7.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2827,20 +2832,23 @@ } }, "node_modules/eslint": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", - "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", + "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.10.0", - "@eslint/plugin-kit": "^0.1.0", + "@eslint/js": "9.11.1", + "@eslint/plugin-kit": "^0.2.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -6024,14 +6032,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.6.0.tgz", - "integrity": "sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.7.0.tgz", + "integrity": "sha512-nEHbEYJyHwsuf7c3V3RS7Saq+1+la3i0ieR3qP0yjqWSzVmh8Drp47uOl9LjbPANac4S7EFSqvcYIKXUUwIfIQ==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.6.0", - "@typescript-eslint/parser": "8.6.0", - "@typescript-eslint/utils": "8.6.0" + "@typescript-eslint/eslint-plugin": "8.7.0", + "@typescript-eslint/parser": "8.7.0", + "@typescript-eslint/utils": "8.7.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6813,6 +6821,12 @@ "minimatch": "^3.1.2" } }, + "@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true + }, "@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -6839,9 +6853,9 @@ } }, "@eslint/js": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", - "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", + "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", "dev": true }, "@eslint/object-schema": { @@ -6851,9 +6865,9 @@ "dev": true }, "@eslint/plugin-kit": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz", - "integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", "dev": true, "requires": { "levn": "^0.4.1" @@ -7623,12 +7637,10 @@ } }, "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "optional": true, - "peer": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true }, "@types/graceful-fs": { "version": "4.1.6", @@ -7682,9 +7694,7 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "optional": true, - "peer": true + "dev": true }, "@types/ms": { "version": "0.7.31", @@ -7692,9 +7702,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.5.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz", - "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==", + "version": "22.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", + "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", "dev": true, "requires": { "undici-types": "~6.19.2" @@ -7722,16 +7732,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz", - "integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", + "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.6.0", - "@typescript-eslint/type-utils": "8.6.0", - "@typescript-eslint/utils": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0", + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/type-utils": "8.7.0", + "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7739,54 +7749,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz", - "integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", + "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.6.0", - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/typescript-estree": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0", + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/typescript-estree": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", - "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", + "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", "dev": true, "requires": { - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0" + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0" } }, "@typescript-eslint/type-utils": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", - "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", + "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.6.0", - "@typescript-eslint/utils": "8.6.0", + "@typescript-eslint/typescript-estree": "8.7.0", + "@typescript-eslint/utils": "8.7.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", - "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", + "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", - "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", + "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", "dev": true, "requires": { - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7816,24 +7826,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", - "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", + "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.6.0", - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/typescript-estree": "8.6.0" + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/typescript-estree": "8.7.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", - "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", + "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", "dev": true, "requires": { - "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/types": "8.7.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -8344,20 +8354,23 @@ "dev": true }, "eslint": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", - "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", + "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.10.0", - "@eslint/plugin-kit": "^0.1.0", + "@eslint/js": "9.11.1", + "@eslint/plugin-kit": "^0.2.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -10552,14 +10565,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.6.0.tgz", - "integrity": "sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.7.0.tgz", + "integrity": "sha512-nEHbEYJyHwsuf7c3V3RS7Saq+1+la3i0ieR3qP0yjqWSzVmh8Drp47uOl9LjbPANac4S7EFSqvcYIKXUUwIfIQ==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.6.0", - "@typescript-eslint/parser": "8.6.0", - "@typescript-eslint/utils": "8.6.0" + "@typescript-eslint/eslint-plugin": "8.7.0", + "@typescript-eslint/parser": "8.7.0", + "@typescript-eslint/utils": "8.7.0" } }, "undici-types": { diff --git a/package.json b/package.json index 735c288221..8b329ab2cb 100644 --- a/package.json +++ b/package.json @@ -109,12 +109,12 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.10.0", + "@eslint/js": "^9.11.1", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.13", - "@types/node": "^22.5.5", - "eslint": "^9.10.0", + "@types/node": "^22.6.1", + "eslint": "^9.11.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", @@ -127,6 +127,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.2", - "typescript-eslint": "^8.6.0" + "typescript-eslint": "^8.7.0" } } From 4e161f6b72597f998dccdcec25c907840175b6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 27 Sep 2024 02:26:32 +0200 Subject: [PATCH 506/525] npm audit fix --- package-lock.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index bd5ec41db7..f78f6f8cf8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4703,12 +4703,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -9693,12 +9693,12 @@ "dev": true }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, From df0074b5b04ef17d7034f555b862a77d38e094cf Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Sat, 28 Sep 2024 12:09:30 +0300 Subject: [PATCH 507/525] Bring back RTP and RTCP notifications (#1455) --- Cargo.lock | 4 ++-- rust/src/router/consumer.rs | 21 ++++++++++++++------- rust/src/router/direct_transport.rs | 28 +++++++++++++--------------- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa2c9cddaf..5cf4281fc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1354,7 +1354,7 @@ checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" [[package]] name = "mediasoup" -version = "0.17.0" +version = "0.17.1" dependencies = [ "actix", "actix-web", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "mediasoup-sys" -version = "0.9.0" +version = "0.9.1" dependencies = [ "planus", "planus-codegen", diff --git a/rust/src/router/consumer.rs b/rust/src/router/consumer.rs index 8d58811aea..8fa10b6420 100644 --- a/rust/src/router/consumer.rs +++ b/rust/src/router/consumer.rs @@ -593,8 +593,7 @@ enum Notification { ProducerClose, ProducerPause, ProducerResume, - // TODO. - // Rtp, + Rtp(Vec), Score(ConsumerScore), LayersChange(Option), Trace(ConsumerTraceEventData), @@ -608,6 +607,17 @@ impl Notification { notification::Event::ConsumerProducerClose => Ok(Notification::ProducerClose), notification::Event::ConsumerProducerPause => Ok(Notification::ProducerPause), notification::Event::ConsumerProducerResume => Ok(Notification::ProducerResume), + notification::Event::ConsumerRtp => { + let Ok(Some(notification::BodyRef::ConsumerRtpNotification(body))) = + notification.body() + else { + panic!("Wrong message from worker: {notification:?}"); + }; + + let rtp_notification_fbs = consumer::RtpNotification::try_from(body).unwrap(); + + Ok(Notification::Rtp(rtp_notification_fbs.data)) + } notification::Event::ConsumerScore => { let Ok(Some(notification::BodyRef::ConsumerScoreNotification(body))) = notification.body() @@ -841,14 +851,11 @@ impl Consumer { handlers.resume.call_simple(); } } - /* - * TODO. - Notification::Rtp => { + Notification::Rtp(data) => { handlers.rtp.call(|callback| { - callback(notification); + callback(&data); }); } - */ Notification::Score(consumer_score) => { *score.lock() = consumer_score.clone(); handlers.score.call_simple(&consumer_score); diff --git a/rust/src/router/direct_transport.rs b/rust/src/router/direct_transport.rs index 38a6857cf0..8222500022 100644 --- a/rust/src/router/direct_transport.rs +++ b/rust/src/router/direct_transport.rs @@ -231,8 +231,7 @@ struct Handlers { #[serde(tag = "event", rename_all = "lowercase", content = "data")] enum Notification { Trace(TransportTraceEventData), - // TODO. - // Rtcp, + Rtcp(Vec), } impl Notification { @@ -252,17 +251,18 @@ impl Notification { Ok(Notification::Trace(trace_notification)) } - /* - * TODO. notification::Event::DirecttransportRtcp => { - let Ok(Some(notification::BodyRef::RtcpNotification(_body))) = notification.body() + let Ok(Some(notification::BodyRef::DirectTransportRtcpNotification(body))) = + notification.body() else { panic!("Wrong message from worker: {notification:?}"); }; - Ok(Notification::Rtcp) + let rtcp_notification_fbs = + direct_transport::RtcpNotification::try_from(body).unwrap(); + + Ok(Notification::Rtcp(rtcp_notification_fbs.data)) } - */ _ => Err(NotificationParseError::InvalidEvent), } } @@ -574,14 +574,12 @@ impl DirectTransport { Ok(notification) => match notification { Notification::Trace(trace_event_data) => { handlers.trace.call_simple(&trace_event_data); - } /* - * TODO. - Notification::Rtcp => { - handlers.rtcp.call(|callback| { - callback(notification); - }); - } - */ + } + Notification::Rtcp(data) => { + handlers.rtcp.call(|callback| { + callback(&data); + }); + } }, Err(error) => { error!("Failed to parse notification: {}", error); From 4dd8a16ab4e1d6e37c89bb5c6b3cfb8ad59b79c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 7 Oct 2024 01:47:55 +0200 Subject: [PATCH 508/525] Do not run test-asan-undefined in CI Linux GCC and upgrade abseil-cpp to 20240722.0 LTS (#1457) Co-authored-by: Garrett Boone <47018474+garrettboone@users.noreply.github.com> --- .github/workflows/mediasoup-node.yaml | 39 ++++++++++++++++++----- .github/workflows/mediasoup-rust.yaml | 6 ++-- .github/workflows/mediasoup-worker.yaml | 41 +++++++++++++++++++++---- worker/subprojects/abseil-cpp.wrap | 18 +++++------ 4 files changed, 79 insertions(+), 25 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 915b62ebf2..1e561e6c9f 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -12,43 +12,67 @@ jobs: ci: strategy: matrix: - ci: + build: - os: ubuntu-20.04 node: 18 + cc: gcc + cxx: g++ - os: ubuntu-22.04 node: 20 + cc: gcc + cxx: g++ - os: ubuntu-22.04 node: 22 + cc: gcc + cxx: g++ - os: ubuntu-24.04 node: 22 + cc: gcc + cxx: g++ meson_args: '-Db_sanitize=address' - os: ubuntu-24.04 node: 22 + cc: clang + cxx: clang++ meson_args: '-Db_sanitize=undefined' - os: ubuntu-24.04 node: 22 + cc: gcc + cxx: g++ meson_args: '-Db_sanitize=thread' - os: macos-12 node: 18 + cc: clang + cxx: clang++ - os: macos-14 node: 20 + cc: clang + cxx: clang++ - os: macos-14 node: 22 + cc: clang + cxx: clang++ - os: windows-2022 node: 20 + cc: cl + cxx: cl - os: windows-2022 + cc: cl + cxx: cl node: 22 build-type: - Release - Debug - runs-on: ${{ matrix.ci.os }} + runs-on: ${{ matrix.build.os }} env: + CC: ${{ matrix.build.cc }} + CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' MEDIASOUP_BUILDTYPE: ${{ matrix.build-type }} - MESON_ARGS: ${{ matrix.ci.meson_args }} + MESON_ARGS: ${{ matrix.build.meson_args }} steps: - name: Checkout @@ -57,21 +81,22 @@ jobs: - name: Node.js uses: actions/setup-node@v4 with: - node-version: ${{ matrix.ci.node }} + node-version: ${{ matrix.build.node }} - name: Configure cache uses: actions/cache@v3 with: path: | ~/.npm - key: ${{ matrix.ci.os }}-node-${{ hashFiles('**/package.json') }} + key: ${{ matrix.build.os }}-node-${{ hashFiles('**/package.json') }} restore-keys: | - ${{ matrix.ci.os }}-node- + ${{ matrix.build.os }}-node- - name: npm ci run: npm ci --foreground-scripts env: - # Disable leak detection because it's detected by the tool flatc uses to build. + # Disable leak detection because it's detected by the tool flatc uses + # to build. ASAN_OPTIONS: 'detect_leaks=0' - name: npm run lint:node diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index afd8575522..f17157ea8d 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -15,7 +15,7 @@ jobs: ci: strategy: matrix: - ci: + build: - os: ubuntu-20.04 - os: ubuntu-22.04 - os: ubuntu-24.04 @@ -23,7 +23,7 @@ jobs: - os: macos-14 - os: windows-2022 - runs-on: ${{ matrix.ci.os }} + runs-on: ${{ matrix.build.os }} env: KEEP_BUILD_ARTIFACTS: '1' @@ -38,7 +38,7 @@ jobs: path: | ~/.cargo/registry ~/.cargo/git - key: ${{ matrix.ci.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} + key: ${{ matrix.build.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - name: cargo fmt run: cargo fmt --all -- --check diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index cfa1498022..29af3e3c86 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -21,35 +21,67 @@ jobs: # Workaround for this issue in Ubunt 20.04: # https://github.com/versatica/mediasoup/actions/runs/9992113733/job/27616379442?pr=1427 workaround-ubuntu-20-04: true + run-test-asan-address: true + # Skip test-asan-undefined in Linux with GCC due to a bug in GCC + # that affects abseil-cpp: + # https://github.com/abseil/abseil-cpp/issues/1634 + run-test-asan-undefined: false + run-test-asan-thread: true - os: ubuntu-20.04 cc: clang cxx: clang++ workaround-ubuntu-20-04: true + run-test-asan-address: true + run-test-asan-undefined: true + run-test-asan-thread: true - os: ubuntu-22.04 cc: gcc cxx: g++ + run-test-asan-address: true + run-test-asan-undefined: false + run-test-asan-thread: true - os: ubuntu-22.04 cc: clang cxx: clang++ + run-test-asan-address: true + run-test-asan-undefined: true + run-test-asan-thread: true - os: ubuntu-24.04 cc: gcc cxx: g++ pip-break-system-packages: true + run-test-asan-address: true + run-test-asan-undefined: false + run-test-asan-thread: true - os: ubuntu-24.04 cc: clang cxx: clang++ pip-break-system-packages: true + run-test-asan-address: true + run-test-asan-undefined: true + run-test-asan-thread: true - os: macos-12 cc: gcc cxx: g++ pip-break-system-packages: true + # Address Sanitizer does not work on MacOS. + run-test-asan-address: false + run-test-asan-undefined: false + run-test-asan-thread: false - os: macos-14 cc: clang cxx: clang++ + run-test-asan-address: false + run-test-asan-undefined: false + run-test-asan-thread: false pip-break-system-packages: true - os: windows-2022 cc: cl cxx: cl + # Address Sanitizer does not work on Windows. + run-test-asan-address: false + run-test-asan-undefined: false + run-test-asan-thread: false # A single Node.js version should be fine for C++. node: - 22 @@ -118,20 +150,17 @@ jobs: name: invoke -r worker test run: invoke -r worker test - # Address Sanitizer only works on Linux. # Let's clean everything before rebuilding worker tests with ASAN. - - if: runner.os == 'Linux' + - if: ${{ matrix.build.run-test-asan-address }} name: invoke -r worker test-asan-address run: invoke -r worker clean-all && invoke -r worker test-asan-address - # Address Sanitizer only works on Linux. # Let's clean everything before rebuilding worker tests with ASAN. - - if: runner.os == 'Linux' + - if: ${{ matrix.build.run-test-asan-undefined }} name: invoke -r worker test-asan-undefined run: invoke -r worker clean-all && invoke -r worker test-asan-undefined - # Address Sanitizer only works on Linux. # Let's clean everything before rebuilding worker tests with ASAN. - - if: runner.os == 'Linux' + - if: ${{ matrix.build.run-test-asan-thread }} name: invoke -r worker test-asan-thread run: invoke -r worker clean-all && invoke -r worker test-asan-thread diff --git a/worker/subprojects/abseil-cpp.wrap b/worker/subprojects/abseil-cpp.wrap index 4e62885650..9a8e07278f 100644 --- a/worker/subprojects/abseil-cpp.wrap +++ b/worker/subprojects/abseil-cpp.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = abseil-cpp-20230802.1 -source_url = https://github.com/abseil/abseil-cpp/archive/20230802.1.tar.gz -source_filename = abseil-cpp-20230802.1.tar.gz -source_hash = 987ce98f02eefbaf930d6e38ab16aa05737234d7afbab2d5c4ea7adbe50c28ed -patch_filename = abseil-cpp_20230802.1-2_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20230802.1-2/get_patch -patch_hash = f6ceb55ca4b0995d826cbdefc0a37e0f8b6202d3e7ecb3436298f54d3a23942b -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20230802.1-2/abseil-cpp-20230802.1.tar.gz -wrapdb_version = 20230802.1-2 +directory = abseil-cpp-20240722.0 +source_url = https://github.com/abseil/abseil-cpp/releases/download/20240722.0/abseil-cpp-20240722.0.tar.gz +source_filename = abseil-cpp-20240722.0.tar.gz +source_hash = f50e5ac311a81382da7fa75b97310e4b9006474f9560ac46f54a9967f07d4ae3 +patch_filename = abseil-cpp_20240722.0-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20240722.0-1/get_patch +patch_hash = 692bbbc39cacaba4dc4b0c8b2fbbe32736c9cde6377acfa0d52088797af14ded +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20240722.0-1/abseil-cpp-20240722.0.tar.gz +wrapdb_version = 20240722.0-1 [provide] absl_base = absl_base_dep From 839fbde0b6218d2eb3adf59f837475ff4e753a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 7 Oct 2024 01:53:19 +0200 Subject: [PATCH 509/525] 3.14.15 --- CHANGELOG.md | 4 + eslint.config.mjs | 2 +- package-lock.json | 411 ++++++++++++++++++++++++---------------------- package.json | 12 +- 4 files changed, 226 insertions(+), 203 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2180b85374..68efc2a2f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### NEXT +### 3.14.15 + +- Update worker abseil-cpp dependency to 20240722.0 LTS (fixes compilation for FreeBSD systems) ([PR #1457](https://github.com/versatica/mediasoup/pull/1457), credits to @garrettboone). + ### 3.14.14 - Sign self generated DTLS certificate with SHA256 ([PR #1450](https://github.com/versatica/mediasoup/pull/1450)). diff --git a/eslint.config.mjs b/eslint.config.mjs index c49dcb532f..5be612ecc7 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -8,7 +8,7 @@ const config = tsEslint.config( { languageOptions: { sourceType: 'module', - globals: { ...globals.node }, + globals: { ...globals.nodeBuiltin }, }, linterOptions: { noInlineConfig: false, diff --git a/package-lock.json b/package-lock.json index f78f6f8cf8..050599c0c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.14", + "version": "3.14.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.14", + "version": "3.14.15", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -20,16 +20,16 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.11.1", + "@eslint/js": "^9.12.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.13", - "@types/node": "^22.6.1", - "eslint": "^9.11.1", + "@types/node": "^22.7.4", + "eslint": "^9.12.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", - "globals": "^15.9.0", + "globals": "^15.10.0", "jest": "^29.7.0", "marked": "^14.1.2", "open-cli": "^8.0.0", @@ -38,7 +38,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.2", - "typescript-eslint": "^8.7.0" + "typescript-eslint": "^8.8.0" }, "engines": { "node": ">=18" @@ -806,9 +806,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", - "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -835,6 +835,28 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -849,9 +871,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, "engines": { "node": ">=18.18" @@ -1877,9 +1899,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", - "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", "dev": true, "dependencies": { "undici-types": "~6.19.2" @@ -1907,16 +1929,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", - "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/type-utils": "8.7.0", - "@typescript-eslint/utils": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1940,15 +1962,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", - "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4" }, "engines": { @@ -1968,13 +1990,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", - "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0" + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1985,13 +2007,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", - "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2009,9 +2031,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", - "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2022,13 +2044,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", - "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2074,15 +2096,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", - "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0" + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2096,12 +2118,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", - "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/types": "8.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2832,9 +2854,9 @@ } }, "node_modules/eslint": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", - "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -2842,11 +2864,11 @@ "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.11.1", + "@eslint/js": "9.12.0", "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", + "@humanwhocodes/retry": "^0.3.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -2854,9 +2876,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2866,13 +2888,11 @@ "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "bin": { @@ -2961,9 +2981,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -2989,9 +3009,9 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3001,14 +3021,14 @@ } }, "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", "dev": true, "dependencies": { "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3018,9 +3038,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3185,9 +3205,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3482,9 +3502,9 @@ } }, "node_modules/globals": { - "version": "15.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", - "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "version": "15.10.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.10.0.tgz", + "integrity": "sha512-tqFIbz83w4Y5TCbtgjZjApohbuh7K9BxGYFm7ifwDR240tvdb7P9x+/9VvUKlmkPoiknoJtanI8UOrqxS3a7lQ==", "dev": true, "engines": { "node": ">=18" @@ -3758,15 +3778,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -6032,14 +6043,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.7.0.tgz", - "integrity": "sha512-nEHbEYJyHwsuf7c3V3RS7Saq+1+la3i0ieR3qP0yjqWSzVmh8Drp47uOl9LjbPANac4S7EFSqvcYIKXUUwIfIQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz", + "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.7.0", - "@typescript-eslint/parser": "8.7.0", - "@typescript-eslint/utils": "8.7.0" + "@typescript-eslint/eslint-plugin": "8.8.0", + "@typescript-eslint/parser": "8.8.0", + "@typescript-eslint/utils": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6853,9 +6864,9 @@ } }, "@eslint/js": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", - "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", "dev": true }, "@eslint/object-schema": { @@ -6873,6 +6884,22 @@ "levn": "^0.4.1" } }, + "@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "dev": true + }, + "@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dev": true, + "requires": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" + } + }, "@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -6880,9 +6907,9 @@ "dev": true }, "@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true }, "@isaacs/cliui": { @@ -7702,9 +7729,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", - "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", "dev": true, "requires": { "undici-types": "~6.19.2" @@ -7732,16 +7759,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", - "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/type-utils": "8.7.0", - "@typescript-eslint/utils": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7749,54 +7776,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", - "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", - "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", "dev": true, "requires": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0" + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" } }, "@typescript-eslint/type-utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", - "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", - "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", - "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", "dev": true, "requires": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7826,24 +7853,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", - "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0" + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", - "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", "dev": true, "requires": { - "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/types": "8.8.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -8354,9 +8381,9 @@ "dev": true }, "eslint": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", - "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", @@ -8364,11 +8391,11 @@ "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.11.1", + "@eslint/js": "9.12.0", "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", + "@humanwhocodes/retry": "^0.3.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -8376,9 +8403,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -8388,20 +8415,18 @@ "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "dependencies": { "eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "dev": true } } @@ -8433,9 +8458,9 @@ } }, "eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -8449,20 +8474,20 @@ "dev": true }, "espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", "dev": true, "requires": { "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.1.0" }, "dependencies": { "eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "dev": true } } @@ -8588,9 +8613,9 @@ "dev": true }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -8800,9 +8825,9 @@ } }, "globals": { - "version": "15.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", - "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "version": "15.10.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.10.0.tgz", + "integrity": "sha512-tqFIbz83w4Y5TCbtgjZjApohbuh7K9BxGYFm7ifwDR240tvdb7P9x+/9VvUKlmkPoiknoJtanI8UOrqxS3a7lQ==", "dev": true }, "graceful-fs": { @@ -8980,12 +9005,6 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -10565,14 +10584,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.7.0.tgz", - "integrity": "sha512-nEHbEYJyHwsuf7c3V3RS7Saq+1+la3i0ieR3qP0yjqWSzVmh8Drp47uOl9LjbPANac4S7EFSqvcYIKXUUwIfIQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz", + "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.7.0", - "@typescript-eslint/parser": "8.7.0", - "@typescript-eslint/utils": "8.7.0" + "@typescript-eslint/eslint-plugin": "8.8.0", + "@typescript-eslint/parser": "8.8.0", + "@typescript-eslint/utils": "8.8.0" } }, "undici-types": { diff --git a/package.json b/package.json index 8b329ab2cb..21f7c528a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.14", + "version": "3.14.15", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -109,16 +109,16 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.11.1", + "@eslint/js": "^9.12.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.13", - "@types/node": "^22.6.1", - "eslint": "^9.11.1", + "@types/node": "^22.7.4", + "eslint": "^9.12.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", - "globals": "^15.9.0", + "globals": "^15.10.0", "jest": "^29.7.0", "marked": "^14.1.2", "open-cli": "^8.0.0", @@ -127,6 +127,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.2", - "typescript-eslint": "^8.7.0" + "typescript-eslint": "^8.8.0" } } From b4c403e5713ea193fb23e0102a28bd739988c704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 17 Oct 2024 18:23:53 +0200 Subject: [PATCH 510/525] CI: Remove deprecated macos12 runner and add macos13 and macos15 (#1458) --- .github/workflows/mediasoup-node.yaml | 6 +++--- .github/workflows/mediasoup-rust.yaml | 3 ++- .github/workflows/mediasoup-worker-prebuild.yaml | 5 ++++- .github/workflows/mediasoup-worker.yaml | 9 ++++++++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 1e561e6c9f..d9e0e634f6 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -40,7 +40,7 @@ jobs: cc: gcc cxx: g++ meson_args: '-Db_sanitize=thread' - - os: macos-12 + - os: macos-13 node: 18 cc: clang cxx: clang++ @@ -48,7 +48,7 @@ jobs: node: 20 cc: clang cxx: clang++ - - os: macos-14 + - os: macos-15 node: 22 cc: clang cxx: clang++ @@ -57,9 +57,9 @@ jobs: cc: cl cxx: cl - os: windows-2022 + node: 22 cc: cl cxx: cl - node: 22 build-type: - Release - Debug diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index f17157ea8d..cf0db637d5 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -19,8 +19,9 @@ jobs: - os: ubuntu-20.04 - os: ubuntu-22.04 - os: ubuntu-24.04 - - os: macos-12 + - os: macos-13 - os: macos-14 + - os: macos-15 - os: windows-2022 runs-on: ${{ matrix.build.os }} diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 5c51a72be8..49d260a811 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -24,12 +24,15 @@ jobs: - os: ubuntu-22.04 cc: gcc cxx: g++ - - os: macos-12 + - os: macos-13 cc: clang cxx: clang++ - os: macos-14 cc: clang cxx: clang++ + - os: macos-15 + cc: clang + cxx: clang++ - os: windows-2022 cc: cl cxx: cl diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 29af3e3c86..059f759349 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -60,7 +60,7 @@ jobs: run-test-asan-address: true run-test-asan-undefined: true run-test-asan-thread: true - - os: macos-12 + - os: macos-13 cc: gcc cxx: g++ pip-break-system-packages: true @@ -75,6 +75,13 @@ jobs: run-test-asan-undefined: false run-test-asan-thread: false pip-break-system-packages: true + - os: macos-15 + cc: clang + cxx: clang++ + run-test-asan-address: false + run-test-asan-undefined: false + run-test-asan-thread: false + pip-break-system-packages: true - os: windows-2022 cc: cl cxx: cl From 3c3223a3bdee3859eb92762ddaf401bed8bdb301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 17 Oct 2024 18:32:12 +0200 Subject: [PATCH 511/525] cosmetic --- .github/workflows/mediasoup-worker.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 059f759349..78c7ddde6d 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -71,17 +71,17 @@ jobs: - os: macos-14 cc: clang cxx: clang++ + pip-break-system-packages: true run-test-asan-address: false run-test-asan-undefined: false run-test-asan-thread: false - pip-break-system-packages: true - os: macos-15 cc: clang cxx: clang++ + pip-break-system-packages: true run-test-asan-address: false run-test-asan-undefined: false run-test-asan-thread: false - pip-break-system-packages: true - os: windows-2022 cc: cl cxx: cl From df55a180f369f4aec935d1f55d99d6e4b6c6f6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 17 Oct 2024 18:32:46 +0200 Subject: [PATCH 512/525] update npm deps --- package-lock.json | 277 +++++++++++++++++++++++++--------------------- package.json | 10 +- 2 files changed, 156 insertions(+), 131 deletions(-) diff --git a/package-lock.json b/package-lock.json index 050599c0c4..4a74b3798c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,21 +24,21 @@ "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.13", - "@types/node": "^22.7.4", + "@types/node": "^22.7.6", "eslint": "^9.12.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", - "globals": "^15.10.0", + "globals": "^15.11.0", "jest": "^29.7.0", - "marked": "^14.1.2", + "marked": "^14.1.3", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.5", - "typescript": "^5.6.2", - "typescript-eslint": "^8.8.0" + "typescript": "^5.6.3", + "typescript-eslint": "^8.9.0" }, "engines": { "node": ">=18" @@ -1437,6 +1437,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1450,6 +1451,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -1459,6 +1461,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1899,10 +1902,11 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "version": "22.7.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz", + "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==", "dev": true, + "license": "MIT", "dependencies": { "undici-types": "~6.19.2" } @@ -1929,16 +1933,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", - "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz", + "integrity": "sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/type-utils": "8.8.0", - "@typescript-eslint/utils": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/type-utils": "8.9.0", + "@typescript-eslint/utils": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1962,15 +1967,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", - "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.9.0.tgz", + "integrity": "sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/typescript-estree": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", "debug": "^4.3.4" }, "engines": { @@ -1990,13 +1996,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", - "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz", + "integrity": "sha512-bZu9bUud9ym1cabmOYH9S6TnbWRzpklVmwqICeOulTCZ9ue2/pczWzQvt/cGj2r2o1RdKoZbuEMalJJSYw3pHQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0" + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2007,13 +2014,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", - "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz", + "integrity": "sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/typescript-estree": "8.9.0", + "@typescript-eslint/utils": "8.9.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2031,10 +2039,11 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", - "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.9.0.tgz", + "integrity": "sha512-SjgkvdYyt1FAPhU9c6FiYCXrldwYYlIQLkuc+LfAhCna6ggp96ACncdtlbn8FmnG72tUkXclrDExOpEYf1nfJQ==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -2044,13 +2053,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", - "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz", + "integrity": "sha512-9iJYTgKLDG6+iqegehc5+EqE6sqaee7kb8vWpmHZ86EqwDjmlqNNHeqDVqb9duh+BY6WCNHfIGvuVU3Tf9Db0g==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2076,6 +2086,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -2085,6 +2096,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2096,15 +2108,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", - "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.9.0.tgz", + "integrity": "sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0" + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/typescript-estree": "8.9.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2118,12 +2131,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", - "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz", + "integrity": "sha512-Ht4y38ubk4L5/U8xKUBfKNYGmvKvA1CANoxiTRMM+tOLk3lbF3DvzZCxJCRSE+2GdCMSh6zq9VZJc3asc1XuAA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/types": "8.9.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3169,6 +3183,7 @@ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -3185,6 +3200,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -3209,6 +3225,7 @@ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -3502,10 +3519,11 @@ } }, "node_modules/globals": { - "version": "15.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.10.0.tgz", - "integrity": "sha512-tqFIbz83w4Y5TCbtgjZjApohbuh7K9BxGYFm7ifwDR240tvdb7P9x+/9VvUKlmkPoiknoJtanI8UOrqxS3a7lQ==", + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", + "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -4675,10 +4693,11 @@ } }, "node_modules/marked": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.2.tgz", - "integrity": "sha512-f3r0yqpz31VXiDB/wj9GaOB0a2PRLQl6vJmXiFrniNwjkKdvakqJRULhjFKJpxOchlCRiG5fcacoUZY5Xa6PEQ==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.3.tgz", + "integrity": "sha512-ZibJqTULGlt9g5k4VMARAktMAjXoVnnr+Y3aCqW1oDftcV4BA3UmrBifzXoZyenHRk75csiPu9iwsTj4VNBT0g==", "dev": true, + "license": "MIT", "bin": { "marked": "bin/marked.js" }, @@ -4709,6 +4728,7 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -5365,7 +5385,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/react-is": { "version": "18.2.0", @@ -5473,6 +5494,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -5509,6 +5531,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -6030,10 +6053,11 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6043,14 +6067,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz", - "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.9.0.tgz", + "integrity": "sha512-AuD/FXGYRQyqyOBCpNLldMlsCGvmDNxptQ3Dp58/NXeB+FqyvTfXmMyba3PYa0Vi9ybnj7G8S/yd/4Cw8y47eA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.8.0", - "@typescript-eslint/parser": "8.8.0", - "@typescript-eslint/utils": "8.8.0" + "@typescript-eslint/eslint-plugin": "8.9.0", + "@typescript-eslint/parser": "8.9.0", + "@typescript-eslint/utils": "8.9.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7729,9 +7754,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "version": "22.7.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz", + "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==", "dev": true, "requires": { "undici-types": "~6.19.2" @@ -7759,16 +7784,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", - "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz", + "integrity": "sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/type-utils": "8.8.0", - "@typescript-eslint/utils": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/type-utils": "8.9.0", + "@typescript-eslint/utils": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7776,54 +7801,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", - "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.9.0.tgz", + "integrity": "sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/typescript-estree": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", - "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz", + "integrity": "sha512-bZu9bUud9ym1cabmOYH9S6TnbWRzpklVmwqICeOulTCZ9ue2/pczWzQvt/cGj2r2o1RdKoZbuEMalJJSYw3pHQ==", "dev": true, "requires": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0" + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0" } }, "@typescript-eslint/type-utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", - "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz", + "integrity": "sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/typescript-estree": "8.9.0", + "@typescript-eslint/utils": "8.9.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", - "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.9.0.tgz", + "integrity": "sha512-SjgkvdYyt1FAPhU9c6FiYCXrldwYYlIQLkuc+LfAhCna6ggp96ACncdtlbn8FmnG72tUkXclrDExOpEYf1nfJQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", - "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz", + "integrity": "sha512-9iJYTgKLDG6+iqegehc5+EqE6sqaee7kb8vWpmHZ86EqwDjmlqNNHeqDVqb9duh+BY6WCNHfIGvuVU3Tf9Db0g==", "dev": true, "requires": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7853,24 +7878,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", - "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.9.0.tgz", + "integrity": "sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0" + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/typescript-estree": "8.9.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", - "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz", + "integrity": "sha512-Ht4y38ubk4L5/U8xKUBfKNYGmvKvA1CANoxiTRMM+tOLk3lbF3DvzZCxJCRSE+2GdCMSh6zq9VZJc3asc1XuAA==", "dev": true, "requires": { - "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/types": "8.9.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -8825,9 +8850,9 @@ } }, "globals": { - "version": "15.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.10.0.tgz", - "integrity": "sha512-tqFIbz83w4Y5TCbtgjZjApohbuh7K9BxGYFm7ifwDR240tvdb7P9x+/9VvUKlmkPoiknoJtanI8UOrqxS3a7lQ==", + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", + "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", "dev": true }, "graceful-fs": { @@ -9688,9 +9713,9 @@ } }, "marked": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.2.tgz", - "integrity": "sha512-f3r0yqpz31VXiDB/wj9GaOB0a2PRLQl6vJmXiFrniNwjkKdvakqJRULhjFKJpxOchlCRiG5fcacoUZY5Xa6PEQ==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.3.tgz", + "integrity": "sha512-ZibJqTULGlt9g5k4VMARAktMAjXoVnnr+Y3aCqW1oDftcV4BA3UmrBifzXoZyenHRk75csiPu9iwsTj4VNBT0g==", "dev": true }, "meow": { @@ -10578,20 +10603,20 @@ "dev": true }, "typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true }, "typescript-eslint": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz", - "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.9.0.tgz", + "integrity": "sha512-AuD/FXGYRQyqyOBCpNLldMlsCGvmDNxptQ3Dp58/NXeB+FqyvTfXmMyba3PYa0Vi9ybnj7G8S/yd/4Cw8y47eA==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.8.0", - "@typescript-eslint/parser": "8.8.0", - "@typescript-eslint/utils": "8.8.0" + "@typescript-eslint/eslint-plugin": "8.9.0", + "@typescript-eslint/parser": "8.9.0", + "@typescript-eslint/utils": "8.9.0" } }, "undici-types": { diff --git a/package.json b/package.json index 21f7c528a4..3761d55715 100644 --- a/package.json +++ b/package.json @@ -113,20 +113,20 @@ "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.13", - "@types/node": "^22.7.4", + "@types/node": "^22.7.6", "eslint": "^9.12.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", - "globals": "^15.10.0", + "globals": "^15.11.0", "jest": "^29.7.0", - "marked": "^14.1.2", + "marked": "^14.1.3", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.5", - "typescript": "^5.6.2", - "typescript-eslint": "^8.8.0" + "typescript": "^5.6.3", + "typescript-eslint": "^8.9.0" } } From 173474c9fe603db648a5106f53585919561a6c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 18 Oct 2024 11:55:54 +0200 Subject: [PATCH 513/525] upps --- eslint.config.mjs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 5be612ecc7..27c4720060 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -173,13 +173,4 @@ const config = tsEslint.config( prettierRecommendedEslint ); -// console.log('*** config:***\n', config); - -// console.log( -// '---tsEslint.configs.strictTypeChecked: %o', -// tsEslint.configs.strictTypeChecked -// ); - -// process.exit(1); - export default config; From 22a5f5fd10a22a6caddace13a98cb1a22c631695 Mon Sep 17 00:00:00 2001 From: Lynnworld Date: Fri, 18 Oct 2024 23:56:20 +0800 Subject: [PATCH 514/525] Fix #492 SimulcastConsumer cannot switch layers if initial tsReferenceSpatialLayer disappears (#1459) --- worker/src/RTC/SimulcastConsumer.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index fcd60c1c5f..5ace36df3d 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -1574,7 +1574,9 @@ namespace RTC MS_TRACE(); // If we don't have yet a RTP timestamp reference, set it now. - if (newTargetSpatialLayer != -1 && this->tsReferenceSpatialLayer == -1) + if ( + newTargetSpatialLayer != -1 && (this->tsReferenceSpatialLayer == -1 || + !GetProducerTsReferenceRtpStream()->GetSenderReportNtpMs())) { MS_DEBUG_TAG( simulcast, "using spatial layer %" PRIi16 " as RTP timestamp reference", newTargetSpatialLayer); @@ -1646,10 +1648,7 @@ namespace RTC return ( this->tsReferenceSpatialLayer == -1 || spatialLayer == this->tsReferenceSpatialLayer || - ( - GetProducerTsReferenceRtpStream()->GetSenderReportNtpMs() && - this->producerRtpStreams.at(spatialLayer)->GetSenderReportNtpMs() - ) + this->producerRtpStreams.at(spatialLayer)->GetSenderReportNtpMs() ); // clang-format on } From a82dba897890a04ed8733c0b4b33991276a05d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 18 Oct 2024 18:02:13 +0200 Subject: [PATCH 515/525] 3.14.16 --- CHANGELOG.md | 4 + package-lock.json | 198 +++++++++++++++++++++++----------------------- package.json | 4 +- 3 files changed, 105 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68efc2a2f6..2cb5c6df80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### NEXT +### 3.14.16 + +- `SimulcastConsumer`: Fix cannot switch layers if initial `tsReferenceSpatialLayer disappears` disappears ([PR #1459](https://github.com/versatica/mediasoup/pull/1459) by @Lynnworld). + ### 3.14.15 - Update worker abseil-cpp dependency to 20240722.0 LTS (fixes compilation for FreeBSD systems) ([PR #1457](https://github.com/versatica/mediasoup/pull/1457), credits to @garrettboone). diff --git a/package-lock.json b/package-lock.json index 4a74b3798c..986f6d051f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.15", + "version": "3.14.16", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.15", + "version": "3.14.16", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -38,7 +38,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.3", - "typescript-eslint": "^8.9.0" + "typescript-eslint": "^8.10.0" }, "engines": { "node": ">=18" @@ -1933,17 +1933,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz", - "integrity": "sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz", + "integrity": "sha512-phuB3hoP7FFKbRXxjl+DRlQDuJqhpOnm5MmtROXyWi3uS/Xg2ZXqiQfcG2BJHiN4QKyzdOJi3NEn/qTnjUlkmQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.9.0", - "@typescript-eslint/type-utils": "8.9.0", - "@typescript-eslint/utils": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0", + "@typescript-eslint/scope-manager": "8.10.0", + "@typescript-eslint/type-utils": "8.10.0", + "@typescript-eslint/utils": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1967,16 +1967,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.9.0.tgz", - "integrity": "sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.10.0.tgz", + "integrity": "sha512-E24l90SxuJhytWJ0pTQydFT46Nk0Z+bsLKo/L8rtQSL93rQ6byd1V/QbDpHUTdLPOMsBCcYXZweADNCfOCmOAg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.9.0", - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/typescript-estree": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0", + "@typescript-eslint/scope-manager": "8.10.0", + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/typescript-estree": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0", "debug": "^4.3.4" }, "engines": { @@ -1996,14 +1996,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz", - "integrity": "sha512-bZu9bUud9ym1cabmOYH9S6TnbWRzpklVmwqICeOulTCZ9ue2/pczWzQvt/cGj2r2o1RdKoZbuEMalJJSYw3pHQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.10.0.tgz", + "integrity": "sha512-AgCaEjhfql9MDKjMUxWvH7HjLeBqMCBfIaBbzzIcBbQPZE7CPh1m6FF+L75NUMJFMLYhCywJXIDEMa3//1A0dw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0" + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2014,14 +2014,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz", - "integrity": "sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.10.0.tgz", + "integrity": "sha512-PCpUOpyQSpxBn230yIcK+LeCQaXuxrgCm2Zk1S+PTIRJsEfU6nJ0TtwyH8pIwPK/vJoA+7TZtzyAJSGBz+s/dg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.9.0", - "@typescript-eslint/utils": "8.9.0", + "@typescript-eslint/typescript-estree": "8.10.0", + "@typescript-eslint/utils": "8.10.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2039,9 +2039,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.9.0.tgz", - "integrity": "sha512-SjgkvdYyt1FAPhU9c6FiYCXrldwYYlIQLkuc+LfAhCna6ggp96ACncdtlbn8FmnG72tUkXclrDExOpEYf1nfJQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.10.0.tgz", + "integrity": "sha512-k/E48uzsfJCRRbGLapdZgrX52csmWJ2rcowwPvOZ8lwPUv3xW6CcFeJAXgx4uJm+Ge4+a4tFOkdYvSpxhRhg1w==", "dev": true, "license": "MIT", "engines": { @@ -2053,14 +2053,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz", - "integrity": "sha512-9iJYTgKLDG6+iqegehc5+EqE6sqaee7kb8vWpmHZ86EqwDjmlqNNHeqDVqb9duh+BY6WCNHfIGvuVU3Tf9Db0g==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.10.0.tgz", + "integrity": "sha512-3OE0nlcOHaMvQ8Xu5gAfME3/tWVDpb/HxtpUZ1WeOAksZ/h/gwrBzCklaGzwZT97/lBbbxJ16dMA98JMEngW4w==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0", + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2108,16 +2108,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.9.0.tgz", - "integrity": "sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.10.0.tgz", + "integrity": "sha512-Oq4uZ7JFr9d1ZunE/QKy5egcDRXT/FrS2z/nlxzPua2VHFtmMvFNDvpq1m/hq0ra+T52aUezfcjGRIB7vNJF9w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.9.0", - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/typescript-estree": "8.9.0" + "@typescript-eslint/scope-manager": "8.10.0", + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/typescript-estree": "8.10.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2131,13 +2131,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz", - "integrity": "sha512-Ht4y38ubk4L5/U8xKUBfKNYGmvKvA1CANoxiTRMM+tOLk3lbF3DvzZCxJCRSE+2GdCMSh6zq9VZJc3asc1XuAA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.10.0.tgz", + "integrity": "sha512-k8nekgqwr7FadWk548Lfph6V3r9OVqjzAIVskE7orMZR23cGJjAOVazsZSJW+ElyjfTM4wx/1g88Mi70DDtG9A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/types": "8.10.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -6067,15 +6067,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.9.0.tgz", - "integrity": "sha512-AuD/FXGYRQyqyOBCpNLldMlsCGvmDNxptQ3Dp58/NXeB+FqyvTfXmMyba3PYa0Vi9ybnj7G8S/yd/4Cw8y47eA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.10.0.tgz", + "integrity": "sha512-YIu230PeN7z9zpu/EtqCIuRVHPs4iSlqW6TEvjbyDAE3MZsSl2RXBo+5ag+lbABCG8sFM1WVKEXhlQ8Ml8A3Fw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.9.0", - "@typescript-eslint/parser": "8.9.0", - "@typescript-eslint/utils": "8.9.0" + "@typescript-eslint/eslint-plugin": "8.10.0", + "@typescript-eslint/parser": "8.10.0", + "@typescript-eslint/utils": "8.10.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7784,16 +7784,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz", - "integrity": "sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz", + "integrity": "sha512-phuB3hoP7FFKbRXxjl+DRlQDuJqhpOnm5MmtROXyWi3uS/Xg2ZXqiQfcG2BJHiN4QKyzdOJi3NEn/qTnjUlkmQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.9.0", - "@typescript-eslint/type-utils": "8.9.0", - "@typescript-eslint/utils": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0", + "@typescript-eslint/scope-manager": "8.10.0", + "@typescript-eslint/type-utils": "8.10.0", + "@typescript-eslint/utils": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7801,54 +7801,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.9.0.tgz", - "integrity": "sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.10.0.tgz", + "integrity": "sha512-E24l90SxuJhytWJ0pTQydFT46Nk0Z+bsLKo/L8rtQSL93rQ6byd1V/QbDpHUTdLPOMsBCcYXZweADNCfOCmOAg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.9.0", - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/typescript-estree": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0", + "@typescript-eslint/scope-manager": "8.10.0", + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/typescript-estree": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz", - "integrity": "sha512-bZu9bUud9ym1cabmOYH9S6TnbWRzpklVmwqICeOulTCZ9ue2/pczWzQvt/cGj2r2o1RdKoZbuEMalJJSYw3pHQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.10.0.tgz", + "integrity": "sha512-AgCaEjhfql9MDKjMUxWvH7HjLeBqMCBfIaBbzzIcBbQPZE7CPh1m6FF+L75NUMJFMLYhCywJXIDEMa3//1A0dw==", "dev": true, "requires": { - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0" + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0" } }, "@typescript-eslint/type-utils": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz", - "integrity": "sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.10.0.tgz", + "integrity": "sha512-PCpUOpyQSpxBn230yIcK+LeCQaXuxrgCm2Zk1S+PTIRJsEfU6nJ0TtwyH8pIwPK/vJoA+7TZtzyAJSGBz+s/dg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.9.0", - "@typescript-eslint/utils": "8.9.0", + "@typescript-eslint/typescript-estree": "8.10.0", + "@typescript-eslint/utils": "8.10.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.9.0.tgz", - "integrity": "sha512-SjgkvdYyt1FAPhU9c6FiYCXrldwYYlIQLkuc+LfAhCna6ggp96ACncdtlbn8FmnG72tUkXclrDExOpEYf1nfJQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.10.0.tgz", + "integrity": "sha512-k/E48uzsfJCRRbGLapdZgrX52csmWJ2rcowwPvOZ8lwPUv3xW6CcFeJAXgx4uJm+Ge4+a4tFOkdYvSpxhRhg1w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz", - "integrity": "sha512-9iJYTgKLDG6+iqegehc5+EqE6sqaee7kb8vWpmHZ86EqwDjmlqNNHeqDVqb9duh+BY6WCNHfIGvuVU3Tf9Db0g==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.10.0.tgz", + "integrity": "sha512-3OE0nlcOHaMvQ8Xu5gAfME3/tWVDpb/HxtpUZ1WeOAksZ/h/gwrBzCklaGzwZT97/lBbbxJ16dMA98JMEngW4w==", "dev": true, "requires": { - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0", + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7878,24 +7878,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.9.0.tgz", - "integrity": "sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.10.0.tgz", + "integrity": "sha512-Oq4uZ7JFr9d1ZunE/QKy5egcDRXT/FrS2z/nlxzPua2VHFtmMvFNDvpq1m/hq0ra+T52aUezfcjGRIB7vNJF9w==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.9.0", - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/typescript-estree": "8.9.0" + "@typescript-eslint/scope-manager": "8.10.0", + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/typescript-estree": "8.10.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz", - "integrity": "sha512-Ht4y38ubk4L5/U8xKUBfKNYGmvKvA1CANoxiTRMM+tOLk3lbF3DvzZCxJCRSE+2GdCMSh6zq9VZJc3asc1XuAA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.10.0.tgz", + "integrity": "sha512-k8nekgqwr7FadWk548Lfph6V3r9OVqjzAIVskE7orMZR23cGJjAOVazsZSJW+ElyjfTM4wx/1g88Mi70DDtG9A==", "dev": true, "requires": { - "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/types": "8.10.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -10609,14 +10609,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.9.0.tgz", - "integrity": "sha512-AuD/FXGYRQyqyOBCpNLldMlsCGvmDNxptQ3Dp58/NXeB+FqyvTfXmMyba3PYa0Vi9ybnj7G8S/yd/4Cw8y47eA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.10.0.tgz", + "integrity": "sha512-YIu230PeN7z9zpu/EtqCIuRVHPs4iSlqW6TEvjbyDAE3MZsSl2RXBo+5ag+lbABCG8sFM1WVKEXhlQ8Ml8A3Fw==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.9.0", - "@typescript-eslint/parser": "8.9.0", - "@typescript-eslint/utils": "8.9.0" + "@typescript-eslint/eslint-plugin": "8.10.0", + "@typescript-eslint/parser": "8.10.0", + "@typescript-eslint/utils": "8.10.0" } }, "undici-types": { diff --git a/package.json b/package.json index 3761d55715..8b5adbf077 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.15", + "version": "3.14.16", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -127,6 +127,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.3", - "typescript-eslint": "^8.9.0" + "typescript-eslint": "^8.10.0" } } From c03711bdaca264a30d9cb4be38c753577f3e6ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 8 Nov 2024 08:47:39 +0100 Subject: [PATCH 516/525] update npm deps --- package-lock.json | 497 +++++++++++++++++++++++++--------------------- package.json | 16 +- 2 files changed, 275 insertions(+), 238 deletions(-) diff --git a/package-lock.json b/package-lock.json index 986f6d051f..8a75a725e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,25 +20,25 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.12.0", + "@eslint/js": "^9.14.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.13", - "@types/node": "^22.7.6", - "eslint": "^9.12.0", + "@types/jest": "^29.5.14", + "@types/node": "^22.9.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.8.3", + "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", - "globals": "^15.11.0", + "globals": "^15.12.0", "jest": "^29.7.0", - "marked": "^14.1.3", + "marked": "^14.1.4", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.3", - "typescript-eslint": "^8.10.0" + "typescript-eslint": "^8.13.0" }, "engines": { "node": ">=18" @@ -739,10 +739,11 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -762,10 +763,11 @@ } }, "node_modules/@eslint/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", - "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -806,10 +808,11 @@ } }, "node_modules/@eslint/js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", - "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -836,27 +839,43 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -871,10 +890,11 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -1881,10 +1901,11 @@ } }, "node_modules/@types/jest": { - "version": "29.5.13", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", - "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -1902,13 +1923,13 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.7.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz", - "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/stack-utils": { @@ -1933,17 +1954,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz", - "integrity": "sha512-phuB3hoP7FFKbRXxjl+DRlQDuJqhpOnm5MmtROXyWi3uS/Xg2ZXqiQfcG2BJHiN4QKyzdOJi3NEn/qTnjUlkmQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", + "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.10.0", - "@typescript-eslint/type-utils": "8.10.0", - "@typescript-eslint/utils": "8.10.0", - "@typescript-eslint/visitor-keys": "8.10.0", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/type-utils": "8.13.0", + "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1967,16 +1988,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.10.0.tgz", - "integrity": "sha512-E24l90SxuJhytWJ0pTQydFT46Nk0Z+bsLKo/L8rtQSL93rQ6byd1V/QbDpHUTdLPOMsBCcYXZweADNCfOCmOAg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", + "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.10.0", - "@typescript-eslint/types": "8.10.0", - "@typescript-eslint/typescript-estree": "8.10.0", - "@typescript-eslint/visitor-keys": "8.10.0", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4" }, "engines": { @@ -1996,14 +2017,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.10.0.tgz", - "integrity": "sha512-AgCaEjhfql9MDKjMUxWvH7HjLeBqMCBfIaBbzzIcBbQPZE7CPh1m6FF+L75NUMJFMLYhCywJXIDEMa3//1A0dw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", + "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.10.0", - "@typescript-eslint/visitor-keys": "8.10.0" + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2014,14 +2035,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.10.0.tgz", - "integrity": "sha512-PCpUOpyQSpxBn230yIcK+LeCQaXuxrgCm2Zk1S+PTIRJsEfU6nJ0TtwyH8pIwPK/vJoA+7TZtzyAJSGBz+s/dg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", + "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.10.0", - "@typescript-eslint/utils": "8.10.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/utils": "8.13.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2039,9 +2060,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.10.0.tgz", - "integrity": "sha512-k/E48uzsfJCRRbGLapdZgrX52csmWJ2rcowwPvOZ8lwPUv3xW6CcFeJAXgx4uJm+Ge4+a4tFOkdYvSpxhRhg1w==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", + "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", "dev": true, "license": "MIT", "engines": { @@ -2053,14 +2074,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.10.0.tgz", - "integrity": "sha512-3OE0nlcOHaMvQ8Xu5gAfME3/tWVDpb/HxtpUZ1WeOAksZ/h/gwrBzCklaGzwZT97/lBbbxJ16dMA98JMEngW4w==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", + "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.10.0", - "@typescript-eslint/visitor-keys": "8.10.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2108,16 +2129,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.10.0.tgz", - "integrity": "sha512-Oq4uZ7JFr9d1ZunE/QKy5egcDRXT/FrS2z/nlxzPua2VHFtmMvFNDvpq1m/hq0ra+T52aUezfcjGRIB7vNJF9w==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", + "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.10.0", - "@typescript-eslint/types": "8.10.0", - "@typescript-eslint/typescript-estree": "8.10.0" + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2131,13 +2152,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.10.0.tgz", - "integrity": "sha512-k8nekgqwr7FadWk548Lfph6V3r9OVqjzAIVskE7orMZR23cGJjAOVazsZSJW+ElyjfTM4wx/1g88Mi70DDtG9A==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", + "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/types": "8.13.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2149,10 +2170,11 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -2868,21 +2890,22 @@ } }, "node_modules/eslint": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", - "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", + "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.12.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -2890,9 +2913,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2940,10 +2963,11 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.8.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", - "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==", + "version": "28.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.9.0.tgz", + "integrity": "sha512-rLu1s1Wf96TgUUxSw6loVIkNtUjq1Re7A9QdCCHSohnvXEBAjuL420h0T/fMmkQlNsQP2GhQzEUpYHPfxBkvYQ==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" }, @@ -2995,10 +3019,11 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -3023,10 +3048,11 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -3035,14 +3061,15 @@ } }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3052,10 +3079,11 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -3093,6 +3121,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -3519,9 +3548,9 @@ } }, "node_modules/globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true, "license": "MIT", "engines": { @@ -4693,9 +4722,9 @@ } }, "node_modules/marked": { - "version": "14.1.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.3.tgz", - "integrity": "sha512-ZibJqTULGlt9g5k4VMARAktMAjXoVnnr+Y3aCqW1oDftcV4BA3UmrBifzXoZyenHRk75csiPu9iwsTj4VNBT0g==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.4.tgz", + "integrity": "sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg==", "dev": true, "license": "MIT", "bin": { @@ -6067,15 +6096,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.10.0.tgz", - "integrity": "sha512-YIu230PeN7z9zpu/EtqCIuRVHPs4iSlqW6TEvjbyDAE3MZsSl2RXBo+5ag+lbABCG8sFM1WVKEXhlQ8Ml8A3Fw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.13.0.tgz", + "integrity": "sha512-vIMpDRJrQd70au2G8w34mPps0ezFSPMEX4pXkTzUkrNbRX+36ais2ksGWN0esZL+ZMaFJEneOBHzCgSqle7DHw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.10.0", - "@typescript-eslint/parser": "8.10.0", - "@typescript-eslint/utils": "8.10.0" + "@typescript-eslint/eslint-plugin": "8.13.0", + "@typescript-eslint/parser": "8.13.0", + "@typescript-eslint/utils": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6841,9 +6870,9 @@ } }, "@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true }, "@eslint/config-array": { @@ -6858,9 +6887,9 @@ } }, "@eslint/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", - "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", "dev": true }, "@eslint/eslintrc": { @@ -6889,9 +6918,9 @@ } }, "@eslint/js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", - "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true }, "@eslint/object-schema": { @@ -6910,19 +6939,27 @@ } }, "@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true }, "@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "requires": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" + }, + "dependencies": { + "@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true + } } }, "@humanwhocodes/module-importer": { @@ -6932,9 +6969,9 @@ "dev": true }, "@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true }, "@isaacs/cliui": { @@ -7733,9 +7770,9 @@ } }, "@types/jest": { - "version": "29.5.13", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", - "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", "dev": true, "requires": { "expect": "^29.0.0", @@ -7754,12 +7791,12 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.7.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz", - "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "dev": true, "requires": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "@types/stack-utils": { @@ -7784,16 +7821,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz", - "integrity": "sha512-phuB3hoP7FFKbRXxjl+DRlQDuJqhpOnm5MmtROXyWi3uS/Xg2ZXqiQfcG2BJHiN4QKyzdOJi3NEn/qTnjUlkmQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", + "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.10.0", - "@typescript-eslint/type-utils": "8.10.0", - "@typescript-eslint/utils": "8.10.0", - "@typescript-eslint/visitor-keys": "8.10.0", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/type-utils": "8.13.0", + "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7801,54 +7838,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.10.0.tgz", - "integrity": "sha512-E24l90SxuJhytWJ0pTQydFT46Nk0Z+bsLKo/L8rtQSL93rQ6byd1V/QbDpHUTdLPOMsBCcYXZweADNCfOCmOAg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", + "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.10.0", - "@typescript-eslint/types": "8.10.0", - "@typescript-eslint/typescript-estree": "8.10.0", - "@typescript-eslint/visitor-keys": "8.10.0", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.10.0.tgz", - "integrity": "sha512-AgCaEjhfql9MDKjMUxWvH7HjLeBqMCBfIaBbzzIcBbQPZE7CPh1m6FF+L75NUMJFMLYhCywJXIDEMa3//1A0dw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", + "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", "dev": true, "requires": { - "@typescript-eslint/types": "8.10.0", - "@typescript-eslint/visitor-keys": "8.10.0" + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0" } }, "@typescript-eslint/type-utils": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.10.0.tgz", - "integrity": "sha512-PCpUOpyQSpxBn230yIcK+LeCQaXuxrgCm2Zk1S+PTIRJsEfU6nJ0TtwyH8pIwPK/vJoA+7TZtzyAJSGBz+s/dg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", + "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.10.0", - "@typescript-eslint/utils": "8.10.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/utils": "8.13.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.10.0.tgz", - "integrity": "sha512-k/E48uzsfJCRRbGLapdZgrX52csmWJ2rcowwPvOZ8lwPUv3xW6CcFeJAXgx4uJm+Ge4+a4tFOkdYvSpxhRhg1w==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", + "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.10.0.tgz", - "integrity": "sha512-3OE0nlcOHaMvQ8Xu5gAfME3/tWVDpb/HxtpUZ1WeOAksZ/h/gwrBzCklaGzwZT97/lBbbxJ16dMA98JMEngW4w==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", + "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", "dev": true, "requires": { - "@typescript-eslint/types": "8.10.0", - "@typescript-eslint/visitor-keys": "8.10.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7878,31 +7915,31 @@ } }, "@typescript-eslint/utils": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.10.0.tgz", - "integrity": "sha512-Oq4uZ7JFr9d1ZunE/QKy5egcDRXT/FrS2z/nlxzPua2VHFtmMvFNDvpq1m/hq0ra+T52aUezfcjGRIB7vNJF9w==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", + "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.10.0", - "@typescript-eslint/types": "8.10.0", - "@typescript-eslint/typescript-estree": "8.10.0" + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.10.0.tgz", - "integrity": "sha512-k8nekgqwr7FadWk548Lfph6V3r9OVqjzAIVskE7orMZR23cGJjAOVazsZSJW+ElyjfTM4wx/1g88Mi70DDtG9A==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", + "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", "dev": true, "requires": { - "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/types": "8.13.0", "eslint-visitor-keys": "^3.4.3" } }, "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true }, "acorn-jsx": { @@ -8406,21 +8443,21 @@ "dev": true }, "eslint": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", - "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", + "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.12.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -8428,9 +8465,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -8449,9 +8486,9 @@ }, "dependencies": { "eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true } } @@ -8464,9 +8501,9 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "28.8.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", - "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==", + "version": "28.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.9.0.tgz", + "integrity": "sha512-rLu1s1Wf96TgUUxSw6loVIkNtUjq1Re7A9QdCCHSohnvXEBAjuL420h0T/fMmkQlNsQP2GhQzEUpYHPfxBkvYQ==", "dev": true, "requires": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -8483,9 +8520,9 @@ } }, "eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -8499,20 +8536,20 @@ "dev": true }, "espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "requires": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "dependencies": { "eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true } } @@ -8850,9 +8887,9 @@ } }, "globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true }, "graceful-fs": { @@ -9713,9 +9750,9 @@ } }, "marked": { - "version": "14.1.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.3.tgz", - "integrity": "sha512-ZibJqTULGlt9g5k4VMARAktMAjXoVnnr+Y3aCqW1oDftcV4BA3UmrBifzXoZyenHRk75csiPu9iwsTj4VNBT0g==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.4.tgz", + "integrity": "sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg==", "dev": true }, "meow": { @@ -10609,14 +10646,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.10.0.tgz", - "integrity": "sha512-YIu230PeN7z9zpu/EtqCIuRVHPs4iSlqW6TEvjbyDAE3MZsSl2RXBo+5ag+lbABCG8sFM1WVKEXhlQ8Ml8A3Fw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.13.0.tgz", + "integrity": "sha512-vIMpDRJrQd70au2G8w34mPps0ezFSPMEX4pXkTzUkrNbRX+36ais2ksGWN0esZL+ZMaFJEneOBHzCgSqle7DHw==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.10.0", - "@typescript-eslint/parser": "8.10.0", - "@typescript-eslint/utils": "8.10.0" + "@typescript-eslint/eslint-plugin": "8.13.0", + "@typescript-eslint/parser": "8.13.0", + "@typescript-eslint/utils": "8.13.0" } }, "undici-types": { diff --git a/package.json b/package.json index 8b5adbf077..164a1512d0 100644 --- a/package.json +++ b/package.json @@ -109,24 +109,24 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.12.0", + "@eslint/js": "^9.14.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", - "@types/jest": "^29.5.13", - "@types/node": "^22.7.6", - "eslint": "^9.12.0", + "@types/jest": "^29.5.14", + "@types/node": "^22.9.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^28.8.3", + "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", - "globals": "^15.11.0", + "globals": "^15.12.0", "jest": "^29.7.0", - "marked": "^14.1.3", + "marked": "^14.1.4", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.3", - "typescript-eslint": "^8.10.0" + "typescript-eslint": "^8.13.0" } } From e0621613794e9f946c860d15b473f181d8ee33fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 8 Nov 2024 09:08:28 +0100 Subject: [PATCH 517/525] ESLint: require TS return type --- eslint.config.mjs | 1 + node/src/DirectTransport.ts | 2 +- node/src/Producer.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 27c4720060..858191d02c 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -145,6 +145,7 @@ const config = tsEslint.config( '@typescript-eslint/consistent-type-definitions': 0, // Sorry, we need many `any` usage. '@typescript-eslint/no-explicit-any': 0, + '@typescript-eslint/explicit-function-return-type': 2, '@typescript-eslint/no-unsafe-member-access': 0, '@typescript-eslint/no-unsafe-assignment': 0, '@typescript-eslint/no-unsafe-call': 0, diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 0774a088f7..044dd2d443 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -217,7 +217,7 @@ export class DirectTransport< /** * Send RTCP packet. */ - sendRtcp(rtcpPacket: Buffer) { + sendRtcp(rtcpPacket: Buffer): void { if (!Buffer.isBuffer(rtcpPacket)) { throw new TypeError('rtcpPacket must be a Buffer'); } diff --git a/node/src/Producer.ts b/node/src/Producer.ts index c9c05b2aec..42e2d2b1ee 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -505,7 +505,7 @@ export class Producer< /** * Send RTP packet (just valid for Producers created on a DirectTransport). */ - send(rtpPacket: Buffer) { + send(rtpPacket: Buffer): void { if (!Buffer.isBuffer(rtpPacket)) { throw new TypeError('rtpPacket must be a Buffer'); } From 877c489091804522c7b8816b7aec0431559effb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 11 Nov 2024 12:56:24 +0100 Subject: [PATCH 518/525] Add TypeScript interfaces for all exported classes (#1463) --- CHANGELOG.md | 4 + eslint.config.mjs | 2 + node/src/ActiveSpeakerObserver.ts | 86 ++- node/src/ActiveSpeakerObserverTypes.ts | 59 ++ node/src/AudioLevelObserver.ts | 113 ++-- node/src/AudioLevelObserverTypes.ts | 81 +++ node/src/Channel.ts | 9 - node/src/Consumer.ts | 447 +++------------ node/src/ConsumerTypes.ts | 393 +++++++++++++ node/src/DataConsumer.ts | 254 ++------- node/src/DataConsumerTypes.ts | 233 ++++++++ node/src/DataProducer.ts | 161 +----- node/src/DataProducerTypes.ts | 171 ++++++ node/src/DirectTransport.ts | 130 ++--- node/src/DirectTransportTypes.ts | 89 +++ node/src/Logger.ts | 2 +- node/src/PipeTransport.ts | 238 +++----- node/src/PipeTransportTypes.ts | 200 +++++++ node/src/PlainTransport.ts | 223 ++------ node/src/PlainTransportTypes.ts | 209 +++++++ node/src/Producer.ts | 267 ++------- node/src/ProducerTypes.ts | 253 +++++++++ node/src/Router.ts | 368 ++++-------- node/src/RouterTypes.ts | 291 ++++++++++ node/src/RtpObserver.ts | 91 +-- node/src/RtpObserverTypes.ts | 105 ++++ node/src/Transport.ts | 526 ++++-------------- node/src/TransportTypes.ts | 399 +++++++++++++ node/src/WebRtcServer.ts | 138 ++--- node/src/WebRtcServerTypes.ts | 112 ++++ node/src/WebRtcTransport.ts | 344 ++---------- node/src/WebRtcTransportTypes.ts | 319 +++++++++++ node/src/Worker.ts | 305 ++-------- node/src/WorkerTypes.ts | 279 ++++++++++ node/src/enhancedEvents.ts | 9 +- node/src/fbsUtils.ts | 115 ++++ node/src/index.ts | 35 +- node/src/ortc.ts | 19 +- ...Parameters.ts => rtpParametersFbsUtils.ts} | 381 +------------ node/src/rtpParametersTypes.ts | 357 ++++++++++++ ...RtpStream.ts => rtpStreamStatsFbsUtils.ts} | 45 +- node/src/rtpStreamStatsTypes.ts | 38 ++ node/src/scalabilityModesTypes.ts | 5 + ...ilityModes.ts => scalabilityModesUtils.ts} | 12 +- node/src/sctpParametersFbsUtils.ts | 54 ++ ...tpParameters.ts => sctpParametersTypes.ts} | 51 -- ...arameters.ts => srtpParametersFbsUtils.ts} | 25 +- node/src/srtpParametersTypes.ts | 23 + node/src/supportedRtpCapabilities.ts | 2 +- node/src/test/test-ActiveSpeakerObserver.ts | 11 +- node/src/test/test-AudioLevelObserver.ts | 3 +- node/src/test/test-Consumer.ts | 9 +- node/src/test/test-DataConsumer.ts | 2 +- node/src/test/test-DataProducer.ts | 2 +- node/src/test/test-DirectTransport.ts | 5 +- node/src/test/test-PipeTransport.ts | 8 +- node/src/test/test-PlainTransport.ts | 7 +- node/src/test/test-Producer.ts | 9 +- node/src/test/test-Router.ts | 11 +- node/src/test/test-WebRtcServer.ts | 61 +- node/src/test/test-WebRtcTransport.ts | 14 +- node/src/test/test-Worker.ts | 6 +- node/src/test/test-mediasoup.ts | 2 +- node/src/test/test-multiopus.ts | 2 +- node/src/test/test-node-sctp.ts | 2 +- node/src/types.ts | 60 +- node/src/utils.ts | 144 ----- 67 files changed, 4735 insertions(+), 3695 deletions(-) create mode 100644 node/src/ActiveSpeakerObserverTypes.ts create mode 100644 node/src/AudioLevelObserverTypes.ts create mode 100644 node/src/ConsumerTypes.ts create mode 100644 node/src/DataConsumerTypes.ts create mode 100644 node/src/DataProducerTypes.ts create mode 100644 node/src/DirectTransportTypes.ts create mode 100644 node/src/PipeTransportTypes.ts create mode 100644 node/src/PlainTransportTypes.ts create mode 100644 node/src/ProducerTypes.ts create mode 100644 node/src/RouterTypes.ts create mode 100644 node/src/RtpObserverTypes.ts create mode 100644 node/src/TransportTypes.ts create mode 100644 node/src/WebRtcServerTypes.ts create mode 100644 node/src/WebRtcTransportTypes.ts create mode 100644 node/src/WorkerTypes.ts create mode 100644 node/src/fbsUtils.ts rename node/src/{RtpParameters.ts => rtpParametersFbsUtils.ts} (55%) create mode 100644 node/src/rtpParametersTypes.ts rename node/src/{RtpStream.ts => rtpStreamStatsFbsUtils.ts} (78%) create mode 100644 node/src/rtpStreamStatsTypes.ts create mode 100644 node/src/scalabilityModesTypes.ts rename node/src/{scalabilityModes.ts => scalabilityModesUtils.ts} (69%) create mode 100644 node/src/sctpParametersFbsUtils.ts rename node/src/{SctpParameters.ts => sctpParametersTypes.ts} (67%) rename node/src/{SrtpParameters.ts => srtpParametersFbsUtils.ts} (81%) create mode 100644 node/src/srtpParametersTypes.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cb5c6df80..aadea8be76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### NEXT +- Node: Add TypeScript interfaces for all exported classes ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)). +- Node: Add new `transport.type` getter than returns `'webrtc' | 'plain' | 'pipe' | 'direct'` ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)). +- Node: Add new `rtpObserver.type` getter than returns `'activespeaker' | 'audiolevel'` ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)). + ### 3.14.16 - `SimulcastConsumer`: Fix cannot switch layers if initial `tsReferenceSpatialLayer disappears` disappears ([PR #1459](https://github.com/versatica/mediasoup/pull/1459) by @Lynnworld). diff --git a/eslint.config.mjs b/eslint.config.mjs index 858191d02c..1e596554d8 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -90,6 +90,7 @@ const config = tsEslint.config( 2, { vars: 'all', args: 'after-used', caughtErrors: 'none' }, ], + 'no-unused-private-class-members': 2, 'no-use-before-define': 0, 'no-useless-call': 2, 'no-useless-computed-key': 2, @@ -127,6 +128,7 @@ const config = tsEslint.config( }, }, rules: { + '@typescript-eslint/class-literal-property-style': [2, 'getters'], '@typescript-eslint/consistent-generic-constructors': [ 2, 'type-annotation', diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index 609e6581e5..a46ac16ab4 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -1,60 +1,33 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; -import { - RtpObserver, - RtpObserverEvents, - RtpObserverObserverEvents, - RtpObserverConstructorOptions, -} from './RtpObserver'; -import { Producer } from './Producer'; -import { AppData } from './types'; +import type { + ActiveSpeakerObserver, + ActiveSpeakerObserverDominantSpeaker, + ActiveSpeakerObserverEvents, + ActiveSpeakerObserverObserver, + ActiveSpeakerObserverObserverEvents, +} from './ActiveSpeakerObserverTypes'; +import type { RtpObserver } from './RtpObserverTypes'; +import { RtpObserverImpl, RtpObserverConstructorOptions } from './RtpObserver'; +import type { AppData } from './types'; import { Event, Notification } from './fbs/notification'; import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; -export type ActiveSpeakerObserverOptions< - ActiveSpeakerObserverAppData extends AppData = AppData, -> = { - interval?: number; - - /** - * Custom application data. - */ - appData?: ActiveSpeakerObserverAppData; -}; - -export type ActiveSpeakerObserverDominantSpeaker = { - /** - * The audio Producer instance. - */ - producer: Producer; -}; - -export type ActiveSpeakerObserverEvents = RtpObserverEvents & { - dominantspeaker: [ActiveSpeakerObserverDominantSpeaker]; -}; - -export type ActiveSpeakerObserverObserver = - EnhancedEventEmitter; - -export type ActiveSpeakerObserverObserverEvents = RtpObserverObserverEvents & { - dominantspeaker: [ActiveSpeakerObserverDominantSpeaker]; -}; - type RtpObserverObserverConstructorOptions = RtpObserverConstructorOptions; const logger = new Logger('ActiveSpeakerObserver'); -export class ActiveSpeakerObserver< - ActiveSpeakerObserverAppData extends AppData = AppData, -> extends RtpObserver< - ActiveSpeakerObserverAppData, - ActiveSpeakerObserverEvents, - ActiveSpeakerObserverObserver -> { - /** - * @private - */ +export class ActiveSpeakerObserverImpl< + ActiveSpeakerObserverAppData extends AppData = AppData, + > + extends RtpObserverImpl< + ActiveSpeakerObserverAppData, + ActiveSpeakerObserverEvents, + ActiveSpeakerObserverObserver + > + implements RtpObserver, ActiveSpeakerObserver +{ constructor( options: RtpObserverObserverConstructorOptions ) { @@ -64,13 +37,13 @@ export class ActiveSpeakerObserver< super(options, observer); this.handleWorkerNotifications(); + this.handleListenerError(); + } + + get type(): 'activespeaker' { + return 'activespeaker'; } - /** - * Observer. - * - * @override - */ get observer(): ActiveSpeakerObserverObserver { return super.observer; } @@ -109,4 +82,13 @@ export class ActiveSpeakerObserver< } ); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } diff --git a/node/src/ActiveSpeakerObserverTypes.ts b/node/src/ActiveSpeakerObserverTypes.ts new file mode 100644 index 0000000000..9d00005697 --- /dev/null +++ b/node/src/ActiveSpeakerObserverTypes.ts @@ -0,0 +1,59 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { + RtpObserver, + RtpObserverEvents, + RtpObserverObserverEvents, +} from './RtpObserverTypes'; +import type { Producer } from './ProducerTypes'; +import type { AppData } from './types'; + +export type ActiveSpeakerObserverOptions< + ActiveSpeakerObserverAppData extends AppData = AppData, +> = { + interval?: number; + + /** + * Custom application data. + */ + appData?: ActiveSpeakerObserverAppData; +}; + +export type ActiveSpeakerObserverDominantSpeaker = { + /** + * The audio Producer instance. + */ + producer: Producer; +}; + +export type ActiveSpeakerObserverEvents = RtpObserverEvents & { + dominantspeaker: [ActiveSpeakerObserverDominantSpeaker]; +}; + +export type ActiveSpeakerObserverObserver = + EnhancedEventEmitter; + +export type ActiveSpeakerObserverObserverEvents = RtpObserverObserverEvents & { + dominantspeaker: [ActiveSpeakerObserverDominantSpeaker]; +}; + +export interface ActiveSpeakerObserver< + ActiveSpeakerObserverAppData extends AppData = AppData, +> extends RtpObserver< + ActiveSpeakerObserverAppData, + ActiveSpeakerObserverEvents, + ActiveSpeakerObserverObserver + > { + /** + * RtpObserver type. + * + * @override + */ + get type(): 'activespeaker'; + + /** + * Observer. + * + * @override + */ + get observer(): ActiveSpeakerObserverObserver; +} diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index d429933954..5890956fdb 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -1,83 +1,35 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; -import { - RtpObserver, - RtpObserverEvents, - RtpObserverObserverEvents, - RtpObserverConstructorOptions, -} from './RtpObserver'; -import { Producer } from './Producer'; -import { AppData } from './types'; -import * as utils from './utils'; +import type { + AudioLevelObserver, + AudioLevelObserverVolume, + AudioLevelObserverEvents, + AudioLevelObserverObserver, + AudioLevelObserverObserverEvents, +} from './AudioLevelObserverTypes'; +import type { RtpObserver } from './RtpObserverTypes'; +import { RtpObserverImpl, RtpObserverConstructorOptions } from './RtpObserver'; +import type { Producer } from './ProducerTypes'; +import type { AppData } from './types'; +import * as fbsUtils from './fbsUtils'; import { Event, Notification } from './fbs/notification'; import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; -export type AudioLevelObserverOptions< - AudioLevelObserverAppData extends AppData = AppData, -> = { - /** - * Maximum number of entries in the 'volumes”' event. Default 1. - */ - maxEntries?: number; - - /** - * Minimum average volume (in dBvo from -127 to 0) for entries in the - * 'volumes' event. Default -80. - */ - threshold?: number; - - /** - * Interval in ms for checking audio volumes. Default 1000. - */ - interval?: number; - - /** - * Custom application data. - */ - appData?: AudioLevelObserverAppData; -}; - -export type AudioLevelObserverVolume = { - /** - * The audio Producer instance. - */ - producer: Producer; - - /** - * The average volume (in dBvo from -127 to 0) of the audio Producer in the - * last interval. - */ - volume: number; -}; - -export type AudioLevelObserverEvents = RtpObserverEvents & { - volumes: [AudioLevelObserverVolume[]]; - silence: []; -}; - -export type AudioLevelObserverObserver = - EnhancedEventEmitter; - -export type AudioLevelObserverObserverEvents = RtpObserverObserverEvents & { - volumes: [AudioLevelObserverVolume[]]; - silence: []; -}; - type AudioLevelObserverConstructorOptions = RtpObserverConstructorOptions; const logger = new Logger('AudioLevelObserver'); -export class AudioLevelObserver< - AudioLevelObserverAppData extends AppData = AppData, -> extends RtpObserver< - AudioLevelObserverAppData, - AudioLevelObserverEvents, - AudioLevelObserverObserver -> { - /** - * @private - */ +export class AudioLevelObserverImpl< + AudioLevelObserverAppData extends AppData = AppData, + > + extends RtpObserverImpl< + AudioLevelObserverAppData, + AudioLevelObserverEvents, + AudioLevelObserverObserver + > + implements RtpObserver, AudioLevelObserver +{ constructor( options: AudioLevelObserverConstructorOptions ) { @@ -87,13 +39,13 @@ export class AudioLevelObserver< super(options, observer); this.handleWorkerNotifications(); + this.handleListenerError(); + } + + get type(): 'audiolevel' { + return 'audiolevel'; } - /** - * Observer. - * - * @override - */ get observer(): AudioLevelObserverObserver { return super.observer; } @@ -111,7 +63,7 @@ export class AudioLevelObserver< // Get the corresponding Producer instance and remove entries with // no Producer (it may have been closed in the meanwhile). - const volumes: AudioLevelObserverVolume[] = utils + const volumes: AudioLevelObserverVolume[] = fbsUtils .parseVector(notification, 'volumes', parseVolume) .map( ({ @@ -153,6 +105,15 @@ export class AudioLevelObserver< } ); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } function parseVolume(binary: FbsAudioLevelObserver.Volume): { diff --git a/node/src/AudioLevelObserverTypes.ts b/node/src/AudioLevelObserverTypes.ts new file mode 100644 index 0000000000..dca5b0e568 --- /dev/null +++ b/node/src/AudioLevelObserverTypes.ts @@ -0,0 +1,81 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { + RtpObserver, + RtpObserverEvents, + RtpObserverObserverEvents, +} from './RtpObserverTypes'; +import type { Producer } from './ProducerTypes'; +import type { AppData } from './types'; + +export type AudioLevelObserverOptions< + AudioLevelObserverAppData extends AppData = AppData, +> = { + /** + * Maximum number of entries in the 'volumes”' event. Default 1. + */ + maxEntries?: number; + + /** + * Minimum average volume (in dBvo from -127 to 0) for entries in the + * 'volumes' event. Default -80. + */ + threshold?: number; + + /** + * Interval in ms for checking audio volumes. Default 1000. + */ + interval?: number; + + /** + * Custom application data. + */ + appData?: AudioLevelObserverAppData; +}; + +export type AudioLevelObserverVolume = { + /** + * The audio Producer instance. + */ + producer: Producer; + + /** + * The average volume (in dBvo from -127 to 0) of the audio Producer in the + * last interval. + */ + volume: number; +}; + +export type AudioLevelObserverEvents = RtpObserverEvents & { + volumes: [AudioLevelObserverVolume[]]; + silence: []; +}; + +export type AudioLevelObserverObserver = + EnhancedEventEmitter; + +export type AudioLevelObserverObserverEvents = RtpObserverObserverEvents & { + volumes: [AudioLevelObserverVolume[]]; + silence: []; +}; + +export interface AudioLevelObserver< + AudioLevelObserverAppData extends AppData = AppData, +> extends RtpObserver< + AudioLevelObserverAppData, + AudioLevelObserverEvents, + AudioLevelObserverObserver + > { + /** + * RtpObserver type. + * + * @override + */ + get type(): 'audiolevel'; + + /** + * Observer. + * + * @override + */ + get observer(): AudioLevelObserverObserver; +} diff --git a/node/src/Channel.ts b/node/src/Channel.ts index 97ec868bdb..6621d1e188 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -53,9 +53,6 @@ export class Channel extends EnhancedEventEmitter { // flatbuffers builder. #bufferBuilder: flatbuffers.Builder = new flatbuffers.Builder(1024); - /** - * @private - */ constructor({ producerSocket, consumerSocket, @@ -200,9 +197,6 @@ export class Channel extends EnhancedEventEmitter { return this.#bufferBuilder; } - /** - * @private - */ close(): void { if (this.#closed) { return; @@ -236,9 +230,6 @@ export class Channel extends EnhancedEventEmitter { } catch (error) {} } - /** - * @private - */ notify( event: Event, bodyType?: NotificationBody, diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 5945f8993b..ac092a5d2f 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -1,19 +1,38 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; +import type { + Consumer, + ConsumerType, + ConsumerScore, + ConsumerLayers, + ConsumerDump, + SimpleConsumerDump, + SimulcastConsumerDump, + SvcConsumerDump, + PipeConsumerDump, + BaseConsumerDump, + RtpStreamDump, + RtpStreamParametersDump, + RtxStreamDump, + RtxStreamParameters, + ConsumerStat, + ConsumerTraceEventType, + ConsumerTraceEventData, + ConsumerEvents, + ConsumerObserver, + ConsumerObserverEvents, +} from './ConsumerTypes'; import { Channel } from './Channel'; -import { TransportInternal } from './Transport'; -import { ProducerStat } from './Producer'; +import type { TransportInternal } from './Transport'; +import type { ProducerStat } from './ProducerTypes'; +import type { MediaKind, RtpParameters } from './rtpParametersTypes'; import { - MediaKind, - RtpCapabilities, - RtpEncodingParameters, - RtpParameters, parseRtpEncodingParameters, parseRtpParameters, -} from './RtpParameters'; -import { parseRtpStreamStats, RtpStreamSendStats } from './RtpStream'; -import { AppData } from './types'; -import * as utils from './utils'; +} from './rtpParametersFbsUtils'; +import { parseRtpStreamStats } from './rtpStreamStatsFbsUtils'; +import type { AppData } from './types'; +import * as fbsUtils from './fbsUtils'; import { Event, Notification } from './fbs/notification'; import { TraceDirection as FbsTraceDirection } from './fbs/common'; import * as FbsRequest from './fbs/request'; @@ -25,200 +44,6 @@ import * as FbsRtxStream from './fbs/rtx-stream'; import { Type as FbsRtpParametersType } from './fbs/rtp-parameters'; import * as FbsRtpParameters from './fbs/rtp-parameters'; -export type ConsumerOptions = { - /** - * The id of the Producer to consume. - */ - producerId: string; - - /** - * RTP capabilities of the consuming endpoint. - */ - rtpCapabilities: RtpCapabilities; - - /** - * Whether the consumer must start in paused mode. Default false. - * - * When creating a video Consumer, it's recommended to set paused to true, - * then transmit the Consumer parameters to the consuming endpoint and, once - * the consuming endpoint has created its local side Consumer, unpause the - * server side Consumer using the resume() method. This is an optimization - * to make it possible for the consuming endpoint to render the video as far - * as possible. If the server side Consumer was created with paused: false, - * mediasoup will immediately request a key frame to the remote Producer and - * suych a key frame may reach the consuming endpoint even before it's ready - * to consume it, generating “black” video until the device requests a keyframe - * by itself. - */ - paused?: boolean; - - /** - * The MID for the Consumer. If not specified, a sequentially growing - * number will be assigned. - */ - mid?: string; - - /** - * Preferred spatial and temporal layer for simulcast or SVC media sources. - * If unset, the highest ones are selected. - */ - preferredLayers?: ConsumerLayers; - - /** - * Whether this Consumer should enable RTP retransmissions, storing sent RTP - * and processing the incoming RTCP NACK from the remote Consumer. If not set - * it's true by default for video codecs and false for audio codecs. If set - * to true, NACK will be enabled if both endpoints (mediasoup and the remote - * Consumer) support NACK for this codec. When it comes to audio codecs, just - * OPUS supports NACK. - */ - enableRtx?: boolean; - - /** - * Whether this Consumer should ignore DTX packets (only valid for Opus codec). - * If set, DTX packets are not forwarded to the remote Consumer. - */ - ignoreDtx?: boolean; - - /** - * Whether this Consumer should consume all RTP streams generated by the - * Producer. - */ - pipe?: boolean; - - /** - * Custom application data. - */ - appData?: ConsumerAppData; -}; - -/** - * Valid types for 'trace' event. - */ -export type ConsumerTraceEventType = - | 'rtp' - | 'keyframe' - | 'nack' - | 'pli' - | 'fir'; - -/** - * 'trace' event data. - */ -export type ConsumerTraceEventData = { - /** - * Trace type. - */ - type: ConsumerTraceEventType; - - /** - * Event timestamp. - */ - timestamp: number; - - /** - * Event direction. - */ - direction: 'in' | 'out'; - - /** - * Per type information. - */ - info: any; -}; - -export type ConsumerScore = { - /** - * The score of the RTP stream of the consumer. - */ - score: number; - - /** - * The score of the currently selected RTP stream of the producer. - */ - producerScore: number; - - /** - * The scores of all RTP streams in the producer ordered by encoding (just - * useful when the producer uses simulcast). - */ - producerScores: number[]; -}; - -export type ConsumerLayers = { - /** - * The spatial layer index (from 0 to N). - */ - spatialLayer: number; - - /** - * The temporal layer index (from 0 to N). - */ - temporalLayer?: number; -}; - -export type ConsumerStat = RtpStreamSendStats; - -/** - * Consumer type. - */ -export type ConsumerType = 'simple' | 'simulcast' | 'svc' | 'pipe'; - -export type ConsumerEvents = { - transportclose: []; - producerclose: []; - producerpause: []; - producerresume: []; - score: [ConsumerScore]; - layerschange: [ConsumerLayers?]; - trace: [ConsumerTraceEventData]; - rtp: [Buffer]; - listenererror: [string, Error]; - // Private events. - '@close': []; - '@producerclose': []; -}; - -export type ConsumerObserver = EnhancedEventEmitter; - -export type ConsumerObserverEvents = { - close: []; - pause: []; - resume: []; - score: [ConsumerScore]; - layerschange: [ConsumerLayers?]; - trace: [ConsumerTraceEventData]; -}; - -export type SimpleConsumerDump = BaseConsumerDump & { - type: string; - rtpStream: RtpStreamDump; -}; - -export type SimulcastConsumerDump = BaseConsumerDump & { - type: string; - rtpStream: RtpStreamDump; - preferredSpatialLayer: number; - targetSpatialLayer: number; - currentSpatialLayer: number; - preferredTemporalLayer: number; - targetTemporalLayer: number; - currentTemporalLayer: number; -}; - -export type SvcConsumerDump = SimulcastConsumerDump; - -export type PipeConsumerDump = BaseConsumerDump & { - type: string; - rtpStreams: RtpStreamDump[]; -}; - -export type ConsumerDump = - | SimpleConsumerDump - | SimulcastConsumerDump - | SvcConsumerDump - | PipeConsumerDump; - type ConsumerInternal = TransportInternal & { consumerId: string; }; @@ -230,62 +55,12 @@ type ConsumerData = { type: ConsumerType; }; -type BaseConsumerDump = { - id: string; - producerId: string; - kind: MediaKind; - rtpParameters: RtpParameters; - consumableRtpEncodings?: RtpEncodingParameters[]; - supportedCodecPayloadTypes: number[]; - traceEventTypes: string[]; - paused: boolean; - producerPaused: boolean; - priority: number; -}; - -type RtpStreamParameters = { - encodingIdx: number; - ssrc: number; - payloadType: number; - mimeType: string; - clockRate: number; - rid?: string; - cname: string; - rtxSsrc?: number; - rtxPayloadType?: number; - useNack: boolean; - usePli: boolean; - useFir: boolean; - useInBandFec: boolean; - useDtx: boolean; - spatialLayers: number; - temporalLayers: number; -}; - -type RtpStreamDump = { - params: RtpStreamParameters; - score: number; - rtxStream?: RtxStreamDump; -}; - -type RtxStreamParameters = { - ssrc: number; - payloadType: number; - mimeType: string; - clockRate: number; - rrid?: string; - cname: string; -}; - -type RtxStreamDump = { - params: RtxStreamParameters; -}; - const logger = new Logger('Consumer'); -export class Consumer< - ConsumerAppData extends AppData = AppData, -> extends EnhancedEventEmitter { +export class ConsumerImpl + extends EnhancedEventEmitter + implements Consumer +{ // Internal data. readonly #internal: ConsumerInternal; @@ -323,9 +98,6 @@ export class Consumer< readonly #observer: ConsumerObserver = new EnhancedEventEmitter(); - /** - * @private - */ constructor({ internal, data, @@ -359,124 +131,78 @@ export class Consumer< this.#appData = appData ?? ({} as ConsumerAppData); this.handleWorkerNotifications(); + this.handleListenerError(); } - /** - * Consumer id. - */ get id(): string { return this.#internal.consumerId; } - /** - * Associated Producer id. - */ get producerId(): string { return this.#data.producerId; } - /** - * Whether the Consumer is closed. - */ get closed(): boolean { return this.#closed; } - /** - * Media kind. - */ get kind(): MediaKind { return this.#data.kind; } - /** - * RTP parameters. - */ get rtpParameters(): RtpParameters { return this.#data.rtpParameters; } - /** - * Consumer type. - */ get type(): ConsumerType { return this.#data.type; } - /** - * Whether the Consumer is paused. - */ get paused(): boolean { return this.#paused; } - /** - * Whether the associate Producer is paused. - */ get producerPaused(): boolean { return this.#producerPaused; } - /** - * Current priority. - */ get priority(): number { return this.#priority; } - /** - * Consumer score. - */ get score(): ConsumerScore { return this.#score; } - /** - * Preferred video layers. - */ get preferredLayers(): ConsumerLayers | undefined { return this.#preferredLayers; } - /** - * Current video layers. - */ get currentLayers(): ConsumerLayers | undefined { return this.#currentLayers; } - /** - * App custom data. - */ get appData(): ConsumerAppData { return this.#appData; } - /** - * App custom data setter. - */ set appData(appData: ConsumerAppData) { this.#appData = appData; } - /** - * Observer. - */ get observer(): ConsumerObserver { return this.#observer; } /** - * @private * Just for testing purposes. + * + * @private */ get channelForTesting(): Channel { return this.#channel; } - /** - * Close the Consumer. - */ close(): void { if (this.#closed) { return; @@ -509,11 +235,6 @@ export class Consumer< this.#observer.safeEmit('close'); } - /** - * Transport was closed. - * - * @private - */ transportClosed(): void { if (this.#closed) { return; @@ -532,9 +253,6 @@ export class Consumer< this.#observer.safeEmit('close'); } - /** - * Dump Consumer. - */ async dump(): Promise { logger.debug('dump()'); @@ -553,9 +271,6 @@ export class Consumer< return parseConsumerDumpResponse(data); } - /** - * Get Consumer stats. - */ async getStats(): Promise<(ConsumerStat | ProducerStat)[]> { logger.debug('getStats()'); @@ -574,9 +289,6 @@ export class Consumer< return parseConsumerStats(data); } - /** - * Pause the Consumer. - */ async pause(): Promise { logger.debug('pause()'); @@ -597,9 +309,6 @@ export class Consumer< } } - /** - * Resume the Consumer. - */ async resume(): Promise { logger.debug('resume()'); @@ -620,9 +329,6 @@ export class Consumer< } } - /** - * Set preferred video layers. - */ async setPreferredLayers({ spatialLayer, temporalLayer, @@ -677,9 +383,6 @@ export class Consumer< this.#preferredLayers = preferredLayers; } - /** - * Set priority. - */ async setPriority(priority: number): Promise { logger.debug('setPriority()'); @@ -709,18 +412,12 @@ export class Consumer< this.#priority = status.priority; } - /** - * Unset priority. - */ async unsetPriority(): Promise { logger.debug('unsetPriority()'); await this.setPriority(1); } - /** - * Request a key frame to the Producer. - */ async requestKeyFrame(): Promise { logger.debug('requestKeyFrame()'); @@ -732,9 +429,6 @@ export class Consumer< ); } - /** - * Enable 'trace' event. - */ async enableTraceEvent(types: ConsumerTraceEventType[] = []): Promise { logger.debug('enableTraceEvent()'); @@ -905,6 +599,15 @@ export class Consumer< } ); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } export function parseTraceEventData( @@ -1000,9 +703,25 @@ function parseConsumerLayers(data: FbsConsumer.ConsumerLayers): ConsumerLayers { }; } +function parseRtpStream(data: FbsRtpStream.Dump): RtpStreamDump { + const params = parseRtpStreamParameters(data.params()!); + + let rtxStream: RtxStreamDump | undefined; + + if (data.rtxStream()) { + rtxStream = parseRtxStream(data.rtxStream()!); + } + + return { + params, + score: data.score(), + rtxStream, + }; +} + function parseRtpStreamParameters( data: FbsRtpStream.Params -): RtpStreamParameters { +): RtpStreamParametersDump { return { encodingIdx: data.encodingIdx(), ssrc: data.ssrc(), @@ -1024,6 +743,14 @@ function parseRtpStreamParameters( }; } +function parseRtxStream(data: FbsRtxStream.RtxDump): RtxStreamDump { + const params = parseRtxStreamParameters(data.params()!); + + return { + params, + }; +} + function parseRtxStreamParameters( data: FbsRtxStream.Params ): RtxStreamParameters { @@ -1037,30 +764,6 @@ function parseRtxStreamParameters( }; } -function parseRtxStream(data: FbsRtxStream.RtxDump): RtxStreamDump { - const params = parseRtxStreamParameters(data.params()!); - - return { - params, - }; -} - -function parseRtpStream(data: FbsRtpStream.Dump): RtpStreamDump { - const params = parseRtpStreamParameters(data.params()!); - - let rtxStream: RtxStreamDump | undefined; - - if (data.rtxStream()) { - rtxStream = parseRtxStream(data.rtxStream()!); - } - - return { - params, - score: data.score(), - rtxStream, - }; -} - function parseBaseConsumerDump( data: FbsConsumer.BaseConsumerDump ): BaseConsumerDump { @@ -1071,18 +774,18 @@ function parseBaseConsumerDump( rtpParameters: parseRtpParameters(data.rtpParameters()!), consumableRtpEncodings: data.consumableRtpEncodingsLength() > 0 - ? utils.parseVector( + ? fbsUtils.parseVector( data, 'consumableRtpEncodings', parseRtpEncodingParameters ) : undefined, - traceEventTypes: utils.parseVector( + traceEventTypes: fbsUtils.parseVector( data, 'traceEventTypes', consumerTraceEventTypeFromFbs ), - supportedCodecPayloadTypes: utils.parseVector( + supportedCodecPayloadTypes: fbsUtils.parseVector( data, 'supportedCodecPayloadTypes' ), @@ -1136,7 +839,7 @@ function parsePipeConsumerDump( data: FbsConsumer.ConsumerDump ): PipeConsumerDump { const base = parseBaseConsumerDump(data.base()!); - const rtpStreams = utils.parseVector(data, 'rtpStreams', parseRtpStream); + const rtpStreams = fbsUtils.parseVector(data, 'rtpStreams', parseRtpStream); return { ...base, @@ -1192,5 +895,5 @@ function parseConsumerDumpResponse( function parseConsumerStats( binary: FbsConsumer.GetStatsResponse ): (ConsumerStat | ProducerStat)[] { - return utils.parseVector(binary, 'stats', parseRtpStreamStats); + return fbsUtils.parseVector(binary, 'stats', parseRtpStreamStats); } diff --git a/node/src/ConsumerTypes.ts b/node/src/ConsumerTypes.ts new file mode 100644 index 0000000000..2b1fbf7fd0 --- /dev/null +++ b/node/src/ConsumerTypes.ts @@ -0,0 +1,393 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { ProducerStat } from './ProducerTypes'; +import type { + MediaKind, + RtpCapabilities, + RtpEncodingParameters, + RtpParameters, +} from './rtpParametersTypes'; +import type { RtpStreamSendStats } from './rtpStreamStatsTypes'; +import type { AppData } from './types'; + +export type ConsumerOptions = { + /** + * The id of the Producer to consume. + */ + producerId: string; + + /** + * RTP capabilities of the consuming endpoint. + */ + rtpCapabilities: RtpCapabilities; + + /** + * Whether the consumer must start in paused mode. Default false. + * + * When creating a video Consumer, it's recommended to set paused to true, + * then transmit the Consumer parameters to the consuming endpoint and, once + * the consuming endpoint has created its local side Consumer, unpause the + * server side Consumer using the resume() method. This is an optimization + * to make it possible for the consuming endpoint to render the video as far + * as possible. If the server side Consumer was created with paused: false, + * mediasoup will immediately request a key frame to the remote Producer and + * suych a key frame may reach the consuming endpoint even before it's ready + * to consume it, generating “black” video until the device requests a keyframe + * by itself. + */ + paused?: boolean; + + /** + * The MID for the Consumer. If not specified, a sequentially growing + * number will be assigned. + */ + mid?: string; + + /** + * Preferred spatial and temporal layer for simulcast or SVC media sources. + * If unset, the highest ones are selected. + */ + preferredLayers?: ConsumerLayers; + + /** + * Whether this Consumer should enable RTP retransmissions, storing sent RTP + * and processing the incoming RTCP NACK from the remote Consumer. If not set + * it's true by default for video codecs and false for audio codecs. If set + * to true, NACK will be enabled if both endpoints (mediasoup and the remote + * Consumer) support NACK for this codec. When it comes to audio codecs, just + * OPUS supports NACK. + */ + enableRtx?: boolean; + + /** + * Whether this Consumer should ignore DTX packets (only valid for Opus codec). + * If set, DTX packets are not forwarded to the remote Consumer. + */ + ignoreDtx?: boolean; + + /** + * Whether this Consumer should consume all RTP streams generated by the + * Producer. + */ + pipe?: boolean; + + /** + * Custom application data. + */ + appData?: ConsumerAppData; +}; + +/** + * Consumer type. + */ +export type ConsumerType = 'simple' | 'simulcast' | 'svc' | 'pipe'; + +export type ConsumerScore = { + /** + * The score of the RTP stream of the consumer. + */ + score: number; + + /** + * The score of the currently selected RTP stream of the producer. + */ + producerScore: number; + + /** + * The scores of all RTP streams in the producer ordered by encoding (just + * useful when the producer uses simulcast). + */ + producerScores: number[]; +}; + +export type ConsumerLayers = { + /** + * The spatial layer index (from 0 to N). + */ + spatialLayer: number; + + /** + * The temporal layer index (from 0 to N). + */ + temporalLayer?: number; +}; + +export type ConsumerDump = + | SimpleConsumerDump + | SimulcastConsumerDump + | SvcConsumerDump + | PipeConsumerDump; + +export type SimpleConsumerDump = BaseConsumerDump & { + type: string; + rtpStream: RtpStreamDump; +}; + +export type SimulcastConsumerDump = BaseConsumerDump & { + type: string; + rtpStream: RtpStreamDump; + preferredSpatialLayer: number; + targetSpatialLayer: number; + currentSpatialLayer: number; + preferredTemporalLayer: number; + targetTemporalLayer: number; + currentTemporalLayer: number; +}; + +export type SvcConsumerDump = SimulcastConsumerDump; + +export type PipeConsumerDump = BaseConsumerDump & { + type: string; + rtpStreams: RtpStreamDump[]; +}; + +export type BaseConsumerDump = { + id: string; + producerId: string; + kind: MediaKind; + rtpParameters: RtpParameters; + consumableRtpEncodings?: RtpEncodingParameters[]; + supportedCodecPayloadTypes: number[]; + traceEventTypes: string[]; + paused: boolean; + producerPaused: boolean; + priority: number; +}; + +export type RtpStreamDump = { + params: RtpStreamParametersDump; + score: number; + rtxStream?: RtxStreamDump; +}; + +export type RtpStreamParametersDump = { + encodingIdx: number; + ssrc: number; + payloadType: number; + mimeType: string; + clockRate: number; + rid?: string; + cname: string; + rtxSsrc?: number; + rtxPayloadType?: number; + useNack: boolean; + usePli: boolean; + useFir: boolean; + useInBandFec: boolean; + useDtx: boolean; + spatialLayers: number; + temporalLayers: number; +}; + +export type RtxStreamDump = { + params: RtxStreamParameters; +}; + +export type RtxStreamParameters = { + ssrc: number; + payloadType: number; + mimeType: string; + clockRate: number; + rrid?: string; + cname: string; +}; + +export type ConsumerStat = RtpStreamSendStats; + +/** + * Valid types for 'trace' event. + */ +export type ConsumerTraceEventType = + | 'rtp' + | 'keyframe' + | 'nack' + | 'pli' + | 'fir'; + +/** + * 'trace' event data. + */ +export type ConsumerTraceEventData = { + /** + * Trace type. + */ + type: ConsumerTraceEventType; + + /** + * Event timestamp. + */ + timestamp: number; + + /** + * Event direction. + */ + direction: 'in' | 'out'; + + /** + * Per type information. + */ + info: any; +}; + +export type ConsumerEvents = { + transportclose: []; + producerclose: []; + producerpause: []; + producerresume: []; + score: [ConsumerScore]; + layerschange: [ConsumerLayers?]; + trace: [ConsumerTraceEventData]; + rtp: [Buffer]; + listenererror: [string, Error]; + // Private events. + '@close': []; + '@producerclose': []; +}; + +export type ConsumerObserver = EnhancedEventEmitter; + +export type ConsumerObserverEvents = { + close: []; + pause: []; + resume: []; + score: [ConsumerScore]; + layerschange: [ConsumerLayers?]; + trace: [ConsumerTraceEventData]; +}; + +export interface Consumer + extends EnhancedEventEmitter { + /** + * Consumer id. + */ + get id(): string; + + /** + * Associated Producer id. + */ + get producerId(): string; + + /** + * Whether the Consumer is closed. + */ + get closed(): boolean; + + /** + * Media kind. + */ + get kind(): MediaKind; + + /** + * RTP parameters. + */ + get rtpParameters(): RtpParameters; + + /** + * Consumer type. + */ + get type(): ConsumerType; + + /** + * Whether the Consumer is paused. + */ + get paused(): boolean; + + /** + * Whether the associate Producer is paused. + */ + get producerPaused(): boolean; + + /** + * Current priority. + */ + get priority(): number; + + /** + * Consumer score. + */ + get score(): ConsumerScore; + + /** + * Preferred video layers. + */ + get preferredLayers(): ConsumerLayers | undefined; + + /** + * Current video layers. + */ + get currentLayers(): ConsumerLayers | undefined; + + /** + * App custom data. + */ + get appData(): ConsumerAppData; + + /** + * App custom data setter. + */ + set appData(appData: ConsumerAppData); + + /** + * Observer. + */ + get observer(): ConsumerObserver; + + /** + * Close the Consumer. + */ + close(): void; + + /** + * Transport was closed. + * + * @private + */ + transportClosed(): void; + + /** + * Dump Consumer. + */ + dump(): Promise; + + /** + * Get Consumer stats. + */ + getStats(): Promise<(ConsumerStat | ProducerStat)[]>; + + /** + * Pause the Consumer. + */ + pause(): Promise; + + /** + * Resume the Consumer. + */ + resume(): Promise; + + /** + * Set preferred video layers. + */ + setPreferredLayers({ + spatialLayer, + temporalLayer, + }: ConsumerLayers): Promise; + + /** + * Set priority. + */ + setPriority(priority: number): Promise; + + /** + * Unset priority. + */ + unsetPriority(): Promise; + + /** + * Request a key frame to the Producer. + */ + requestKeyFrame(): Promise; + + /** + * Enable 'trace' event. + */ + enableTraceEvent(types?: ConsumerTraceEventType[]): Promise; +} diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index f05b998d17..3bcc932069 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -1,113 +1,26 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; +import type { + DataConsumer, + DataConsumerType, + DataConsumerDump, + DataConsumerStat, + DataConsumerEvents, + DataConsumerObserver, + DataConsumerObserverEvents, +} from './DataConsumerTypes'; import { Channel } from './Channel'; -import { TransportInternal } from './Transport'; -import { - SctpStreamParameters, - parseSctpStreamParameters, -} from './SctpParameters'; -import { AppData } from './types'; -import * as utils from './utils'; +import type { TransportInternal } from './Transport'; +import type { SctpStreamParameters } from './sctpParametersTypes'; +import { parseSctpStreamParameters } from './sctpParametersFbsUtils'; +import type { AppData } from './types'; +import * as fbsUtils from './fbsUtils'; import { Event, Notification } from './fbs/notification'; import * as FbsTransport from './fbs/transport'; import * as FbsRequest from './fbs/request'; import * as FbsDataConsumer from './fbs/data-consumer'; import * as FbsDataProducer from './fbs/data-producer'; -export type DataConsumerOptions = - { - /** - * The id of the DataProducer to consume. - */ - dataProducerId: string; - - /** - * Just if consuming over SCTP. - * Whether data messages must be received in order. If true the messages will - * be sent reliably. Defaults to the value in the DataProducer if it has type - * 'sctp' or to true if it has type 'direct'. - */ - ordered?: boolean; - - /** - * Just if consuming over SCTP. - * When ordered is false indicates the time (in milliseconds) after which a - * SCTP packet will stop being retransmitted. Defaults to the value in the - * DataProducer if it has type 'sctp' or unset if it has type 'direct'. - */ - maxPacketLifeTime?: number; - - /** - * Just if consuming over SCTP. - * When ordered is false indicates the maximum number of times a packet will - * be retransmitted. Defaults to the value in the DataProducer if it has type - * 'sctp' or unset if it has type 'direct'. - */ - maxRetransmits?: number; - - /** - * Whether the data consumer must start in paused mode. Default false. - */ - paused?: boolean; - - /** - * Subchannels this data consumer initially subscribes to. - * Only used in case this data consumer receives messages from a local data - * producer that specifies subchannel(s) when calling send(). - */ - subchannels?: number[]; - - /** - * Custom application data. - */ - appData?: DataConsumerAppData; - }; - -export type DataConsumerStat = { - type: string; - timestamp: number; - label: string; - protocol: string; - messagesSent: number; - bytesSent: number; - bufferedAmount: number; -}; - -/** - * DataConsumer type. - */ -export type DataConsumerType = 'sctp' | 'direct'; - -export type DataConsumerEvents = { - transportclose: []; - dataproducerclose: []; - dataproducerpause: []; - dataproducerresume: []; - message: [Buffer, number]; - sctpsendbufferfull: []; - bufferedamountlow: [number]; - listenererror: [string, Error]; - // Private events. - '@close': []; - '@dataproducerclose': []; -}; - -export type DataConsumerObserver = - EnhancedEventEmitter; - -export type DataConsumerObserverEvents = { - close: []; - pause: []; - resume: []; -}; - -type DataConsumerDump = DataConsumerData & { - id: string; - paused: boolean; - dataProducerPaused: boolean; - subchannels: number[]; -}; - type DataConsumerInternal = TransportInternal & { dataConsumerId: string; }; @@ -123,9 +36,10 @@ type DataConsumerData = { const logger = new Logger('DataConsumer'); -export class DataConsumer< - DataConsumerAppData extends AppData = AppData, -> extends EnhancedEventEmitter { +export class DataConsumerImpl + extends EnhancedEventEmitter + implements DataConsumer +{ // Internal data. readonly #internal: DataConsumerInternal; @@ -154,9 +68,6 @@ export class DataConsumer< readonly #observer: DataConsumerObserver = new EnhancedEventEmitter(); - /** - * @private - */ constructor({ internal, data, @@ -187,102 +98,61 @@ export class DataConsumer< this.#appData = appData ?? ({} as DataConsumerAppData); this.handleWorkerNotifications(); + this.handleListenerError(); } - /** - * DataConsumer id. - */ get id(): string { return this.#internal.dataConsumerId; } - /** - * Associated DataProducer id. - */ get dataProducerId(): string { return this.#data.dataProducerId; } - /** - * Whether the DataConsumer is closed. - */ get closed(): boolean { return this.#closed; } - /** - * DataConsumer type. - */ get type(): DataConsumerType { return this.#data.type; } - /** - * SCTP stream parameters. - */ get sctpStreamParameters(): SctpStreamParameters | undefined { return this.#data.sctpStreamParameters; } - /** - * DataChannel label. - */ get label(): string { return this.#data.label; } - /** - * DataChannel protocol. - */ get protocol(): string { return this.#data.protocol; } - /** - * Whether the DataConsumer is paused. - */ get paused(): boolean { return this.#paused; } - /** - * Whether the associate DataProducer is paused. - */ get dataProducerPaused(): boolean { return this.#dataProducerPaused; } - /** - * Get current subchannels this data consumer is subscribed to. - */ get subchannels(): number[] { return Array.from(this.#subchannels); } - /** - * App custom data. - */ get appData(): DataConsumerAppData { return this.#appData; } - /** - * App custom data setter. - */ set appData(appData: DataConsumerAppData) { this.#appData = appData; } - /** - * Observer. - */ get observer(): DataConsumerObserver { return this.#observer; } - /** - * Close the DataConsumer. - */ close(): void { if (this.#closed) { return; @@ -315,11 +185,6 @@ export class DataConsumer< this.#observer.safeEmit('close'); } - /** - * Transport was closed. - * - * @private - */ transportClosed(): void { if (this.#closed) { return; @@ -338,9 +203,6 @@ export class DataConsumer< this.#observer.safeEmit('close'); } - /** - * Dump DataConsumer. - */ async dump(): Promise { logger.debug('dump()'); @@ -359,9 +221,6 @@ export class DataConsumer< return parseDataConsumerDumpResponse(dumpResponse); } - /** - * Get DataConsumer stats. - */ async getStats(): Promise { logger.debug('getStats()'); @@ -380,9 +239,6 @@ export class DataConsumer< return [parseDataConsumerStats(data)]; } - /** - * Pause the DataConsumer. - */ async pause(): Promise { logger.debug('pause()'); @@ -403,9 +259,6 @@ export class DataConsumer< } } - /** - * Resume the DataConsumer. - */ async resume(): Promise { logger.debug('resume()'); @@ -426,9 +279,6 @@ export class DataConsumer< } } - /** - * Set buffered amount low threshold. - */ async setBufferedAmountLowThreshold(threshold: number): Promise { logger.debug(`setBufferedAmountLowThreshold() [threshold:${threshold}]`); @@ -447,9 +297,23 @@ export class DataConsumer< ); } - /** - * Send data. - */ + async getBufferedAmount(): Promise { + logger.debug('getBufferedAmount()'); + + const response = await this.#channel.request( + FbsRequest.Method.DATACONSUMER_GET_BUFFERED_AMOUNT, + undefined, + undefined, + this.#internal.dataConsumerId + ); + + const data = new FbsDataConsumer.GetBufferedAmountResponse(); + + response.body(data); + + return data.bufferedAmount(); + } + async send(message: string | Buffer, ppid?: number): Promise { if (typeof message !== 'string' && !Buffer.isBuffer(message)) { throw new TypeError('message must be a string or a Buffer'); @@ -513,29 +377,6 @@ export class DataConsumer< ); } - /** - * Get buffered amount size. - */ - async getBufferedAmount(): Promise { - logger.debug('getBufferedAmount()'); - - const response = await this.#channel.request( - FbsRequest.Method.DATACONSUMER_GET_BUFFERED_AMOUNT, - undefined, - undefined, - this.#internal.dataConsumerId - ); - - const data = new FbsDataConsumer.GetBufferedAmountResponse(); - - response.body(data); - - return data.bufferedAmount(); - } - - /** - * Set subchannels. - */ async setSubchannels(subchannels: number[]): Promise { logger.debug('setSubchannels()'); @@ -557,12 +398,9 @@ export class DataConsumer< response.body(data); // Update subchannels. - this.#subchannels = utils.parseVector(data, 'subchannels'); + this.#subchannels = fbsUtils.parseVector(data, 'subchannels'); } - /** - * Add a subchannel. - */ async addSubchannel(subchannel: number): Promise { logger.debug('addSubchannel()'); @@ -586,12 +424,9 @@ export class DataConsumer< response.body(data); // Update subchannels. - this.#subchannels = utils.parseVector(data, 'subchannels'); + this.#subchannels = fbsUtils.parseVector(data, 'subchannels'); } - /** - * Remove a subchannel. - */ async removeSubchannel(subchannel: number): Promise { logger.debug('removeSubchannel()'); @@ -615,7 +450,7 @@ export class DataConsumer< response.body(data); // Update subchannels. - this.#subchannels = utils.parseVector(data, 'subchannels'); + this.#subchannels = fbsUtils.parseVector(data, 'subchannels'); } private handleWorkerNotifications(): void { @@ -720,6 +555,15 @@ export class DataConsumer< } ); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } export function dataConsumerTypeToFbs( @@ -770,7 +614,7 @@ export function parseDataConsumerDumpResponse( bufferedAmountLowThreshold: data.bufferedAmountLowThreshold(), paused: data.paused(), dataProducerPaused: data.dataProducerPaused(), - subchannels: utils.parseVector(data, 'subchannels'), + subchannels: fbsUtils.parseVector(data, 'subchannels'), }; } diff --git a/node/src/DataConsumerTypes.ts b/node/src/DataConsumerTypes.ts new file mode 100644 index 0000000000..5f0d06815c --- /dev/null +++ b/node/src/DataConsumerTypes.ts @@ -0,0 +1,233 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { SctpStreamParameters } from './sctpParametersTypes'; +import type { AppData } from './types'; + +export type DataConsumerOptions = + { + /** + * The id of the DataProducer to consume. + */ + dataProducerId: string; + + /** + * Just if consuming over SCTP. + * Whether data messages must be received in order. If true the messages will + * be sent reliably. Defaults to the value in the DataProducer if it has type + * 'sctp' or to true if it has type 'direct'. + */ + ordered?: boolean; + + /** + * Just if consuming over SCTP. + * When ordered is false indicates the time (in milliseconds) after which a + * SCTP packet will stop being retransmitted. Defaults to the value in the + * DataProducer if it has type 'sctp' or unset if it has type 'direct'. + */ + maxPacketLifeTime?: number; + + /** + * Just if consuming over SCTP. + * When ordered is false indicates the maximum number of times a packet will + * be retransmitted. Defaults to the value in the DataProducer if it has type + * 'sctp' or unset if it has type 'direct'. + */ + maxRetransmits?: number; + + /** + * Whether the data consumer must start in paused mode. Default false. + */ + paused?: boolean; + + /** + * Subchannels this data consumer initially subscribes to. + * Only used in case this data consumer receives messages from a local data + * producer that specifies subchannel(s) when calling send(). + */ + subchannels?: number[]; + + /** + * Custom application data. + */ + appData?: DataConsumerAppData; + }; + +/** + * DataConsumer type. + */ +export type DataConsumerType = 'sctp' | 'direct'; + +export type DataConsumerDump = { + id: string; + paused: boolean; + dataProducerPaused: boolean; + subchannels: number[]; + dataProducerId: string; + type: DataConsumerType; + sctpStreamParameters?: SctpStreamParameters; + label: string; + protocol: string; + bufferedAmountLowThreshold: number; +}; + +export type DataConsumerStat = { + type: string; + timestamp: number; + label: string; + protocol: string; + messagesSent: number; + bytesSent: number; + bufferedAmount: number; +}; + +export type DataConsumerEvents = { + transportclose: []; + dataproducerclose: []; + dataproducerpause: []; + dataproducerresume: []; + message: [Buffer, number]; + sctpsendbufferfull: []; + bufferedamountlow: [number]; + listenererror: [string, Error]; + // Private events. + '@close': []; + '@dataproducerclose': []; +}; + +export type DataConsumerObserver = + EnhancedEventEmitter; + +export type DataConsumerObserverEvents = { + close: []; + pause: []; + resume: []; +}; + +export interface DataConsumer + extends EnhancedEventEmitter { + /** + * DataConsumer id. + */ + get id(): string; + + /** + * Associated DataProducer id. + */ + get dataProducerId(): string; + + /** + * Whether the DataConsumer is closed. + */ + get closed(): boolean; + + /** + * DataConsumer type. + */ + get type(): DataConsumerType; + + /** + * SCTP stream parameters. + */ + get sctpStreamParameters(): SctpStreamParameters | undefined; + + /** + * DataChannel label. + */ + get label(): string; + + /** + * DataChannel protocol. + */ + get protocol(): string; + + /** + * Whether the DataConsumer is paused. + */ + get paused(): boolean; + + /** + * Whether the associate DataProducer is paused. + */ + get dataProducerPaused(): boolean; + + /** + * Get current subchannels this data consumer is subscribed to. + */ + get subchannels(): number[]; + + /** + * App custom data. + */ + get appData(): DataConsumerAppData; + + /** + * App custom data setter. + */ + set appData(appData: DataConsumerAppData); + + /** + * Observer. + */ + get observer(): DataConsumerObserver; + + /** + * Close the DataConsumer. + */ + close(): void; + + /** + * Transport was closed. + * + * @private + */ + transportClosed(): void; + + /** + * Dump DataConsumer. + */ + dump(): Promise; + + /** + * Get DataConsumer stats. + */ + getStats(): Promise; + + /** + * Pause the DataConsumer. + */ + pause(): Promise; + + /** + * Resume the DataConsumer. + */ + resume(): Promise; + + /** + * Set buffered amount low threshold. + */ + setBufferedAmountLowThreshold(threshold: number): Promise; + + /** + * Get buffered amount size. + */ + getBufferedAmount(): Promise; + + /** + * Send a message. + */ + send(message: string | Buffer, ppid?: number): Promise; + + /** + * Set subchannels. + */ + setSubchannels(subchannels: number[]): Promise; + + /** + * Add a subchannel. + */ + addSubchannel(subchannel: number): Promise; + + /** + * Remove a subchannel. + */ + removeSubchannel(subchannel: number): Promise; +} diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index e4ac42884e..e1c2c0f6e1 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -1,86 +1,24 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; +import type { + DataProducer, + DataProducerType, + DataProducerDump, + DataProducerStat, + DataProducerEvents, + DataProducerObserver, + DataProducerObserverEvents, +} from './DataProducerTypes'; import { Channel } from './Channel'; -import { TransportInternal } from './Transport'; -import { - SctpStreamParameters, - parseSctpStreamParameters, -} from './SctpParameters'; -import { AppData } from './types'; +import type { TransportInternal } from './Transport'; +import type { SctpStreamParameters } from './sctpParametersTypes'; +import { parseSctpStreamParameters } from './sctpParametersFbsUtils'; +import type { AppData } from './types'; import * as FbsTransport from './fbs/transport'; import * as FbsNotification from './fbs/notification'; import * as FbsRequest from './fbs/request'; import * as FbsDataProducer from './fbs/data-producer'; -export type DataProducerOptions = - { - /** - * DataProducer id (just for Router.pipeToRouter() method). - */ - id?: string; - - /** - * SCTP parameters defining how the endpoint is sending the data. - * Just if messages are sent over SCTP. - */ - sctpStreamParameters?: SctpStreamParameters; - - /** - * A label which can be used to distinguish this DataChannel from others. - */ - label?: string; - - /** - * Name of the sub-protocol used by this DataChannel. - */ - protocol?: string; - - /** - * Whether the data producer must start in paused mode. Default false. - */ - paused?: boolean; - - /** - * Custom application data. - */ - appData?: DataProducerAppData; - }; - -export type DataProducerStat = { - type: string; - timestamp: number; - label: string; - protocol: string; - messagesReceived: number; - bytesReceived: number; -}; - -/** - * DataProducer type. - */ -export type DataProducerType = 'sctp' | 'direct'; - -export type DataProducerEvents = { - transportclose: []; - listenererror: [string, Error]; - // Private events. - '@close': []; -}; - -export type DataProducerObserver = - EnhancedEventEmitter; - -export type DataProducerObserverEvents = { - close: []; - pause: []; - resume: []; -}; - -type DataProducerDump = DataProducerData & { - id: string; - paused: boolean; -}; - type DataProducerInternal = TransportInternal & { dataProducerId: string; }; @@ -94,9 +32,10 @@ type DataProducerData = { const logger = new Logger('DataProducer'); -export class DataProducer< - DataProducerAppData extends AppData = AppData, -> extends EnhancedEventEmitter { +export class DataProducerImpl + extends EnhancedEventEmitter + implements DataProducer +{ // Internal data. readonly #internal: DataProducerInternal; @@ -119,9 +58,6 @@ export class DataProducer< readonly #observer: DataProducerObserver = new EnhancedEventEmitter(); - /** - * @private - */ constructor({ internal, data, @@ -146,81 +82,49 @@ export class DataProducer< this.#appData = appData ?? ({} as DataProducerAppData); this.handleWorkerNotifications(); + this.handleListenerError(); } - /** - * DataProducer id. - */ get id(): string { return this.#internal.dataProducerId; } - /** - * Whether the DataProducer is closed. - */ get closed(): boolean { return this.#closed; } - /** - * DataProducer type. - */ get type(): DataProducerType { return this.#data.type; } - /** - * SCTP stream parameters. - */ get sctpStreamParameters(): SctpStreamParameters | undefined { return this.#data.sctpStreamParameters; } - /** - * DataChannel label. - */ get label(): string { return this.#data.label; } - /** - * DataChannel protocol. - */ get protocol(): string { return this.#data.protocol; } - /** - * Whether the DataProducer is paused. - */ get paused(): boolean { return this.#paused; } - /** - * App custom data. - */ get appData(): DataProducerAppData { return this.#appData; } - /** - * App custom data setter. - */ set appData(appData: DataProducerAppData) { this.#appData = appData; } - /** - * Observer. - */ get observer(): DataProducerObserver { return this.#observer; } - /** - * Close the DataProducer. - */ close(): void { if (this.#closed) { return; @@ -253,11 +157,6 @@ export class DataProducer< this.#observer.safeEmit('close'); } - /** - * Transport was closed. - * - * @private - */ transportClosed(): void { if (this.#closed) { return; @@ -276,9 +175,6 @@ export class DataProducer< this.#observer.safeEmit('close'); } - /** - * Dump DataProducer. - */ async dump(): Promise { logger.debug('dump()'); @@ -297,9 +193,6 @@ export class DataProducer< return parseDataProducerDumpResponse(produceResponse); } - /** - * Get DataProducer stats. - */ async getStats(): Promise { logger.debug('getStats()'); @@ -318,9 +211,6 @@ export class DataProducer< return [parseDataProducerStats(data)]; } - /** - * Pause the DataProducer. - */ async pause(): Promise { logger.debug('pause()'); @@ -341,9 +231,6 @@ export class DataProducer< } } - /** - * Resume the DataProducer. - */ async resume(): Promise { logger.debug('resume()'); @@ -364,9 +251,6 @@ export class DataProducer< } } - /** - * Send data (just valid for DataProducers created on a DirectTransport). - */ send( message: string | Buffer, ppid?: number, @@ -450,6 +334,15 @@ export class DataProducer< private handleWorkerNotifications(): void { // No need to subscribe to any event. } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } export function dataProducerTypeToFbs( diff --git a/node/src/DataProducerTypes.ts b/node/src/DataProducerTypes.ts new file mode 100644 index 0000000000..efb64d35bf --- /dev/null +++ b/node/src/DataProducerTypes.ts @@ -0,0 +1,171 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { SctpStreamParameters } from './sctpParametersTypes'; +import type { AppData } from './types'; + +export type DataProducerOptions = + { + /** + * DataProducer id (just for Router.pipeToRouter() method). + */ + id?: string; + + /** + * SCTP parameters defining how the endpoint is sending the data. + * Just if messages are sent over SCTP. + */ + sctpStreamParameters?: SctpStreamParameters; + + /** + * A label which can be used to distinguish this DataChannel from others. + */ + label?: string; + + /** + * Name of the sub-protocol used by this DataChannel. + */ + protocol?: string; + + /** + * Whether the data producer must start in paused mode. Default false. + */ + paused?: boolean; + + /** + * Custom application data. + */ + appData?: DataProducerAppData; + }; + +/** + * DataProducer type. + */ +export type DataProducerType = 'sctp' | 'direct'; + +export type DataProducerDump = { + id: string; + paused: boolean; + type: DataProducerType; + sctpStreamParameters?: SctpStreamParameters; + label: string; + protocol: string; +}; + +export type DataProducerStat = { + type: string; + timestamp: number; + label: string; + protocol: string; + messagesReceived: number; + bytesReceived: number; +}; + +export type DataProducerEvents = { + transportclose: []; + listenererror: [string, Error]; + // Private events. + '@close': []; +}; + +export type DataProducerObserver = + EnhancedEventEmitter; + +export type DataProducerObserverEvents = { + close: []; + pause: []; + resume: []; +}; + +export interface DataProducer + extends EnhancedEventEmitter { + /** + * DataProducer id. + */ + get id(): string; + + /** + * Whether the DataProducer is closed. + */ + get closed(): boolean; + + /** + * DataProducer type. + */ + get type(): DataProducerType; + + /** + * SCTP stream parameters. + */ + get sctpStreamParameters(): SctpStreamParameters | undefined; + + /** + * DataChannel label. + */ + get label(): string; + + /** + * DataChannel protocol. + */ + get protocol(): string; + + /** + * Whether the DataProducer is paused. + */ + get paused(): boolean; + + /** + * App custom data. + */ + get appData(): DataProducerAppData; + + /** + * App custom data setter. + */ + set appData(appData: DataProducerAppData); + + /** + * Observer. + */ + get observer(): DataProducerObserver; + + /** + * Close the DataProducer. + */ + close(): void; + + /** + * Transport was closed. + * + * @private + */ + transportClosed(): void; + + /** + * Dump DataProducer. + */ + dump(): Promise; + + /** + * Get DataProducer stats. + */ + getStats(): Promise; + + /** + * Pause the DataProducer. + */ + pause(): Promise; + + /** + * Resume the DataProducer. + */ + resume(): Promise; + + /** + * Send data (just valid for DataProducers created on a DirectTransport). + */ + send( + message: string | Buffer, + ppid?: number, + subchannels?: number[], + requiredSubchannel?: number + ): void; +} diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 044dd2d443..a75d4b18bb 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -1,57 +1,30 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; -import { UnsupportedError } from './errors'; +import type { + DirectTransport, + DirectTransportDump, + DirectTransportStat, + DirectTransportEvents, + DirectTransportObserver, + DirectTransportObserverEvents, +} from './DirectTransportTypes'; +import type { Transport, BaseTransportDump } from './TransportTypes'; import { - BaseTransportDump, - BaseTransportStats, + TransportImpl, + TransportConstructorOptions, parseBaseTransportDump, parseBaseTransportStats, parseTransportTraceEventData, - Transport, - TransportEvents, - TransportObserverEvents, - TransportConstructorOptions, } from './Transport'; -import { SctpParameters } from './SctpParameters'; -import { AppData } from './types'; +import type { SctpParameters } from './sctpParametersTypes'; +import type { AppData } from './types'; +import { UnsupportedError } from './errors'; import { Event, Notification } from './fbs/notification'; import * as FbsDirectTransport from './fbs/direct-transport'; import * as FbsTransport from './fbs/transport'; import * as FbsNotification from './fbs/notification'; import * as FbsRequest from './fbs/request'; -export type DirectTransportOptions< - DirectTransportAppData extends AppData = AppData, -> = { - /** - * Maximum allowed size for direct messages sent from DataProducers. - * Default 262144. - */ - maxMessageSize: number; - - /** - * Custom application data. - */ - appData?: DirectTransportAppData; -}; - -export type DirectTransportDump = BaseTransportDump; - -export type DirectTransportStat = BaseTransportStats & { - type: string; -}; - -export type DirectTransportEvents = TransportEvents & { - rtcp: [Buffer]; -}; - -export type DirectTransportObserver = - EnhancedEventEmitter; - -export type DirectTransportObserverEvents = TransportObserverEvents & { - rtcp: [Buffer]; -}; - type DirectTransportConstructorOptions = TransportConstructorOptions & { data: DirectTransportData; @@ -63,20 +36,20 @@ export type DirectTransportData = { const logger = new Logger('DirectTransport'); -export class DirectTransport< - DirectTransportAppData extends AppData = AppData, -> extends Transport< - DirectTransportAppData, - DirectTransportEvents, - DirectTransportObserver -> { +export class DirectTransportImpl< + DirectTransportAppData extends AppData = AppData, + > + extends TransportImpl< + DirectTransportAppData, + DirectTransportEvents, + DirectTransportObserver + > + implements Transport, DirectTransport +{ // DirectTransport data. // eslint-disable-next-line no-unused-private-class-members readonly #data: DirectTransportData; - /** - * @private - */ constructor( options: DirectTransportConstructorOptions ) { @@ -92,22 +65,17 @@ export class DirectTransport< }; this.handleWorkerNotifications(); + this.handleListenerError(); + } + + get type(): 'direct' { + return 'direct'; } - /** - * Observer. - * - * @override - */ get observer(): DirectTransportObserver { return super.observer; } - /** - * Close the DirectTransport. - * - * @override - */ close(): void { if (this.closed) { return; @@ -116,12 +84,6 @@ export class DirectTransport< super.close(); } - /** - * Router was closed. - * - * @private - * @override - */ routerClosed(): void { if (this.closed) { return; @@ -130,9 +92,6 @@ export class DirectTransport< super.routerClosed(); } - /** - * Dump Transport. - */ async dump(): Promise { logger.debug('dump()'); @@ -151,11 +110,6 @@ export class DirectTransport< return parseDirectTransportDumpResponse(data); } - /** - * Get DirectTransport stats. - * - * @override - */ async getStats(): Promise { logger.debug('getStats()'); @@ -174,19 +128,11 @@ export class DirectTransport< return [parseGetStatsResponse(data)]; } - /** - * NO-OP method in DirectTransport. - * - * @override - */ // eslint-disable-next-line @typescript-eslint/require-await async connect(): Promise { logger.debug('connect()'); } - /** - * @override - */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async setMaxIncomingBitrate(bitrate: number): Promise { throw new UnsupportedError( @@ -194,9 +140,6 @@ export class DirectTransport< ); } - /** - * @override - */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async setMaxOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( @@ -204,9 +147,6 @@ export class DirectTransport< ); } - /** - * @override - */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async setMinOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( @@ -214,9 +154,6 @@ export class DirectTransport< ); } - /** - * Send RTCP packet. - */ sendRtcp(rtcpPacket: Buffer): void { if (!Buffer.isBuffer(rtcpPacket)) { throw new TypeError('rtcpPacket must be a Buffer'); @@ -282,6 +219,15 @@ export class DirectTransport< } ); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } export function parseDirectTransportDumpResponse( diff --git a/node/src/DirectTransportTypes.ts b/node/src/DirectTransportTypes.ts new file mode 100644 index 0000000000..85bb824341 --- /dev/null +++ b/node/src/DirectTransportTypes.ts @@ -0,0 +1,89 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { + Transport, + BaseTransportDump, + BaseTransportStats, + TransportEvents, + TransportObserverEvents, +} from './TransportTypes'; +import type { AppData } from './types'; + +export type DirectTransportOptions< + DirectTransportAppData extends AppData = AppData, +> = { + /** + * Maximum allowed size for direct messages sent from DataProducers. + * Default 262144. + */ + maxMessageSize: number; + + /** + * Custom application data. + */ + appData?: DirectTransportAppData; +}; + +export type DirectTransportDump = BaseTransportDump; + +export type DirectTransportStat = BaseTransportStats & { + type: string; +}; + +export type DirectTransportEvents = TransportEvents & { + rtcp: [Buffer]; +}; + +export type DirectTransportObserver = + EnhancedEventEmitter; + +export type DirectTransportObserverEvents = TransportObserverEvents & { + rtcp: [Buffer]; +}; + +export interface DirectTransport< + DirectTransportAppData extends AppData = AppData, +> extends Transport< + DirectTransportAppData, + DirectTransportEvents, + DirectTransportObserver + > { + /** + * Transport type. + * + * @override + */ + get type(): 'direct'; + + /** + * Observer. + * + * @override + */ + get observer(): DirectTransportObserver; + + /** + * Dump DirectTransport. + * + * @override + */ + dump(): Promise; + + /** + * Get DirectTransport stats. + * + * @override + */ + getStats(): Promise; + + /** + * NO-OP method in DirectTransport. + * + * @override + */ + connect(): Promise; + + /** + * Send RTCP packet. + */ + sendRtcp(rtcpPacket: Buffer): void; +} diff --git a/node/src/Logger.ts b/node/src/Logger.ts index 66b5456c0c..1dd0b30a75 100644 --- a/node/src/Logger.ts +++ b/node/src/Logger.ts @@ -1,5 +1,5 @@ import debug from 'debug'; -import { EnhancedEventEmitter } from './enhancedEvents'; +import type { EnhancedEventEmitter } from './enhancedEvents'; const APP_NAME = 'mediasoup'; diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index d15dd5025a..266c0d50d4 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -2,37 +2,40 @@ import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; +import type { + PipeTransport, + PipeConsumerOptions, + PipeTransportDump, + PipeTransportStat, + PipeTransportEvents, + PipeTransportObserver, + PipeTransportObserverEvents, +} from './PipeTransportTypes'; +import type { Transport, TransportTuple, SctpState } from './TransportTypes'; import { - BaseTransportDump, - BaseTransportStats, + TransportImpl, + TransportConstructorOptions, parseBaseTransportDump, parseBaseTransportStats, parseSctpState, parseTuple, parseTransportTraceEventData, - Transport, - TransportListenInfo, - TransportListenIp, - TransportTuple, - TransportEvents, - TransportObserverEvents, - TransportConstructorOptions, - SctpState, } from './Transport'; -import { Consumer, ConsumerType } from './Consumer'; -import { Producer } from './Producer'; +import type { Producer } from './ProducerTypes'; +import type { Consumer, ConsumerType } from './ConsumerTypes'; +import { ConsumerImpl } from './Consumer'; +import type { RtpParameters } from './rtpParametersTypes'; import { - RtpParameters, serializeRtpEncodingParameters, serializeRtpParameters, -} from './RtpParameters'; -import { SctpParameters, NumSctpStreams } from './SctpParameters'; +} from './rtpParametersFbsUtils'; +import type { SctpParameters } from './sctpParametersTypes'; +import type { SrtpParameters } from './srtpParametersTypes'; import { parseSrtpParameters, serializeSrtpParameters, - SrtpParameters, -} from './SrtpParameters'; -import { AppData, Either } from './types'; +} from './srtpParametersFbsUtils'; +import type { AppData } from './types'; import { generateUUIDv4 } from './utils'; import { MediaKind as FbsMediaKind } from './fbs/rtp-parameters/media-kind'; import * as FbsRtpParameters from './fbs/rtp-parameters'; @@ -41,104 +44,6 @@ import * as FbsRequest from './fbs/request'; import * as FbsTransport from './fbs/transport'; import * as FbsPipeTransport from './fbs/pipe-transport'; -type PipeTransportListenInfo = { - /** - * Listening info. - */ - listenInfo: TransportListenInfo; -}; - -type PipeTransportListenIp = { - /** - * Listening IP address. - */ - listenIp: TransportListenIp | string; - - /** - * Fixed port to listen on instead of selecting automatically from Worker's port - * range. - */ - port?: number; -}; - -type PipeTransportListen = Either< - PipeTransportListenInfo, - PipeTransportListenIp ->; - -export type PipeTransportOptions< - PipeTransportAppData extends AppData = AppData, -> = { - /** - * Create a SCTP association. Default false. - */ - enableSctp?: boolean; - - /** - * SCTP streams number. - */ - numSctpStreams?: NumSctpStreams; - - /** - * Maximum allowed size for SCTP messages sent by DataProducers. - * Default 268435456. - */ - maxSctpMessageSize?: number; - - /** - * Maximum SCTP send buffer used by DataConsumers. - * Default 268435456. - */ - sctpSendBufferSize?: number; - - /** - * Enable RTX and NACK for RTP retransmission. Useful if both Routers are - * located in different hosts and there is packet lost in the link. For this - * to work, both PipeTransports must enable this setting. Default false. - */ - enableRtx?: boolean; - - /** - * Enable SRTP. Useful to protect the RTP and RTCP traffic if both Routers - * are located in different hosts. For this to work, connect() must be called - * with remote SRTP parameters. Default false. - */ - enableSrtp?: boolean; - - /** - * Custom application data. - */ - appData?: PipeTransportAppData; -} & PipeTransportListen; - -export type PipeTransportStat = BaseTransportStats & { - type: string; - tuple: TransportTuple; -}; - -export type PipeConsumerOptions = { - /** - * The id of the Producer to consume. - */ - producerId: string; - - /** - * Custom application data. - */ - appData?: ConsumerAppData; -}; - -export type PipeTransportEvents = TransportEvents & { - sctpstatechange: [SctpState]; -}; - -export type PipeTransportObserver = - EnhancedEventEmitter; - -export type PipeTransportObserverEvents = TransportObserverEvents & { - sctpstatechange: [SctpState]; -}; - type PipeTransportConstructorOptions = TransportConstructorOptions & { data: PipeTransportData; @@ -152,27 +57,19 @@ export type PipeTransportData = { srtpParameters?: SrtpParameters; }; -export type PipeTransportDump = BaseTransportDump & { - tuple: TransportTuple; - rtx: boolean; - srtpParameters?: SrtpParameters; -}; - const logger = new Logger('PipeTransport'); -export class PipeTransport< - PipeTransportAppData extends AppData = AppData, -> extends Transport< - PipeTransportAppData, - PipeTransportEvents, - PipeTransportObserver -> { +export class PipeTransportImpl + extends TransportImpl< + PipeTransportAppData, + PipeTransportEvents, + PipeTransportObserver + > + implements Transport, PipeTransport +{ // PipeTransport data. readonly #data: PipeTransportData; - /** - * @private - */ constructor(options: PipeTransportConstructorOptions) { const observer: PipeTransportObserver = new EnhancedEventEmitter(); @@ -192,50 +89,33 @@ export class PipeTransport< }; this.handleWorkerNotifications(); + this.handleListenerError(); + } + + get type(): 'pipe' { + return 'pipe'; } - /** - * Observer. - * - * @override - */ get observer(): PipeTransportObserver { return super.observer; } - /** - * Transport tuple. - */ get tuple(): TransportTuple { return this.#data.tuple; } - /** - * SCTP parameters. - */ get sctpParameters(): SctpParameters | undefined { return this.#data.sctpParameters; } - /** - * SCTP state. - */ get sctpState(): SctpState | undefined { return this.#data.sctpState; } - /** - * SRTP parameters. - */ get srtpParameters(): SrtpParameters | undefined { return this.#data.srtpParameters; } - /** - * Close the PipeTransport. - * - * @override - */ close(): void { if (this.closed) { return; @@ -248,12 +128,6 @@ export class PipeTransport< super.close(); } - /** - * Router was closed. - * - * @private - * @override - */ routerClosed(): void { if (this.closed) { return; @@ -266,11 +140,24 @@ export class PipeTransport< super.routerClosed(); } - /** - * Get PipeTransport stats. - * - * @override - */ + async dump(): Promise { + logger.debug('dump()'); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_DUMP, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPipeTransport.DumpResponse(); + + response.body(data); + + return parsePipeTransportDumpResponse(data); + } + async getStats(): Promise { logger.debug('getStats()'); @@ -289,11 +176,6 @@ export class PipeTransport< return [parseGetStatsResponse(data)]; } - /** - * Provide the PipeTransport remote parameters. - * - * @override - */ async connect({ ip, port, @@ -331,11 +213,6 @@ export class PipeTransport< } } - /** - * Create a pipe Consumer. - * - * @override - */ async consume({ producerId, appData, @@ -390,7 +267,7 @@ export class PipeTransport< type: 'pipe' as ConsumerType, }; - const consumer: Consumer = new Consumer({ + const consumer: Consumer = new ConsumerImpl({ internal: { ...this.internal, consumerId, @@ -456,6 +333,15 @@ export class PipeTransport< } ); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } /* diff --git a/node/src/PipeTransportTypes.ts b/node/src/PipeTransportTypes.ts new file mode 100644 index 0000000000..4bc9734eb8 --- /dev/null +++ b/node/src/PipeTransportTypes.ts @@ -0,0 +1,200 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { + Transport, + TransportListenInfo, + TransportListenIp, + TransportTuple, + SctpState, + BaseTransportDump, + BaseTransportStats, + TransportEvents, + TransportObserverEvents, +} from './TransportTypes'; +import type { Consumer } from './ConsumerTypes'; +import type { SrtpParameters } from './srtpParametersTypes'; +import type { SctpParameters, NumSctpStreams } from './sctpParametersTypes'; +import type { Either, AppData } from './types'; + +export type PipeTransportOptions< + PipeTransportAppData extends AppData = AppData, +> = { + /** + * Create a SCTP association. Default false. + */ + enableSctp?: boolean; + + /** + * SCTP streams number. + */ + numSctpStreams?: NumSctpStreams; + + /** + * Maximum allowed size for SCTP messages sent by DataProducers. + * Default 268435456. + */ + maxSctpMessageSize?: number; + + /** + * Maximum SCTP send buffer used by DataConsumers. + * Default 268435456. + */ + sctpSendBufferSize?: number; + + /** + * Enable RTX and NACK for RTP retransmission. Useful if both Routers are + * located in different hosts and there is packet lost in the link. For this + * to work, both PipeTransports must enable this setting. Default false. + */ + enableRtx?: boolean; + + /** + * Enable SRTP. Useful to protect the RTP and RTCP traffic if both Routers + * are located in different hosts. For this to work, connect() must be called + * with remote SRTP parameters. Default false. + */ + enableSrtp?: boolean; + + /** + * Custom application data. + */ + appData?: PipeTransportAppData; +} & PipeTransportListen; + +type PipeTransportListen = Either< + PipeTransportListenInfo, + PipeTransportListenIp +>; + +type PipeTransportListenInfo = { + /** + * Listening info. + */ + listenInfo: TransportListenInfo; +}; + +type PipeTransportListenIp = { + /** + * Listening IP address. + */ + listenIp: TransportListenIp | string; + + /** + * Fixed port to listen on instead of selecting automatically from Worker's + * port range. + */ + port?: number; +}; + +export type PipeConsumerOptions = { + /** + * The id of the Producer to consume. + */ + producerId: string; + + /** + * Custom application data. + */ + appData?: ConsumerAppData; +}; + +export type PipeTransportDump = BaseTransportDump & { + tuple: TransportTuple; + rtx: boolean; + srtpParameters?: SrtpParameters; +}; + +export type PipeTransportStat = BaseTransportStats & { + type: string; + tuple: TransportTuple; +}; + +export type PipeTransportEvents = TransportEvents & { + sctpstatechange: [SctpState]; +}; + +export type PipeTransportObserver = + EnhancedEventEmitter; + +export type PipeTransportObserverEvents = TransportObserverEvents & { + sctpstatechange: [SctpState]; +}; + +export interface PipeTransport + extends Transport< + PipeTransportAppData, + PipeTransportEvents, + PipeTransportObserver + > { + /** + * Transport type. + * + * @override + */ + get type(): 'pipe'; + + /** + * Observer. + * + * @override + */ + get observer(): PipeTransportObserver; + + /** + * PipeTransport tuple. + */ + get tuple(): TransportTuple; + + /** + * SCTP parameters. + */ + get sctpParameters(): SctpParameters | undefined; + + /** + * SCTP state. + */ + get sctpState(): SctpState | undefined; + + /** + * SRTP parameters. + */ + get srtpParameters(): SrtpParameters | undefined; + + /** + * Dump PipeTransport. + * + * @override + */ + dump(): Promise; + + /** + * Get PipeTransport stats. + * + * @override + */ + getStats(): Promise; + + /** + * Provide the PipeTransport remote parameters. + * + * @override + */ + connect({ + ip, + port, + srtpParameters, + }: { + ip: string; + port: number; + srtpParameters?: SrtpParameters; + }): Promise; + + /** + * Create a pipe Consumer. + * + * @override + */ + consume({ + producerId, + appData, + }: PipeConsumerOptions): Promise>; +} diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index e1eabcac62..5e595152c1 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -1,145 +1,36 @@ import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; +import type { + PlainTransport, + PlainTransportDump, + PlainTransportStat, + PlainTransportEvents, + PlainTransportObserver, + PlainTransportObserverEvents, +} from './PlainTransportTypes'; +import type { Transport, TransportTuple, SctpState } from './TransportTypes'; import { + TransportImpl, + TransportConstructorOptions, parseSctpState, - BaseTransportDump, - BaseTransportStats, parseTuple, parseBaseTransportDump, parseBaseTransportStats, parseTransportTraceEventData, - Transport, - TransportListenInfo, - TransportListenIp, - TransportTuple, - TransportEvents, - TransportObserverEvents, - TransportConstructorOptions, - SctpState, } from './Transport'; -import { SctpParameters, NumSctpStreams } from './SctpParameters'; +import type { SctpParameters } from './sctpParametersTypes'; +import type { SrtpParameters } from './srtpParametersTypes'; import { parseSrtpParameters, serializeSrtpParameters, - SrtpParameters, - SrtpCryptoSuite, -} from './SrtpParameters'; -import { AppData, Either } from './types'; +} from './srtpParametersFbsUtils'; +import type { AppData } from './types'; import { Event, Notification } from './fbs/notification'; import * as FbsRequest from './fbs/request'; import * as FbsTransport from './fbs/transport'; import * as FbsPlainTransport from './fbs/plain-transport'; -type PlainTransportListenInfo = { - /** - * Listening info. - */ - listenInfo: TransportListenInfo; - - /** - * Optional listening info for RTCP. - */ - rtcpListenInfo?: TransportListenInfo; -}; - -type PlainTransportListenIp = { - /** - * Listening IP address. - */ - listenIp: TransportListenIp | string; - - /** - * Fixed port to listen on instead of selecting automatically from Worker's port - * range. - */ - port?: number; -}; - -type PlainTransportListen = Either< - PlainTransportListenInfo, - PlainTransportListenIp ->; - -export type PlainTransportOptions< - PlainTransportAppData extends AppData = AppData, -> = { - /** - * Use RTCP-mux (RTP and RTCP in the same port). Default true. - */ - rtcpMux?: boolean; - - /** - * Whether remote IP:port should be auto-detected based on first RTP/RTCP - * packet received. If enabled, connect() method must not be called unless - * SRTP is enabled. If so, it must be called with just remote SRTP parameters. - * Default false. - */ - comedia?: boolean; - - /** - * Create a SCTP association. Default false. - */ - enableSctp?: boolean; - - /** - * SCTP streams number. - */ - numSctpStreams?: NumSctpStreams; - - /** - * Maximum allowed size for SCTP messages sent by DataProducers. - * Default 262144. - */ - maxSctpMessageSize?: number; - - /** - * Maximum SCTP send buffer used by DataConsumers. - * Default 262144. - */ - sctpSendBufferSize?: number; - - /** - * Enable SRTP. For this to work, connect() must be called - * with remote SRTP parameters. Default false. - */ - enableSrtp?: boolean; - - /** - * The SRTP crypto suite to be used if enableSrtp is set. Default - * 'AES_CM_128_HMAC_SHA1_80'. - */ - srtpCryptoSuite?: SrtpCryptoSuite; - - /** - * Custom application data. - */ - appData?: PlainTransportAppData; -} & PlainTransportListen; - -export type PlainTransportStat = BaseTransportStats & { - type: string; - rtcpMux: boolean; - comedia: boolean; - tuple: TransportTuple; - rtcpTuple?: TransportTuple; -}; - -export type PlainTransportEvents = TransportEvents & { - tuple: [TransportTuple]; - rtcptuple: [TransportTuple]; - sctpstatechange: [SctpState]; -}; - -export type PlainTransportObserver = - EnhancedEventEmitter; - -export type PlainTransportObserverEvents = TransportObserverEvents & { - tuple: [TransportTuple]; - rtcptuple: [TransportTuple]; - sctpstatechange: [SctpState]; -}; - type PlainTransportConstructorOptions = TransportConstructorOptions & { data: PlainTransportData; @@ -155,29 +46,19 @@ export type PlainTransportData = { srtpParameters?: SrtpParameters; }; -type PlainTransportDump = BaseTransportDump & { - rtcpMux: boolean; - comedia: boolean; - tuple: TransportTuple; - rtcpTuple?: TransportTuple; - srtpParameters?: SrtpParameters; -}; - const logger = new Logger('PlainTransport'); -export class PlainTransport< - PlainTransportAppData extends AppData = AppData, -> extends Transport< - PlainTransportAppData, - PlainTransportEvents, - PlainTransportObserver -> { +export class PlainTransportImpl + extends TransportImpl< + PlainTransportAppData, + PlainTransportEvents, + PlainTransportObserver + > + implements Transport, PlainTransport +{ // PlainTransport data. readonly #data: PlainTransportData; - /** - * @private - */ constructor( options: PlainTransportConstructorOptions ) { @@ -201,57 +82,37 @@ export class PlainTransport< }; this.handleWorkerNotifications(); + this.handleListenerError(); + } + + get type(): 'plain' { + return 'plain'; } - /** - * Observer. - * - * @override - */ get observer(): PlainTransportObserver { return super.observer; } - /** - * Transport tuple. - */ get tuple(): TransportTuple { return this.#data.tuple; } - /** - * Transport RTCP tuple. - */ get rtcpTuple(): TransportTuple | undefined { return this.#data.rtcpTuple; } - /** - * SCTP parameters. - */ get sctpParameters(): SctpParameters | undefined { return this.#data.sctpParameters; } - /** - * SCTP state. - */ get sctpState(): SctpState | undefined { return this.#data.sctpState; } - /** - * SRTP parameters. - */ get srtpParameters(): SrtpParameters | undefined { return this.#data.srtpParameters; } - /** - * Close the PlainTransport. - * - * @override - */ close(): void { if (this.closed) { return; @@ -264,12 +125,6 @@ export class PlainTransport< super.close(); } - /** - * Router was closed. - * - * @private - * @override - */ routerClosed(): void { if (this.closed) { return; @@ -282,9 +137,6 @@ export class PlainTransport< super.routerClosed(); } - /** - * Dump Transport. - */ async dump(): Promise { logger.debug('dump()'); @@ -303,11 +155,6 @@ export class PlainTransport< return parsePlainTransportDumpResponse(data); } - /** - * Get PlainTransport stats. - * - * @override - */ async getStats(): Promise { logger.debug('getStats()'); @@ -326,11 +173,6 @@ export class PlainTransport< return [parseGetStatsResponse(data)]; } - /** - * Provide the PlainTransport remote parameters. - * - * @override - */ async connect({ ip, port, @@ -457,6 +299,15 @@ export class PlainTransport< } ); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } export function parsePlainTransportDumpResponse( diff --git a/node/src/PlainTransportTypes.ts b/node/src/PlainTransportTypes.ts new file mode 100644 index 0000000000..383a29c04a --- /dev/null +++ b/node/src/PlainTransportTypes.ts @@ -0,0 +1,209 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { + Transport, + TransportListenInfo, + TransportListenIp, + TransportTuple, + SctpState, + BaseTransportDump, + BaseTransportStats, + TransportEvents, + TransportObserverEvents, +} from './TransportTypes'; +import type { SrtpParameters, SrtpCryptoSuite } from './srtpParametersTypes'; +import type { SctpParameters, NumSctpStreams } from './sctpParametersTypes'; +import type { Either, AppData } from './types'; + +export type PlainTransportOptions< + PlainTransportAppData extends AppData = AppData, +> = { + /** + * Use RTCP-mux (RTP and RTCP in the same port). Default true. + */ + rtcpMux?: boolean; + + /** + * Whether remote IP:port should be auto-detected based on first RTP/RTCP + * packet received. If enabled, connect() method must not be called unless + * SRTP is enabled. If so, it must be called with just remote SRTP parameters. + * Default false. + */ + comedia?: boolean; + + /** + * Create a SCTP association. Default false. + */ + enableSctp?: boolean; + + /** + * SCTP streams number. + */ + numSctpStreams?: NumSctpStreams; + + /** + * Maximum allowed size for SCTP messages sent by DataProducers. + * Default 262144. + */ + maxSctpMessageSize?: number; + + /** + * Maximum SCTP send buffer used by DataConsumers. + * Default 262144. + */ + sctpSendBufferSize?: number; + + /** + * Enable SRTP. For this to work, connect() must be called + * with remote SRTP parameters. Default false. + */ + enableSrtp?: boolean; + + /** + * The SRTP crypto suite to be used if enableSrtp is set. Default + * 'AES_CM_128_HMAC_SHA1_80'. + */ + srtpCryptoSuite?: SrtpCryptoSuite; + + /** + * Custom application data. + */ + appData?: PlainTransportAppData; +} & PlainTransportListen; + +type PlainTransportListen = Either< + PlainTransportListenInfo, + PlainTransportListenIp +>; + +type PlainTransportListenInfo = { + /** + * Listening info. + */ + listenInfo: TransportListenInfo; + + /** + * Optional listening info for RTCP. + */ + rtcpListenInfo?: TransportListenInfo; +}; + +type PlainTransportListenIp = { + /** + * Listening IP address. + */ + listenIp: TransportListenIp | string; + + /** + * Fixed port to listen on instead of selecting automatically from Worker's + * port range. + */ + port?: number; +}; + +export type PlainTransportDump = BaseTransportDump & { + rtcpMux: boolean; + comedia: boolean; + tuple: TransportTuple; + rtcpTuple?: TransportTuple; + srtpParameters?: SrtpParameters; +}; + +export type PlainTransportStat = BaseTransportStats & { + type: string; + rtcpMux: boolean; + comedia: boolean; + tuple: TransportTuple; + rtcpTuple?: TransportTuple; +}; + +export type PlainTransportEvents = TransportEvents & { + tuple: [TransportTuple]; + rtcptuple: [TransportTuple]; + sctpstatechange: [SctpState]; +}; + +export type PlainTransportObserver = + EnhancedEventEmitter; + +export type PlainTransportObserverEvents = TransportObserverEvents & { + tuple: [TransportTuple]; + rtcptuple: [TransportTuple]; + sctpstatechange: [SctpState]; +}; + +export interface PlainTransport + extends Transport< + PlainTransportAppData, + PlainTransportEvents, + PlainTransportObserver + > { + /** + * Transport type. + * + * @override + */ + get type(): 'plain'; + + /** + * Observer. + * + * @override + */ + get observer(): PlainTransportObserver; + + /** + * PlainTransport tuple. + */ + get tuple(): TransportTuple; + + /** + * PlainTransport RTCP tuple. + */ + get rtcpTuple(): TransportTuple | undefined; + + /** + * SCTP parameters. + */ + get sctpParameters(): SctpParameters | undefined; + + /** + * SCTP state. + */ + get sctpState(): SctpState | undefined; + + /** + * SRTP parameters. + */ + get srtpParameters(): SrtpParameters | undefined; + + /** + * Dump PlainTransport. + * + * @override + */ + dump(): Promise; + + /** + * Get PlainTransport stats. + * + * @override + */ + getStats(): Promise; + + /** + * Provide the PlainTransport remote parameters. + * + * @override + */ + connect({ + ip, + port, + rtcpPort, + srtpParameters, + }: { + ip?: string; + port?: number; + rtcpPort?: number; + srtpParameters?: SrtpParameters; + }): Promise; +} diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 42e2d2b1ee..9420b8f8eb 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -1,12 +1,26 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; +import type { + Producer, + ProducerType, + ProducerScore, + ProducerVideoOrientation, + ProducerDump, + ProducerStat, + ProducerTraceEventType, + ProducerTraceEventData, + ProducerEvents, + ProducerObserver, + ProducerObserverEvents, +} from './ProducerTypes'; import { Channel } from './Channel'; -import { TransportInternal } from './Transport'; -import { MediaKind, RtpParameters, parseRtpParameters } from './RtpParameters'; +import type { TransportInternal } from './Transport'; +import type { MediaKind, RtpParameters } from './rtpParametersTypes'; +import { parseRtpParameters } from './rtpParametersFbsUtils'; +import { parseRtpStreamRecvStats } from './rtpStreamStatsFbsUtils'; +import type { AppData } from './types'; +import * as fbsUtils from './fbsUtils'; import { Event, Notification } from './fbs/notification'; -import { parseRtpStreamRecvStats, RtpStreamRecvStats } from './RtpStream'; -import { AppData } from './types'; -import * as utils from './utils'; import { TraceDirection as FbsTraceDirection } from './fbs/common'; import * as FbsNotification from './fbs/notification'; import * as FbsRequest from './fbs/request'; @@ -15,157 +29,12 @@ import * as FbsProducer from './fbs/producer'; import * as FbsProducerTraceInfo from './fbs/producer/trace-info'; import * as FbsRtpParameters from './fbs/rtp-parameters'; -export type ProducerOptions = { - /** - * Producer id (just for Router.pipeToRouter() method). - */ - id?: string; - - /** - * Media kind ('audio' or 'video'). - */ - kind: MediaKind; - - /** - * RTP parameters defining what the endpoint is sending. - */ - rtpParameters: RtpParameters; - - /** - * Whether the producer must start in paused mode. Default false. - */ - paused?: boolean; - - /** - * Just for video. Time (in ms) before asking the sender for a new key frame - * after having asked a previous one. Default 0. - */ - keyFrameRequestDelay?: number; - - /** - * Custom application data. - */ - appData?: ProducerAppData; -}; - -/** - * Valid types for 'trace' event. - */ -export type ProducerTraceEventType = - | 'rtp' - | 'keyframe' - | 'nack' - | 'pli' - | 'fir' - | 'sr'; - -/** - * 'trace' event data. - */ -export type ProducerTraceEventData = { - /** - * Trace type. - */ - type: ProducerTraceEventType; - - /** - * Event timestamp. - */ - timestamp: number; - - /** - * Event direction. - */ - direction: 'in' | 'out'; - - /** - * Per type information. - */ - info: any; -}; - -export type ProducerScore = { - /** - * Index of the RTP stream in the rtpParameters.encodings array. - */ - encodingIdx: number; - - /** - * SSRC of the RTP stream. - */ - ssrc: number; - - /** - * RID of the RTP stream. - */ - rid?: string; - - /** - * The score of the RTP stream. - */ - score: number; -}; - -export type ProducerVideoOrientation = { - /** - * Whether the source is a video camera. - */ - camera: boolean; - - /** - * Whether the video source is flipped. - */ - flip: boolean; - - /** - * Rotation degrees (0, 90, 180 or 270). - */ - rotation: number; -}; - -export type ProducerStat = RtpStreamRecvStats; - -/** - * Producer type. - */ -export type ProducerType = 'simple' | 'simulcast' | 'svc'; - -export type ProducerEvents = { - transportclose: []; - score: [ProducerScore[]]; - videoorientationchange: [ProducerVideoOrientation]; - trace: [ProducerTraceEventData]; - listenererror: [string, Error]; - // Private events. - '@close': []; -}; - -export type ProducerObserver = EnhancedEventEmitter; - -export type ProducerObserverEvents = { - close: []; - pause: []; - resume: []; - score: [ProducerScore[]]; - videoorientationchange: [ProducerVideoOrientation]; - trace: [ProducerTraceEventData]; -}; - -type ProducerDump = { - id: string; - kind: string; - type: ProducerType; - rtpParameters: RtpParameters; - rtpMapping: any; - rtpStreams: any; - traceEventTypes: string[]; - paused: boolean; -}; - type ProducerInternal = TransportInternal & { producerId: string; }; +const logger = new Logger('Producer'); + type ProducerData = { kind: MediaKind; rtpParameters: RtpParameters; @@ -173,11 +42,10 @@ type ProducerData = { consumableRtpParameters: RtpParameters; }; -const logger = new Logger('Producer'); - -export class Producer< - ProducerAppData extends AppData = AppData, -> extends EnhancedEventEmitter { +export class ProducerImpl + extends EnhancedEventEmitter + implements Producer +{ // Internal data. readonly #internal: ProducerInternal; @@ -203,9 +71,6 @@ export class Producer< readonly #observer: ProducerObserver = new EnhancedEventEmitter(); - /** - * @private - */ constructor({ internal, data, @@ -230,98 +95,62 @@ export class Producer< this.#appData = appData ?? ({} as ProducerAppData); this.handleWorkerNotifications(); + this.handleListenerError(); } - /** - * Producer id. - */ get id(): string { return this.#internal.producerId; } - /** - * Whether the Producer is closed. - */ get closed(): boolean { return this.#closed; } - /** - * Media kind. - */ get kind(): MediaKind { return this.#data.kind; } - /** - * RTP parameters. - */ get rtpParameters(): RtpParameters { return this.#data.rtpParameters; } - /** - * Producer type. - */ get type(): ProducerType { return this.#data.type; } - /** - * Consumable RTP parameters. - * - * @private - */ get consumableRtpParameters(): RtpParameters { return this.#data.consumableRtpParameters; } - /** - * Whether the Producer is paused. - */ get paused(): boolean { return this.#paused; } - /** - * Producer score list. - */ get score(): ProducerScore[] { return this.#score; } - /** - * App custom data. - */ get appData(): ProducerAppData { return this.#appData; } - /** - * App custom data setter. - */ set appData(appData: ProducerAppData) { this.#appData = appData; } - /** - * Observer. - */ get observer(): ProducerObserver { return this.#observer; } /** - * @private * Just for testing purposes. + * + * @private */ get channelForTesting(): Channel { return this.#channel; } - /** - * Close the Producer. - */ close(): void { if (this.#closed) { return; @@ -354,11 +183,6 @@ export class Producer< this.#observer.safeEmit('close'); } - /** - * Transport was closed. - * - * @private - */ transportClosed(): void { if (this.#closed) { return; @@ -377,9 +201,6 @@ export class Producer< this.#observer.safeEmit('close'); } - /** - * Dump Producer. - */ async dump(): Promise { logger.debug('dump()'); @@ -398,9 +219,6 @@ export class Producer< return parseProducerDump(dumpResponse); } - /** - * Get Producer stats. - */ async getStats(): Promise { logger.debug('getStats()'); @@ -419,9 +237,6 @@ export class Producer< return parseProducerStats(data); } - /** - * Pause the Producer. - */ async pause(): Promise { logger.debug('pause()'); @@ -442,9 +257,6 @@ export class Producer< } } - /** - * Resume the Producer. - */ async resume(): Promise { logger.debug('resume()'); @@ -465,9 +277,6 @@ export class Producer< } } - /** - * Enable 'trace' event. - */ async enableTraceEvent(types: ProducerTraceEventType[] = []): Promise { logger.debug('enableTraceEvent()'); @@ -502,9 +311,6 @@ export class Producer< ); } - /** - * Send RTP packet (just valid for Producers created on a DirectTransport). - */ send(rtpPacket: Buffer): void { if (!Buffer.isBuffer(rtpPacket)) { throw new TypeError('rtpPacket must be a Buffer'); @@ -536,7 +342,7 @@ export class Producer< data!.body(notification); - const score: ProducerScore[] = utils.parseVector( + const score: ProducerScore[] = fbsUtils.parseVector( notification, 'scores', parseProducerScore @@ -592,6 +398,15 @@ export class Producer< } ); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } export function producerTypeFromFbs(type: FbsRtpParameters.Type): ProducerType { @@ -713,11 +528,11 @@ export function parseProducerDump( // TODO: Make flatbuffers TS return undefined instead of null. rtpStreams: data.rtpStreamsLength() > 0 - ? utils.parseVector(data, 'rtpStreams', (rtpStream: any) => + ? fbsUtils.parseVector(data, 'rtpStreams', (rtpStream: any) => rtpStream.unpack() ) : undefined, - traceEventTypes: utils.parseVector( + traceEventTypes: fbsUtils.parseVector( data, 'traceEventTypes', producerTraceEventTypeFromFbs @@ -729,7 +544,7 @@ export function parseProducerDump( function parseProducerStats( binary: FbsProducer.GetStatsResponse ): ProducerStat[] { - return utils.parseVector(binary, 'stats', parseRtpStreamRecvStats); + return fbsUtils.parseVector(binary, 'stats', parseRtpStreamRecvStats); } function parseProducerScore(binary: FbsProducer.Score): ProducerScore { diff --git a/node/src/ProducerTypes.ts b/node/src/ProducerTypes.ts new file mode 100644 index 0000000000..989acf72c0 --- /dev/null +++ b/node/src/ProducerTypes.ts @@ -0,0 +1,253 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { MediaKind, RtpParameters } from './rtpParametersTypes'; +import type { RtpStreamRecvStats } from './rtpStreamStatsTypes'; +import type { AppData } from './types'; + +export type ProducerOptions = { + /** + * Producer id (just for Router.pipeToRouter() method). + */ + id?: string; + + /** + * Media kind ('audio' or 'video'). + */ + kind: MediaKind; + + /** + * RTP parameters defining what the endpoint is sending. + */ + rtpParameters: RtpParameters; + + /** + * Whether the producer must start in paused mode. Default false. + */ + paused?: boolean; + + /** + * Just for video. Time (in ms) before asking the sender for a new key frame + * after having asked a previous one. Default 0. + */ + keyFrameRequestDelay?: number; + + /** + * Custom application data. + */ + appData?: ProducerAppData; +}; + +/** + * Producer type. + */ +export type ProducerType = 'simple' | 'simulcast' | 'svc'; + +export type ProducerScore = { + /** + * Index of the RTP stream in the rtpParameters.encodings array. + */ + encodingIdx: number; + + /** + * SSRC of the RTP stream. + */ + ssrc: number; + + /** + * RID of the RTP stream. + */ + rid?: string; + + /** + * The score of the RTP stream. + */ + score: number; +}; + +export type ProducerVideoOrientation = { + /** + * Whether the source is a video camera. + */ + camera: boolean; + + /** + * Whether the video source is flipped. + */ + flip: boolean; + + /** + * Rotation degrees (0, 90, 180 or 270). + */ + rotation: number; +}; + +export type ProducerDump = { + id: string; + kind: string; + type: ProducerType; + rtpParameters: RtpParameters; + rtpMapping: any; + rtpStreams: any; + traceEventTypes: string[]; + paused: boolean; +}; + +export type ProducerStat = RtpStreamRecvStats; + +/** + * Valid types for 'trace' event. + */ +export type ProducerTraceEventType = + | 'rtp' + | 'keyframe' + | 'nack' + | 'pli' + | 'fir' + | 'sr'; + +/** + * 'trace' event data. + */ +export type ProducerTraceEventData = { + /** + * Trace type. + */ + type: ProducerTraceEventType; + + /** + * Event timestamp. + */ + timestamp: number; + + /** + * Event direction. + */ + direction: 'in' | 'out'; + + /** + * Per type information. + */ + info: any; +}; + +export type ProducerEvents = { + transportclose: []; + score: [ProducerScore[]]; + videoorientationchange: [ProducerVideoOrientation]; + trace: [ProducerTraceEventData]; + listenererror: [string, Error]; + // Private events. + '@close': []; +}; + +export type ProducerObserver = EnhancedEventEmitter; + +export type ProducerObserverEvents = { + close: []; + pause: []; + resume: []; + score: [ProducerScore[]]; + videoorientationchange: [ProducerVideoOrientation]; + trace: [ProducerTraceEventData]; +}; + +export interface Producer + extends EnhancedEventEmitter { + /** + * Producer id. + */ + get id(): string; + + /** + * Whether the Producer is closed. + */ + get closed(): boolean; + + /** + * Media kind. + */ + get kind(): MediaKind; + + /** + * RTP parameters. + */ + get rtpParameters(): RtpParameters; + + /** + * Producer type. + */ + get type(): ProducerType; + + /** + * Consumable RTP parameters. + * + * @private + */ + get consumableRtpParameters(): RtpParameters; + + /** + * Whether the Producer is paused. + */ + get paused(): boolean; + + /** + * Producer score list. + */ + get score(): ProducerScore[]; + + /** + * App custom data. + */ + get appData(): ProducerAppData; + + /** + * App custom data setter. + */ + set appData(appData: ProducerAppData); + + /** + * Observer. + */ + get observer(): ProducerObserver; + + /** + * Close the Producer. + */ + close(): void; + + /** + * Transport was closed. + * + * @private + */ + transportClosed(): void; + + /** + * Dump Producer. + */ + dump(): Promise; + + /** + * Get Producer stats. + */ + getStats(): Promise; + + /** + * Pause the Producer. + */ + pause(): Promise; + + /** + * Resume the Producer. + */ + resume(): Promise; + + /** + * Enable 'trace' event. + */ + enableTraceEvent(types?: ProducerTraceEventType[]): Promise; + + /** + * Send RTP packet (just valid for Producers created on a DirectTransport). + */ + send(rtpPacket: Buffer): void; +} diff --git a/node/src/Router.ts b/node/src/Router.ts index 755d579f72..ebe6a3f1a7 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -2,59 +2,72 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; import { InvalidStateError } from './errors'; -import { Channel } from './Channel'; -import { +import type { Channel } from './Channel'; +import type { + Router, + PipeToRouterOptions, + PipeToRouterResult, + PipeTransportPair, + RouterDump, + RouterEvents, + RouterObserver, + RouterObserverEvents, +} from './RouterTypes'; +import type { Transport, - TransportListenInfo, TransportListenIp, TransportProtocol, - portRangeToFbs, - socketFlagsToFbs, -} from './Transport'; -import { +} from './TransportTypes'; +import { portRangeToFbs, socketFlagsToFbs } from './Transport'; +import type { WebRtcTransport, WebRtcTransportOptions, +} from './WebRtcTransportTypes'; +import { + WebRtcTransportImpl, parseWebRtcTransportDumpResponse, } from './WebRtcTransport'; -import { +import type { PlainTransport, PlainTransportOptions, +} from './PlainTransportTypes'; +import { + PlainTransportImpl, parsePlainTransportDumpResponse, } from './PlainTransport'; +import type { PipeTransport, PipeTransportOptions } from './PipeTransportTypes'; import { - PipeTransport, - PipeTransportOptions, + PipeTransportImpl, parsePipeTransportDumpResponse, } from './PipeTransport'; -import { +import type { DirectTransport, DirectTransportOptions, +} from './DirectTransportTypes'; +import { + DirectTransportImpl, parseDirectTransportDumpResponse, } from './DirectTransport'; -import { Producer } from './Producer'; -import { Consumer } from './Consumer'; -import { DataProducer } from './DataProducer'; -import { DataConsumer } from './DataConsumer'; -import { RtpObserver } from './RtpObserver'; -import { +import type { Producer } from './ProducerTypes'; +import type { Consumer } from './ConsumerTypes'; +import type { DataProducer } from './DataProducerTypes'; +import type { DataConsumer } from './DataConsumerTypes'; +import type { RtpObserver } from './RtpObserverTypes'; +import type { ActiveSpeakerObserver, ActiveSpeakerObserverOptions, -} from './ActiveSpeakerObserver'; -import { +} from './ActiveSpeakerObserverTypes'; +import { ActiveSpeakerObserverImpl } from './ActiveSpeakerObserver'; +import type { AudioLevelObserver, AudioLevelObserverOptions, -} from './AudioLevelObserver'; -import { RtpCapabilities, RtpCodecCapability } from './RtpParameters'; -import { cryptoSuiteToFbs } from './SrtpParameters'; -import { NumSctpStreams } from './SctpParameters'; -import { AppData, Either } from './types'; -import { - clone, - generateUUIDv4, - parseVector, - parseStringStringVector, - parseStringStringArrayVector, -} from './utils'; +} from './AudioLevelObserverTypes'; +import { AudioLevelObserverImpl } from './AudioLevelObserver'; +import type { RtpCapabilities } from './rtpParametersTypes'; +import { cryptoSuiteToFbs } from './srtpParametersFbsUtils'; +import type { AppData } from './types'; +import * as utils from './utils'; +import * as fbsUtils from './fbsUtils'; import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; import * as FbsRequest from './fbs/request'; @@ -68,144 +81,6 @@ import * as FbsPipeTransport from './fbs/pipe-transport'; import * as FbsDirectTransport from './fbs/direct-transport'; import * as FbsSctpParameters from './fbs/sctp-parameters'; -export type RouterOptions = { - /** - * Router media codecs. - */ - mediaCodecs?: RtpCodecCapability[]; - - /** - * Custom application data. - */ - appData?: RouterAppData; -}; - -type PipeToRouterListenInfo = { - listenInfo: TransportListenInfo; -}; - -type PipeToRouterListenIp = { - /** - * IP used in the PipeTransport pair. Default '127.0.0.1'. - */ - listenIp?: TransportListenIp | string; -}; - -type PipeToRouterListen = Either; - -export type PipeToRouterOptions = { - /** - * The id of the Producer to consume. - */ - producerId?: string; - - /** - * The id of the DataProducer to consume. - */ - dataProducerId?: string; - - /** - * Target Router instance. - */ - router: Router; - - /** - * Create a SCTP association. Default true. - */ - enableSctp?: boolean; - - /** - * SCTP streams number. - */ - numSctpStreams?: NumSctpStreams; - - /** - * Enable RTX and NACK for RTP retransmission. - */ - enableRtx?: boolean; - - /** - * Enable SRTP. - */ - enableSrtp?: boolean; -} & PipeToRouterListen; - -export type PipeToRouterResult = { - /** - * The Consumer created in the current Router. - */ - pipeConsumer?: Consumer; - - /** - * The Producer created in the target Router. - */ - pipeProducer?: Producer; - - /** - * The DataConsumer created in the current Router. - */ - pipeDataConsumer?: DataConsumer; - - /** - * The DataProducer created in the target Router. - */ - pipeDataProducer?: DataProducer; -}; - -export type RouterDump = { - /** - * The Router id. - */ - id: string; - /** - * Id of Transports. - */ - transportIds: string[]; - /** - * Id of RtpObservers. - */ - rtpObserverIds: string[]; - /** - * Array of Producer id and its respective Consumer ids. - */ - mapProducerIdConsumerIds: { key: string; values: string[] }[]; - /** - * Array of Consumer id and its Producer id. - */ - mapConsumerIdProducerId: { key: string; value: string }[]; - /** - * Array of Producer id and its respective Observer ids. - */ - mapProducerIdObserverIds: { key: string; values: string[] }[]; - /** - * Array of Producer id and its respective DataConsumer ids. - */ - mapDataProducerIdDataConsumerIds: { key: string; values: string[] }[]; - /** - * Array of DataConsumer id and its DataProducer id. - */ - mapDataConsumerIdDataProducerId: { key: string; value: string }[]; -}; - -type PipeTransportPair = { - [key: string]: PipeTransport; -}; - -export type RouterEvents = { - workerclose: []; - listenererror: [string, Error]; - // Private events. - '@close': []; -}; - -export type RouterObserver = EnhancedEventEmitter; - -export type RouterObserverEvents = { - close: []; - newtransport: [Transport]; - newrtpobserver: [RtpObserver]; -}; - export type RouterInternal = { routerId: string; }; @@ -216,9 +91,10 @@ type RouterData = { const logger = new Logger('Router'); -export class Router< - RouterAppData extends AppData = AppData, -> extends EnhancedEventEmitter { +export class RouterImpl + extends EnhancedEventEmitter + implements Router +{ // Internal data. readonly #internal: RouterInternal; @@ -257,9 +133,6 @@ export class Router< readonly #observer: RouterObserver = new EnhancedEventEmitter(); - /** - * @private - */ constructor({ internal, data, @@ -279,61 +152,43 @@ export class Router< this.#data = data; this.#channel = channel; this.#appData = appData ?? ({} as RouterAppData); + + this.handleListenerError(); } - /** - * Router id. - */ get id(): string { return this.#internal.routerId; } - /** - * Whether the Router is closed. - */ get closed(): boolean { return this.#closed; } - /** - * RTP capabilities of the Router. - */ get rtpCapabilities(): RtpCapabilities { return this.#data.rtpCapabilities; } - /** - * App custom data. - */ get appData(): RouterAppData { return this.#appData; } - /** - * App custom data setter. - */ set appData(appData: RouterAppData) { this.#appData = appData; } - /** - * Observer. - */ get observer(): RouterObserver { return this.#observer; } /** - * @private * Just for testing purposes. + * + * @private */ get transportsForTesting(): Map { return this.#transports; } - /** - * Close the Router. - */ close(): void { if (this.#closed) { return; @@ -379,11 +234,6 @@ export class Router< this.#observer.safeEmit('close'); } - /** - * Worker was closed. - * - * @private - */ workerClosed(): void { if (this.#closed) { return; @@ -417,9 +267,6 @@ export class Router< this.#observer.safeEmit('close'); } - /** - * Dump Router. - */ async dump(): Promise { logger.debug('dump()'); @@ -439,9 +286,6 @@ export class Router< return parseRouterDumpResponse(dump); } - /** - * Create a WebRtcTransport. - */ async createWebRtcTransport< WebRtcTransportAppData extends AppData = AppData, >({ @@ -538,7 +382,7 @@ export class Router< } } - const transportId = generateUUIDv4(); + const transportId = utils.generateUUIDv4(); /* Build Request. */ let webRtcTransportListenServer: @@ -628,7 +472,7 @@ export class Router< const webRtcTransportData = parseWebRtcTransportDumpResponse(data); const transport: WebRtcTransport = - new WebRtcTransport({ + new WebRtcTransportImpl({ internal: { ...this.#internal, transportId: transportId, @@ -673,9 +517,6 @@ export class Router< return transport; } - /** - * Create a PlainTransport. - */ async createPlainTransport({ listenInfo, rtcpListenInfo, @@ -729,7 +570,7 @@ export class Router< }; } - const transportId = generateUUIDv4(); + const transportId = utils.generateUUIDv4(); /* Build Request. */ const baseTransportOptions = new FbsTransport.OptionsT( @@ -799,8 +640,8 @@ export class Router< const plainTransportData = parsePlainTransportDumpResponse(data); - const transport: PlainTransport = new PlainTransport( - { + const transport: PlainTransport = + new PlainTransportImpl({ internal: { ...this.#internal, transportId: transportId, @@ -815,8 +656,7 @@ export class Router< getDataProducerById: ( dataProducerId: string ): DataProducer | undefined => this.#dataProducers.get(dataProducerId), - } - ); + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); @@ -842,9 +682,6 @@ export class Router< return transport; } - /** - * Create a PipeTransport. - */ async createPipeTransport({ listenInfo, listenIp, @@ -886,7 +723,7 @@ export class Router< }; } - const transportId = generateUUIDv4(); + const transportId = utils.generateUUIDv4(); /* Build Request. */ const baseTransportOptions = new FbsTransport.OptionsT( @@ -940,21 +777,23 @@ export class Router< const plainTransportData = parsePipeTransportDumpResponse(data); - const transport: PipeTransport = new PipeTransport({ - internal: { - ...this.#internal, - transportId, - }, - data: plainTransportData, - channel: this.#channel, - appData, - getRouterRtpCapabilities: (): RtpCapabilities => - this.#data.rtpCapabilities, - getProducerById: (producerId: string): Producer | undefined => - this.#producers.get(producerId), - getDataProducerById: (dataProducerId: string): DataProducer | undefined => - this.#dataProducers.get(dataProducerId), - }); + const transport: PipeTransport = + new PipeTransportImpl({ + internal: { + ...this.#internal, + transportId, + }, + data: plainTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: ( + dataProducerId: string + ): DataProducer | undefined => this.#dataProducers.get(dataProducerId), + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); @@ -980,9 +819,6 @@ export class Router< return transport; } - /** - * Create a DirectTransport. - */ async createDirectTransport( { maxMessageSize = 262144, @@ -999,7 +835,7 @@ export class Router< throw new TypeError('if given, appData must be an object'); } - const transportId = generateUUIDv4(); + const transportId = utils.generateUUIDv4(); /* Build Request. */ const baseTransportOptions = new FbsTransport.OptionsT( @@ -1036,7 +872,7 @@ export class Router< const directTransportData = parseDirectTransportDumpResponse(data); const transport: DirectTransport = - new DirectTransport({ + new DirectTransportImpl({ internal: { ...this.#internal, transportId: transportId, @@ -1077,9 +913,6 @@ export class Router< return transport; } - /** - * Pipes the given Producer or DataProducer into another Router in same host. - */ async pipeToRouter({ producerId, dataProducerId, @@ -1340,9 +1173,6 @@ export class Router< } } - /** - * @private - */ addPipeTransportPair( pipeTransportPairKey: string, pipeTransportPairPromise: Promise @@ -1377,9 +1207,6 @@ export class Router< }); } - /** - * Create an ActiveSpeakerObserver - */ async createActiveSpeakerObserver< ActiveSpeakerObserverAppData extends AppData = AppData, >({ @@ -1396,7 +1223,7 @@ export class Router< throw new TypeError('if given, appData must be an object'); } - const rtpObserverId = generateUUIDv4(); + const rtpObserverId = utils.generateUUIDv4(); /* Build Request. */ const activeRtpObserverOptions = @@ -1415,7 +1242,7 @@ export class Router< ); const activeSpeakerObserver: ActiveSpeakerObserver = - new ActiveSpeakerObserver({ + new ActiveSpeakerObserverImpl({ internal: { ...this.#internal, rtpObserverId: rtpObserverId, @@ -1437,9 +1264,6 @@ export class Router< return activeSpeakerObserver; } - /** - * Create an AudioLevelObserver. - */ async createAudioLevelObserver< AudioLevelObserverAppData extends AppData = AppData, >({ @@ -1468,7 +1292,7 @@ export class Router< throw new TypeError('if given, appData must be an object'); } - const rtpObserverId = generateUUIDv4(); + const rtpObserverId = utils.generateUUIDv4(); /* Build Request. */ const audioLevelObserverOptions = @@ -1491,7 +1315,7 @@ export class Router< ); const audioLevelObserver: AudioLevelObserver = - new AudioLevelObserver({ + new AudioLevelObserverImpl({ internal: { ...this.#internal, rtpObserverId: rtpObserverId, @@ -1513,9 +1337,6 @@ export class Router< return audioLevelObserver; } - /** - * Check whether the given RTP capabilities can consume the given Producer. - */ canConsume({ producerId, rtpCapabilities, @@ -1532,7 +1353,7 @@ export class Router< } // Clone given RTP capabilities to not modify input data. - const clonedRtpCapabilities = clone(rtpCapabilities); + const clonedRtpCapabilities = utils.clone(rtpCapabilities); try { return ortc.canConsume( @@ -1545,6 +1366,15 @@ export class Router< return false; } } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } export function parseRouterDumpResponse( @@ -1552,25 +1382,25 @@ export function parseRouterDumpResponse( ): RouterDump { return { id: binary.id()!, - transportIds: parseVector(binary, 'transportIds'), - rtpObserverIds: parseVector(binary, 'rtpObserverIds'), - mapProducerIdConsumerIds: parseStringStringArrayVector( + transportIds: fbsUtils.parseVector(binary, 'transportIds'), + rtpObserverIds: fbsUtils.parseVector(binary, 'rtpObserverIds'), + mapProducerIdConsumerIds: fbsUtils.parseStringStringArrayVector( binary, 'mapProducerIdConsumerIds' ), - mapConsumerIdProducerId: parseStringStringVector( + mapConsumerIdProducerId: fbsUtils.parseStringStringVector( binary, 'mapConsumerIdProducerId' ), - mapProducerIdObserverIds: parseStringStringArrayVector( + mapProducerIdObserverIds: fbsUtils.parseStringStringArrayVector( binary, 'mapProducerIdObserverIds' ), - mapDataProducerIdDataConsumerIds: parseStringStringArrayVector( + mapDataProducerIdDataConsumerIds: fbsUtils.parseStringStringArrayVector( binary, 'mapDataProducerIdDataConsumerIds' ), - mapDataConsumerIdDataProducerId: parseStringStringVector( + mapDataConsumerIdDataProducerId: fbsUtils.parseStringStringVector( binary, 'mapDataConsumerIdDataProducerId' ), diff --git a/node/src/RouterTypes.ts b/node/src/RouterTypes.ts new file mode 100644 index 0000000000..5a7db9be1e --- /dev/null +++ b/node/src/RouterTypes.ts @@ -0,0 +1,291 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { + Transport, + TransportListenInfo, + TransportListenIp, +} from './TransportTypes'; +import type { + WebRtcTransport, + WebRtcTransportOptions, +} from './WebRtcTransportTypes'; +import type { + PlainTransport, + PlainTransportOptions, +} from './PlainTransportTypes'; +import type { PipeTransport, PipeTransportOptions } from './PipeTransportTypes'; +import type { + DirectTransport, + DirectTransportOptions, +} from './DirectTransportTypes'; +import type { Producer } from './ProducerTypes'; +import type { Consumer } from './ConsumerTypes'; +import type { DataProducer } from './DataProducerTypes'; +import type { DataConsumer } from './DataConsumerTypes'; +import type { RtpObserver } from './RtpObserverTypes'; +import type { + ActiveSpeakerObserver, + ActiveSpeakerObserverOptions, +} from './ActiveSpeakerObserverTypes'; +import type { + AudioLevelObserver, + AudioLevelObserverOptions, +} from './AudioLevelObserverTypes'; +import type { RtpCapabilities, RtpCodecCapability } from './rtpParametersTypes'; +import type { NumSctpStreams } from './sctpParametersTypes'; +import type { Either, AppData } from './types'; + +export type RouterOptions = { + /** + * Router media codecs. + */ + mediaCodecs?: RtpCodecCapability[]; + + /** + * Custom application data. + */ + appData?: RouterAppData; +}; + +export type PipeToRouterOptions = { + /** + * The id of the Producer to consume. + */ + producerId?: string; + + /** + * The id of the DataProducer to consume. + */ + dataProducerId?: string; + + /** + * Target Router instance. + */ + router: Router; + + /** + * Create a SCTP association. Default true. + */ + enableSctp?: boolean; + + /** + * SCTP streams number. + */ + numSctpStreams?: NumSctpStreams; + + /** + * Enable RTX and NACK for RTP retransmission. + */ + enableRtx?: boolean; + + /** + * Enable SRTP. + */ + enableSrtp?: boolean; +} & PipeToRouterListen; + +type PipeToRouterListen = Either; + +type PipeToRouterListenInfo = { + listenInfo: TransportListenInfo; +}; + +type PipeToRouterListenIp = { + /** + * IP used in the PipeTransport pair. Default '127.0.0.1'. + */ + listenIp?: TransportListenIp | string; +}; + +export type PipeToRouterResult = { + /** + * The Consumer created in the current Router. + */ + pipeConsumer?: Consumer; + + /** + * The Producer created in the target Router. + */ + pipeProducer?: Producer; + + /** + * The DataConsumer created in the current Router. + */ + pipeDataConsumer?: DataConsumer; + + /** + * The DataProducer created in the target Router. + */ + pipeDataProducer?: DataProducer; +}; + +export type PipeTransportPair = { + [key: string]: PipeTransport; +}; + +export type RouterDump = { + /** + * The Router id. + */ + id: string; + /** + * Id of Transports. + */ + transportIds: string[]; + /** + * Id of RtpObservers. + */ + rtpObserverIds: string[]; + /** + * Array of Producer id and its respective Consumer ids. + */ + mapProducerIdConsumerIds: { key: string; values: string[] }[]; + /** + * Array of Consumer id and its Producer id. + */ + mapConsumerIdProducerId: { key: string; value: string }[]; + /** + * Array of Producer id and its respective Observer ids. + */ + mapProducerIdObserverIds: { key: string; values: string[] }[]; + /** + * Array of Producer id and its respective DataConsumer ids. + */ + mapDataProducerIdDataConsumerIds: { key: string; values: string[] }[]; + /** + * Array of DataConsumer id and its DataProducer id. + */ + mapDataConsumerIdDataProducerId: { key: string; value: string }[]; +}; + +export type RouterEvents = { + workerclose: []; + listenererror: [string, Error]; + // Private events. + '@close': []; +}; + +export type RouterObserver = EnhancedEventEmitter; + +export type RouterObserverEvents = { + close: []; + newtransport: [Transport]; + newrtpobserver: [RtpObserver]; +}; + +export interface Router + extends EnhancedEventEmitter { + /** + * Router id. + */ + get id(): string; + + /** + * Whether the Router is closed. + */ + get closed(): boolean; + + /** + * RTP capabilities of the Router. + */ + get rtpCapabilities(): RtpCapabilities; + + /** + * App custom data. + */ + get appData(): RouterAppData; + + /** + * App custom data setter. + */ + set appData(appData: RouterAppData); + + /** + * Observer. + */ + get observer(): RouterObserver; + + /** + * Close the Router. + */ + close(): void; + + /** + * Worker was closed. + * + * @private + */ + workerClosed(): void; + + /** + * Dump Router. + */ + dump(): Promise; + + /** + * Create a WebRtcTransport. + */ + createWebRtcTransport( + options: WebRtcTransportOptions + ): Promise>; + + /** + * Create a PlainTransport. + */ + createPlainTransport( + options: PlainTransportOptions + ): Promise>; + + /** + * Create a PipeTransport. + */ + createPipeTransport( + options: PipeTransportOptions + ): Promise>; + + /** + * Create a DirectTransport. + */ + createDirectTransport( + options?: DirectTransportOptions + ): Promise>; + + /** + * Pipes the given Producer or DataProducer into another Router in same host. + */ + pipeToRouter(options: PipeToRouterOptions): Promise; + + /** + * @private + */ + addPipeTransportPair( + pipeTransportPairKey: string, + pipeTransportPairPromise: Promise + ): void; + + /** + * Create an ActiveSpeakerObserver + */ + createActiveSpeakerObserver< + ActiveSpeakerObserverAppData extends AppData = AppData, + >( + options?: ActiveSpeakerObserverOptions + ): Promise>; + + /** + * Create an AudioLevelObserver. + */ + createAudioLevelObserver( + options?: AudioLevelObserverOptions + ): Promise>; + + /** + * Check whether the given RTP capabilities can consume the given Producer. + */ + canConsume({ + producerId, + rtpCapabilities, + }: { + producerId: string; + rtpCapabilities: RtpCapabilities; + }): boolean; +} diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index a64abc3747..ec42cedc6d 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -1,31 +1,17 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; -import { Channel } from './Channel'; -import { RouterInternal } from './Router'; -import { Producer } from './Producer'; -import { AppData } from './types'; +import type { + RtpObserverEvents, + RtpObserverObserver, +} from './RtpObserverTypes'; +import type { Channel } from './Channel'; +import type { RouterInternal } from './Router'; +import type { Producer } from './ProducerTypes'; +import type { AppData } from './types'; import * as FbsRequest from './fbs/request'; import * as FbsRouter from './fbs/router'; import * as FbsRtpObserver from './fbs/rtp-observer'; -export type RtpObserverEvents = { - routerclose: []; - listenererror: [string, Error]; - // Private events. - '@close': []; -}; - -export type RtpObserverObserver = - EnhancedEventEmitter; - -export type RtpObserverObserverEvents = { - close: []; - pause: []; - resume: []; - addproducer: [Producer]; - removeproducer: [Producer]; -}; - export type RtpObserverConstructorOptions = { internal: RtpObserverObserverInternal; channel: Channel; @@ -33,20 +19,13 @@ export type RtpObserverConstructorOptions = { getProducerById: (producerId: string) => Producer | undefined; }; -export type RtpObserverObserverInternal = RouterInternal & { +type RtpObserverObserverInternal = RouterInternal & { rtpObserverId: string; }; const logger = new Logger('RtpObserver'); -export type RtpObserverAddRemoveProducerOptions = { - /** - * The id of the Producer to be added or removed. - */ - producerId: string; -}; - -export abstract class RtpObserver< +export abstract class RtpObserverImpl< RtpObserverAppData extends AppData = AppData, Events extends RtpObserverEvents = RtpObserverEvents, Observer extends RtpObserverObserver = RtpObserverObserver, @@ -74,10 +53,6 @@ export abstract class RtpObserver< // Observer instance. readonly #observer: Observer; - /** - * @private - * @interface - */ constructor( { internal, @@ -98,51 +73,30 @@ export abstract class RtpObserver< this.#observer = observer; } - /** - * RtpObserver id. - */ get id(): string { return this.internal.rtpObserverId; } - /** - * Whether the RtpObserver is closed. - */ get closed(): boolean { return this.#closed; } - /** - * Whether the RtpObserver is paused. - */ get paused(): boolean { return this.#paused; } - /** - * App custom data. - */ get appData(): RtpObserverAppData { return this.#appData; } - /** - * App custom data setter. - */ set appData(appData: RtpObserverAppData) { this.#appData = appData; } - /** - * Observer. - */ get observer(): Observer { return this.#observer; } - /** - * Close the RtpObserver. - */ close(): void { if (this.#closed) { return; @@ -175,11 +129,6 @@ export abstract class RtpObserver< this.#observer.safeEmit('close'); } - /** - * Router was closed. - * - * @private - */ routerClosed(): void { if (this.#closed) { return; @@ -198,9 +147,6 @@ export abstract class RtpObserver< this.#observer.safeEmit('close'); } - /** - * Pause the RtpObserver. - */ async pause(): Promise { logger.debug('pause()'); @@ -221,9 +167,6 @@ export abstract class RtpObserver< } } - /** - * Resume the RtpObserver. - */ async resume(): Promise { logger.debug('resume()'); @@ -244,12 +187,7 @@ export abstract class RtpObserver< } } - /** - * Add a Producer to the RtpObserver. - */ - async addProducer({ - producerId, - }: RtpObserverAddRemoveProducerOptions): Promise { + async addProducer({ producerId }: { producerId: string }): Promise { logger.debug('addProducer()'); const producer = this.getProducerById(producerId); @@ -273,12 +211,7 @@ export abstract class RtpObserver< this.#observer.safeEmit('addproducer', producer); } - /** - * Remove a Producer from the RtpObserver. - */ - async removeProducer({ - producerId, - }: RtpObserverAddRemoveProducerOptions): Promise { + async removeProducer({ producerId }: { producerId: string }): Promise { logger.debug('removeProducer()'); const producer = this.getProducerById(producerId); diff --git a/node/src/RtpObserverTypes.ts b/node/src/RtpObserverTypes.ts new file mode 100644 index 0000000000..4e04f9d056 --- /dev/null +++ b/node/src/RtpObserverTypes.ts @@ -0,0 +1,105 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { Producer } from './ProducerTypes'; +import type { AppData } from './types'; + +/** + * RtpObserver type. + */ +export type RtpObserverType = 'audiolevel' | 'activespeaker'; + +export type RtpObserverEvents = { + routerclose: []; + listenererror: [string, Error]; + // Private events. + '@close': []; +}; + +export type RtpObserverObserver = + EnhancedEventEmitter; + +export type RtpObserverObserverEvents = { + close: []; + pause: []; + resume: []; + addproducer: [Producer]; + removeproducer: [Producer]; +}; + +export interface RtpObserver< + RtpObserverAppData extends AppData = AppData, + Events extends RtpObserverEvents = RtpObserverEvents, + Observer extends RtpObserverObserver = RtpObserverObserver, +> extends EnhancedEventEmitter { + /** + * RtpObserver id. + */ + get id(): string; + + /** + * Whether the RtpObserver is closed. + */ + get closed(): boolean; + + /** + * RtpObserver type. + * + * @virtual + * @privateRemarks + * - It's marked as virtual getter since each RtpObserver class overrides it. + */ + get type(): RtpObserverType; + + /** + * Whether the RtpObserver is paused. + */ + get paused(): boolean; + + /** + * App custom data. + */ + get appData(): RtpObserverAppData; + + /** + * App custom data setter. + */ + set appData(appData: RtpObserverAppData); + + /** + * Observer. + * + * @virtual + */ + get observer(): Observer; + + /** + * Close the RtpObserver. + */ + close(): void; + + /** + * Router was closed. + * + * @private + */ + routerClosed(): void; + + /** + * Pause the RtpObserver. + */ + pause(): Promise; + + /** + * Resume the RtpObserver. + */ + resume(): Promise; + + /** + * Add a Producer to the RtpObserver. + */ + addProducer({ producerId }: { producerId: string }): Promise; + + /** + * Remove a Producer from the RtpObserver. + */ + removeProducer({ producerId }: { producerId: string }): Promise; +} diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 7448e8a438..7bbc28f4dd 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -2,53 +2,83 @@ import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; -import { Channel } from './Channel'; -import { RouterInternal } from './Router'; -import { WebRtcTransportData } from './WebRtcTransport'; -import { PlainTransportData } from './PlainTransport'; -import { PipeTransportData } from './PipeTransport'; -import { DirectTransportData } from './DirectTransport'; +import type { + Transport, + TransportType, + TransportProtocol, + TransportPortRange, + TransportSocketFlags, + TransportTuple, + SctpState, + RtpListenerDump, + SctpListenerDump, + RecvRtpHeaderExtensions, + BaseTransportDump, + BaseTransportStats, + TransportTraceEventType, + TransportTraceEventData, + TransportEvents, + TransportObserver, +} from './TransportTypes'; +import type { Channel } from './Channel'; +import type { RouterInternal } from './Router'; +import type { WebRtcTransportData } from './WebRtcTransport'; +import type { PlainTransportData } from './PlainTransport'; +import type { PipeTransportData } from './PipeTransport'; +import type { DirectTransportData } from './DirectTransport'; +import type { Producer, ProducerOptions } from './ProducerTypes'; import { - Producer, - ProducerOptions, + ProducerImpl, producerTypeFromFbs, producerTypeToFbs, } from './Producer'; -import { +import type { Consumer, ConsumerOptions, ConsumerType, ConsumerLayers, -} from './Consumer'; -import { +} from './ConsumerTypes'; +import { ConsumerImpl } from './Consumer'; +import type { DataProducer, DataProducerOptions, DataProducerType, +} from './DataProducerTypes'; +import { + DataProducerImpl, dataProducerTypeToFbs, parseDataProducerDumpResponse, } from './DataProducer'; -import { +import type { DataConsumer, DataConsumerOptions, DataConsumerType, +} from './DataConsumerTypes'; +import { + DataConsumerImpl, dataConsumerTypeToFbs, parseDataConsumerDumpResponse, } from './DataConsumer'; -import { +import type { MediaKind, RtpCapabilities, RtpParameters, +} from './rtpParametersTypes'; +import { serializeRtpEncodingParameters, serializeRtpParameters, -} from './RtpParameters'; +} from './rtpParametersFbsUtils'; +import type { + SctpParameters, + SctpStreamParameters, +} from './sctpParametersTypes'; import { parseSctpParametersDump, serializeSctpStreamParameters, - SctpParameters, - SctpStreamParameters, -} from './SctpParameters'; -import { AppData } from './types'; +} from './sctpParametersFbsUtils'; +import type { AppData } from './types'; import * as utils from './utils'; +import * as fbsUtils from './fbsUtils'; import { TraceDirection as FbsTraceDirection } from './fbs/common'; import * as FbsRequest from './fbs/request'; import { MediaKind as FbsMediaKind } from './fbs/rtp-parameters/media-kind'; @@ -60,180 +90,6 @@ import * as FbsRouter from './fbs/router'; import * as FbsRtpParameters from './fbs/rtp-parameters'; import { SctpState as FbsSctpState } from './fbs/sctp-association/sctp-state'; -export type TransportListenInfo = { - /** - * Network protocol. - */ - protocol: TransportProtocol; - - /** - * Listening IPv4 or IPv6. - */ - ip: string; - - /** - * @deprecated Use |announcedAddress| instead. - * - * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT - * with private IP). - */ - announcedIp?: string; - - /** - * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT - * with private IP). - */ - announcedAddress?: string; - - /** - * Listening port. - */ - port?: number; - - /** - * Listening port range. If given then |port| will be ignored. - */ - portRange?: TransportPortRange; - - /** - * Socket flags. - */ - flags?: TransportSocketFlags; - - /** - * Send buffer size (bytes). - */ - sendBufferSize?: number; - - /** - * Recv buffer size (bytes). - */ - recvBufferSize?: number; -}; - -/** - * Use TransportListenInfo instead. - * @deprecated - */ -export type TransportListenIp = { - /** - * Listening IPv4 or IPv6. - */ - ip: string; - - /** - * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT - * with private IP). - */ - announcedIp?: string; -}; - -/** - * Transport protocol. - */ -export type TransportProtocol = 'udp' | 'tcp'; - -/** - * Port range.. - */ -export type TransportPortRange = { - /** - * Lowest port in the range. - */ - min: number; - /** - * Highest port in the range. - */ - max: number; -}; - -/** - * UDP/TCP socket flags. - */ -export type TransportSocketFlags = { - /** - * Disable dual-stack support so only IPv6 is used (only if |ip| is IPv6). - */ - ipv6Only?: boolean; - /** - * Make different transports bind to the same IP and port (only for UDP). - * Useful for multicast scenarios with plain transport. Use with caution. - */ - udpReusePort?: boolean; -}; - -export type TransportTuple = { - // @deprecated Use localAddress instead. - localIp: string; - localAddress: string; - localPort: number; - remoteIp?: string; - remotePort?: number; - protocol: TransportProtocol; -}; - -/** - * Valid types for 'trace' event. - */ -export type TransportTraceEventType = 'probation' | 'bwe'; - -/** - * 'trace' event data. - */ -export type TransportTraceEventData = { - /** - * Trace type. - */ - type: TransportTraceEventType; - - /** - * Event timestamp. - */ - timestamp: number; - - /** - * Event direction. - */ - direction: 'in' | 'out'; - - /** - * Per type information. - */ - info: any; -}; - -export type SctpState = - | 'new' - | 'connecting' - | 'connected' - | 'failed' - | 'closed'; - -export type TransportEvents = { - routerclose: []; - listenserverclose: []; - trace: [TransportTraceEventData]; - listenererror: [string, Error]; - // Private events. - '@close': []; - '@newproducer': [Producer]; - '@producerclose': [Producer]; - '@newdataproducer': [DataProducer]; - '@dataproducerclose': [DataProducer]; - '@listenserverclose': []; -}; - -export type TransportObserver = EnhancedEventEmitter; - -export type TransportObserverEvents = { - close: []; - newproducer: [Producer]; - newconsumer: [Consumer]; - newdataproducer: [DataProducer]; - newdataconsumer: [DataConsumer]; - trace: [TransportTraceEventData]; -}; - export type TransportConstructorOptions = { internal: TransportInternal; data: TransportData; @@ -248,82 +104,22 @@ export type TransportInternal = RouterInternal & { transportId: string; }; -export type BaseTransportDump = { - id: string; - direct: boolean; - producerIds: string[]; - consumerIds: string[]; - mapSsrcConsumerId: { key: number; value: string }[]; - mapRtxSsrcConsumerId: { key: number; value: string }[]; - recvRtpHeaderExtensions: RecvRtpHeaderExtensions; - rtpListener: RtpListenerDump; - maxMessageSize: number; - dataProducerIds: string[]; - dataConsumerIds: string[]; - sctpParameters?: SctpParameters; - sctpState?: SctpState; - sctpListener?: SctpListenerDump; - traceEventTypes?: string[]; -}; - -export type BaseTransportStats = { - transportId: string; - timestamp: number; - sctpState?: SctpState; - bytesReceived: number; - recvBitrate: number; - bytesSent: number; - sendBitrate: number; - rtpBytesReceived: number; - rtpRecvBitrate: number; - rtpBytesSent: number; - rtpSendBitrate: number; - rtxBytesReceived: number; - rtxRecvBitrate: number; - rtxBytesSent: number; - rtxSendBitrate: number; - probationBytesSent: number; - probationSendBitrate: number; - availableOutgoingBitrate?: number; - availableIncomingBitrate?: number; - maxIncomingBitrate?: number; - maxOutgoingBitrate?: number; - minOutgoingBitrate?: number; - rtpPacketLossReceived?: number; - rtpPacketLossSent?: number; -}; - type TransportData = | WebRtcTransportData | PlainTransportData | PipeTransportData | DirectTransportData; -type RtpListenerDump = { - ssrcTable: { key: number; value: string }[]; - midTable: { key: number; value: string }[]; - ridTable: { key: number; value: string }[]; -}; - -type SctpListenerDump = { - streamIdTable: { key: number; value: string }[]; -}; - -type RecvRtpHeaderExtensions = { - mid?: number; - rid?: number; - rrid?: number; - absSendTime?: number; - transportWideCc01?: number; -}; - const logger = new Logger('Transport'); -export abstract class Transport< - TransportAppData extends AppData = AppData, - Events extends TransportEvents = TransportEvents, - Observer extends TransportObserver = TransportObserver, -> extends EnhancedEventEmitter { +export abstract class TransportImpl< + TransportAppData extends AppData = AppData, + Events extends TransportEvents = TransportEvents, + Observer extends TransportObserver = TransportObserver, + > + extends EnhancedEventEmitter + implements Transport +{ // Internal data. protected readonly internal: TransportInternal; @@ -379,10 +175,6 @@ export abstract class Transport< // Observer instance. readonly #observer: Observer; - /** - * @private - * @interface - */ constructor( { internal, @@ -409,52 +201,35 @@ export abstract class Transport< this.#observer = observer; } - /** - * Transport id. - */ get id(): string { return this.internal.transportId; } - /** - * Whether the Transport is closed. - */ get closed(): boolean { return this.#closed; } - /** - * App custom data. - */ + abstract get type(): TransportType; + get appData(): TransportAppData { return this.#appData; } - /** - * App custom data setter. - */ set appData(appData: TransportAppData) { this.#appData = appData; } - /** - * Observer. - */ get observer(): Observer { return this.#observer; } /** - * @private * Just for testing purposes. */ get channelForTesting(): Channel { return this.channel; } - /** - * Close the Transport. - */ close(): void { if (this.#closed) { return; @@ -517,12 +292,6 @@ export abstract class Transport< this.#observer.safeEmit('close'); } - /** - * Router was closed. - * - * @private - * @virtual - */ routerClosed(): void { if (this.#closed) { return; @@ -571,12 +340,6 @@ export abstract class Transport< this.#observer.safeEmit('close'); } - /** - * Listen server was closed (this just happens in WebRtcTransports when their - * associated WebRtcServer is closed). - * - * @private - */ listenServerClosed(): void { if (this.#closed) { return; @@ -630,42 +393,12 @@ export abstract class Transport< this.#observer.safeEmit('close'); } - /** - * Dump Transport. - * - * @abstract - */ - // eslint-disable-next-line @typescript-eslint/require-await - async dump(): Promise { - // Should not happen. - throw new Error('method implemented in the subclass'); - } + abstract dump(): Promise; - /** - * Get Transport stats. - * - * @abstract - */ - // eslint-disable-next-line @typescript-eslint/require-await - async getStats(): Promise { - // Should not happen. - throw new Error('method implemented in the subclass'); - } + abstract getStats(): Promise; - /** - * Provide the Transport remote parameters. - * - * @abstract - */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await - async connect(params: any): Promise { - // Should not happen. - throw new Error('method implemented in the subclass'); - } + abstract connect(params: any): Promise; - /** - * Set maximum incoming bitrate for receiving media. - */ async setMaxIncomingBitrate(bitrate: number): Promise { logger.debug(`setMaxIncomingBitrate() [bitrate:${bitrate}]`); @@ -684,9 +417,6 @@ export abstract class Transport< ); } - /** - * Set maximum outgoing bitrate for sending media. - */ async setMaxOutgoingBitrate(bitrate: number): Promise { logger.debug(`setMaxOutgoingBitrate() [bitrate:${bitrate}]`); @@ -703,9 +433,6 @@ export abstract class Transport< ); } - /** - * Set minimum outgoing bitrate for sending media. - */ async setMinOutgoingBitrate(bitrate: number): Promise { logger.debug(`setMinOutgoingBitrate() [bitrate:${bitrate}]`); @@ -722,9 +449,6 @@ export abstract class Transport< ); } - /** - * Create a Producer. - */ async produce({ id = undefined, kind, @@ -760,7 +484,7 @@ export abstract class Transport< // Don't do this in PipeTransports since there we must keep CNAME value in // each Producer. - if (this.constructor.name !== 'PipeTransport') { + if (this.type !== 'pipe') { // If CNAME is given and we don't have yet a CNAME for Producers in this // Transport, take it. if (!this.#cnameForProducers && clonedRtpParameters.rtcp?.cname) { @@ -825,7 +549,7 @@ export abstract class Transport< consumableRtpParameters, }; - const producer: Producer = new Producer({ + const producer: Producer = new ProducerImpl({ internal: { ...this.internal, producerId, @@ -850,11 +574,6 @@ export abstract class Transport< return producer; } - /** - * Create a Consumer. - * - * @virtual - */ async consume({ producerId, rtpCapabilities, @@ -952,7 +671,7 @@ export abstract class Transport< type: pipe ? 'pipe' : (producer.type as ConsumerType), }; - const consumer: Consumer = new Consumer({ + const consumer: Consumer = new ConsumerImpl({ internal: { ...this.internal, consumerId, @@ -981,9 +700,6 @@ export abstract class Transport< return consumer; } - /** - * Create a DataProducer. - */ async produceData({ id = undefined, sctpStreamParameters, @@ -1010,7 +726,7 @@ export abstract class Transport< >(sctpStreamParameters); // If this is not a DirectTransport, sctpStreamParameters are required. - if (this.constructor.name !== 'DirectTransport') { + if (this.type !== 'direct') { type = 'sctp'; // This may throw. @@ -1054,21 +770,22 @@ export abstract class Transport< const dump = parseDataProducerDumpResponse(produceDataResponse); - const dataProducer: DataProducer = new DataProducer({ - internal: { - ...this.internal, - dataProducerId, - }, - data: { - type: dump.type, - sctpStreamParameters: dump.sctpStreamParameters, - label: dump.label, - protocol: dump.protocol, - }, - channel: this.channel, - paused, - appData, - }); + const dataProducer: DataProducer = + new DataProducerImpl({ + internal: { + ...this.internal, + dataProducerId, + }, + data: { + type: dump.type, + sctpStreamParameters: dump.sctpStreamParameters, + label: dump.label, + protocol: dump.protocol, + }, + channel: this.channel, + paused, + appData, + }); this.dataProducers.set(dataProducer.id, dataProducer); dataProducer.on('@close', () => { @@ -1084,9 +801,6 @@ export abstract class Transport< return dataProducer; } - /** - * Create a DataConsumer. - */ async consumeData({ dataProducerId, ordered, @@ -1118,7 +832,7 @@ export abstract class Transport< // If this is not a DirectTransport, use sctpStreamParameters from the // DataProducer (if type 'sctp') unless they are given in method parameters. - if (this.constructor.name !== 'DirectTransport') { + if (this.type !== 'direct') { type = 'sctp'; sctpStreamParameters = @@ -1189,25 +903,26 @@ export abstract class Transport< const dump = parseDataConsumerDumpResponse(consumeDataResponse); - const dataConsumer: DataConsumer = new DataConsumer({ - internal: { - ...this.internal, - dataConsumerId, - }, - data: { - dataProducerId: dump.dataProducerId, - type: dump.type, - sctpStreamParameters: dump.sctpStreamParameters, - label: dump.label, - protocol: dump.protocol, - bufferedAmountLowThreshold: dump.bufferedAmountLowThreshold, - }, - channel: this.channel, - paused: dump.paused, - subchannels: dump.subchannels, - dataProducerPaused: dump.dataProducerPaused, - appData, - }); + const dataConsumer: DataConsumer = + new DataConsumerImpl({ + internal: { + ...this.internal, + dataConsumerId, + }, + data: { + dataProducerId: dump.dataProducerId, + type: dump.type, + sctpStreamParameters: dump.sctpStreamParameters, + label: dump.label, + protocol: dump.protocol, + bufferedAmountLowThreshold: dump.bufferedAmountLowThreshold, + }, + channel: this.channel, + paused: dump.paused, + subchannels: dump.subchannels, + dataProducerPaused: dump.dataProducerPaused, + appData, + }); this.dataConsumers.set(dataConsumer.id, dataConsumer); dataConsumer.on('@close', () => { @@ -1231,9 +946,6 @@ export abstract class Transport< return dataConsumer; } - /** - * Enable 'trace' event. - */ async enableTraceEvent(types: TransportTraceEventType[] = []): Promise { logger.debug('enableTraceEvent()'); @@ -1381,23 +1093,29 @@ export function parseBaseTransportDump( binary: FbsTransport.Dump ): BaseTransportDump { // Retrieve producerIds. - const producerIds = utils.parseVector(binary, 'producerIds'); + const producerIds = fbsUtils.parseVector(binary, 'producerIds'); // Retrieve consumerIds. - const consumerIds = utils.parseVector(binary, 'consumerIds'); + const consumerIds = fbsUtils.parseVector(binary, 'consumerIds'); // Retrieve map SSRC consumerId. - const mapSsrcConsumerId = utils.parseUint32StringVector( + const mapSsrcConsumerId = fbsUtils.parseUint32StringVector( binary, 'mapSsrcConsumerId' ); // Retrieve map RTX SSRC consumerId. - const mapRtxSsrcConsumerId = utils.parseUint32StringVector( + const mapRtxSsrcConsumerId = fbsUtils.parseUint32StringVector( binary, 'mapRtxSsrcConsumerId' ); // Retrieve dataProducerIds. - const dataProducerIds = utils.parseVector(binary, 'dataProducerIds'); + const dataProducerIds = fbsUtils.parseVector( + binary, + 'dataProducerIds' + ); // Retrieve dataConsumerIds. - const dataConsumerIds = utils.parseVector(binary, 'dataConsumerIds'); + const dataConsumerIds = fbsUtils.parseVector( + binary, + 'dataConsumerIds' + ); // Retrieve recvRtpHeaderExtesions. const recvRtpHeaderExtensions = parseRecvRtpHeaderExtensions( binary.recvRtpHeaderExtensions()! @@ -1425,7 +1143,7 @@ export function parseBaseTransportDump( : undefined; // Retrieve traceEventTypes. - const traceEventTypes = utils.parseVector( + const traceEventTypes = fbsUtils.parseVector( binary, 'traceEventTypes', transportTraceEventTypeFromFbs @@ -1433,7 +1151,6 @@ export function parseBaseTransportDump( return { id: binary.id()!, - direct: binary.direct(), producerIds: producerIds, consumerIds: consumerIds, mapSsrcConsumerId: mapSsrcConsumerId, @@ -1703,7 +1420,7 @@ function createProduceRequest({ producerId: string; kind: MediaKind; rtpParameters: RtpParameters; - rtpMapping: ortc.RtpMapping; + rtpMapping: ortc.RtpCodecsEncodingsMapping; keyFrameRequestDelay?: number; paused: boolean; }): number { @@ -1850,11 +1567,11 @@ function parseRtpListenerDump( binary: FbsTransport.RtpListener ): RtpListenerDump { // Retrieve ssrcTable. - const ssrcTable = utils.parseUint32StringVector(binary, 'ssrcTable'); + const ssrcTable = fbsUtils.parseUint32StringVector(binary, 'ssrcTable'); // Retrieve midTable. - const midTable = utils.parseUint32StringVector(binary, 'midTable'); + const midTable = fbsUtils.parseUint32StringVector(binary, 'midTable'); // Retrieve ridTable. - const ridTable = utils.parseUint32StringVector(binary, 'ridTable'); + const ridTable = fbsUtils.parseUint32StringVector(binary, 'ridTable'); return { ssrcTable, @@ -1867,7 +1584,10 @@ function parseSctpListenerDump( binary: FbsTransport.SctpListener ): SctpListenerDump { // Retrieve streamIdTable. - const streamIdTable = utils.parseUint32StringVector(binary, 'streamIdTable'); + const streamIdTable = fbsUtils.parseUint32StringVector( + binary, + 'streamIdTable' + ); return { streamIdTable }; } diff --git a/node/src/TransportTypes.ts b/node/src/TransportTypes.ts new file mode 100644 index 0000000000..26aac8cbd5 --- /dev/null +++ b/node/src/TransportTypes.ts @@ -0,0 +1,399 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { Producer, ProducerOptions } from './ProducerTypes'; +import type { Consumer, ConsumerOptions } from './ConsumerTypes'; +import type { DataProducer, DataProducerOptions } from './DataProducerTypes'; +import type { DataConsumer, DataConsumerOptions } from './DataConsumerTypes'; +import type { SctpParameters } from './sctpParametersTypes'; +import type { AppData } from './types'; + +/** + * Transport type. + */ +export type TransportType = 'webrtc' | 'plain' | 'pipe' | 'direct'; + +export type TransportListenInfo = { + /** + * Network protocol. + */ + protocol: TransportProtocol; + + /** + * Listening IPv4 or IPv6. + */ + ip: string; + + /** + * @deprecated Use |announcedAddress| instead. + * + * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT + * with private IP). + */ + announcedIp?: string; + + /** + * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT + * with private IP). + */ + announcedAddress?: string; + + /** + * Listening port. + */ + port?: number; + + /** + * Listening port range. If given then |port| will be ignored. + */ + portRange?: TransportPortRange; + + /** + * Socket flags. + */ + flags?: TransportSocketFlags; + + /** + * Send buffer size (bytes). + */ + sendBufferSize?: number; + + /** + * Recv buffer size (bytes). + */ + recvBufferSize?: number; +}; + +/** + * Use TransportListenInfo instead. + * @deprecated + */ +export type TransportListenIp = { + /** + * Listening IPv4 or IPv6. + */ + ip: string; + + /** + * Announced IPv4, IPv6 or hostname (useful when running mediasoup behind NAT + * with private IP). + */ + announcedIp?: string; +}; + +/** + * Transport protocol. + */ +export type TransportProtocol = 'udp' | 'tcp'; + +/** + * Port range.. + */ +export type TransportPortRange = { + /** + * Lowest port in the range. + */ + min: number; + /** + * Highest port in the range. + */ + max: number; +}; + +/** + * UDP/TCP socket flags. + */ +export type TransportSocketFlags = { + /** + * Disable dual-stack support so only IPv6 is used (only if |ip| is IPv6). + */ + ipv6Only?: boolean; + /** + * Make different transports bind to the same IP and port (only for UDP). + * Useful for multicast scenarios with plain transport. Use with caution. + */ + udpReusePort?: boolean; +}; + +export type TransportTuple = { + // @deprecated Use localAddress instead. + localIp: string; + localAddress: string; + localPort: number; + remoteIp?: string; + remotePort?: number; + protocol: TransportProtocol; +}; + +export type SctpState = + | 'new' + | 'connecting' + | 'connected' + | 'failed' + | 'closed'; + +export type RtpListenerDump = { + ssrcTable: { key: number; value: string }[]; + midTable: { key: number; value: string }[]; + ridTable: { key: number; value: string }[]; +}; + +export type SctpListenerDump = { + streamIdTable: { key: number; value: string }[]; +}; + +export type RecvRtpHeaderExtensions = { + mid?: number; + rid?: number; + rrid?: number; + absSendTime?: number; + transportWideCc01?: number; +}; + +export type BaseTransportDump = { + id: string; + producerIds: string[]; + consumerIds: string[]; + mapSsrcConsumerId: { key: number; value: string }[]; + mapRtxSsrcConsumerId: { key: number; value: string }[]; + recvRtpHeaderExtensions: RecvRtpHeaderExtensions; + rtpListener: RtpListenerDump; + maxMessageSize: number; + dataProducerIds: string[]; + dataConsumerIds: string[]; + sctpParameters?: SctpParameters; + sctpState?: SctpState; + sctpListener?: SctpListenerDump; + traceEventTypes?: string[]; +}; + +export type BaseTransportStats = { + transportId: string; + timestamp: number; + sctpState?: SctpState; + bytesReceived: number; + recvBitrate: number; + bytesSent: number; + sendBitrate: number; + rtpBytesReceived: number; + rtpRecvBitrate: number; + rtpBytesSent: number; + rtpSendBitrate: number; + rtxBytesReceived: number; + rtxRecvBitrate: number; + rtxBytesSent: number; + rtxSendBitrate: number; + probationBytesSent: number; + probationSendBitrate: number; + availableOutgoingBitrate?: number; + availableIncomingBitrate?: number; + maxIncomingBitrate?: number; + maxOutgoingBitrate?: number; + minOutgoingBitrate?: number; + rtpPacketLossReceived?: number; + rtpPacketLossSent?: number; +}; + +/** + * Valid types for 'trace' event. + */ +export type TransportTraceEventType = 'probation' | 'bwe'; + +/** + * 'trace' event data. + */ +export type TransportTraceEventData = { + /** + * Trace type. + */ + type: TransportTraceEventType; + + /** + * Event timestamp. + */ + timestamp: number; + + /** + * Event direction. + */ + direction: 'in' | 'out'; + + /** + * Per type information. + */ + info: unknown; +}; + +export type TransportEvents = { + routerclose: []; + listenserverclose: []; + trace: [TransportTraceEventData]; + listenererror: [string, Error]; + // Private events. + '@close': []; + '@newproducer': [Producer]; + '@producerclose': [Producer]; + '@newdataproducer': [DataProducer]; + '@dataproducerclose': [DataProducer]; + '@listenserverclose': []; +}; + +export type TransportObserver = EnhancedEventEmitter; + +export type TransportObserverEvents = { + close: []; + newproducer: [Producer]; + newconsumer: [Consumer]; + newdataproducer: [DataProducer]; + newdataconsumer: [DataConsumer]; + trace: [TransportTraceEventData]; +}; + +export interface Transport< + TransportAppData extends AppData = AppData, + Events extends TransportEvents = TransportEvents, + Observer extends TransportObserver = TransportObserver, +> extends EnhancedEventEmitter { + /** + * Transport id. + */ + get id(): string; + + /** + * Whether the Transport is closed. + */ + get closed(): boolean; + + /** + * Transport type. + * + * @virtual + * @privateRemarks + * - It's marked as virtual getter since each Transport class overrides it. + */ + get type(): TransportType; + + /** + * App custom data. + */ + get appData(): TransportAppData; + + /** + * App custom data setter. + */ + set appData(appData: TransportAppData); + + /** + * Observer. + * + * @virtual + */ + get observer(): Observer; + + /** + * Close the Transport. + * + * @virtual + */ + close(): void; + + /** + * Router was closed. + * + * @private + * @virtual + */ + routerClosed(): void; + + /** + * Listen server was closed (this just happens in WebRtcTransports when their + * associated WebRtcServer is closed). + * + * @private + * @virtual + */ + listenServerClosed(): void; + + /** + * Dump Transport. + * + * @abstract + */ + dump(): Promise; + + /** + * Get Transport stats. + * + * @abstract + */ + getStats(): Promise; + + /** + * Provide the Transport remote parameters. + * + * @abstract + */ + connect(params: unknown): Promise; + + /** + * Set maximum incoming bitrate for receiving media. + * + * @virtual + * @privateRemarks + * - It's marked as virtual method because DirectTransport overrides it. + */ + setMaxIncomingBitrate(bitrate: number): Promise; + + /** + * Set maximum outgoing bitrate for sending media. + * + * @virtual + * @privateRemarks + * - It's marked as virtual method because DirectTransport overrides it. + */ + setMaxOutgoingBitrate(bitrate: number): Promise; + + /** + * Set minimum outgoing bitrate for sending media. + * + * @virtual + * @privateRemarks + * - It's marked as virtual method because DirectTransport overrides it. + */ + setMinOutgoingBitrate(bitrate: number): Promise; + + /** + * Create a Producer. + */ + produce( + options: ProducerOptions + ): Promise>; + + /** + * Create a Consumer. + * + * @virtual + * @privateRemarks + * - It's marked as virtual method because PipeTransport overrides it. + */ + consume( + options: ConsumerOptions + ): Promise>; + + /** + * Create a DataProducer. + */ + produceData( + options?: DataProducerOptions + ): Promise>; + + /** + * Create a DataConsumer. + */ + consumeData( + options: DataConsumerOptions + ): Promise>; + + /** + * Enable 'trace' event. + */ + enableTraceEvent(types?: TransportTraceEventType[]): Promise; +} diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 385a49e638..1a04379e2a 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -1,81 +1,33 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; -import { Channel } from './Channel'; -import { TransportListenInfo } from './Transport'; -import { WebRtcTransport } from './WebRtcTransport'; -import { AppData } from './types'; -import * as utils from './utils'; +import type { Channel } from './Channel'; +import type { + WebRtcServer, + IpPort, + IceUserNameFragment, + TupleHash, + WebRtcServerDump, + WebRtcServerEvents, + WebRtcServerObserver, + WebRtcServerObserverEvents, +} from './WebRtcServerTypes'; +import type { WebRtcTransport } from './WebRtcTransportTypes'; +import type { AppData } from './types'; +import * as fbsUtils from './fbsUtils'; import { Body as RequestBody, Method } from './fbs/request'; import * as FbsWorker from './fbs/worker'; import * as FbsWebRtcServer from './fbs/web-rtc-server'; -export type WebRtcServerOptions = - { - /** - * Listen infos. - */ - listenInfos: TransportListenInfo[]; - - /** - * Custom application data. - */ - appData?: WebRtcServerAppData; - }; - -/** - * @deprecated Use TransportListenInfo instead. - */ -export type WebRtcServerListenInfo = TransportListenInfo; - -export type WebRtcServerEvents = { - workerclose: []; - listenererror: [string, Error]; - // Private events. - '@close': []; -}; - -export type WebRtcServerObserver = - EnhancedEventEmitter; - -export type WebRtcServerObserverEvents = { - close: []; - webrtctransporthandled: [WebRtcTransport]; - webrtctransportunhandled: [WebRtcTransport]; -}; - -export type WebRtcServerDump = { - id: string; - udpSockets: IpPort[]; - tcpServers: IpPort[]; - webRtcTransportIds: string[]; - localIceUsernameFragments: IceUserNameFragment[]; - tupleHashes: TupleHash[]; -}; - -type IpPort = { - ip: string; - port: number; -}; - -type IceUserNameFragment = { - localIceUsernameFragment: string; - webRtcTransportId: string; -}; - -type TupleHash = { - tupleHash: number; - webRtcTransportId: string; -}; - type WebRtcServerInternal = { webRtcServerId: string; }; const logger = new Logger('WebRtcServer'); -export class WebRtcServer< - WebRtcServerAppData extends AppData = AppData, -> extends EnhancedEventEmitter { +export class WebRtcServerImpl + extends EnhancedEventEmitter + implements WebRtcServer +{ // Internal data. readonly #internal: WebRtcServerInternal; @@ -95,9 +47,6 @@ export class WebRtcServer< readonly #observer: WebRtcServerObserver = new EnhancedEventEmitter(); - /** - * @private - */ constructor({ internal, channel, @@ -114,54 +63,37 @@ export class WebRtcServer< this.#internal = internal; this.#channel = channel; this.#appData = appData ?? ({} as WebRtcServerAppData); + + this.handleListenerError(); } - /** - * WebRtcServer id. - */ get id(): string { return this.#internal.webRtcServerId; } - /** - * Whether the WebRtcServer is closed. - */ get closed(): boolean { return this.#closed; } - /** - * App custom data. - */ get appData(): WebRtcServerAppData { return this.#appData; } - /** - * App custom data setter. - */ set appData(appData: WebRtcServerAppData) { this.#appData = appData; } - /** - * Observer. - */ get observer(): WebRtcServerObserver { return this.#observer; } /** - * @private * Just for testing purposes. */ get webRtcTransportsForTesting(): Map { return this.#webRtcTransports; } - /** - * Close the WebRtcServer. - */ close(): void { if (this.#closed) { return; @@ -199,11 +131,6 @@ export class WebRtcServer< this.#observer.safeEmit('close'); } - /** - * Worker was closed. - * - * @private - */ workerClosed(): void { if (this.#closed) { return; @@ -223,9 +150,6 @@ export class WebRtcServer< this.#observer.safeEmit('close'); } - /** - * Dump WebRtcServer. - */ async dump(): Promise { logger.debug('dump()'); @@ -244,9 +168,6 @@ export class WebRtcServer< return parseWebRtcServerDump(dump); } - /** - * @private - */ handleWebRtcTransport(webRtcTransport: WebRtcTransport): void { this.#webRtcTransports.set(webRtcTransport.id, webRtcTransport); @@ -260,6 +181,15 @@ export class WebRtcServer< this.#observer.safeEmit('webrtctransportunhandled', webRtcTransport); }); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } function parseIpPort(binary: FbsWebRtcServer.IpPort): IpPort { @@ -290,14 +220,14 @@ function parseWebRtcServerDump( ): WebRtcServerDump { return { id: data.id()!, - udpSockets: utils.parseVector(data, 'udpSockets', parseIpPort), - tcpServers: utils.parseVector(data, 'tcpServers', parseIpPort), - webRtcTransportIds: utils.parseVector(data, 'webRtcTransportIds'), - localIceUsernameFragments: utils.parseVector( + udpSockets: fbsUtils.parseVector(data, 'udpSockets', parseIpPort), + tcpServers: fbsUtils.parseVector(data, 'tcpServers', parseIpPort), + webRtcTransportIds: fbsUtils.parseVector(data, 'webRtcTransportIds'), + localIceUsernameFragments: fbsUtils.parseVector( data, 'localIceUsernameFragments', parseIceUserNameFragment ), - tupleHashes: utils.parseVector(data, 'tupleHashes', parseTupleHash), + tupleHashes: fbsUtils.parseVector(data, 'tupleHashes', parseTupleHash), }; } diff --git a/node/src/WebRtcServerTypes.ts b/node/src/WebRtcServerTypes.ts new file mode 100644 index 0000000000..936e4af7cd --- /dev/null +++ b/node/src/WebRtcServerTypes.ts @@ -0,0 +1,112 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { TransportListenInfo } from './TransportTypes'; +import type { WebRtcTransport } from './WebRtcTransportTypes'; +import type { AppData } from './types'; + +export type WebRtcServerOptions = + { + /** + * Listen infos. + */ + listenInfos: TransportListenInfo[]; + + /** + * Custom application data. + */ + appData?: WebRtcServerAppData; + }; + +/** + * @deprecated Use TransportListenInfo instead. + */ +export type WebRtcServerListenInfo = TransportListenInfo; + +export type IpPort = { + ip: string; + port: number; +}; + +export type IceUserNameFragment = { + localIceUsernameFragment: string; + webRtcTransportId: string; +}; + +export type TupleHash = { + tupleHash: number; + webRtcTransportId: string; +}; + +export type WebRtcServerDump = { + id: string; + udpSockets: IpPort[]; + tcpServers: IpPort[]; + webRtcTransportIds: string[]; + localIceUsernameFragments: IceUserNameFragment[]; + tupleHashes: TupleHash[]; +}; + +export type WebRtcServerEvents = { + workerclose: []; + listenererror: [string, Error]; + // Private events. + '@close': []; +}; + +export type WebRtcServerObserver = + EnhancedEventEmitter; + +export type WebRtcServerObserverEvents = { + close: []; + webrtctransporthandled: [WebRtcTransport]; + webrtctransportunhandled: [WebRtcTransport]; +}; + +export interface WebRtcServer + extends EnhancedEventEmitter { + /** + * WebRtcServer id. + */ + get id(): string; + + /** + * Whether the WebRtcServer is closed. + */ + get closed(): boolean; + + /** + * App custom data. + */ + get appData(): WebRtcServerAppData; + + /** + * App custom data setter. + */ + set appData(appData: WebRtcServerAppData); + + /** + * Observer. + */ + get observer(): WebRtcServerObserver; + + /** + * Close the WebRtcServer. + */ + close(): void; + + /** + * Worker was closed. + * + * @private + */ + workerClosed(): void; + + /** + * Dump WebRtcServer. + */ + dump(): Promise; + + /** + * @private + */ + handleWebRtcTransport(webRtcTransport: WebRtcTransport): void; +} diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 9f908ec19c..522882cd65 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -1,29 +1,39 @@ import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; +import type { + WebRtcTransport, + IceParameters, + IceCandidate, + DtlsParameters, + FingerprintAlgorithm, + DtlsFingerprint, + IceRole, + IceState, + IceCandidateType, + IceCandidateTcpType, + DtlsRole, + DtlsState, + WebRtcTransportDump, + WebRtcTransportStat, + WebRtcTransportEvents, + WebRtcTransportObserver, + WebRtcTransportObserverEvents, +} from './WebRtcTransportTypes'; +import type { Transport, TransportTuple, SctpState } from './TransportTypes'; import { + TransportImpl, + TransportConstructorOptions, parseSctpState, parseBaseTransportDump, parseBaseTransportStats, parseProtocol, parseTransportTraceEventData, parseTuple, - BaseTransportDump, - BaseTransportStats, - Transport, - TransportListenInfo, - TransportListenIp, - TransportProtocol, - TransportTuple, - TransportEvents, - TransportObserverEvents, - TransportConstructorOptions, - SctpState, } from './Transport'; -import { WebRtcServer } from './WebRtcServer'; -import { SctpParameters, NumSctpStreams } from './SctpParameters'; -import { AppData, Either } from './types'; -import { parseVector } from './utils'; +import type { SctpParameters } from './sctpParametersTypes'; +import type { AppData } from './types'; +import * as fbsUtils from './fbsUtils'; import { Event, Notification } from './fbs/notification'; import * as FbsRequest from './fbs/request'; import * as FbsTransport from './fbs/transport'; @@ -36,196 +46,6 @@ import { IceRole as FbsIceRole } from './fbs/web-rtc-transport/ice-role'; import { IceCandidateType as FbsIceCandidateType } from './fbs/web-rtc-transport/ice-candidate-type'; import { IceCandidateTcpType as FbsIceCandidateTcpType } from './fbs/web-rtc-transport/ice-candidate-tcp-type'; -export type WebRtcTransportOptions< - WebRtcTransportAppData extends AppData = AppData, -> = WebRtcTransportOptionsBase & WebRtcTransportListen; - -type WebRtcTransportListenIndividualListenInfo = { - /** - * Listening info. - */ - listenInfos: TransportListenInfo[]; -}; - -type WebRtcTransportListenIndividualListenIp = { - /** - * Listening IP address or addresses in order of preference (first one is the - * preferred one). - */ - listenIps: (TransportListenIp | string)[]; - - /** - * Fixed port to listen on instead of selecting automatically from Worker's port - * range. - */ - port?: number; -}; - -type WebRtcTransportListenServer = { - /** - * Instance of WebRtcServer. - */ - webRtcServer: WebRtcServer; -}; - -type WebRtcTransportListen = Either< - Either< - WebRtcTransportListenIndividualListenInfo, - WebRtcTransportListenIndividualListenIp - >, - WebRtcTransportListenServer ->; - -export type WebRtcTransportOptionsBase = { - /** - * Listen in UDP. Default true. - */ - enableUdp?: boolean; - - /** - * Listen in TCP. Default true if webrtcServer is given, false otherwise. - */ - enableTcp?: boolean; - - /** - * Prefer UDP. Default false. - */ - preferUdp?: boolean; - - /** - * Prefer TCP. Default false. - */ - preferTcp?: boolean; - - /** - * ICE consent timeout (in seconds). If 0 it is disabled. Default 30. - */ - iceConsentTimeout?: number; - - /** - * Initial available outgoing bitrate (in bps). Default 600000. - */ - initialAvailableOutgoingBitrate?: number; - - /** - * Create a SCTP association. Default false. - */ - enableSctp?: boolean; - - /** - * SCTP streams number. - */ - numSctpStreams?: NumSctpStreams; - - /** - * Maximum allowed size for SCTP messages sent by DataProducers. - * Default 262144. - */ - maxSctpMessageSize?: number; - - /** - * Maximum SCTP send buffer used by DataConsumers. - * Default 262144. - */ - sctpSendBufferSize?: number; - - /** - * Custom application data. - */ - appData?: WebRtcTransportAppData; -}; - -export type IceParameters = { - usernameFragment: string; - password: string; - iceLite?: boolean; -}; - -export type IceCandidate = { - foundation: string; - priority: number; - // @deprecated Use |address| instead. - ip: string; - address: string; - protocol: TransportProtocol; - port: number; - type: IceCandidateType; - tcpType?: IceCandidateTcpType; -}; - -export type DtlsParameters = { - role?: DtlsRole; - fingerprints: DtlsFingerprint[]; -}; - -/** - * The hash function algorithm (as defined in the "Hash function Textual Names" - * registry initially specified in RFC 4572 Section 8). - */ -export type FingerprintAlgorithm = - | 'sha-1' - | 'sha-224' - | 'sha-256' - | 'sha-384' - | 'sha-512'; - -/** - * The hash function algorithm and its corresponding certificate fingerprint - * value (in lowercase hex string as expressed utilizing the syntax of - * "fingerprint" in RFC 4572 Section 5). - */ -export type DtlsFingerprint = { - algorithm: FingerprintAlgorithm; - value: string; -}; - -export type IceRole = 'controlled' | 'controlling'; - -export type IceState = - | 'new' - | 'connected' - | 'completed' - | 'disconnected' - | 'closed'; - -export type IceCandidateType = 'host'; - -export type IceCandidateTcpType = 'passive'; - -export type DtlsRole = 'auto' | 'client' | 'server'; - -export type DtlsState = - | 'new' - | 'connecting' - | 'connected' - | 'failed' - | 'closed'; - -export type WebRtcTransportStat = BaseTransportStats & { - type: string; - iceRole: string; - iceState: IceState; - iceSelectedTuple?: TransportTuple; - dtlsState: DtlsState; -}; - -export type WebRtcTransportEvents = TransportEvents & { - icestatechange: [IceState]; - iceselectedtuplechange: [TransportTuple]; - dtlsstatechange: [DtlsState]; - sctpstatechange: [SctpState]; -}; - -export type WebRtcTransportObserver = - EnhancedEventEmitter; - -export type WebRtcTransportObserverEvents = TransportObserverEvents & { - icestatechange: [IceState]; - iceselectedtuplechange: [TransportTuple]; - dtlsstatechange: [DtlsState]; - sctpstatechange: [SctpState]; -}; - type WebRtcTransportConstructorOptions = TransportConstructorOptions & { data: WebRtcTransportData; @@ -244,32 +64,21 @@ export type WebRtcTransportData = { sctpState?: SctpState; }; -type WebRtcTransportDump = BaseTransportDump & { - iceRole: 'controlled'; - iceParameters: IceParameters; - iceCandidates: IceCandidate[]; - iceState: IceState; - iceSelectedTuple?: TransportTuple; - dtlsParameters: DtlsParameters; - dtlsState: DtlsState; - dtlsRemoteCert?: string; -}; - const logger = new Logger('WebRtcTransport'); -export class WebRtcTransport< - WebRtcTransportAppData extends AppData = AppData, -> extends Transport< - WebRtcTransportAppData, - WebRtcTransportEvents, - WebRtcTransportObserver -> { +export class WebRtcTransportImpl< + WebRtcTransportAppData extends AppData = AppData, + > + extends TransportImpl< + WebRtcTransportAppData, + WebRtcTransportEvents, + WebRtcTransportObserver + > + implements Transport, WebRtcTransport +{ // WebRtcTransport data. readonly #data: WebRtcTransportData; - /** - * @private - */ constructor( options: WebRtcTransportConstructorOptions ) { @@ -296,92 +105,57 @@ export class WebRtcTransport< }; this.handleWorkerNotifications(); + this.handleListenerError(); + } + + get type(): 'webrtc' { + return 'webrtc'; } - /** - * Observer. - * - * @override - */ get observer(): WebRtcTransportObserver { return super.observer; } - /** - * ICE role. - */ get iceRole(): 'controlled' { return this.#data.iceRole; } - /** - * ICE parameters. - */ get iceParameters(): IceParameters { return this.#data.iceParameters; } - /** - * ICE candidates. - */ get iceCandidates(): IceCandidate[] { return this.#data.iceCandidates; } - /** - * ICE state. - */ get iceState(): IceState { return this.#data.iceState; } - /** - * ICE selected tuple. - */ get iceSelectedTuple(): TransportTuple | undefined { return this.#data.iceSelectedTuple; } - /** - * DTLS parameters. - */ get dtlsParameters(): DtlsParameters { return this.#data.dtlsParameters; } - /** - * DTLS state. - */ get dtlsState(): DtlsState { return this.#data.dtlsState; } - /** - * Remote certificate in PEM format. - */ get dtlsRemoteCert(): string | undefined { return this.#data.dtlsRemoteCert; } - /** - * SCTP parameters. - */ get sctpParameters(): SctpParameters | undefined { return this.#data.sctpParameters; } - /** - * SCTP state. - */ get sctpState(): SctpState | undefined { return this.#data.sctpState; } - /** - * Close the WebRtcTransport. - * - * @override - */ close(): void { if (this.closed) { return; @@ -398,12 +172,6 @@ export class WebRtcTransport< super.close(); } - /** - * Router was closed. - * - * @private - * @override - */ routerClosed(): void { if (this.closed) { return; @@ -420,11 +188,6 @@ export class WebRtcTransport< super.routerClosed(); } - /** - * Called when closing the associated listenServer (WebRtcServer). - * - * @private - */ listenServerClosed(): void { if (this.closed) { return; @@ -441,9 +204,6 @@ export class WebRtcTransport< super.listenServerClosed(); } - /** - * Dump Transport. - */ async dump(): Promise { logger.debug('dump()'); @@ -462,11 +222,6 @@ export class WebRtcTransport< return parseWebRtcTransportDumpResponse(data); } - /** - * Get WebRtcTransport stats. - * - * @override - */ async getStats(): Promise { logger.debug('getStats()'); @@ -485,11 +240,6 @@ export class WebRtcTransport< return [parseGetStatsResponse(data)]; } - /** - * Provide the WebRtcTransport remote parameters. - * - * @override - */ async connect({ dtlsParameters, }: { @@ -519,9 +269,6 @@ export class WebRtcTransport< this.#data.dtlsParameters.role = dtlsRoleFromFbs(data.dtlsLocalRole()); } - /** - * Restart ICE. - */ async restartIce(): Promise { logger.debug('restartIce()'); @@ -650,6 +397,15 @@ export class WebRtcTransport< } ); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } function iceStateFromFbs(fbsIceState: FbsIceState): IceState { @@ -824,7 +580,7 @@ export function parseWebRtcTransportDumpResponse( // Retrieve BaseTransportDump. const baseTransportDump = parseBaseTransportDump(binary.base()!); // Retrieve ICE candidates. - const iceCandidates = parseVector( + const iceCandidates = fbsUtils.parseVector( binary, 'iceCandidates', parseIceCandidate diff --git a/node/src/WebRtcTransportTypes.ts b/node/src/WebRtcTransportTypes.ts new file mode 100644 index 0000000000..b466da87e1 --- /dev/null +++ b/node/src/WebRtcTransportTypes.ts @@ -0,0 +1,319 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { + Transport, + TransportListenInfo, + TransportListenIp, + TransportProtocol, + TransportTuple, + SctpState, + BaseTransportDump, + BaseTransportStats, + TransportEvents, + TransportObserverEvents, +} from './TransportTypes'; +import type { WebRtcServer } from './WebRtcServerTypes'; +import type { SctpParameters, NumSctpStreams } from './sctpParametersTypes'; +import type { Either, AppData } from './types'; + +export type WebRtcTransportOptions< + WebRtcTransportAppData extends AppData = AppData, +> = WebRtcTransportOptionsBase & WebRtcTransportListen; + +type WebRtcTransportOptionsBase = { + /** + * Listen in UDP. Default true. + */ + enableUdp?: boolean; + + /** + * Listen in TCP. Default true if webrtcServer is given, false otherwise. + */ + enableTcp?: boolean; + + /** + * Prefer UDP. Default false. + */ + preferUdp?: boolean; + + /** + * Prefer TCP. Default false. + */ + preferTcp?: boolean; + + /** + * ICE consent timeout (in seconds). If 0 it is disabled. Default 30. + */ + iceConsentTimeout?: number; + + /** + * Initial available outgoing bitrate (in bps). Default 600000. + */ + initialAvailableOutgoingBitrate?: number; + + /** + * Create a SCTP association. Default false. + */ + enableSctp?: boolean; + + /** + * SCTP streams number. + */ + numSctpStreams?: NumSctpStreams; + + /** + * Maximum allowed size for SCTP messages sent by DataProducers. + * Default 262144. + */ + maxSctpMessageSize?: number; + + /** + * Maximum SCTP send buffer used by DataConsumers. + * Default 262144. + */ + sctpSendBufferSize?: number; + + /** + * Custom application data. + */ + appData?: WebRtcTransportAppData; +}; + +type WebRtcTransportListen = Either< + Either< + WebRtcTransportListenIndividualListenInfo, + WebRtcTransportListenIndividualListenIp + >, + WebRtcTransportListenServer +>; + +type WebRtcTransportListenIndividualListenInfo = { + /** + * Listening info. + */ + listenInfos: TransportListenInfo[]; +}; + +type WebRtcTransportListenIndividualListenIp = { + /** + * Listening IP address or addresses in order of preference (first one is the + * preferred one). + */ + listenIps: (TransportListenIp | string)[]; + + /** + * Fixed port to listen on instead of selecting automatically from Worker's port + * range. + */ + port?: number; +}; + +type WebRtcTransportListenServer = { + /** + * Instance of WebRtcServer. + */ + webRtcServer: WebRtcServer; +}; + +export type IceParameters = { + usernameFragment: string; + password: string; + iceLite?: boolean; +}; + +export type IceCandidate = { + foundation: string; + priority: number; + // @deprecated Use |address| instead. + ip: string; + address: string; + protocol: TransportProtocol; + port: number; + type: IceCandidateType; + tcpType?: IceCandidateTcpType; +}; + +export type DtlsParameters = { + role?: DtlsRole; + fingerprints: DtlsFingerprint[]; +}; + +/** + * The hash function algorithm (as defined in the "Hash function Textual Names" + * registry initially specified in RFC 4572 Section 8). + */ +export type FingerprintAlgorithm = + | 'sha-1' + | 'sha-224' + | 'sha-256' + | 'sha-384' + | 'sha-512'; + +/** + * The hash function algorithm and its corresponding certificate fingerprint + * value (in lowercase hex string as expressed utilizing the syntax of + * "fingerprint" in RFC 4572 Section 5). + */ +export type DtlsFingerprint = { + algorithm: FingerprintAlgorithm; + value: string; +}; + +export type IceRole = 'controlled' | 'controlling'; + +export type IceState = + | 'new' + | 'connected' + | 'completed' + | 'disconnected' + | 'closed'; + +export type IceCandidateType = 'host'; + +export type IceCandidateTcpType = 'passive'; + +export type DtlsRole = 'auto' | 'client' | 'server'; + +export type DtlsState = + | 'new' + | 'connecting' + | 'connected' + | 'failed' + | 'closed'; + +export type WebRtcTransportDump = BaseTransportDump & { + iceRole: 'controlled'; + iceParameters: IceParameters; + iceCandidates: IceCandidate[]; + iceState: IceState; + iceSelectedTuple?: TransportTuple; + dtlsParameters: DtlsParameters; + dtlsState: DtlsState; + dtlsRemoteCert?: string; +}; + +export type WebRtcTransportStat = BaseTransportStats & { + type: string; + iceRole: string; + iceState: IceState; + iceSelectedTuple?: TransportTuple; + dtlsState: DtlsState; +}; + +export type WebRtcTransportEvents = TransportEvents & { + icestatechange: [IceState]; + iceselectedtuplechange: [TransportTuple]; + dtlsstatechange: [DtlsState]; + sctpstatechange: [SctpState]; +}; + +export type WebRtcTransportObserver = + EnhancedEventEmitter; + +export type WebRtcTransportObserverEvents = TransportObserverEvents & { + icestatechange: [IceState]; + iceselectedtuplechange: [TransportTuple]; + dtlsstatechange: [DtlsState]; + sctpstatechange: [SctpState]; +}; + +export interface WebRtcTransport< + WebRtcTransportAppData extends AppData = AppData, +> extends Transport< + WebRtcTransportAppData, + WebRtcTransportEvents, + WebRtcTransportObserver + > { + /** + * Transport type. + * + * @override + */ + get type(): 'webrtc'; + + /** + * Observer. + * + * @override + */ + get observer(): WebRtcTransportObserver; + + /** + * ICE role. + */ + get iceRole(): 'controlled'; + + /** + * ICE parameters. + */ + get iceParameters(): IceParameters; + + /** + * ICE candidates. + */ + get iceCandidates(): IceCandidate[]; + + /** + * ICE state. + */ + get iceState(): IceState; + + /** + * ICE selected tuple. + */ + get iceSelectedTuple(): TransportTuple | undefined; + + /** + * DTLS parameters. + */ + get dtlsParameters(): DtlsParameters; + + /** + * DTLS state. + */ + get dtlsState(): DtlsState; + + /** + * Remote certificate in PEM format. + */ + get dtlsRemoteCert(): string | undefined; + + /** + * SCTP parameters. + */ + get sctpParameters(): SctpParameters | undefined; + + /** + * SCTP state. + */ + get sctpState(): SctpState | undefined; + + /** + * Dump WebRtcTransport. + * + * @override + */ + dump(): Promise; + + /** + * Get WebRtcTransport stats. + * + * @override + */ + getStats(): Promise; + + /** + * Provide the WebRtcTransport remote parameters. + * + * @override + */ + connect({ + dtlsParameters, + }: { + dtlsParameters: DtlsParameters; + }): Promise; + + /** + * Restart ICE. + */ + restartIce(): Promise; +} diff --git a/node/src/Worker.ts b/node/src/Worker.ts index c1d2e20f7c..b30c5d70ba 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -5,220 +5,32 @@ import { version } from './'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; +import type { + Worker, + WorkerSettings, + WorkerUpdateableSettings, + WorkerResourceUsage, + WorkerDump, + WorkerEvents, + WorkerObserver, + WorkerObserverEvents, +} from './WorkerTypes'; import { Channel } from './Channel'; -import { Router, RouterOptions } from './Router'; -import { WebRtcServer, WebRtcServerOptions } from './WebRtcServer'; +import type { WebRtcServer, WebRtcServerOptions } from './WebRtcServerTypes'; +import { WebRtcServerImpl } from './WebRtcServer'; +import type { Router, RouterOptions } from './RouterTypes'; +import { RouterImpl } from './Router'; import { portRangeToFbs, socketFlagsToFbs } from './Transport'; -import { RtpCodecCapability } from './RtpParameters'; -import { AppData } from './types'; +import type { RtpCodecCapability } from './rtpParametersTypes'; import * as utils from './utils'; +import * as fbsUtils from './fbsUtils'; +import type { AppData } from './types'; import { Event } from './fbs/notification'; import * as FbsRequest from './fbs/request'; import * as FbsWorker from './fbs/worker'; import * as FbsTransport from './fbs/transport'; import { Protocol as FbsTransportProtocol } from './fbs/transport/protocol'; -export type WorkerLogLevel = 'debug' | 'warn' | 'error' | 'none'; - -export type WorkerLogTag = - | 'info' - | 'ice' - | 'dtls' - | 'rtp' - | 'srtp' - | 'rtcp' - | 'rtx' - | 'bwe' - | 'score' - | 'simulcast' - | 'svc' - | 'sctp' - | 'message'; - -export type WorkerSettings = { - /** - * Logging level for logs generated by the media worker subprocesses (check - * the Debugging documentation). Valid values are 'debug', 'warn', 'error' and - * 'none'. Default 'error'. - */ - logLevel?: WorkerLogLevel; - - /** - * Log tags for debugging. Check the meaning of each available tag in the - * Debugging documentation. - */ - logTags?: WorkerLogTag[]; - - /** - * Minimun RTC port for ICE, DTLS, RTP, etc. Default 10000. - * @deprecated Use |portRange| in TransportListenInfo object instead. - */ - rtcMinPort?: number; - - /** - * Maximum RTC port for ICE, DTLS, RTP, etc. Default 59999. - * @deprecated Use |portRange| in TransportListenInfo object instead. - */ - rtcMaxPort?: number; - - /** - * Path to the DTLS public certificate file in PEM format. If unset, a - * certificate is dynamically created. - */ - dtlsCertificateFile?: string; - - /** - * Path to the DTLS certificate private key file in PEM format. If unset, a - * certificate is dynamically created. - */ - dtlsPrivateKeyFile?: string; - - /** - * Field trials for libwebrtc. - * @private - * - * NOTE: For advanced users only. An invalid value will make the worker crash. - * Default value is - * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/". - */ - libwebrtcFieldTrials?: string; - - /** - * Disable liburing (io_uring) despite it's supported in current host. - */ - disableLiburing?: boolean; - - /** - * Custom application data. - */ - appData?: WorkerAppData; -}; - -export type WorkerUpdateableSettings = Pick< - WorkerSettings, - 'logLevel' | 'logTags' ->; - -/** - * An object with the fields of the uv_rusage_t struct. - * - * - http://docs.libuv.org/en/v1.x/misc.html#c.uv_rusage_t - * - https://linux.die.net/man/2/getrusage - */ -export type WorkerResourceUsage = { - /** - * User CPU time used (in ms). - */ - ru_utime: number; - - /** - * System CPU time used (in ms). - */ - ru_stime: number; - - /** - * Maximum resident set size. - */ - ru_maxrss: number; - - /** - * Integral shared memory size. - */ - ru_ixrss: number; - - /** - * Integral unshared data size. - */ - ru_idrss: number; - - /** - * Integral unshared stack size. - */ - ru_isrss: number; - - /** - * Page reclaims (soft page faults). - */ - ru_minflt: number; - - /** - * Page faults (hard page faults). - */ - ru_majflt: number; - - /** - * Swaps. - */ - ru_nswap: number; - - /** - * Block input operations. - */ - ru_inblock: number; - - /** - * Block output operations. - */ - ru_oublock: number; - - /** - * IPC messages sent. - */ - ru_msgsnd: number; - - /** - * IPC messages received. - */ - ru_msgrcv: number; - - /** - * Signals received. - */ - ru_nsignals: number; - - /** - * Voluntary context switches. - */ - ru_nvcsw: number; - - /** - * Involuntary context switches. - */ - ru_nivcsw: number; -}; - -export type WorkerDump = { - pid: number; - webRtcServerIds: string[]; - routerIds: string[]; - channelMessageHandlers: { - channelRequestHandlers: string[]; - channelNotificationHandlers: string[]; - }; - liburing?: { - sqeProcessCount: number; - sqeMissCount: number; - userDataMissCount: number; - }; -}; - -export type WorkerEvents = { - died: [Error]; - subprocessclose: []; - listenererror: [string, Error]; - // Private events. - '@success': []; - '@failure': [Error]; -}; - -export type WorkerObserver = EnhancedEventEmitter; - -export type WorkerObserverEvents = { - close: []; - newwebrtcserver: [WebRtcServer]; - newrouter: [Router]; -}; - // If env MEDIASOUP_WORKER_BIN is given, use it as worker binary. // Otherwise if env MEDIASOUP_BUILDTYPE is 'Debug' use the Debug binary. // Otherwise use the Release binary. @@ -247,9 +59,10 @@ export const workerBin = process.env.MEDIASOUP_WORKER_BIN const logger = new Logger('Worker'); const workerLogger = new Logger('Worker'); -export class Worker< - WorkerAppData extends AppData = AppData, -> extends EnhancedEventEmitter { +export class WorkerImpl + extends EnhancedEventEmitter + implements Worker +{ // mediasoup-worker child process. #child: ChildProcess; @@ -281,9 +94,6 @@ export class Worker< readonly #observer: WorkerObserver = new EnhancedEventEmitter(); - /** - * @private - */ constructor({ logLevel, logTags, @@ -489,59 +299,39 @@ export class Worker< } } }); + + this.handleListenerError(); } - /** - * Worker process identifier (PID). - */ get pid(): number { return this.#pid; } - /** - * Whether the Worker is closed. - */ get closed(): boolean { return this.#closed; } - /** - * Whether the Worker died. - */ get died(): boolean { return this.#died; } - /** - * Whether the Worker subprocess is closed. - */ get subprocessClosed(): boolean { return this.#subprocessClosed; } - /** - * App custom data. - */ get appData(): WorkerAppData { return this.#appData; } - /** - * App custom data setter. - */ set appData(appData: WorkerAppData) { this.#appData = appData; } - /** - * Observer. - */ get observer(): WorkerObserver { return this.#observer; } /** - * @private * Just for testing purposes. */ get webRtcServersForTesting(): Set { @@ -549,16 +339,12 @@ export class Worker< } /** - * @private * Just for testing purposes. */ get routersForTesting(): Set { return this.#routers; } - /** - * Close the Worker. - */ close(): void { if (this.#closed) { return; @@ -590,9 +376,6 @@ export class Worker< this.#observer.safeEmit('close'); } - /** - * Dump Worker. - */ async dump(): Promise { logger.debug('dump()'); @@ -607,9 +390,6 @@ export class Worker< return parseWorkerDumpResponse(dump); } - /** - * Get mediasoup-worker process resource usage. - */ async getResourceUsage(): Promise { logger.debug('getResourceUsage()'); @@ -644,9 +424,6 @@ export class Worker< }; } - /** - * Update settings. - */ async updateSettings({ logLevel, logTags, @@ -666,9 +443,6 @@ export class Worker< ); } - /** - * Create a WebRtcServer. - */ async createWebRtcServer({ listenInfos, appData, @@ -715,11 +489,12 @@ export class Worker< createWebRtcServerRequestOffset ); - const webRtcServer: WebRtcServer = new WebRtcServer({ - internal: { webRtcServerId }, - channel: this.#channel, - appData, - }); + const webRtcServer: WebRtcServer = + new WebRtcServerImpl({ + internal: { webRtcServerId }, + channel: this.#channel, + appData, + }); this.#webRtcServers.add(webRtcServer); webRtcServer.on('@close', () => this.#webRtcServers.delete(webRtcServer)); @@ -730,9 +505,6 @@ export class Worker< return webRtcServer; } - /** - * Create a Router. - */ async createRouter({ mediaCodecs, appData, @@ -766,7 +538,7 @@ export class Worker< ); const data = { rtpCapabilities }; - const router: Router = new Router({ + const router: Router = new RouterImpl({ internal: { routerId, }, @@ -814,6 +586,15 @@ export class Worker< // Emit observer event. this.#observer.safeEmit('close'); } + + private handleListenerError(): void { + this.on('listenererror', (eventName, error) => { + logger.error( + `event listener threw an error [eventName:${eventName}]:`, + error + ); + }); + } } export function parseWorkerDumpResponse( @@ -821,14 +602,14 @@ export function parseWorkerDumpResponse( ): WorkerDump { const dump: WorkerDump = { pid: binary.pid(), - webRtcServerIds: utils.parseVector(binary, 'webRtcServerIds'), - routerIds: utils.parseVector(binary, 'routerIds'), + webRtcServerIds: fbsUtils.parseVector(binary, 'webRtcServerIds'), + routerIds: fbsUtils.parseVector(binary, 'routerIds'), channelMessageHandlers: { - channelRequestHandlers: utils.parseVector( + channelRequestHandlers: fbsUtils.parseVector( binary.channelMessageHandlers()!, 'channelRequestHandlers' ), - channelNotificationHandlers: utils.parseVector( + channelNotificationHandlers: fbsUtils.parseVector( binary.channelMessageHandlers()!, 'channelNotificationHandlers' ), diff --git a/node/src/WorkerTypes.ts b/node/src/WorkerTypes.ts new file mode 100644 index 0000000000..337b0c4ea8 --- /dev/null +++ b/node/src/WorkerTypes.ts @@ -0,0 +1,279 @@ +import type { EnhancedEventEmitter } from './enhancedEvents'; +import type { WebRtcServer, WebRtcServerOptions } from './WebRtcServerTypes'; +import type { Router, RouterOptions } from './RouterTypes'; +import type { AppData } from './types'; + +export type WorkerLogLevel = 'debug' | 'warn' | 'error' | 'none'; + +export type WorkerLogTag = + | 'info' + | 'ice' + | 'dtls' + | 'rtp' + | 'srtp' + | 'rtcp' + | 'rtx' + | 'bwe' + | 'score' + | 'simulcast' + | 'svc' + | 'sctp' + | 'message'; + +export type WorkerSettings = { + /** + * Logging level for logs generated by the media worker subprocesses (check + * the Debugging documentation). Valid values are 'debug', 'warn', 'error' and + * 'none'. Default 'error'. + */ + logLevel?: WorkerLogLevel; + + /** + * Log tags for debugging. Check the meaning of each available tag in the + * Debugging documentation. + */ + logTags?: WorkerLogTag[]; + + /** + * Minimun RTC port for ICE, DTLS, RTP, etc. Default 10000. + * @deprecated Use |portRange| in TransportListenInfo object instead. + */ + rtcMinPort?: number; + + /** + * Maximum RTC port for ICE, DTLS, RTP, etc. Default 59999. + * @deprecated Use |portRange| in TransportListenInfo object instead. + */ + rtcMaxPort?: number; + + /** + * Path to the DTLS public certificate file in PEM format. If unset, a + * certificate is dynamically created. + */ + dtlsCertificateFile?: string; + + /** + * Path to the DTLS certificate private key file in PEM format. If unset, a + * certificate is dynamically created. + */ + dtlsPrivateKeyFile?: string; + + /** + * Field trials for libwebrtc. + * @private + * + * NOTE: For advanced users only. An invalid value will make the worker crash. + * Default value is + * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/". + */ + libwebrtcFieldTrials?: string; + + /** + * Disable liburing (io_uring) despite it's supported in current host. + */ + disableLiburing?: boolean; + + /** + * Custom application data. + */ + appData?: WorkerAppData; +}; + +export type WorkerUpdateableSettings = Pick< + WorkerSettings, + 'logLevel' | 'logTags' +>; + +/** + * An object with the fields of the uv_rusage_t struct. + * + * - http://docs.libuv.org/en/v1.x/misc.html#c.uv_rusage_t + * - https://linux.die.net/man/2/getrusage + */ +export type WorkerResourceUsage = { + /** + * User CPU time used (in ms). + */ + ru_utime: number; + + /** + * System CPU time used (in ms). + */ + ru_stime: number; + + /** + * Maximum resident set size. + */ + ru_maxrss: number; + + /** + * Integral shared memory size. + */ + ru_ixrss: number; + + /** + * Integral unshared data size. + */ + ru_idrss: number; + + /** + * Integral unshared stack size. + */ + ru_isrss: number; + + /** + * Page reclaims (soft page faults). + */ + ru_minflt: number; + + /** + * Page faults (hard page faults). + */ + ru_majflt: number; + + /** + * Swaps. + */ + ru_nswap: number; + + /** + * Block input operations. + */ + ru_inblock: number; + + /** + * Block output operations. + */ + ru_oublock: number; + + /** + * IPC messages sent. + */ + ru_msgsnd: number; + + /** + * IPC messages received. + */ + ru_msgrcv: number; + + /** + * Signals received. + */ + ru_nsignals: number; + + /** + * Voluntary context switches. + */ + ru_nvcsw: number; + + /** + * Involuntary context switches. + */ + ru_nivcsw: number; +}; + +export type WorkerDump = { + pid: number; + webRtcServerIds: string[]; + routerIds: string[]; + channelMessageHandlers: { + channelRequestHandlers: string[]; + channelNotificationHandlers: string[]; + }; + liburing?: { + sqeProcessCount: number; + sqeMissCount: number; + userDataMissCount: number; + }; +}; + +export type WorkerEvents = { + died: [Error]; + subprocessclose: []; + listenererror: [string, Error]; + // Private events. + '@success': []; + '@failure': [Error]; +}; + +export type WorkerObserver = EnhancedEventEmitter; + +export type WorkerObserverEvents = { + close: []; + newwebrtcserver: [WebRtcServer]; + newrouter: [Router]; +}; + +export interface Worker + extends EnhancedEventEmitter { + /** + * Worker process identifier (PID). + */ + get pid(): number; + + /** + * Whether the Worker is closed. + */ + get closed(): boolean; + + /** + * Whether the Worker died. + */ + get died(): boolean; + + /** + * Whether the Worker subprocess is closed. + */ + get subprocessClosed(): boolean; + + /** + * App custom data. + */ + get appData(): WorkerAppData; + + /** + * App custom data setter. + */ + set appData(appData: WorkerAppData); + + /** + * Observer. + */ + get observer(): WorkerObserver; + + /** + * Close the Worker. + */ + close(): void; + + /** + * Dump Worker. + */ + dump(): Promise; + + /** + * Get mediasoup-worker process resource usage. + */ + getResourceUsage(): Promise; + + /** + * Update settings. + */ + updateSettings( + options?: WorkerUpdateableSettings + ): Promise; + + /** + * Create a WebRtcServer. + */ + createWebRtcServer( + options: WebRtcServerOptions + ): Promise>; + + /** + * Create a Router. + */ + createRouter( + options?: RouterOptions + ): Promise>; +} diff --git a/node/src/enhancedEvents.ts b/node/src/enhancedEvents.ts index a0fbfba558..8f7a5eb59a 100644 --- a/node/src/enhancedEvents.ts +++ b/node/src/enhancedEvents.ts @@ -1,7 +1,4 @@ import { EventEmitter, once } from 'node:events'; -import { Logger } from './Logger'; - -const enhancedEventEmitterLogger = new Logger('EnhancedEventEmitter'); type Events = Record; @@ -10,6 +7,7 @@ export class EnhancedEventEmitter< > extends EventEmitter { constructor() { super(); + this.setMaxListeners(Infinity); } @@ -24,11 +22,6 @@ export class EnhancedEventEmitter< try { return super.emit(eventName, ...args); } catch (error) { - enhancedEventEmitterLogger.error( - `safeEmit() | event listener threw an error [eventName:${eventName}]:`, - error as Error - ); - try { super.emit('listenererror', eventName, error); } catch (error2) { diff --git a/node/src/fbsUtils.ts b/node/src/fbsUtils.ts new file mode 100644 index 0000000000..502a9bc2a3 --- /dev/null +++ b/node/src/fbsUtils.ts @@ -0,0 +1,115 @@ +/** + * Parse flatbuffers vector into an array of the given T. + */ +export function parseVector( + binary: any, + methodName: string, + parseFn?: (binary2: any) => T +): T[] { + const array: T[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { + if (parseFn) { + array.push(parseFn(binary[methodName](i))); + } else { + array.push(binary[methodName](i) as T); + } + } + + return array; +} + +/** + * Parse flatbuffers vector of StringString into the corresponding array. + */ +export function parseStringStringVector( + binary: any, + methodName: string +): { key: string; value: string }[] { + const array: { key: string; value: string }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { + const kv = binary[methodName](i)!; + + array.push({ key: kv.key(), value: kv.value() }); + } + + return array; +} + +/** + * Parse flatbuffers vector of StringUint8 into the corresponding array. + */ +export function parseStringUint8Vector( + binary: any, + methodName: string +): { key: string; value: number }[] { + const array: { key: string; value: number }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { + const kv = binary[methodName](i)!; + + array.push({ key: kv.key(), value: kv.value() }); + } + + return array; +} + +/** + * Parse flatbuffers vector of Uint16String into the corresponding array. + */ +export function parseUint16StringVector( + binary: any, + methodName: string +): { key: number; value: string }[] { + const array: { key: number; value: string }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { + const kv = binary[methodName](i)!; + + array.push({ key: kv.key(), value: kv.value() }); + } + + return array; +} + +/** + * Parse flatbuffers vector of Uint32String into the corresponding array. + */ +export function parseUint32StringVector( + binary: any, + methodName: string +): { key: number; value: string }[] { + const array: { key: number; value: string }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { + const kv = binary[methodName](i)!; + + array.push({ key: kv.key(), value: kv.value() }); + } + + return array; +} + +/** + * Parse flatbuffers vector of StringStringArray into the corresponding array. + */ +export function parseStringStringArrayVector( + binary: any, + methodName: string +): { key: string; values: string[] }[] { + const array: { key: string; values: string[] }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) { + const kv = binary[methodName](i)!; + const values: string[] = []; + + for (let i2 = 0; i2 < kv.valuesLength(); ++i2) { + values.push(kv.values(i2)! as string); + } + + array.push({ key: kv.key(), values }); + } + + return array; +} diff --git a/node/src/index.ts b/node/src/index.ts index 9239dc77ac..c366b0d357 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -1,11 +1,11 @@ import { Logger, LoggerEmitter } from './Logger'; import { EnhancedEventEmitter } from './enhancedEvents'; -import { workerBin, Worker, WorkerSettings } from './Worker'; -import * as utils from './utils'; +import type { Worker, WorkerSettings } from './WorkerTypes'; +import { WorkerImpl, workerBin } from './Worker'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; -import { RtpCapabilities } from './RtpParameters'; - -import * as types from './types'; +import type { RtpCapabilities } from './rtpParametersTypes'; +import type * as types from './types'; +import * as utils from './utils'; /** * Expose all types. @@ -18,11 +18,6 @@ export { types }; // eslint-disable-next-line @typescript-eslint/no-require-imports export const version: string = require('../../package.json').version; -/** - * Expose parseScalabilityMode() function. - */ -export { parse as parseScalabilityMode } from './scalabilityModes'; - export type Observer = EnhancedEventEmitter; export type ObserverEvents = { @@ -43,15 +38,6 @@ export { workerBin }; const logger = new Logger(); -/** - * Event listeners for mediasoup generated logs. - */ -export type LogEventListeners = { - ondebug?: (namespace: string, log: string) => void; - onwarn?: (namespace: string, log: string) => void; - onerror?: (namespace: string, log: string, error?: Error) => void; -}; - /** * Set event listeners for mediasoup generated logs. If called with no arguments * then no events will be emitted. @@ -73,7 +59,9 @@ export type LogEventListeners = { * }); * ``` */ -export function setLogEventListeners(listeners?: LogEventListeners): void { +export function setLogEventListeners( + listeners?: types.LogEventListeners +): void { logger.debug('setLogEventListeners()'); let debugLogEmitter: LoggerEmitter | undefined; @@ -123,7 +111,7 @@ export async function createWorker< throw new TypeError('if given, appData must be an object'); } - const worker: Worker = new Worker({ + const worker: Worker = new WorkerImpl({ logLevel, logTags, rtcMinPort, @@ -153,3 +141,8 @@ export async function createWorker< export function getSupportedRtpCapabilities(): RtpCapabilities { return utils.clone(supportedRtpCapabilities); } + +/** + * Expose parseScalabilityMode() function. + */ +export { parseScalabilityMode } from './scalabilityModesUtils'; diff --git a/node/src/ortc.ts b/node/src/ortc.ts index 3b36297493..be79bab7c2 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -1,8 +1,8 @@ import * as h264 from 'h264-profile-level-id'; import * as flatbuffers from 'flatbuffers'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; -import { parse as parseScalabilityMode } from './scalabilityModes'; -import { +import { parseScalabilityMode } from './scalabilityModesUtils'; +import type { RtpCapabilities, MediaKind, RtpCodecCapability, @@ -13,18 +13,17 @@ import { RtpEncodingParameters, RtpHeaderExtensionParameters, RtcpParameters, -} from './RtpParameters'; -import { SctpStreamParameters } from './SctpParameters'; +} from './rtpParametersTypes'; +import type { SctpStreamParameters } from './sctpParametersTypes'; import * as utils from './utils'; import { UnsupportedError } from './errors'; import * as FbsRtpParameters from './fbs/rtp-parameters'; -export type RtpMapping = { +export type RtpCodecsEncodingsMapping = { codecs: { payloadType: number; mappedPayloadType: number; }[]; - encodings: { ssrc?: number; rid?: string; @@ -309,8 +308,8 @@ export function generateRouterRtpCapabilities( export function getProducerRtpParametersMapping( params: RtpParameters, caps: RtpCapabilities -): RtpMapping { - const rtpMapping: RtpMapping = { +): RtpCodecsEncodingsMapping { + const rtpMapping: RtpCodecsEncodingsMapping = { codecs: [], encodings: [], }; @@ -415,7 +414,7 @@ export function getConsumableRtpParameters( kind: string, params: RtpParameters, caps: RtpCapabilities, - rtpMapping: RtpMapping + rtpMapping: RtpCodecsEncodingsMapping ): RtpParameters { const consumableParams: RtpParameters = { codecs: [], @@ -915,7 +914,7 @@ function matchCodecs( export function serializeRtpMapping( builder: flatbuffers.Builder, - rtpMapping: RtpMapping + rtpMapping: RtpCodecsEncodingsMapping ): number { const codecs: number[] = []; diff --git a/node/src/RtpParameters.ts b/node/src/rtpParametersFbsUtils.ts similarity index 55% rename from node/src/RtpParameters.ts rename to node/src/rtpParametersFbsUtils.ts index 4c1e7631dc..727eb1cd1e 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/rtpParametersFbsUtils.ts @@ -1,4 +1,14 @@ import * as flatbuffers from 'flatbuffers'; +import type { + RtpParameters, + RtpCodecParameters, + RtcpFeedback, + RtpEncodingParameters, + RtpHeaderExtensionUri, + RtpHeaderExtensionParameters, + RtcpParameters, +} from './rtpParametersTypes'; +import * as fbsUtils from './fbsUtils'; import { Boolean as FbsBoolean, Double as FbsDouble, @@ -16,365 +26,6 @@ import { Rtx as FbsRtx, Value as FbsValue, } from './fbs/rtp-parameters'; -import * as utils from './utils'; - -/** - * The RTP capabilities define what mediasoup or an endpoint can receive at - * media level. - */ -export type RtpCapabilities = { - /** - * Supported media and RTX codecs. - */ - codecs?: RtpCodecCapability[]; - - /** - * Supported RTP header extensions. - */ - headerExtensions?: RtpHeaderExtension[]; -}; - -/** - * Media kind ('audio' or 'video'). - */ -export type MediaKind = 'audio' | 'video'; - -/** - * Provides information on the capabilities of a codec within the RTP - * capabilities. The list of media codecs supported by mediasoup and their - * settings is defined in the supportedRtpCapabilities.ts file. - * - * Exactly one RtpCodecCapability will be present for each supported combination - * of parameters that requires a distinct value of preferredPayloadType. For - * example: - * - * - Multiple H264 codecs, each with their own distinct 'packetization-mode' and - * 'profile-level-id' values. - * - Multiple VP9 codecs, each with their own distinct 'profile-id' value. - * - * RtpCodecCapability entries in the mediaCodecs array of RouterOptions do not - * require preferredPayloadType field (if unset, mediasoup will choose a random - * one). If given, make sure it's in the 96-127 range. - */ -export type RtpCodecCapability = { - /** - * Media kind. - */ - kind: MediaKind; - - /** - * The codec MIME media type/subtype (e.g. 'audio/opus', 'video/VP8'). - */ - mimeType: string; - - /** - * The preferred RTP payload type. - */ - preferredPayloadType?: number; - - /** - * Codec clock rate expressed in Hertz. - */ - clockRate: number; - - /** - * The number of channels supported (e.g. two for stereo). Just for audio. - * Default 1. - */ - channels?: number; - - /** - * Codec specific parameters. Some parameters (such as 'packetization-mode' - * and 'profile-level-id' in H264 or 'profile-id' in VP9) are critical for - * codec matching. - */ - parameters?: any; - - /** - * Transport layer and codec-specific feedback messages for this codec. - */ - rtcpFeedback?: RtcpFeedback[]; -}; - -/** - * Direction of RTP header extension. - */ -export type RtpHeaderExtensionDirection = - | 'sendrecv' - | 'sendonly' - | 'recvonly' - | 'inactive'; - -/** - * Provides information relating to supported header extensions. The list of - * RTP header extensions supported by mediasoup is defined in the - * supportedRtpCapabilities.ts file. - * - * mediasoup does not currently support encrypted RTP header extensions. The - * direction field is just present in mediasoup RTP capabilities (retrieved via - * router.rtpCapabilities or mediasoup.getSupportedRtpCapabilities()). It's - * ignored if present in endpoints' RTP capabilities. - */ -export type RtpHeaderExtension = { - /** - * Media kind. - */ - kind: MediaKind; - - /* - * The URI of the RTP header extension, as defined in RFC 5285. - */ - uri: RtpHeaderExtensionUri; - - /** - * The preferred numeric identifier that goes in the RTP packet. Must be - * unique. - */ - preferredId: number; - - /** - * If true, it is preferred that the value in the header be encrypted as per - * RFC 6904. Default false. - */ - preferredEncrypt?: boolean; - - /** - * If 'sendrecv', mediasoup supports sending and receiving this RTP extension. - * 'sendonly' means that mediasoup can send (but not receive) it. 'recvonly' - * means that mediasoup can receive (but not send) it. - */ - direction?: RtpHeaderExtensionDirection; -}; - -/** - * The RTP send parameters describe a media stream received by mediasoup from - * an endpoint through its corresponding mediasoup Producer. These parameters - * may include a mid value that the mediasoup transport will use to match - * received RTP packets based on their MID RTP extension value. - * - * mediasoup allows RTP send parameters with a single encoding and with multiple - * encodings (simulcast). In the latter case, each entry in the encodings array - * must include a ssrc field or a rid field (the RID RTP extension value). Check - * the Simulcast and SVC sections for more information. - * - * The RTP receive parameters describe a media stream as sent by mediasoup to - * an endpoint through its corresponding mediasoup Consumer. The mid value is - * unset (mediasoup does not include the MID RTP extension into RTP packets - * being sent to endpoints). - * - * There is a single entry in the encodings array (even if the corresponding - * producer uses simulcast). The consumer sends a single and continuous RTP - * stream to the endpoint and spatial/temporal layer selection is possible via - * consumer.setPreferredLayers(). - * - * As an exception, previous bullet is not true when consuming a stream over a - * PipeTransport, in which all RTP streams from the associated producer are - * forwarded verbatim through the consumer. - * - * The RTP receive parameters will always have their ssrc values randomly - * generated for all of its encodings (and optional rtx: { ssrc: XXXX } if the - * endpoint supports RTX), regardless of the original RTP send parameters in - * the associated producer. This applies even if the producer's encodings have - * rid set. - */ -export type RtpParameters = { - /** - * The MID RTP extension value as defined in the BUNDLE specification. - */ - mid?: string; - - /** - * Media and RTX codecs in use. - */ - codecs: RtpCodecParameters[]; - - /** - * RTP header extensions in use. - */ - headerExtensions?: RtpHeaderExtensionParameters[]; - - /** - * Transmitted RTP streams and their settings. - */ - encodings?: RtpEncodingParameters[]; - - /** - * Parameters used for RTCP. - */ - rtcp?: RtcpParameters; -}; - -/** - * Provides information on codec settings within the RTP parameters. The list - * of media codecs supported by mediasoup and their settings is defined in the - * supportedRtpCapabilities.ts file. - */ -export type RtpCodecParameters = { - /** - * The codec MIME media type/subtype (e.g. 'audio/opus', 'video/VP8'). - */ - mimeType: string; - - /** - * The value that goes in the RTP Payload Type Field. Must be unique. - */ - payloadType: number; - - /** - * Codec clock rate expressed in Hertz. - */ - clockRate: number; - - /** - * The number of channels supported (e.g. two for stereo). Just for audio. - * Default 1. - */ - channels?: number; - - /** - * Codec-specific parameters available for signaling. Some parameters (such - * as 'packetization-mode' and 'profile-level-id' in H264 or 'profile-id' in - * VP9) are critical for codec matching. - */ - parameters?: any; - - /** - * Transport layer and codec-specific feedback messages for this codec. - */ - rtcpFeedback?: RtcpFeedback[]; -}; - -/** - * Provides information on RTCP feedback messages for a specific codec. Those - * messages can be transport layer feedback messages or codec-specific feedback - * messages. The list of RTCP feedbacks supported by mediasoup is defined in the - * supportedRtpCapabilities.ts file. - */ -export type RtcpFeedback = { - /** - * RTCP feedback type. - */ - type: string; - - /** - * RTCP feedback parameter. - */ - parameter?: string; -}; - -/** - * Provides information relating to an encoding, which represents a media RTP - * stream and its associated RTX stream (if any). - */ -export type RtpEncodingParameters = { - /** - * The media SSRC. - */ - ssrc?: number; - - /** - * The RID RTP extension value. Must be unique. - */ - rid?: string; - - /** - * Codec payload type this encoding affects. If unset, first media codec is - * chosen. - */ - codecPayloadType?: number; - - /** - * RTX stream information. It must contain a numeric ssrc field indicating - * the RTX SSRC. - */ - rtx?: { ssrc: number }; - - /** - * It indicates whether discontinuous RTP transmission will be used. Useful - * for audio (if the codec supports it) and for video screen sharing (when - * static content is being transmitted, this option disables the RTP - * inactivity checks in mediasoup). Default false. - */ - dtx?: boolean; - - /** - * Number of spatial and temporal layers in the RTP stream (e.g. 'L1T3'). - * See webrtc-svc. - */ - scalabilityMode?: string; - - /** - * Others. - */ - scaleResolutionDownBy?: number; - maxBitrate?: number; -}; - -export type RtpHeaderExtensionUri = - | 'urn:ietf:params:rtp-hdrext:sdes:mid' - | 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id' - | 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id' - | 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07' - | 'urn:ietf:params:rtp-hdrext:framemarking' - | 'urn:ietf:params:rtp-hdrext:ssrc-audio-level' - | 'urn:3gpp:video-orientation' - | 'urn:ietf:params:rtp-hdrext:toffset' - | 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' - | 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' - | 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time' - | 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay'; - -/** - * Defines a RTP header extension within the RTP parameters. The list of RTP - * header extensions supported by mediasoup is defined in the - * supportedRtpCapabilities.ts file. - * - * mediasoup does not currently support encrypted RTP header extensions and no - * parameters are currently considered. - */ -export type RtpHeaderExtensionParameters = { - /** - * The URI of the RTP header extension, as defined in RFC 5285. - */ - uri: RtpHeaderExtensionUri; - - /** - * The numeric identifier that goes in the RTP packet. Must be unique. - */ - id: number; - - /** - * If true, the value in the header is encrypted as per RFC 6904. Default false. - */ - encrypt?: boolean; - - /** - * Configuration parameters for the header extension. - */ - parameters?: any; -}; - -/** - * Provides information on RTCP settings within the RTP parameters. - * - * If no cname is given in a producer's RTP parameters, the mediasoup transport - * will choose a random one that will be used into RTCP SDES messages sent to - * all its associated consumers. - * - * mediasoup assumes reducedSize to always be true. - */ -export type RtcpParameters = { - /** - * The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages). - */ - cname?: string; - - /** - * Whether reduced size RTCP RFC 5506 is configured (if true) or compound RTCP - * as specified in RFC 3550 (if false). Default true. - */ - reducedSize?: boolean; -}; export function serializeRtpParameters( builder: flatbuffers.Builder, @@ -694,7 +345,11 @@ export function parseRtpCodecParameters( let rtcpFeedback: RtcpFeedback[] = []; if (data.rtcpFeedbackLength() > 0) { - rtcpFeedback = utils.parseVector(data, 'rtcpFeedback', parseRtcpFeedback); + rtcpFeedback = fbsUtils.parseVector( + data, + 'rtcpFeedback', + parseRtcpFeedback + ); } return { @@ -846,12 +501,12 @@ export function parseRtpEncodingParameters( } export function parseRtpParameters(data: FbsRtpParameters): RtpParameters { - const codecs = utils.parseVector(data, 'codecs', parseRtpCodecParameters); + const codecs = fbsUtils.parseVector(data, 'codecs', parseRtpCodecParameters); let headerExtensions: RtpHeaderExtensionParameters[] = []; if (data.headerExtensionsLength() > 0) { - headerExtensions = utils.parseVector( + headerExtensions = fbsUtils.parseVector( data, 'headerExtensions', parseRtpHeaderExtensionParameters @@ -861,7 +516,7 @@ export function parseRtpParameters(data: FbsRtpParameters): RtpParameters { let encodings: RtpEncodingParameters[] = []; if (data.encodingsLength() > 0) { - encodings = utils.parseVector( + encodings = fbsUtils.parseVector( data, 'encodings', parseRtpEncodingParameters diff --git a/node/src/rtpParametersTypes.ts b/node/src/rtpParametersTypes.ts new file mode 100644 index 0000000000..fa7e618863 --- /dev/null +++ b/node/src/rtpParametersTypes.ts @@ -0,0 +1,357 @@ +/** + * The RTP capabilities define what mediasoup or an endpoint can receive at + * media level. + */ +export type RtpCapabilities = { + /** + * Supported media and RTX codecs. + */ + codecs?: RtpCodecCapability[]; + + /** + * Supported RTP header extensions. + */ + headerExtensions?: RtpHeaderExtension[]; +}; + +/** + * Media kind ('audio' or 'video'). + */ +export type MediaKind = 'audio' | 'video'; + +/** + * Provides information on the capabilities of a codec within the RTP + * capabilities. The list of media codecs supported by mediasoup and their + * settings is defined in the supportedRtpCapabilities.ts file. + * + * Exactly one RtpCodecCapability will be present for each supported combination + * of parameters that requires a distinct value of preferredPayloadType. For + * example: + * + * - Multiple H264 codecs, each with their own distinct 'packetization-mode' and + * 'profile-level-id' values. + * - Multiple VP9 codecs, each with their own distinct 'profile-id' value. + * + * RtpCodecCapability entries in the mediaCodecs array of RouterOptions do not + * require preferredPayloadType field (if unset, mediasoup will choose a random + * one). If given, make sure it's in the 96-127 range. + */ +export type RtpCodecCapability = { + /** + * Media kind. + */ + kind: MediaKind; + + /** + * The codec MIME media type/subtype (e.g. 'audio/opus', 'video/VP8'). + */ + mimeType: string; + + /** + * The preferred RTP payload type. + */ + preferredPayloadType?: number; + + /** + * Codec clock rate expressed in Hertz. + */ + clockRate: number; + + /** + * The number of channels supported (e.g. two for stereo). Just for audio. + * Default 1. + */ + channels?: number; + + /** + * Codec specific parameters. Some parameters (such as 'packetization-mode' + * and 'profile-level-id' in H264 or 'profile-id' in VP9) are critical for + * codec matching. + */ + parameters?: any; + + /** + * Transport layer and codec-specific feedback messages for this codec. + */ + rtcpFeedback?: RtcpFeedback[]; +}; + +/** + * Direction of RTP header extension. + */ +export type RtpHeaderExtensionDirection = + | 'sendrecv' + | 'sendonly' + | 'recvonly' + | 'inactive'; + +/** + * Provides information relating to supported header extensions. The list of + * RTP header extensions supported by mediasoup is defined in the + * supportedRtpCapabilities.ts file. + * + * mediasoup does not currently support encrypted RTP header extensions. The + * direction field is just present in mediasoup RTP capabilities (retrieved via + * router.rtpCapabilities or mediasoup.getSupportedRtpCapabilities()). It's + * ignored if present in endpoints' RTP capabilities. + */ +export type RtpHeaderExtension = { + /** + * Media kind. + */ + kind: MediaKind; + + /* + * The URI of the RTP header extension, as defined in RFC 5285. + */ + uri: RtpHeaderExtensionUri; + + /** + * The preferred numeric identifier that goes in the RTP packet. Must be + * unique. + */ + preferredId: number; + + /** + * If true, it is preferred that the value in the header be encrypted as per + * RFC 6904. Default false. + */ + preferredEncrypt?: boolean; + + /** + * If 'sendrecv', mediasoup supports sending and receiving this RTP extension. + * 'sendonly' means that mediasoup can send (but not receive) it. 'recvonly' + * means that mediasoup can receive (but not send) it. + */ + direction?: RtpHeaderExtensionDirection; +}; + +/** + * The RTP send parameters describe a media stream received by mediasoup from + * an endpoint through its corresponding mediasoup Producer. These parameters + * may include a mid value that the mediasoup transport will use to match + * received RTP packets based on their MID RTP extension value. + * + * mediasoup allows RTP send parameters with a single encoding and with multiple + * encodings (simulcast). In the latter case, each entry in the encodings array + * must include a ssrc field or a rid field (the RID RTP extension value). Check + * the Simulcast and SVC sections for more information. + * + * The RTP receive parameters describe a media stream as sent by mediasoup to + * an endpoint through its corresponding mediasoup Consumer. The mid value is + * unset (mediasoup does not include the MID RTP extension into RTP packets + * being sent to endpoints). + * + * There is a single entry in the encodings array (even if the corresponding + * producer uses simulcast). The consumer sends a single and continuous RTP + * stream to the endpoint and spatial/temporal layer selection is possible via + * consumer.setPreferredLayers(). + * + * As an exception, previous bullet is not true when consuming a stream over a + * PipeTransport, in which all RTP streams from the associated producer are + * forwarded verbatim through the consumer. + * + * The RTP receive parameters will always have their ssrc values randomly + * generated for all of its encodings (and optional rtx: { ssrc: XXXX } if the + * endpoint supports RTX), regardless of the original RTP send parameters in + * the associated producer. This applies even if the producer's encodings have + * rid set. + */ +export type RtpParameters = { + /** + * The MID RTP extension value as defined in the BUNDLE specification. + */ + mid?: string; + + /** + * Media and RTX codecs in use. + */ + codecs: RtpCodecParameters[]; + + /** + * RTP header extensions in use. + */ + headerExtensions?: RtpHeaderExtensionParameters[]; + + /** + * Transmitted RTP streams and their settings. + */ + encodings?: RtpEncodingParameters[]; + + /** + * Parameters used for RTCP. + */ + rtcp?: RtcpParameters; +}; + +/** + * Provides information on codec settings within the RTP parameters. The list + * of media codecs supported by mediasoup and their settings is defined in the + * supportedRtpCapabilities.ts file. + */ +export type RtpCodecParameters = { + /** + * The codec MIME media type/subtype (e.g. 'audio/opus', 'video/VP8'). + */ + mimeType: string; + + /** + * The value that goes in the RTP Payload Type Field. Must be unique. + */ + payloadType: number; + + /** + * Codec clock rate expressed in Hertz. + */ + clockRate: number; + + /** + * The number of channels supported (e.g. two for stereo). Just for audio. + * Default 1. + */ + channels?: number; + + /** + * Codec-specific parameters available for signaling. Some parameters (such + * as 'packetization-mode' and 'profile-level-id' in H264 or 'profile-id' in + * VP9) are critical for codec matching. + */ + parameters?: any; + + /** + * Transport layer and codec-specific feedback messages for this codec. + */ + rtcpFeedback?: RtcpFeedback[]; +}; + +/** + * Provides information on RTCP feedback messages for a specific codec. Those + * messages can be transport layer feedback messages or codec-specific feedback + * messages. The list of RTCP feedbacks supported by mediasoup is defined in the + * supportedRtpCapabilities.ts file. + */ +export type RtcpFeedback = { + /** + * RTCP feedback type. + */ + type: string; + + /** + * RTCP feedback parameter. + */ + parameter?: string; +}; + +/** + * Provides information relating to an encoding, which represents a media RTP + * stream and its associated RTX stream (if any). + */ +export type RtpEncodingParameters = { + /** + * The media SSRC. + */ + ssrc?: number; + + /** + * The RID RTP extension value. Must be unique. + */ + rid?: string; + + /** + * Codec payload type this encoding affects. If unset, first media codec is + * chosen. + */ + codecPayloadType?: number; + + /** + * RTX stream information. It must contain a numeric ssrc field indicating + * the RTX SSRC. + */ + rtx?: { ssrc: number }; + + /** + * It indicates whether discontinuous RTP transmission will be used. Useful + * for audio (if the codec supports it) and for video screen sharing (when + * static content is being transmitted, this option disables the RTP + * inactivity checks in mediasoup). Default false. + */ + dtx?: boolean; + + /** + * Number of spatial and temporal layers in the RTP stream (e.g. 'L1T3'). + * See webrtc-svc. + */ + scalabilityMode?: string; + + /** + * Others. + */ + scaleResolutionDownBy?: number; + maxBitrate?: number; +}; + +export type RtpHeaderExtensionUri = + | 'urn:ietf:params:rtp-hdrext:sdes:mid' + | 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id' + | 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id' + | 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07' + | 'urn:ietf:params:rtp-hdrext:framemarking' + | 'urn:ietf:params:rtp-hdrext:ssrc-audio-level' + | 'urn:3gpp:video-orientation' + | 'urn:ietf:params:rtp-hdrext:toffset' + | 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01' + | 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time' + | 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time' + | 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay'; + +/** + * Defines a RTP header extension within the RTP parameters. The list of RTP + * header extensions supported by mediasoup is defined in the + * supportedRtpCapabilities.ts file. + * + * mediasoup does not currently support encrypted RTP header extensions and no + * parameters are currently considered. + */ +export type RtpHeaderExtensionParameters = { + /** + * The URI of the RTP header extension, as defined in RFC 5285. + */ + uri: RtpHeaderExtensionUri; + + /** + * The numeric identifier that goes in the RTP packet. Must be unique. + */ + id: number; + + /** + * If true, the value in the header is encrypted as per RFC 6904. Default false. + */ + encrypt?: boolean; + + /** + * Configuration parameters for the header extension. + */ + parameters?: any; +}; + +/** + * Provides information on RTCP settings within the RTP parameters. + * + * If no cname is given in a producer's RTP parameters, the mediasoup transport + * will choose a random one that will be used into RTCP SDES messages sent to + * all its associated consumers. + * + * mediasoup assumes reducedSize to always be true. + */ +export type RtcpParameters = { + /** + * The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages). + */ + cname?: string; + + /** + * Whether reduced size RTCP RFC 5506 is configured (if true) or compound RTCP + * as specified in RFC 3550 (if false). Default true. + */ + reducedSize?: boolean; +}; diff --git a/node/src/RtpStream.ts b/node/src/rtpStreamStatsFbsUtils.ts similarity index 78% rename from node/src/RtpStream.ts rename to node/src/rtpStreamStatsFbsUtils.ts index 47acfd44a0..96d941e739 100644 --- a/node/src/RtpStream.ts +++ b/node/src/rtpStreamStatsFbsUtils.ts @@ -1,45 +1,12 @@ +import { + RtpStreamRecvStats, + RtpStreamSendStats, + BaseRtpStreamStats, + BitrateByLayer, +} from './rtpStreamStatsTypes'; import * as FbsRtpStream from './fbs/rtp-stream'; import * as FbsRtpParameters from './fbs/rtp-parameters'; -type BitrateByLayer = { [key: string]: number }; - -export type RtpStreamRecvStats = BaseRtpStreamStats & { - type: string; - jitter: number; - packetCount: number; - byteCount: number; - bitrate: number; - bitrateByLayer: BitrateByLayer; -}; - -export type RtpStreamSendStats = BaseRtpStreamStats & { - type: string; - packetCount: number; - byteCount: number; - bitrate: number; -}; - -type BaseRtpStreamStats = { - timestamp: number; - ssrc: number; - rtxSsrc?: number; - rid?: string; - kind: string; - mimeType: string; - packetsLost: number; - fractionLost: number; - packetsDiscarded: number; - packetsRetransmitted: number; - packetsRepaired: number; - nackCount: number; - nackPacketCount: number; - pliCount: number; - firCount: number; - score: number; - roundTripTime?: number; - rtxPacketsDiscarded?: number; -}; - export function parseRtpStreamStats( binary: FbsRtpStream.Stats ): RtpStreamRecvStats | RtpStreamSendStats { diff --git a/node/src/rtpStreamStatsTypes.ts b/node/src/rtpStreamStatsTypes.ts new file mode 100644 index 0000000000..aa806d6c7c --- /dev/null +++ b/node/src/rtpStreamStatsTypes.ts @@ -0,0 +1,38 @@ +export type RtpStreamRecvStats = BaseRtpStreamStats & { + type: string; + jitter: number; + packetCount: number; + byteCount: number; + bitrate: number; + bitrateByLayer: BitrateByLayer; +}; + +export type RtpStreamSendStats = BaseRtpStreamStats & { + type: string; + packetCount: number; + byteCount: number; + bitrate: number; +}; + +export type BaseRtpStreamStats = { + timestamp: number; + ssrc: number; + rtxSsrc?: number; + rid?: string; + kind: string; + mimeType: string; + packetsLost: number; + fractionLost: number; + packetsDiscarded: number; + packetsRetransmitted: number; + packetsRepaired: number; + nackCount: number; + nackPacketCount: number; + pliCount: number; + firCount: number; + score: number; + roundTripTime?: number; + rtxPacketsDiscarded?: number; +}; + +export type BitrateByLayer = { [key: string]: number }; diff --git a/node/src/scalabilityModesTypes.ts b/node/src/scalabilityModesTypes.ts new file mode 100644 index 0000000000..8d66dd8c0d --- /dev/null +++ b/node/src/scalabilityModesTypes.ts @@ -0,0 +1,5 @@ +export type ScalabilityMode = { + spatialLayers: number; + temporalLayers: number; + ksvc: boolean; +}; diff --git a/node/src/scalabilityModes.ts b/node/src/scalabilityModesUtils.ts similarity index 69% rename from node/src/scalabilityModes.ts rename to node/src/scalabilityModesUtils.ts index 291255092a..3cbb70ab3e 100644 --- a/node/src/scalabilityModes.ts +++ b/node/src/scalabilityModesUtils.ts @@ -1,14 +1,12 @@ +import { ScalabilityMode } from './scalabilityModesTypes'; + const ScalabilityModeRegex = new RegExp( '^[LS]([1-9]\\d{0,1})T([1-9]\\d{0,1})(_KEY)?' ); -export type ScalabilityMode = { - spatialLayers: number; - temporalLayers: number; - ksvc: boolean; -}; - -export function parse(scalabilityMode?: string): ScalabilityMode { +export function parseScalabilityMode( + scalabilityMode?: string +): ScalabilityMode { const match = ScalabilityModeRegex.exec(scalabilityMode ?? ''); if (match) { diff --git a/node/src/sctpParametersFbsUtils.ts b/node/src/sctpParametersFbsUtils.ts new file mode 100644 index 0000000000..a99f86d88b --- /dev/null +++ b/node/src/sctpParametersFbsUtils.ts @@ -0,0 +1,54 @@ +import * as flatbuffers from 'flatbuffers'; +import type { + SctpStreamParameters, + SctpParametersDump, +} from './sctpParametersTypes'; +import * as FbsSctpParameters from './fbs/sctp-parameters'; + +export function parseSctpParametersDump( + binary: FbsSctpParameters.SctpParameters +): SctpParametersDump { + return { + port: binary.port(), + OS: binary.os(), + MIS: binary.mis(), + maxMessageSize: binary.maxMessageSize(), + sendBufferSize: binary.sendBufferSize(), + sctpBufferedAmount: binary.sctpBufferedAmount(), + isDataChannel: binary.isDataChannel(), + }; +} + +export function serializeSctpStreamParameters( + builder: flatbuffers.Builder, + parameters: SctpStreamParameters +): number { + return FbsSctpParameters.SctpStreamParameters.createSctpStreamParameters( + builder, + parameters.streamId, + parameters.ordered!, + typeof parameters.maxPacketLifeTime === 'number' + ? parameters.maxPacketLifeTime + : null, + typeof parameters.maxRetransmits === 'number' + ? parameters.maxRetransmits + : null + ); +} + +export function parseSctpStreamParameters( + parameters: FbsSctpParameters.SctpStreamParameters +): SctpStreamParameters { + return { + streamId: parameters.streamId(), + ordered: parameters.ordered()!, + maxPacketLifeTime: + parameters.maxPacketLifeTime() !== null + ? parameters.maxPacketLifeTime()! + : undefined, + maxRetransmits: + parameters.maxRetransmits() !== null + ? parameters.maxRetransmits()! + : undefined, + }; +} diff --git a/node/src/SctpParameters.ts b/node/src/sctpParametersTypes.ts similarity index 67% rename from node/src/SctpParameters.ts rename to node/src/sctpParametersTypes.ts index 849ff20143..3e8803408a 100644 --- a/node/src/SctpParameters.ts +++ b/node/src/sctpParametersTypes.ts @@ -1,6 +1,3 @@ -import * as flatbuffers from 'flatbuffers'; -import * as FbsSctpParameters from './fbs/sctp-parameters'; - export type SctpCapabilities = { numStreams: NumSctpStreams; }; @@ -102,51 +99,3 @@ export type SctpParametersDump = { sctpBufferedAmount: number; isDataChannel: boolean; }; - -export function parseSctpParametersDump( - binary: FbsSctpParameters.SctpParameters -): SctpParametersDump { - return { - port: binary.port(), - OS: binary.os(), - MIS: binary.mis(), - maxMessageSize: binary.maxMessageSize(), - sendBufferSize: binary.sendBufferSize(), - sctpBufferedAmount: binary.sctpBufferedAmount(), - isDataChannel: binary.isDataChannel(), - }; -} - -export function serializeSctpStreamParameters( - builder: flatbuffers.Builder, - parameters: SctpStreamParameters -): number { - return FbsSctpParameters.SctpStreamParameters.createSctpStreamParameters( - builder, - parameters.streamId, - parameters.ordered!, - typeof parameters.maxPacketLifeTime === 'number' - ? parameters.maxPacketLifeTime - : null, - typeof parameters.maxRetransmits === 'number' - ? parameters.maxRetransmits - : null - ); -} - -export function parseSctpStreamParameters( - parameters: FbsSctpParameters.SctpStreamParameters -): SctpStreamParameters { - return { - streamId: parameters.streamId(), - ordered: parameters.ordered()!, - maxPacketLifeTime: - parameters.maxPacketLifeTime() !== null - ? parameters.maxPacketLifeTime()! - : undefined, - maxRetransmits: - parameters.maxRetransmits() !== null - ? parameters.maxRetransmits()! - : undefined, - }; -} diff --git a/node/src/SrtpParameters.ts b/node/src/srtpParametersFbsUtils.ts similarity index 81% rename from node/src/SrtpParameters.ts rename to node/src/srtpParametersFbsUtils.ts index 1077ed5207..b7b5f0dc48 100644 --- a/node/src/SrtpParameters.ts +++ b/node/src/srtpParametersFbsUtils.ts @@ -1,30 +1,7 @@ import * as flatbuffers from 'flatbuffers'; +import type { SrtpParameters, SrtpCryptoSuite } from './srtpParametersTypes'; import * as FbsSrtpParameters from './fbs/srtp-parameters'; -/** - * SRTP parameters. - */ -export type SrtpParameters = { - /** - * Encryption and authentication transforms to be used. - */ - cryptoSuite: SrtpCryptoSuite; - - /** - * SRTP keying material (master key and salt) in Base64. - */ - keyBase64: string; -}; - -/** - * SRTP crypto suite. - */ -export type SrtpCryptoSuite = - | 'AEAD_AES_256_GCM' - | 'AEAD_AES_128_GCM' - | 'AES_CM_128_HMAC_SHA1_80' - | 'AES_CM_128_HMAC_SHA1_32'; - export function cryptoSuiteFromFbs( binary: FbsSrtpParameters.SrtpCryptoSuite ): SrtpCryptoSuite { diff --git a/node/src/srtpParametersTypes.ts b/node/src/srtpParametersTypes.ts new file mode 100644 index 0000000000..d9150bbeb3 --- /dev/null +++ b/node/src/srtpParametersTypes.ts @@ -0,0 +1,23 @@ +/** + * SRTP parameters. + */ +export type SrtpParameters = { + /** + * Encryption and authentication transforms to be used. + */ + cryptoSuite: SrtpCryptoSuite; + + /** + * SRTP keying material (master key and salt) in Base64. + */ + keyBase64: string; +}; + +/** + * SRTP crypto suite. + */ +export type SrtpCryptoSuite = + | 'AEAD_AES_256_GCM' + | 'AEAD_AES_128_GCM' + | 'AES_CM_128_HMAC_SHA1_80' + | 'AES_CM_128_HMAC_SHA1_32'; diff --git a/node/src/supportedRtpCapabilities.ts b/node/src/supportedRtpCapabilities.ts index 042e2746cb..2a0d1f5788 100644 --- a/node/src/supportedRtpCapabilities.ts +++ b/node/src/supportedRtpCapabilities.ts @@ -1,4 +1,4 @@ -import { RtpCapabilities } from './RtpParameters'; +import type { RtpCapabilities } from './rtpParametersTypes'; const supportedRtpCapabilities: RtpCapabilities = { codecs: [ diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index aaa922390d..7467dac16a 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -1,6 +1,6 @@ import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, ActiveSpeakerObserverEvents } from '../types'; +import type { WorkerEvents, ActiveSpeakerObserverEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -48,6 +48,7 @@ test('router.createActiveSpeakerObserver() succeeds', async () => { expect(onObserverNewRtpObserver).toHaveBeenCalledWith(activeSpeakerObserver); expect(typeof activeSpeakerObserver.id).toBe('string'); expect(activeSpeakerObserver.closed).toBe(false); + expect(activeSpeakerObserver.type).toBe('activespeaker'); expect(activeSpeakerObserver.paused).toBe(false); expect(activeSpeakerObserver.appData).toEqual({}); @@ -85,8 +86,8 @@ test('activeSpeakerObserver.pause() and resume() succeed', async () => { }, 2000); test('activeSpeakerObserver.close() succeeds', async () => { - const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver({ - maxEntries: 8, + const activeSpeakerObserver = await ctx.router!.createActiveSpeakerObserver({ + interval: 500, }); let dump = await ctx.router!.dump(); @@ -103,7 +104,7 @@ test('activeSpeakerObserver.close() succeeds', async () => { }, 2000); test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () => { - const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); + const activeSpeakerObserver = await ctx.router!.createActiveSpeakerObserver(); const promise = enhancedOnce( activeSpeakerObserver, @@ -117,7 +118,7 @@ test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () = }, 2000); test('ActiveSpeakerObserver emits "routerclose" if Worker is closed', async () => { - const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); + const activeSpeakerObserver = await ctx.router!.createActiveSpeakerObserver(); const promise = enhancedOnce( activeSpeakerObserver, diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index f1a1a5fb17..e10d1245a8 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -1,6 +1,6 @@ import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, AudioLevelObserverEvents } from '../types'; +import type { WorkerEvents, AudioLevelObserverEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -48,6 +48,7 @@ test('router.createAudioLevelObserver() succeeds', async () => { expect(onObserverNewRtpObserver).toHaveBeenCalledWith(audioLevelObserver); expect(typeof audioLevelObserver.id).toBe('string'); expect(audioLevelObserver.closed).toBe(false); + expect(audioLevelObserver.type).toBe('audiolevel'); expect(audioLevelObserver.paused).toBe(false); expect(audioLevelObserver.appData).toEqual({}); diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index aad102f089..286076c27a 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -1,7 +1,8 @@ import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, ConsumerEvents } from '../types'; +import type { WorkerEvents, ConsumerEvents } from '../types'; +import type { ConsumerImpl } from '../Consumer'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; import { @@ -975,7 +976,7 @@ test('consumer.enableTraceEvent() succeed', async () => { expect(dump1.traceEventTypes).toEqual(expect.arrayContaining(['rtp', 'pli'])); - await audioConsumer.enableTraceEvent([]); + await audioConsumer.enableTraceEvent(); const dump2 = await audioConsumer.dump(); @@ -1052,8 +1053,8 @@ test('Consumer emits "score"', async () => { rtpCapabilities: ctx.consumerDeviceCapabilities, }); - // Private API. - const channel = audioConsumer.channelForTesting; + // API not exposed in the interface. + const channel = (audioConsumer as ConsumerImpl).channelForTesting; const onScore = jest.fn(); audioConsumer.on('score', onScore); diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index f61bb8291c..d8e800855b 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -1,6 +1,6 @@ import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, DataConsumerEvents } from '../types'; +import type { WorkerEvents, DataConsumerEvents } from '../types'; import * as utils from '../utils'; type TestContext = { diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index 4f490792ce..1dbd8691e7 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -1,6 +1,6 @@ import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, DataProducerEvents } from '../types'; +import type { WorkerEvents, DataProducerEvents } from '../types'; import * as utils from '../utils'; type TestContext = { diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index e8812257b4..a552e78b39 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -1,6 +1,7 @@ import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, DirectTransportEvents } from '../types'; +import type { DirectTransportEvents } from '../DirectTransportTypes'; +import type { WorkerEvents } from '../types'; type TestContext = { worker?: mediasoup.types.Worker; @@ -39,13 +40,13 @@ test('router.createDirectTransport() succeeds', async () => { expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(directTransport); expect(typeof directTransport.id).toBe('string'); + expect(directTransport.type).toBe('direct'); expect(directTransport.closed).toBe(false); expect(directTransport.appData).toEqual({ foo: 'bar' }); const dump = await directTransport.dump(); expect(dump.id).toBe(directTransport.id); - expect(dump.direct).toBe(true); expect(dump.producerIds).toEqual([]); expect(dump.consumerIds).toEqual([]); expect(dump.dataProducerIds).toEqual([]); diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 854636ffa4..2bffccc5a8 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -1,7 +1,7 @@ import { pickPort } from 'pick-port'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { +import type { WorkerEvents, ConsumerEvents, ProducerObserverEvents, @@ -524,6 +524,8 @@ test('router.createPipeTransport() with enableRtx succeeds', async () => { enableRtx: true, }); + expect(pipeTransport.type).toBe('pipe'); + const pipeConsumer = await pipeTransport.consume({ producerId: ctx.videoProducer!.id, }); @@ -1081,7 +1083,7 @@ test('router.pipeToRouter() called in two Routers passing one to each other as a const pipeTransportsB = new Map(); routerA.observer.on('newtransport', transport => { - if (transport.constructor.name !== 'PipeTransport') { + if (transport.constructor.name !== 'PipeTransportImpl') { return; } @@ -1090,7 +1092,7 @@ test('router.pipeToRouter() called in two Routers passing one to each other as a }); routerB.observer.on('newtransport', transport => { - if (transport.constructor.name !== 'PipeTransport') { + if (transport.constructor.name !== 'PipeTransportImpl') { return; } diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index abd7c326b9..9fd58564a6 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -2,7 +2,7 @@ import * as os from 'node:os'; import { pickPort } from 'pick-port'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, PlainTransportEvents } from '../types'; +import type { WorkerEvents, PlainTransportEvents } from '../types'; import * as utils from '../utils'; const IS_WINDOWS = os.platform() === 'win32'; @@ -91,6 +91,7 @@ test('router.createPlainTransport() succeeds', async () => { expect(onObserverNewTransport).toHaveBeenCalledWith(plainTransport2); expect(typeof plainTransport2.id).toBe('string'); expect(plainTransport2.closed).toBe(false); + expect(plainTransport2.type).toBe('plain'); expect(plainTransport2.appData).toEqual({ foo: 'bar' }); expect(typeof plainTransport2.tuple).toBe('object'); // @deprecated Use tuple.localAddress instead. @@ -111,7 +112,6 @@ test('router.createPlainTransport() succeeds', async () => { const dump1 = await plainTransport2.dump(); expect(dump1.id).toBe(plainTransport2.id); - expect(dump1.direct).toBe(false); expect(dump1.producerIds).toEqual([]); expect(dump1.consumerIds).toEqual([]); expect(dump1.tuple).toEqual(plainTransport2.tuple); @@ -166,7 +166,6 @@ test('router.createPlainTransport() succeeds', async () => { const dump2 = await transport2.dump(); expect(dump2.id).toBe(transport2.id); - expect(dump2.direct).toBe(false); expect(dump2.tuple).toEqual(transport2.tuple); expect(dump2.rtcpTuple).toEqual(transport2.rtcpTuple); expect(dump2.sctpState).toBeUndefined(); @@ -196,7 +195,7 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' ).rejects.toThrow(TypeError); await expect( - ctx.router!.createPipeTransport({ + ctx.router!.createPlainTransport({ listenInfo: { protocol: 'tcp', ip: '127.0.0.1' }, }) ).rejects.toThrow(TypeError); diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index 661c60faf1..38ad33607f 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -1,7 +1,8 @@ import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, ProducerEvents } from '../types'; +import type { WorkerEvents, ProducerEvents } from '../types'; +import type { ProducerImpl } from '../Producer'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; import { @@ -680,7 +681,7 @@ test('producer.enableTraceEvent() succeed', async () => { expect(dump1.traceEventTypes).toEqual(expect.arrayContaining(['rtp', 'pli'])); - await audioProducer.enableTraceEvent([]); + await audioProducer.enableTraceEvent(); const dump2 = await audioProducer.dump(); @@ -726,8 +727,8 @@ test('Producer emits "score"', async () => { ctx.videoProducerOptions ); - // Private API. - const channel = videoProducer.channelForTesting; + // API not exposed in the interface. + const channel = (videoProducer as ProducerImpl).channelForTesting; const onScore = jest.fn(); videoProducer.on('score', onScore); diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index 615ff4176c..0affb75ef6 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -1,6 +1,7 @@ import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, RouterEvents } from '../types'; +import type { WorkerImpl } from '../Worker'; +import type { WorkerEvents, RouterEvents } from '../types'; import { InvalidStateError } from '../errors'; import * as utils from '../utils'; @@ -94,15 +95,15 @@ test('worker.createRouter() succeeds', async () => { mapDataConsumerIdDataProducerId: {}, }); - // Private API. - expect(ctx.worker!.routersForTesting.size).toBe(1); + // API not exposed in the interface. + expect((ctx.worker! as WorkerImpl).routersForTesting.size).toBe(1); ctx.worker!.close(); expect(router.closed).toBe(true); - // Private API. - expect(ctx.worker!.routersForTesting.size).toBe(0); + // API not exposed in the interface. + expect((ctx.worker! as WorkerImpl).routersForTesting.size).toBe(0); }, 2000); test('worker.createRouter() with wrong arguments rejects with TypeError', async () => { diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index a6c5e8bec0..669e8ab8ef 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -1,7 +1,10 @@ import { pickPort } from 'pick-port'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, WebRtcServerEvents } from '../types'; +import type { WorkerImpl } from '../Worker'; +import type { WorkerEvents, WebRtcServerEvents } from '../types'; +import type { WebRtcServerImpl } from '../WebRtcServer'; +import type { RouterImpl } from '../Router'; import { InvalidStateError } from '../errors'; type TestContext = { @@ -80,15 +83,15 @@ test('worker.createWebRtcServer() succeeds', async () => { tupleHashes: [], }); - // Private API. - expect(ctx.worker!.webRtcServersForTesting.size).toBe(1); + // API not exposed in the interface. + expect((ctx.worker! as WorkerImpl).webRtcServersForTesting.size).toBe(1); ctx.worker!.close(); expect(webRtcServer.closed).toBe(true); - // Private API. - expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); + // API not exposed in the interface. + expect((ctx.worker! as WorkerImpl).webRtcServersForTesting.size).toBe(0); }, 2000); test('worker.createWebRtcServer() with portRange succeeds', async () => { @@ -149,15 +152,15 @@ test('worker.createWebRtcServer() with portRange succeeds', async () => { tupleHashes: [], }); - // Private API. - expect(ctx.worker!.webRtcServersForTesting.size).toBe(1); + // API not exposed in the interface. + expect((ctx.worker! as WorkerImpl).webRtcServersForTesting.size).toBe(1); ctx.worker!.close(); expect(webRtcServer.closed).toBe(true); - // Private API. - expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); + // API not exposed in the interface. + expect((ctx.worker! as WorkerImpl).webRtcServersForTesting.size).toBe(0); }, 2000); test('worker.createWebRtcServer() without specifying port/portRange succeeds', async () => { @@ -205,15 +208,15 @@ test('worker.createWebRtcServer() without specifying port/portRange succeeds', a tupleHashes: [], }); - // Private API. - expect(ctx.worker!.webRtcServersForTesting.size).toBe(1); + // API not exposed in the interface. + expect((ctx.worker! as WorkerImpl).webRtcServersForTesting.size).toBe(1); ctx.worker!.close(); expect(webRtcServer.closed).toBe(true); - // Private API. - expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); + // API not exposed in the interface. + expect((ctx.worker! as WorkerImpl).webRtcServersForTesting.size).toBe(0); }, 2000); test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', async () => { @@ -435,8 +438,12 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is expect(transport.iceState).toBe('new'); expect(transport.iceSelectedTuple).toBeUndefined(); - expect(webRtcServer.webRtcTransportsForTesting.size).toBe(1); - expect(router.transportsForTesting.size).toBe(1); + // API not exposed in the interface. + expect( + (webRtcServer as WebRtcServerImpl).webRtcTransportsForTesting.size + ).toBe(1); + // API not exposed in the interface. + expect((router as RouterImpl).transportsForTesting.size).toBe(1); await expect(webRtcServer.dump()).resolves.toMatchObject({ id: webRtcServer.id, @@ -454,8 +461,12 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is expect(transport.closed).toBe(true); expect(onObserverWebRtcTransportUnhandled).toHaveBeenCalledTimes(1); expect(onObserverWebRtcTransportUnhandled).toHaveBeenCalledWith(transport); - expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); - expect(router.transportsForTesting.size).toBe(0); + // API not exposed in the interface. + expect( + (webRtcServer as WebRtcServerImpl).webRtcTransportsForTesting.size + ).toBe(0); + // API not exposed in the interface. + expect((router as RouterImpl).transportsForTesting.size).toBe(0); await expect(webRtcServer.dump()).resolves.toMatchObject({ id: webRtcServer.id, @@ -531,8 +542,12 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer expect(transport.iceState).toBe('new'); expect(transport.iceSelectedTuple).toBeUndefined(); - expect(webRtcServer.webRtcTransportsForTesting.size).toBe(1); - expect(router.transportsForTesting.size).toBe(1); + // API not exposed in the interface. + expect( + (webRtcServer as WebRtcServerImpl).webRtcTransportsForTesting.size + ).toBe(1); + // API not exposed in the interface. + expect((router as RouterImpl).transportsForTesting.size).toBe(1); await expect(webRtcServer.dump()).resolves.toMatchObject({ id: webRtcServer.id, @@ -581,8 +596,12 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer expect(transport.iceSelectedTuple).toBe(undefined); expect(transport.dtlsState).toBe('closed'); expect(transport.sctpState).toBe(undefined); - expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); - expect(router.transportsForTesting.size).toBe(0); + // API not exposed in the interface. + expect( + (webRtcServer as WebRtcServerImpl).webRtcTransportsForTesting.size + ).toBe(0); + // API not exposed in the interface. + expect((router as RouterImpl).transportsForTesting.size).toBe(0); await expect(ctx.worker!.dump()).resolves.toMatchObject({ pid: ctx.worker!.pid, diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 400f25c11e..a241bcf2f7 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -2,9 +2,11 @@ import { pickPort } from 'pick-port'; import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents, WebRtcTransportEvents } from '../types'; +import type { WorkerEvents, WebRtcTransportEvents } from '../types'; +import type { WebRtcTransportImpl } from '../WebRtcTransport'; +import type { TransportTuple } from '../TransportTypes'; +import { serializeProtocol } from '../Transport'; import * as utils from '../utils'; -import { serializeProtocol, TransportTuple } from '../Transport'; import { Notification, Body as NotificationBody, @@ -123,6 +125,7 @@ test('router.createWebRtcTransport() succeeds', async () => { expect(onObserverNewTransport).toHaveBeenCalledWith(webRtcTransport); expect(typeof webRtcTransport.id).toBe('string'); expect(webRtcTransport.closed).toBe(false); + expect(webRtcTransport.type).toBe('webrtc'); expect(webRtcTransport.appData).toEqual({ foo: 'bar' }); expect(webRtcTransport.iceRole).toBe('controlled'); expect(typeof webRtcTransport.iceParameters).toBe('object'); @@ -182,7 +185,6 @@ test('router.createWebRtcTransport() succeeds', async () => { const dump = await webRtcTransport.dump(); expect(dump.id).toBe(webRtcTransport.id); - expect(dump.direct).toBe(false); expect(dump.producerIds).toEqual([]); expect(dump.consumerIds).toEqual([]); expect(dump.iceRole).toBe(webRtcTransport.iceRole); @@ -620,7 +622,7 @@ test('transport.enableTraceEvent() succeed', async () => { traceEventTypes: ['probation'], }); - await webRtcTransport.enableTraceEvent([]); + await webRtcTransport.enableTraceEvent(); await expect(webRtcTransport.dump()).resolves.toMatchObject({ traceEventTypes: [], }); @@ -667,8 +669,8 @@ test('WebRtcTransport events succeed', async () => { ], }); - // Private API. - const channel = webRtcTransport.channelForTesting; + // API not exposed in the interface. + const channel = (webRtcTransport as WebRtcTransportImpl).channelForTesting; const onIceStateChange = jest.fn(); webRtcTransport.on('icestatechange', onIceStateChange); diff --git a/node/src/test/test-Worker.ts b/node/src/test/test-Worker.ts index b9e9a1ec16..ecf6210059 100644 --- a/node/src/test/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -3,7 +3,7 @@ import * as process from 'node:process'; import * as path from 'node:path'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents } from '../types'; +import type { WorkerEvents } from '../types'; import { InvalidStateError } from '../errors'; test('Worker.workerBin matches mediasoup-worker absolute path', () => { @@ -43,7 +43,7 @@ test('createWorker() succeeds', async () => { expect(onObserverNewWorker).toHaveBeenCalledTimes(1); expect(onObserverNewWorker).toHaveBeenCalledWith(worker1); - expect(worker1.constructor.name).toBe('Worker'); + expect(worker1.constructor.name).toBe('WorkerImpl'); expect(typeof worker1.pid).toBe('number'); expect(worker1.closed).toBe(false); expect(worker1.died).toBe(false); @@ -67,7 +67,7 @@ test('createWorker() succeeds', async () => { appData: { foo: 456 }, }); - expect(worker2.constructor.name).toBe('Worker'); + expect(worker2.constructor.name).toBe('WorkerImpl'); expect(typeof worker2.pid).toBe('number'); expect(worker2.closed).toBe(false); expect(worker2.died).toBe(false); diff --git a/node/src/test/test-mediasoup.ts b/node/src/test/test-mediasoup.ts index bfafad5f7f..98dad17115 100644 --- a/node/src/test/test-mediasoup.ts +++ b/node/src/test/test-mediasoup.ts @@ -2,7 +2,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; import { enhancedOnce } from '../enhancedEvents'; import * as mediasoup from '../'; -import { WorkerEvents } from '../types'; +import type { WorkerEvents } from '../types'; const PKG = JSON.parse( fs.readFileSync(path.join(__dirname, '..', '..', '..', 'package.json'), { diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index 4b8ab50450..e1925fe7a1 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -1,6 +1,6 @@ import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents } from '../types'; +import type { WorkerEvents } from '../types'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index e344c1a484..87a79cbcc6 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -3,7 +3,7 @@ import * as dgram from 'node:dgram'; import * as sctp from 'sctp'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; -import { WorkerEvents } from '../types'; +import type { WorkerEvents } from '../types'; type TestContext = { worker?: mediasoup.types.Worker; diff --git a/node/src/types.ts b/node/src/types.ts index 14c9e4a0c1..53fda44fc1 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -1,30 +1,29 @@ -export type { Observer, ObserverEvents, LogEventListeners } from './index'; -export type * from './RtpParameters'; -export type * from './SctpParameters'; -export type * from './SrtpParameters'; -export type * from './scalabilityModes'; +export type { Observer, ObserverEvents } from './index'; +export type * from './WorkerTypes'; +export type * from './WebRtcServerTypes'; +export type * from './RouterTypes'; +export type * from './TransportTypes'; +export type * from './WebRtcTransportTypes'; +export type * from './PlainTransportTypes'; +export type * from './PipeTransportTypes'; +export type * from './DirectTransportTypes'; +export type * from './ProducerTypes'; +export type * from './ConsumerTypes'; +export type * from './DataProducerTypes'; +export type * from './DataConsumerTypes'; +export type * from './RtpObserverTypes'; +export type * from './ActiveSpeakerObserverTypes'; +export type * from './AudioLevelObserverTypes'; +export type * from './rtpParametersTypes'; +export type * from './rtpStreamStatsTypes'; +export type * from './sctpParametersTypes'; +export type * from './srtpParametersTypes'; +export type * from './scalabilityModesTypes'; -export * from './Worker'; -export * from './WebRtcServer'; -export * from './Router'; -export * from './Transport'; -export * from './WebRtcTransport'; -export * from './PlainTransport'; -export * from './PipeTransport'; -export * from './DirectTransport'; -export * from './Producer'; -export * from './Consumer'; -export * from './DataProducer'; -export * from './DataConsumer'; -export * from './RtpObserver'; -export * from './ActiveSpeakerObserver'; -export * from './AudioLevelObserver'; +// TODO: Here we are exporting real classes rather than types. This should +// be exported somehow else rather than in mediasoup.types namespace. export * from './errors'; -export type AppData = { - [key: string]: unknown; -}; - type Only = { [P in keyof T]: T[P]; } & { @@ -32,3 +31,16 @@ type Only = { }; export type Either = Only | Only; + +export type AppData = { + [key: string]: unknown; +}; + +/** + * Event listeners for mediasoup generated logs. + */ +export type LogEventListeners = { + ondebug?: (namespace: string, log: string) => void; + onwarn?: (namespace: string, log: string) => void; + onerror?: (namespace: string, log: string, error?: Error) => void; +}; diff --git a/node/src/utils.ts b/node/src/utils.ts index f7c8e8c8b9..e3cba37a8f 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -1,6 +1,4 @@ import { randomUUID, randomInt } from 'node:crypto'; -import { ProducerType } from './Producer'; -import { Type as FbsRtpParametersType } from './fbs/rtp-parameters'; /** * Clones the given value. @@ -32,148 +30,6 @@ export function generateRandomNumber(): number { return randomInt(100_000_000, 999_999_999); } -/** - * Get the flatbuffers RtpParameters type for a given Producer. - */ -export function getRtpParametersType( - producerType: ProducerType, - pipe: boolean -): FbsRtpParametersType { - if (pipe) { - return FbsRtpParametersType.PIPE; - } - - switch (producerType) { - case 'simple': { - return FbsRtpParametersType.SIMPLE; - } - - case 'simulcast': { - return FbsRtpParametersType.SIMULCAST; - } - - case 'svc': { - return FbsRtpParametersType.SVC; - } - } -} - -/** - * Parse flatbuffers vector into an array of the given type. - */ -export function parseVector( - binary: any, - methodName: string, - parseFn?: (binary2: any) => Type -): Type[] { - const array: Type[] = []; - - for (let i = 0; i < binary[`${methodName}Length`](); ++i) { - if (parseFn) { - array.push(parseFn(binary[methodName](i))); - } else { - array.push(binary[methodName](i) as Type); - } - } - - return array; -} - -/** - * Parse flatbuffers vector of StringString into the corresponding array. - */ -export function parseStringStringVector( - binary: any, - methodName: string -): { key: string; value: string }[] { - const array: { key: string; value: string }[] = []; - - for (let i = 0; i < binary[`${methodName}Length`](); ++i) { - const kv = binary[methodName](i)!; - - array.push({ key: kv.key(), value: kv.value() }); - } - - return array; -} - -/** - * Parse flatbuffers vector of StringUint8 into the corresponding array. - */ -export function parseStringUint8Vector( - binary: any, - methodName: string -): { key: string; value: number }[] { - const array: { key: string; value: number }[] = []; - - for (let i = 0; i < binary[`${methodName}Length`](); ++i) { - const kv = binary[methodName](i)!; - - array.push({ key: kv.key(), value: kv.value() }); - } - - return array; -} - -/** - * Parse flatbuffers vector of Uint16String into the corresponding array. - */ -export function parseUint16StringVector( - binary: any, - methodName: string -): { key: number; value: string }[] { - const array: { key: number; value: string }[] = []; - - for (let i = 0; i < binary[`${methodName}Length`](); ++i) { - const kv = binary[methodName](i)!; - - array.push({ key: kv.key(), value: kv.value() }); - } - - return array; -} - -/** - * Parse flatbuffers vector of Uint32String into the corresponding array. - */ -export function parseUint32StringVector( - binary: any, - methodName: string -): { key: number; value: string }[] { - const array: { key: number; value: string }[] = []; - - for (let i = 0; i < binary[`${methodName}Length`](); ++i) { - const kv = binary[methodName](i)!; - - array.push({ key: kv.key(), value: kv.value() }); - } - - return array; -} - -/** - * Parse flatbuffers vector of StringStringArray into the corresponding array. - */ -export function parseStringStringArrayVector( - binary: any, - methodName: string -): { key: string; values: string[] }[] { - const array: { key: string; values: string[] }[] = []; - - for (let i = 0; i < binary[`${methodName}Length`](); ++i) { - const kv = binary[methodName](i)!; - const values: string[] = []; - - for (let i2 = 0; i2 < kv.valuesLength(); ++i2) { - values.push(kv.values(i2)! as string); - } - - array.push({ key: kv.key(), values }); - } - - return array; -} - /** * Make an object or array recursively immutable. * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze. From e257dbc8de0a408020fcf074e668ef0d88e65210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 11 Nov 2024 13:06:37 +0100 Subject: [PATCH 519/525] 3.15.0 --- CHANGELOG.md | 2 ++ package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aadea8be76..8dab8ee44b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +### 3.15.0 + - Node: Add TypeScript interfaces for all exported classes ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)). - Node: Add new `transport.type` getter than returns `'webrtc' | 'plain' | 'pipe' | 'direct'` ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)). - Node: Add new `rtpObserver.type` getter than returns `'activespeaker' | 'audiolevel'` ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)). diff --git a/package-lock.json b/package-lock.json index 8a75a725e5..bdbaeac45a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.16", + "version": "3.15.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.16", + "version": "3.15.0", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -31,7 +31,7 @@ "eslint-plugin-prettier": "^5.2.1", "globals": "^15.12.0", "jest": "^29.7.0", - "marked": "^14.1.4", + "marked": "^15.0.0", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", @@ -4722,9 +4722,9 @@ } }, "node_modules/marked": { - "version": "14.1.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.4.tgz", - "integrity": "sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.0.tgz", + "integrity": "sha512-0mouKmBROJv/WSHJBPZZyYofUgawMChnD5je/g+aOBXsHDjb/IsnTQj7mnhQZu+qPJmRQ0ecX3mLGEUm3BgwYA==", "dev": true, "license": "MIT", "bin": { @@ -9750,9 +9750,9 @@ } }, "marked": { - "version": "14.1.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.4.tgz", - "integrity": "sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.0.tgz", + "integrity": "sha512-0mouKmBROJv/WSHJBPZZyYofUgawMChnD5je/g+aOBXsHDjb/IsnTQj7mnhQZu+qPJmRQ0ecX3mLGEUm3BgwYA==", "dev": true }, "meow": { diff --git a/package.json b/package.json index 164a1512d0..5b0fd08541 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.16", + "version": "3.15.0", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -120,7 +120,7 @@ "eslint-plugin-prettier": "^5.2.1", "globals": "^15.12.0", "jest": "^29.7.0", - "marked": "^14.1.4", + "marked": "^15.0.0", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", From acb841bfc887b326201b6fa19c310e25e23270d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 12 Nov 2024 13:30:58 +0100 Subject: [PATCH 520/525] Expose extras namespace (#1464) --- CHANGELOG.md | 2 ++ node/src/RtpObserver.ts | 2 +- node/src/Transport.ts | 2 +- node/src/extras.ts | 1 + node/src/index.ts | 5 +++++ 5 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 node/src/extras.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dab8ee44b..bc416bf343 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +- Expose `extras` namespace which exports `EnhancedEventEmitter` and `enhancedOnce()` for now ([PR #1464](https://github.com/versatica/mediasoup/pull/1464)). + ### 3.15.0 - Node: Add TypeScript interfaces for all exported classes ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)). diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index ec42cedc6d..93c26e5231 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -53,7 +53,7 @@ export abstract class RtpObserverImpl< // Observer instance. readonly #observer: Observer; - constructor( + protected constructor( { internal, channel, diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 7bbc28f4dd..d298dc5f0b 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -175,7 +175,7 @@ export abstract class TransportImpl< // Observer instance. readonly #observer: Observer; - constructor( + protected constructor( { internal, data, diff --git a/node/src/extras.ts b/node/src/extras.ts new file mode 100644 index 0000000000..72ecee7755 --- /dev/null +++ b/node/src/extras.ts @@ -0,0 +1 @@ +export { EnhancedEventEmitter, enhancedOnce } from './enhancedEvents'; diff --git a/node/src/index.ts b/node/src/index.ts index c366b0d357..241c928ab6 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -146,3 +146,8 @@ export function getSupportedRtpCapabilities(): RtpCapabilities { * Expose parseScalabilityMode() function. */ export { parseScalabilityMode } from './scalabilityModesUtils'; + +/** + * Expose extras module. + */ +export * as extras from './extras'; From f2e39e82e37b2c7bfc241caec2d77995904cac86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 12 Nov 2024 13:33:38 +0100 Subject: [PATCH 521/525] 3.15.1 --- CHANGELOG.md | 2 + package-lock.json | 198 +++++++++++++++++++++++----------------------- package.json | 4 +- 3 files changed, 103 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc416bf343..f4ada478b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +### 3.15.1 + - Expose `extras` namespace which exports `EnhancedEventEmitter` and `enhancedOnce()` for now ([PR #1464](https://github.com/versatica/mediasoup/pull/1464)). ### 3.15.0 diff --git a/package-lock.json b/package-lock.json index bdbaeac45a..f8c60f2832 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.15.0", + "version": "3.15.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.15.0", + "version": "3.15.1", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -38,7 +38,7 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.3", - "typescript-eslint": "^8.13.0" + "typescript-eslint": "^8.14.0" }, "engines": { "node": ">=18" @@ -1954,17 +1954,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", - "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", + "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/type-utils": "8.13.0", - "@typescript-eslint/utils": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/type-utils": "8.14.0", + "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1988,16 +1988,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", - "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", + "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/typescript-estree": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4" }, "engines": { @@ -2017,14 +2017,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", - "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", + "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0" + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2035,14 +2035,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", - "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", + "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.13.0", - "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/utils": "8.14.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2060,9 +2060,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", - "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", + "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", "dev": true, "license": "MIT", "engines": { @@ -2074,14 +2074,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", - "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", + "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2129,16 +2129,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", - "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", + "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/typescript-estree": "8.13.0" + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2152,13 +2152,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", - "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", + "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/types": "8.14.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -6096,15 +6096,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.13.0.tgz", - "integrity": "sha512-vIMpDRJrQd70au2G8w34mPps0ezFSPMEX4pXkTzUkrNbRX+36ais2ksGWN0esZL+ZMaFJEneOBHzCgSqle7DHw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.14.0.tgz", + "integrity": "sha512-K8fBJHxVL3kxMmwByvz8hNdBJ8a0YqKzKDX6jRlrjMuNXyd5T2V02HIq37+OiWXvUUOXgOOGiSSOh26Mh8pC3w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.13.0", - "@typescript-eslint/parser": "8.13.0", - "@typescript-eslint/utils": "8.13.0" + "@typescript-eslint/eslint-plugin": "8.14.0", + "@typescript-eslint/parser": "8.14.0", + "@typescript-eslint/utils": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7821,16 +7821,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", - "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", + "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/type-utils": "8.13.0", - "@typescript-eslint/utils": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/type-utils": "8.14.0", + "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7838,54 +7838,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", - "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", + "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/typescript-estree": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", - "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", + "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", "dev": true, "requires": { - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0" + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0" } }, "@typescript-eslint/type-utils": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", - "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", + "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.13.0", - "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/utils": "8.14.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", - "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", + "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", - "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", + "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", "dev": true, "requires": { - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7915,24 +7915,24 @@ } }, "@typescript-eslint/utils": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", - "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", + "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/typescript-estree": "8.13.0" + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", - "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", + "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", "dev": true, "requires": { - "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/types": "8.14.0", "eslint-visitor-keys": "^3.4.3" } }, @@ -10646,14 +10646,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.13.0.tgz", - "integrity": "sha512-vIMpDRJrQd70au2G8w34mPps0ezFSPMEX4pXkTzUkrNbRX+36ais2ksGWN0esZL+ZMaFJEneOBHzCgSqle7DHw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.14.0.tgz", + "integrity": "sha512-K8fBJHxVL3kxMmwByvz8hNdBJ8a0YqKzKDX6jRlrjMuNXyd5T2V02HIq37+OiWXvUUOXgOOGiSSOh26Mh8pC3w==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.13.0", - "@typescript-eslint/parser": "8.13.0", - "@typescript-eslint/utils": "8.13.0" + "@typescript-eslint/eslint-plugin": "8.14.0", + "@typescript-eslint/parser": "8.14.0", + "@typescript-eslint/utils": "8.14.0" } }, "undici-types": { diff --git a/package.json b/package.json index 5b0fd08541..a3c3d16a6d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.15.0", + "version": "3.15.1", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)", @@ -127,6 +127,6 @@ "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.3", - "typescript-eslint": "^8.13.0" + "typescript-eslint": "^8.14.0" } } From 300e30989d6bbb0f5d7a0e389841d68583dccb38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:55:47 +0100 Subject: [PATCH 522/525] Bump cross-spawn from 7.0.3 to 7.0.6 in the npm_and_yarn group (#1467) Bumps the npm_and_yarn group with 1 update: [cross-spawn](https://github.com/moxystudio/node-cross-spawn). Updates `cross-spawn` from 7.0.3 to 7.0.6 - [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md) - [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6) --- updated-dependencies: - dependency-name: cross-spawn dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8c60f2832..ceaf12c1a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2659,9 +2659,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -8291,9 +8291,9 @@ } }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", From f3bbd269169f2dbe85c9e4852614603bce362761 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:57:51 +0100 Subject: [PATCH 523/525] Bump cross-spawn (#1468) Bumps the npm_and_yarn group with 1 update in the /worker/scripts directory: [cross-spawn](https://github.com/moxystudio/node-cross-spawn). Updates `cross-spawn` from 7.0.3 to 7.0.6 - [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md) - [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6) --- updated-dependencies: - dependency-name: cross-spawn dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- worker/scripts/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/worker/scripts/package-lock.json b/worker/scripts/package-lock.json index 71d690bdba..37003a5f7c 100644 --- a/worker/scripts/package-lock.json +++ b/worker/scripts/package-lock.json @@ -204,9 +204,9 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -742,9 +742,9 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", From 15f8b4c1a910c5378b388c1862e32cfabf1b0d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 21 Nov 2024 15:14:43 +0100 Subject: [PATCH 524/525] Fix crash when two transports use colliding port ranges (#1469) --- CHANGELOG.md | 2 + package-lock.json | 402 ++++++++++++++++++--------------- package.json | 10 +- worker/src/RTC/PortManager.cpp | 8 +- 4 files changed, 229 insertions(+), 193 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4ada478b1..78b6d59521 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +- `Worker`: Fix crash when using colliding `portRange` values in different transports ([PR #1469](https://github.com/versatica/mediasoup/pull/1469)). + ### 3.15.1 - Expose `extras` namespace which exports `EnhancedEventEmitter` and `enhancedOnce()` for now ([PR #1464](https://github.com/versatica/mediasoup/pull/1464)). diff --git a/package-lock.json b/package-lock.json index ceaf12c1a1..d41cc88211 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,25 +20,25 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.14.0", + "@eslint/js": "^9.15.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.14", - "@types/node": "^22.9.0", - "eslint": "^9.14.0", + "@types/node": "^22.9.1", + "eslint": "^9.15.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.12.0", "jest": "^29.7.0", - "marked": "^15.0.0", + "marked": "^15.0.2", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.3", - "typescript-eslint": "^8.14.0" + "typescript-eslint": "^8.15.0" }, "engines": { "node": ">=18" @@ -749,10 +749,11 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", @@ -763,9 +764,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -773,10 +774,11 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -800,6 +802,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -808,9 +811,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", - "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", "dev": true, "license": "MIT", "engines": { @@ -822,15 +825,17 @@ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "levn": "^0.4.1" }, @@ -1923,9 +1928,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "22.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", - "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "version": "22.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.1.tgz", + "integrity": "sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==", "dev": true, "license": "MIT", "dependencies": { @@ -1954,17 +1959,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", - "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/type-utils": "8.14.0", - "@typescript-eslint/utils": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1988,16 +1993,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", - "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/typescript-estree": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4" }, "engines": { @@ -2017,14 +2022,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", - "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0" + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2035,14 +2040,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", - "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.14.0", - "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2053,6 +2058,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -2060,9 +2068,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", - "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", "dev": true, "license": "MIT", "engines": { @@ -2074,14 +2082,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", - "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2129,16 +2137,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", - "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/typescript-estree": "8.14.0" + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2149,17 +2157,22 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", - "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.14.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2169,6 +2182,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", @@ -2187,6 +2213,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -2196,6 +2223,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2273,7 +2301,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/async": { "version": "3.2.5", @@ -2890,27 +2919,27 @@ } }, "node_modules/eslint": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", - "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", + "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.14.0", - "@eslint/plugin-kit": "^0.2.0", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.15.0", + "@eslint/plugin-kit": "^0.2.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.0", + "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.5", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -2929,8 +2958,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -3199,7 +3227,8 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -3658,6 +3687,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -4563,6 +4593,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -4598,7 +4629,8 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -4722,9 +4754,9 @@ } }, "node_modules/marked": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.0.tgz", - "integrity": "sha512-0mouKmBROJv/WSHJBPZZyYofUgawMChnD5je/g+aOBXsHDjb/IsnTQj7mnhQZu+qPJmRQ0ecX3mLGEUm3BgwYA==", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.2.tgz", + "integrity": "sha512-85RUkoYKIVB21PbMKrnD6aCl9ws+XKEyhJNMbLn206NyD3jbBo7Ec7Wi4Jrsn4dV1a2ng7K/jfkmIN0DNoS41w==", "dev": true, "license": "MIT", "bin": { @@ -5094,6 +5126,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -5376,6 +5409,7 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -5505,6 +5539,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -5944,12 +5979,6 @@ "node": ">=8" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -6096,15 +6125,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.14.0.tgz", - "integrity": "sha512-K8fBJHxVL3kxMmwByvz8hNdBJ8a0YqKzKDX6jRlrjMuNXyd5T2V02HIq37+OiWXvUUOXgOOGiSSOh26Mh8pC3w==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.15.0.tgz", + "integrity": "sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.14.0", - "@typescript-eslint/parser": "8.14.0", - "@typescript-eslint/utils": "8.14.0" + "@typescript-eslint/eslint-plugin": "8.15.0", + "@typescript-eslint/parser": "8.15.0", + "@typescript-eslint/utils": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6113,6 +6142,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -6178,6 +6210,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -6876,9 +6909,9 @@ "dev": true }, "@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", "dev": true, "requires": { "@eslint/object-schema": "^2.1.4", @@ -6887,15 +6920,15 @@ } }, "@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", "dev": true }, "@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -6918,9 +6951,9 @@ } }, "@eslint/js": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", - "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", "dev": true }, "@eslint/object-schema": { @@ -6930,9 +6963,9 @@ "dev": true }, "@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, "requires": { "levn": "^0.4.1" @@ -7791,9 +7824,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "22.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", - "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "version": "22.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.1.tgz", + "integrity": "sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==", "dev": true, "requires": { "undici-types": "~6.19.8" @@ -7821,16 +7854,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", - "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/type-utils": "8.14.0", - "@typescript-eslint/utils": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7838,54 +7871,54 @@ } }, "@typescript-eslint/parser": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", - "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/typescript-estree": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", - "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", "dev": true, "requires": { - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0" + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" } }, "@typescript-eslint/type-utils": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", - "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.14.0", - "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", - "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", - "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", "dev": true, "requires": { - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7915,25 +7948,33 @@ } }, "@typescript-eslint/utils": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", - "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/typescript-estree": "8.14.0" + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", - "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", "dev": true, "requires": { - "@typescript-eslint/types": "8.14.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true + } } }, "acorn": { @@ -8443,26 +8484,26 @@ "dev": true }, "eslint": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", - "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", + "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.14.0", - "@eslint/plugin-kit": "^0.2.0", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.15.0", + "@eslint/plugin-kit": "^0.2.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.0", + "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.5", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -8481,8 +8522,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "dependencies": { "eslint-visitor-keys": { @@ -9750,9 +9790,9 @@ } }, "marked": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.0.tgz", - "integrity": "sha512-0mouKmBROJv/WSHJBPZZyYofUgawMChnD5je/g+aOBXsHDjb/IsnTQj7mnhQZu+qPJmRQ0ecX3mLGEUm3BgwYA==", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.2.tgz", + "integrity": "sha512-85RUkoYKIVB21PbMKrnD6aCl9ws+XKEyhJNMbLn206NyD3jbBo7Ec7Wi4Jrsn4dV1a2ng7K/jfkmIN0DNoS41w==", "dev": true }, "meow": { @@ -10557,12 +10597,6 @@ "minimatch": "^3.0.4" } }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -10646,14 +10680,14 @@ "dev": true }, "typescript-eslint": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.14.0.tgz", - "integrity": "sha512-K8fBJHxVL3kxMmwByvz8hNdBJ8a0YqKzKDX6jRlrjMuNXyd5T2V02HIq37+OiWXvUUOXgOOGiSSOh26Mh8pC3w==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.15.0.tgz", + "integrity": "sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "8.14.0", - "@typescript-eslint/parser": "8.14.0", - "@typescript-eslint/utils": "8.14.0" + "@typescript-eslint/eslint-plugin": "8.15.0", + "@typescript-eslint/parser": "8.15.0", + "@typescript-eslint/utils": "8.15.0" } }, "undici-types": { diff --git a/package.json b/package.json index a3c3d16a6d..95f6d12ee1 100644 --- a/package.json +++ b/package.json @@ -109,24 +109,24 @@ "tar": "^7.4.3" }, "devDependencies": { - "@eslint/js": "^9.14.0", + "@eslint/js": "^9.15.0", "@octokit/rest": "^21.0.2", "@types/debug": "^4.1.12", "@types/jest": "^29.5.14", - "@types/node": "^22.9.0", - "eslint": "^9.14.0", + "@types/node": "^22.9.1", + "eslint": "^9.15.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", "globals": "^15.12.0", "jest": "^29.7.0", - "marked": "^15.0.0", + "marked": "^15.0.2", "open-cli": "^8.0.0", "pick-port": "^2.1.0", "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.5", "typescript": "^5.6.3", - "typescript-eslint": "^8.14.0" + "typescript-eslint": "^8.15.0" } } diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index 557596dc04..6767ad7f24 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -678,8 +678,8 @@ namespace RTC // We want it in network order. const uint64_t address = bindAddrIn->sin_addr.s_addr; - hash = static_cast(minPort) << 48; - hash = static_cast(maxPort) << 32; + hash |= static_cast(minPort) << 48; + hash |= static_cast(maxPort) << 32; hash |= (address >> 2) << 2; hash |= 0x0000; // AF_INET. @@ -693,8 +693,8 @@ namespace RTC const auto address = a[0] ^ a[1] ^ a[2] ^ a[3]; - hash = static_cast(minPort) << 48; - hash = static_cast(maxPort) << 32; + hash |= static_cast(minPort) << 48; + hash |= static_cast(maxPort) << 32; hash |= static_cast(address) << 16; hash |= (static_cast(address) >> 2) << 2; hash |= 0x0002; // AF_INET6. From ad02a3ab19c0f9ffa4d9c8efd671d786525d0978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 21 Nov 2024 15:18:20 +0100 Subject: [PATCH 525/525] 3.15.2 --- CHANGELOG.md | 2 ++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78b6d59521..e549f4b45e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### NEXT +### 3.15.2 + - `Worker`: Fix crash when using colliding `portRange` values in different transports ([PR #1469](https://github.com/versatica/mediasoup/pull/1469)). ### 3.15.1 diff --git a/package-lock.json b/package-lock.json index d41cc88211..12844415af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.15.1", + "version": "3.15.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.15.1", + "version": "3.15.2", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 95f6d12ee1..da573333b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.15.1", + "version": "3.15.2", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "Iñaki Baz Castillo (https://inakibaz.me)",

$func_code$count_code
$name$count